install_links.c (3331B)
1 #include "install_links.h" 2 3 #include <stddef.h> 4 5 /* Join DIR + "/" + NAME into a freshly allocated, NUL-terminated path. 6 * Windows executable aliases carry the ordinary .exe suffix so CreateProcess, 7 * cmd, and PowerShell all recognize them as programs; argv[0] dispatch strips 8 * that suffix in driver/main.c. Returns NULL on allocation failure; on success 9 * stores the allocation size in *out_size for driver_free. */ 10 static char* install_join(DriverEnv* env, const char* dir, const char* name, 11 size_t* out_size) { 12 static const char windows_suffix[] = ".exe"; 13 const char* suffix = driver_host_target().os == KIT_OS_WINDOWS 14 ? windows_suffix 15 : ""; 16 size_t dl = driver_strlen(dir); 17 size_t nl = driver_strlen(name); 18 size_t sl = driver_strlen(suffix); 19 int slash = dl > 0 && dir[dl - 1u] != '/'; 20 size_t size = dl + (slash ? 1u : 0u) + nl + sl + 1u; 21 size_t off; 22 char* p = (char*)driver_alloc(env, size); 23 if (!p) return NULL; 24 driver_memcpy(p, dir, dl); 25 off = dl; 26 if (slash) p[off++] = '/'; 27 driver_memcpy(p + off, name, nl); 28 off += nl; 29 if (sl) { 30 driver_memcpy(p + off, suffix, sl); 31 off += sl; 32 } 33 p[off] = '\0'; 34 *out_size = size; 35 return p; 36 } 37 38 int driver_install_link_one(DriverEnv* env, const char* bindir, 39 const char* name, 40 const DriverInstallLinkOpts* opts) { 41 const char* tag = opts->tool_tag; 42 size_t path_size = 0; 43 char* link_path = install_join(env, bindir, name, &path_size); 44 int rc = 0; 45 46 if (!link_path) { 47 driver_errf(tag, "out of memory building path for %s", name); 48 return 1; 49 } 50 51 if (driver_path_lexists(link_path)) { 52 if (!opts->force) { 53 driver_errf(tag, "%s already exists (use -f to overwrite)", link_path); 54 rc = 1; 55 goto done; 56 } 57 if (!opts->dry_run && driver_remove_file(link_path) != 0) { 58 driver_errf(tag, "cannot replace %s", link_path); 59 rc = 1; 60 goto done; 61 } 62 } 63 64 if (opts->dry_run) { 65 driver_printf("%s -> %s (dry-run)\n", link_path, opts->target_exe); 66 goto done; 67 } 68 69 rc = opts->use_hardlink 70 ? driver_create_hardlink(opts->target_exe, link_path) 71 : driver_create_symlink(opts->target_exe, link_path); 72 if (rc != 0) { 73 driver_errf(tag, "failed to %s %s", 74 opts->use_hardlink ? "hard-link" : "symlink", link_path); 75 rc = 1; 76 goto done; 77 } 78 if (opts->verbose) driver_printf("%s -> %s\n", link_path, opts->target_exe); 79 80 done: 81 driver_free(env, link_path, path_size); 82 return rc; 83 } 84 85 unsigned driver_install_links(DriverEnv* env, const char* bindir, 86 unsigned group_mask, 87 const DriverInstallLinkOpts* opts, 88 unsigned* out_done) { 89 unsigned n = driver_tool_count(); 90 unsigned j; 91 unsigned done_count = 0, failures = 0; 92 93 for (j = 0; j < n; ++j) { 94 if (group_mask == DRIVER_GROUP_ALL && !driver_tool_public(j)) continue; 95 if (group_mask != DRIVER_GROUP_ALL && 96 (driver_tool_groups(j) & group_mask) == 0) 97 continue; 98 if (driver_install_link_one(env, bindir, driver_tool_name(j), opts) != 0) 99 ++failures; 100 else 101 ++done_count; 102 } 103 104 if (out_done) *out_done = done_count; 105 return failures; 106 }