kit

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

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 }