linkup

Simple symlink farmer
git clone https://git.sinitax.com/sinitax/linkup
Log | Files | Refs | LICENSE | sfeed.txt

commit 3e8e707fcd07b0a2d5c6516f93b81204a7211540
parent 35668df3e3897b49c0825030a81c2e3c4395b987
Author: Louis Burda <quent.burda@gmail.com>
Date:   Thu, 28 Sep 2023 00:36:13 +0200

Add verbose logging and flag to skip dirs

Diffstat:
Mlinkup.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 59 insertions(+), 23 deletions(-)

diff --git a/linkup.c b/linkup.c @@ -10,12 +10,26 @@ #include <stdio.h> #include <stdlib.h> -static bool force = true; +static bool force = false; static bool install = true; +static bool nodirs = false; +static bool verbose = false; -static const char **ignored = NULL; -static size_t ignorecnt = 0; -static size_t ignorecap = 0; +static const char **excluded = NULL; +static size_t excludecnt = 0; +static size_t excludecap = 0; + +static void +info(const char *fmt, ...) +{ + va_list ap; + + if (!verbose) return; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} static void die(const char *fmt, ...) @@ -89,14 +103,14 @@ realparent(int dirfd, const char *dirpath, const char *file, char *parent) } static void -ignore(const char *arg) +exclude(const char *arg) { - if (ignorecnt == ignorecap) { - ignorecap = (ignorecap + 1) * 2; - ignored = realloc(ignored, ignorecap * sizeof(const char *)); + if (excludecnt == excludecap) { + excludecap = (excludecap + 1) * 2; + excluded = realloc(excluded, excludecap * sizeof(const char *)); } - ignored[ignorecnt] = arg; - ignorecnt++; + excluded[excludecnt] = arg; + excludecnt++; } static void @@ -120,11 +134,14 @@ do_install(const char *src_path, const char *dst_path) if (!strcmp(ent->d_name, "..")) continue; - for (i = 0; i < ignorecnt; i++) { - if (!strcmp(ignored[i], ent->d_name)) + for (i = 0; i < excludecnt; i++) { + if (!strcmp(excluded[i], ent->d_name)) break; } - if (i != ignorecnt) continue; + if (i != excludecnt) { + info("skip %s/%s\n", src_path, ent->d_name); + continue; + } snprintf(src_fpath, PATH_MAX, "%s/%s", src_path, ent->d_name); snprintf(dst_fpath, PATH_MAX, "%s/%s", dst_path, ent->d_name); @@ -132,12 +149,24 @@ do_install(const char *src_path, const char *dst_path) /* ensure link destination does not exist */ if (!fstatat(dirfd(dst_dir), ent->d_name, &attr, AT_SYMLINK_NOFOLLOW)) { - if ((attr.st_mode & S_IFMT) != S_IFLNK && !force) + if (ent->d_type == DT_DIR && (attr.st_mode & S_IFMT) == S_IFDIR) { + info("skip %s\n", src_fpath); + continue; + } + if (!force && (attr.st_mode & S_IFMT) != S_IFLNK) die("dst '%s' already exists", dst_fpath); - if (remove(dst_fpath)) - die("remove '%s' failed:", dst_path); + // TODO: skip if points to src_fpath already + info("rm %s\n", dst_fpath); + if (remove(dst_fpath)) // TODO: removeall + die("remove '%s' failed:", dst_fpath); + } else { + if (nodirs && ent->d_type == DT_DIR) { + info("skip %s\n", src_fpath); + continue; + } } + info("link %s\n", src_fpath, dst_fpath); if (symlink(src_fpath, dst_fpath) < 0) die("linking '%s' failed:", dst_fpath); } @@ -153,8 +182,11 @@ do_install(const char *src_path, const char *dst_path) continue; /* with missing destination */ - if (faccessat(dirfd(dst_dir), ent->d_name, F_OK, 0)) - unlinkat(dirfd(dst_dir), ent->d_name, 0); + if (faccessat(dirfd(dst_dir), ent->d_name, F_OK, 0)) { + info(" unlink %s/%s\n", dst_path, ent->d_name); + if (unlinkat(dirfd(dst_dir), ent->d_name, 0)) + die("unlinking '%s/%s' failed:", dst_path, ent->d_name); + } } closedir(dst_dir); @@ -196,12 +228,16 @@ main(int argc, const char **argv) src_arg = dst_arg = NULL; for (arg = &argv[1]; *arg; arg++) { - if (!strcmp(*arg, "-x")) { - ignore(*arg); - } else if (!strcmp(*arg, "-u")) { + if (!strcmp(*arg, "-x") || !strcmp(*arg, "--exclude")) { + exclude(*++arg); + } else if (!strcmp(*arg, "-u") || !strcmp(*arg, "--uninstall")) { install = false; - } else if (!strcmp(*arg, "-f")) { + } else if (!strcmp(*arg, "-f") || !strcmp(*arg, "--force")) { force = true; + } else if (!strcmp(*arg, "-v") || !strcmp(*arg, "--verbose")) { + verbose = true; + } else if (!strcmp(*arg, "--xdirs")) { + nodirs = true; } else if (!src_arg) { src_arg = *arg; } else if (!dst_arg) { @@ -228,5 +264,5 @@ main(int argc, const char **argv) do_uninstall(src_path, dst_path); } - free(ignored); + free(excluded); }