commit 6557073b7d3c01a99639b5ec31d102bbf0fa77b6
parent da3d9116be8b625fb3a0b18d5338c88a05e52d35
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sat, 9 May 2026 11:14:12 -0700
ar verbose support
Diffstat:
| M | driver/ar.c | | | 57 | ++++++++++++++++++++++++++++++++++++++++++++------------- |
| M | driver/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) ---------------- */