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:
M | linkup.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);
}