Build: add --enable-warnings (-Wall -Wextra); the tree is now warning-free with it, so distributions can opt in without risking a surprise -Werror breakage from a future compiler. Real bugs fixed (each verified by a reproducer): - lib/io.c: open_rollback_file() read 28 bytes into char[28] with no NUL and then strcmp()'d it against a 28-character magic, reading one byte past the array. The condition was also inverted, so a *valid* rollback file was rejected -- but only sometimes: the missing NUL made the result depend on stack garbage (verified: -O0 rejects, -O2 accepts). The whole --save-rollback/--rollback-changes path was unreliable. Now the buffer is sized for the terminator, zeroed, and the comparison is `!= 0`. Verified end to end: save -> reopen -> restore reports "2 blocks restored, 0 skipped"; a random file is rejected. - reiserfscore/reiserfslib.c, reiserfscore/journal.c: asprintf() was called with &fs->fs_file_name / &fs->fs_j_file_name, but those fields are `char *`, not `char **`. Passing a `char **` where `char *` is expected wrote through the wrong pointer -- silent memory corruption on any allocation. Fixed by using the new checked helper. - reiserfscore/node_formats.c: `code < 0` on an unsigned parameter was dead code; the guard never fired. - resize_reiserfs: missing `break` after -j made -j fall into -f, so "-j dev" silently also forced the operation. Sign-compare on the count_blocks() ternary and on count + blocks. - lib/misc.c: strncat with bound == strlen(src) (equivalent to strcat) into char[256] from a char[256] dirent name -- up to 261 bytes. Replaced with snprintf plus an explicit fit check. - lib/misc.c: die() used vsprintf into a fixed 1024-byte buffer. - strncpy with bound == destination size (mkreiserfs, tune, progbar) never terminated; replaced with snprintf. Allocator: drop the homegrown magic-header allocator. It wrote "_mem_begin_" / "mem_end" through strcpy inside the allocation, kept the size in an `int`, and its only safety check (checkmem) was never called -- every call site is commented out. Replaced with a size_t header that is over-aligned via max_align_t, so malloc alignment guarantees still hold. expandmem() now takes the old size from the header instead of a caller-supplied value that could disagree with it. Warnings: annotate the deliberate fallthroughs (fsck pass cascade, unit suffix parsing, percentage parsing), fix the remaining sign-compare and missing-field-initializer sites, and compute addresses of packed members via char* + offsetof instead of &member. Portability: asm/types.h -> linux/types.h, malloc.h and sys/vfs.h dropped from includes.h (nothing used them), sys/vfs.h -> sys/statfs.h for statfs(2). Version: reiserfsprogs.spec said 3.6.23 while configure.ac said 3.6.25. Remove the dead `#if 0` main() from hashes.c. Add .github/workflows/build.yml: gcc, clang, --enable-warnings and --enable-io-failure-emulation, each followed by a format/check/inspect smoke test on a real image. Verified: ./autogen.sh && ./configure --enable-warnings && make is clean from scratch (0 warnings, 51 compile/link steps). mkreiserfs, reiserfsck --check, debugreiserfs -S, reiserfstune -l and a real resize_reiserfs 128M -> 256M all succeed, and fsck reports the resized image clean.
117 lines
2.6 KiB
C
117 lines
2.6 KiB
C
#include <stdio.h>
|
|
#include <sys/time.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "progbar.h"
|
|
|
|
static char bar[128], spaces[128];
|
|
static const char spinner[] = "\\|/-";
|
|
|
|
void progbar_init(struct progbar *ctx, const char *units, FILE * fp)
|
|
{
|
|
memset(ctx, 0, sizeof(*ctx));
|
|
if (!bar[0])
|
|
memset(bar, '=', sizeof(bar) - 1);
|
|
if (!spaces[0])
|
|
memset(spaces, ' ', sizeof(spaces) - 1);
|
|
snprintf(ctx->units, sizeof(ctx->units), "%s", units);
|
|
ctx->file = fp;
|
|
}
|
|
|
|
void progbar_clear(struct progbar *ctx)
|
|
{
|
|
if (!(ctx->flags & E2F_FLAG_PROG_BAR))
|
|
return;
|
|
|
|
fprintf(ctx->file, "\r%*s\r", 80, " ");
|
|
fflush(ctx->file);
|
|
ctx->flags &= ~E2F_FLAG_PROG_BAR;
|
|
}
|
|
|
|
int progbar_update(struct progbar *ctx, const char *label, int curr, int max,
|
|
unsigned int dpynum)
|
|
{
|
|
int i;
|
|
unsigned int tick;
|
|
struct timeval tv;
|
|
int dpywidth;
|
|
int fixed_percent;
|
|
assert (curr >= 0);
|
|
assert (max > 0);
|
|
float percent = ((float)curr) / ((float)max) * 100;
|
|
|
|
if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
|
|
return 0;
|
|
|
|
/*
|
|
* Calculate the new progress position. If the
|
|
* percentage hasn't changed, then we skip out right
|
|
* away.
|
|
*/
|
|
fixed_percent = (int)((10 * percent) + 0.5);
|
|
if (ctx->progress_last_percent == fixed_percent)
|
|
return 0;
|
|
ctx->progress_last_percent = fixed_percent;
|
|
|
|
/*
|
|
* If we've already updated the spinner once within
|
|
* the last 1/8th of a second, no point doing it
|
|
* again.
|
|
*/
|
|
gettimeofday(&tv, NULL);
|
|
tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
|
|
if ((tick == ctx->progress_last_time) &&
|
|
(fixed_percent != 0) && (fixed_percent != 1000))
|
|
return 0;
|
|
ctx->progress_last_time = tick;
|
|
|
|
/*
|
|
* Advance the spinner, and note that the progress bar
|
|
* will be on the screen
|
|
*/
|
|
ctx->progress_pos = (ctx->progress_pos + 1) & 3;
|
|
ctx->flags |= E2F_FLAG_PROG_BAR;
|
|
|
|
dpywidth = 66 - strlen(label);
|
|
dpywidth = 8 * (dpywidth / 8);
|
|
if (dpynum)
|
|
dpywidth -= 8;
|
|
|
|
i = ((percent * dpywidth) + 50) / 100;
|
|
fprintf(ctx->file, "\r%s: |%s%s", label,
|
|
bar + (sizeof(bar) - (i + 1)),
|
|
spaces + (sizeof(spaces) - (dpywidth - i + 1)));
|
|
if (fixed_percent == 1000)
|
|
fputc('|', ctx->file);
|
|
else
|
|
fputc(spinner[ctx->progress_pos & 3], ctx->file);
|
|
fprintf(ctx->file, " %4.1f%% ", percent);
|
|
if (dpynum)
|
|
fprintf(ctx->file, "%u%s\r", dpynum, ctx->units);
|
|
else
|
|
fputs(" \r", ctx->file);
|
|
|
|
if (fixed_percent == 1000)
|
|
progbar_clear(ctx);
|
|
fflush(ctx->file);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void spinner_init(struct spinner *ctx, FILE * fp)
|
|
{
|
|
memset(ctx, 0, sizeof(*ctx));
|
|
ctx->file = fp;
|
|
}
|
|
|
|
void spinner_touch(struct spinner *ctx)
|
|
{
|
|
fprintf(ctx->file, "%c", spinner[ctx->count++ % 4]);
|
|
}
|
|
|
|
void spinner_clear(struct spinner *ctx)
|
|
{
|
|
fputs("", ctx->file);
|
|
}
|