commit 6050e79d8069d21f2dd416b30f4fa5096fb5a0f6
parent a286b18428747eafbb6923b86fe5f25c3f70f7bf
Author: Louis Burda <quent.burda@gmail.com>
Date: Thu, 20 Oct 2022 02:06:37 +0200
Add uninstall option
Diffstat:
M | linkup.c | | | 139 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
1 file changed, 90 insertions(+), 49 deletions(-)
diff --git a/linkup.c b/linkup.c
@@ -14,6 +14,10 @@ static const char usage[] = "linkup [-h] [-x FILE..] SOURCE DEST";
static bool force;
+static const char **ignored;
+static int ignorecnt;
+static int ignorecap;
+
bool
exists(int dirfd, const char *path)
{
@@ -23,7 +27,7 @@ exists(int dirfd, const char *path)
}
void
-removeall(int pfd, const char *path)
+remove_all(int pfd, const char *path)
{
struct dirent *ent;
struct stat attr;
@@ -40,66 +44,22 @@ removeall(int pfd, const char *path)
dir = fdopendir(fd);
if (!dir) err(1, "opendir");
while ((ent = readdir(dir)))
- removeall(fd, ent->d_name);
+ remove_all(fd, ent->d_name);
closedir(dir);
}
unlinkat(pfd, path, AT_REMOVEDIR);
}
-int
-main(int argc, const char **argv)
+void
+do_install(const char *spath, const char *dpath)
{
char spbuf[PATH_MAX], dpbuf[PATH_MAX];
- char spath[PATH_MAX], dpath[PATH_MAX];
struct dirent *ent;
struct stat attr;
- const char *sarg, *darg;
- const char **arg;
DIR *sdir, *ddir;
- const char **ignored;
- int ignorecnt;
- int ignorecap;
int i;
- ignored = NULL;
- ignorecap = 0;
- ignorecnt = 0;
-
- force = false;
- sarg = darg = NULL;
- for (arg = &argv[1]; *arg; arg++) {
- if (!strcmp(*arg, "-x")) {
- if (ignorecnt == ignorecap) {
- ignorecap = (ignorecap + 1) * 2;
- ignored = realloc(ignored,
- ignorecap * sizeof(const char *));
- }
- ignored[ignorecnt] = *arg;
- ignorecnt++;
- } else if (!strcmp(*arg, "-f")) {
- force = true;
- } else if (!sarg) {
- sarg = *arg;
- } else if (!darg) {
- darg = *arg;
- } else {
- printf("Usage: %s\n", usage);
- return 0;
- }
- }
-
- if (!sarg || !darg) {
- fprintf(stderr, "Usage: %s\n", usage);
- return 1;
- }
-
- if (!realpath(sarg, spath))
- err(1, "realpath src");
-
- if (!realpath(darg, dpath))
- err(1, "realpath dst");
-
sdir = opendir(spath);
if (!sdir) err(1, "opendir src");
@@ -125,8 +85,8 @@ main(int argc, const char **argv)
&attr, AT_SYMLINK_NOFOLLOW)) {
if ((attr.st_mode & S_IFMT) != S_IFLNK && !force)
errx(1, "dst %s already exists\n", ent->d_name);
+ remove_all(dirfd(ddir), ent->d_name);
}
- removeall(dirfd(ddir), ent->d_name);
/* create link */
snprintf(spbuf, PATH_MAX, "%s/%s", spath, ent->d_name);
@@ -149,5 +109,86 @@ main(int argc, const char **argv)
unlinkat(dirfd(ddir), ent->d_name, 0);
}
+ closedir(ddir);
+ closedir(sdir);
+}
+
+void
+do_uninstall(const char *spath, const char *dpath)
+{
+ struct dirent *ent;
+ char dpbuf[PATH_MAX];
+ DIR *ddir;
+
+ ddir = opendir(dpath);
+ if (!ddir) err(1, "opendir dst");
+
+ while ((ent = readdir(ddir))) {
+ if (ent->d_type != DT_LNK)
+ continue;
+ snprintf(dpbuf, PATH_MAX, "%s/%s", dpath, ent->d_name);
+ if (readlink(dpbuf, dpbuf, PATH_MAX) < 0)
+ err(1, "readlink");
+ realpath(dpbuf, dpbuf);
+ if (!strncmp(dpbuf, spath, strlen(spath)))
+ unlinkat(dirfd(ddir), ent->d_name, 0);
+ }
+
+ closedir(ddir);
+}
+
+int
+main(int argc, const char **argv)
+{
+ char spath[PATH_MAX], dpath[PATH_MAX];
+ const char *sarg, *darg;
+ const char **arg;
+ bool install;
+ int i;
+
+ ignored = NULL;
+ ignorecap = 0;
+ ignorecnt = 0;
+
+ force = false;
+ install = true;
+ sarg = darg = NULL;
+ for (arg = &argv[1]; *arg; arg++) {
+ if (!strcmp(*arg, "-x")) {
+ if (ignorecnt == ignorecap) {
+ ignorecap = (ignorecap + 1) * 2;
+ ignored = realloc(ignored,
+ ignorecap * sizeof(const char *));
+ }
+ ignored[ignorecnt] = *arg;
+ ignorecnt++;
+ } else if (!strcmp(*arg, "-u")) {
+ install = false;
+ } else if (!strcmp(*arg, "-f")) {
+ force = true;
+ } else if (!sarg) {
+ sarg = *arg;
+ } else if (!darg) {
+ darg = *arg;
+ } else {
+ printf("Usage: %s\n", usage);
+ return 0;
+ }
+ }
+
+ if (!sarg || !darg) {
+ fprintf(stderr, "Usage: %s\n", usage);
+ return 1;
+ }
+
+ if (!realpath(sarg, spath))
+ err(1, "realpath src");
+
+ if (!realpath(darg, dpath))
+ err(1, "realpath dst");
+
+ if (install) do_install(spath, dpath);
+ else do_uninstall(spath, dpath);
+
free(ignored);
}