kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 6557073b7d3c01a99639b5ec31d102bbf0fa77b6
parent da3d9116be8b625fb3a0b18d5338c88a05e52d35
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sat,  9 May 2026 11:14:12 -0700

ar verbose support

Diffstat:
Mdriver/ar.c | 57++++++++++++++++++++++++++++++++++++++++++++-------------
Mdriver/env.c | 66+++++++++++++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 91 insertions(+), 32 deletions(-)

diff --git a/driver/ar.c b/driver/ar.c @@ -184,7 +184,7 @@ static int ar_do_list(DriverEnv* env, const char* archive_path, int verbose) } static int ar_do_extract(DriverEnv* env, const char* archive_path, - int argc, char** argv, int start) + int argc, char** argv, int start, int verbose) { CfreeEnv cenv; CfreeFileData fd = {0}; @@ -216,6 +216,7 @@ static int ar_do_extract(DriverEnv* env, const char* archive_path, rc = 1; } cfree_writer_close(out); + if (verbose) driver_printf("x - %s\n", m.name); } cenv.file_io->release(cenv.file_io->user, &fd); @@ -223,7 +224,7 @@ static int ar_do_extract(DriverEnv* env, const char* archive_path, } static int ar_do_print(DriverEnv* env, const char* archive_path, - int argc, char** argv, int start) + int argc, char** argv, int start, int verbose) { CfreeEnv cenv; CfreeFileData fd = {0}; @@ -231,7 +232,8 @@ static int ar_do_print(DriverEnv* env, const char* archive_path, CfreeArIter it; CfreeArMember m; CfreeWriter* out; - int multi = (argc - start) != 1; /* prefix when 0 or >=2 filters */ + /* prefix when 0 or >=2 filters, or when verbose forces it */ + int header = verbose || (argc - start) != 1; int rc = 0; if (!ar_open_for_read(env, archive_path, &cenv, &fd, &input)) return 1; @@ -250,7 +252,7 @@ static int ar_do_print(DriverEnv* env, const char* archive_path, while (cfree_ar_iter_next(&it, &m)) { if (!ar_name_selected(m.name, argc, argv, start)) continue; - if (multi) driver_printf("%s(%s):\n", archive_path, m.name); + if (header) driver_printf("%s(%s):\n", archive_path, m.name); if (m.size) cfree_writer_write(out, m.data, m.size); } if (cfree_writer_error(out)) rc = 1; @@ -271,7 +273,7 @@ static int ar_do_print(DriverEnv* env, const char* archive_path, */ static int ar_do_write(DriverEnv* env, const char* archive_path, int nmembers, char** member_paths, - int has_r, int has_c, int has_s) + int has_r, int has_c, int has_s, int has_v) { uint32_t nnew = nmembers > 0 ? (uint32_t)nmembers : 0u; CfreeBytesInput* members = NULL; @@ -285,6 +287,12 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, int have_old = 0; int rc = 0; uint32_t i; + /* Old-member name storage. cfree_ar_iter_next returns CfreeArMember.name + * pointing into the iterator's single internal _namebuf, which is + * overwritten on each next(); the seeded members[] outlives iteration, + * so each name must be copied into our own backing buffer. */ + char* old_name_storage = NULL; + size_t old_name_bytes = 0; /* Per-member symbol storage (only used when has_s). msyms is the array * passed to cfree_ar_write; sym_allocs holds the single per-member * blob backing each msyms[i].names + name bytes (one allocation per @@ -313,8 +321,12 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, rc = 1; goto done; } - /* Count first so we can size the array exactly. */ - while (cfree_ar_iter_next(&it, &m)) nold++; + /* Count first so we can size the array exactly, and total the + * name bytes so we can stash a stable copy of each name. */ + while (cfree_ar_iter_next(&it, &m)) { + nold++; + old_name_bytes += driver_strlen(m.name) + 1; + } } else if (!has_c) { /* POSIX: warn (not an error) when `r` creates a new archive. */ driver_errf(AR_TOOL, "creating %s", archive_path); @@ -332,11 +344,25 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, } if (have_old) { + size_t cursor = 0; + if (old_name_bytes > 0) { + old_name_storage = (char*)driver_alloc_zeroed(env, old_name_bytes); + if (!old_name_storage) { + driver_errf(AR_TOOL, "out of memory"); + rc = 1; + goto done; + } + } cfree_ar_iter_init(&it, &input); while (cfree_ar_iter_next(&it, &m) && nm < nold) { - members[nm].name = m.name; + char* dst = old_name_storage + cursor; + const char* p; + for (p = m.name; *p; ++p) *dst++ = *p; + *dst++ = '\0'; + members[nm].name = old_name_storage + cursor; members[nm].data = m.data; members[nm].len = m.size; + cursor = (size_t)(dst - old_name_storage); nm++; } } @@ -390,11 +416,13 @@ static int ar_do_write(DriverEnv* env, const char* archive_path, members[nm].len = new_fds[i].size; nm++; } + if (has_v) driver_printf("%c - %s\n", replaced ? 'r' : 'a', base); } else { members[nm].name = base; members[nm].data = new_fds[i].data; members[nm].len = new_fds[i].size; nm++; + if (has_v) driver_printf("a - %s\n", base); } } } @@ -536,6 +564,7 @@ done: driver_free(env, new_fds, (size_t)nnew * sizeof(*new_fds)); } if (members) driver_free(env, members, members_cap * sizeof(*members)); + if (old_name_storage) driver_free(env, old_name_storage, old_name_bytes); if (have_old) cenv.file_io->release(cenv.file_io->user, &old_fd); return rc; } @@ -552,6 +581,7 @@ int driver_ar(int argc, char** argv) int has_r = 0; int has_c = 0; int has_s = 0; + int has_v = 0; int i; int rc; @@ -573,10 +603,11 @@ int driver_ar(int argc, char** argv) case 'r': do_write = 1; has_r = 1; break; case 'c': do_write = 1; has_c = 1; break; case 's': has_s = 1; break; + case 'v': has_v = 1; break; case 't': do_list = 1; break; case 'x': do_extract = 1; break; case 'p': do_print = 1; break; - case 'd': case 'q': case 'v': + case 'd': case 'q': driver_errf(AR_TOOL, "operation not implemented: %c", mode[i]); return 2; default: @@ -610,14 +641,14 @@ int driver_ar(int argc, char** argv) driver_env_fini(&env); return 2; } - rc = ar_do_list(&env, archive_path); + rc = ar_do_list(&env, archive_path, has_v); } else if (do_extract) { - rc = ar_do_extract(&env, archive_path, argc, argv, 3); + rc = ar_do_extract(&env, archive_path, argc, argv, 3, has_v); } else if (do_print) { - rc = ar_do_print(&env, archive_path, argc, argv, 3); + rc = ar_do_print(&env, archive_path, argc, argv, 3, has_v); } else { rc = ar_do_write(&env, archive_path, argc - 3, argv + 3, - has_r, has_c, has_s); + has_r, has_c, has_s, has_v); } driver_env_fini(&env); diff --git a/driver/env.c b/driver/env.c @@ -172,12 +172,6 @@ static void fdw_close(CfreeWriter* w) fw->heap->free(fw->heap, fw, sizeof(*fw)); } -static void fdw_noclose(CfreeWriter* w) -{ - DriverFdWriter* fw = (DriverFdWriter*)w; - fw->heap->free(fw->heap, fw, sizeof(*fw)); -} - static CfreeWriter* driver_writer_fd(CfreeHeap* h, int fd) { DriverFdWriter* fw = (DriverFdWriter*)h->alloc(h, sizeof(*fw), _Alignof(DriverFdWriter)); @@ -194,21 +188,55 @@ static CfreeWriter* driver_writer_fd(CfreeHeap* h, int fd) return &fw->base; } +/* Stdout writer routes through stdio so it shares libc's buffer with + * driver_printf — otherwise interleaved printf+writer output would land + * in stdout-order surprises (printf is line/full-buffered; raw write(2) + * to fd 1 bypasses that buffer entirely). */ +typedef struct DriverStdioWriter { + CfreeWriter base; + CfreeHeap* heap; + FILE* fp; +} DriverStdioWriter; + +static void stdio_w_write(CfreeWriter* w, const void* data, size_t n) +{ + DriverStdioWriter* sw = (DriverStdioWriter*)w; + if (n) fwrite(data, 1, n, sw->fp); +} +static void stdio_w_seek (CfreeWriter* w, uint64_t off) +{ + DriverStdioWriter* sw = (DriverStdioWriter*)w; + fseek(sw->fp, (long)off, SEEK_SET); +} +static uint64_t stdio_w_tell (CfreeWriter* w) +{ + long t = ftell(((DriverStdioWriter*)w)->fp); + return t < 0 ? 0u : (uint64_t)t; +} +static int stdio_w_error(CfreeWriter* w) +{ + return ferror(((DriverStdioWriter*)w)->fp) ? 1 : 0; +} +static void stdio_w_close(CfreeWriter* w) +{ + DriverStdioWriter* sw = (DriverStdioWriter*)w; + fflush(sw->fp); /* flush but do not close stdout */ + sw->heap->free(sw->heap, sw, sizeof(*sw)); +} + CfreeWriter* driver_stdout_writer(DriverEnv* e) { - DriverFdWriter* fw = (DriverFdWriter*)e->heap->alloc( - e->heap, sizeof(*fw), _Alignof(DriverFdWriter)); - if (!fw) return NULL; - fw->base.write = fdw_write; - fw->base.seek = fdw_seek; - fw->base.tell = fdw_tell; - fw->base.error = fdw_error; - fw->base.close = fdw_noclose; /* do not close fd 1 */ - fw->heap = e->heap; - fw->fd = STDOUT_FILENO; - fw->err = 0; - fw->pos = 0; - return &fw->base; + DriverStdioWriter* sw = (DriverStdioWriter*)e->heap->alloc( + e->heap, sizeof(*sw), _Alignof(DriverStdioWriter)); + if (!sw) return NULL; + sw->base.write = stdio_w_write; + sw->base.seek = stdio_w_seek; + sw->base.tell = stdio_w_tell; + sw->base.error = stdio_w_error; + sw->base.close = stdio_w_close; + sw->heap = e->heap; + sw->fp = stdout; + return &sw->base; } /* ---------------- file_io (POSIX) ---------------- */