ranlib.c (3479B)
1 #include <kit/archive.h> 2 #include <kit/core.h> 3 #include <kit/object.h> 4 5 #include "driver.h" 6 7 /* `kit ranlib` — refresh / add a System-V `/` symbol-index member at the 8 * head of an existing POSIX `ar` archive. Equivalent to `kit ar s ARCHIVE`, 9 * which is reserved by the POSIX ar grammar but not yet implemented in the 10 * ar tool. ranlib is the conventional name and the one Makefiles invoke. 11 * 12 * Operation: read all members, rebuild the archive at the same path with 13 * symbol_index=1 and per-member globally-defined symbols filled in. Long 14 * member names are preserved via the `//` extended-name table. Reproducible 15 * output via SOURCE_DATE_EPOCH (same epoch handling as `kit ar`). 16 * 17 * The read-members / recompute-index / rewrite pipeline is kit_ar_reindex in 18 * libkit (shared with ar / strip via the same symbol-index automation). */ 19 20 #define RANLIB_TOOL "ranlib" 21 22 void driver_help_ranlib(void) { 23 driver_printf( 24 "%.*s", 25 KIT_SLICE_ARG(KIT_SLICE_LIT( 26 "kit ranlib — refresh the symbol index of an `ar` archive\n" 27 "\n" 28 "USAGE\n" 29 " kit ranlib ARCHIVE.a\n" 30 "\n" 31 "DESCRIPTION\n" 32 " Reads every member of ARCHIVE.a, rebuilds the archive in place\n" 33 " with a System-V `/` symbol-index member at the head. Member " 34 "names,\n" 35 " contents, and order are preserved. Reproducible: when\n" 36 " SOURCE_DATE_EPOCH is set to a positive integer, that value is\n" 37 " written to ar_date for every member.\n" 38 "OPTIONS\n" 39 " -h, --help Show this help and exit\n" 40 "\n" 41 "EXAMPLES\n" 42 " kit ar rc libfoo.a a.o b.o\n" 43 " kit ranlib libfoo.a\n" 44 " kit nm -g libfoo.a\n" 45 "\n" 46 "EXIT CODES\n" 47 " 0 success 1 archive I/O error 2 bad " 48 "usage\n"))); 49 } 50 51 int driver_ranlib(int argc, char** argv) { 52 DriverEnv env; 53 KitContext ctx; 54 KitFileData old_fd = {0}; 55 KitSlice input; 56 KitWriter* out = NULL; 57 const char* archive_path; 58 int have_old = 0; 59 int rc = 1; 60 61 if (argc < 2 || driver_argv_wants_help(argc, argv, 1)) { 62 driver_help_ranlib(); 63 return 0; 64 } 65 if (argc != 2) { 66 driver_errf(RANLIB_TOOL, "usage: kit ranlib ARCHIVE.a"); 67 return 2; 68 } 69 archive_path = argv[1]; 70 71 driver_env_init(&env); 72 ctx = driver_env_to_context(&env); 73 74 if (ctx.file_io->read_all(ctx.file_io->user, archive_path, &old_fd) != 75 KIT_OK) { 76 driver_errf(RANLIB_TOOL, "failed to read: %.*s", 77 KIT_SLICE_ARG(kit_slice_cstr(archive_path))); 78 goto out; 79 } 80 have_old = 1; 81 input.data = old_fd.data; 82 input.len = old_fd.size; 83 84 /* Read every member and rewrite the archive with a freshly-computed symbol 85 * index — the whole of ranlib is now kit_ar_reindex. */ 86 if (ctx.file_io->open_writer(ctx.file_io->user, archive_path, &out) != 87 KIT_OK) { 88 driver_errf(RANLIB_TOOL, "failed to open: %.*s", 89 KIT_SLICE_ARG(kit_slice_cstr(archive_path))); 90 goto out; 91 } 92 if (kit_ar_reindex(&ctx, &input, driver_epoch_from_env(), out) != KIT_OK) { 93 driver_errf(RANLIB_TOOL, "not an archive: %.*s", 94 KIT_SLICE_ARG(kit_slice_cstr(archive_path))); 95 goto out; 96 } 97 rc = kit_writer_status(out) == KIT_OK ? 0 : 1; 98 99 out: 100 if (out) kit_writer_close(out); 101 if (have_old) ctx.file_io->release(ctx.file_io->user, &old_fd); 102 driver_env_fini(&env); 103 return rc; 104 }