Files
reiserfsprogs/lib/progbar.c
T
lgcosta 293e6a7280
build / build (clang, ) (push) Failing after 12s
build / build (gcc, ) (push) Failing after 9s
build / build (gcc, --enable-io-failure-emulation) (push) Failing after 8s
build / build (gcc, --enable-warnings) (push) Failing after 6s
Fix real bugs and clean up the build with -Wall -Wextra
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.
2026-11-11 22:02:38 -03:00

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);
}