From 93edebc81c6ef81dc4e4e20d567fa26a1182e67f Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 15 Nov 2024 15:17:21 +0100 Subject: [PATCH] Expand ~ and ~user in config file Fixes #243 --- src/main.c | 16 ++++++++++------ src/util.c | 42 +++++++++++++++++++++++++++++++++++++++++- src/util.h | 2 ++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index 5ba66cd..b6bad44 100644 --- a/src/main.c +++ b/src/main.c @@ -191,7 +191,7 @@ static char *argparser_arg(struct argparser *p) { #define OPT(_s) (strcmp(argparser_state.last, (_s)) == 0) #define ARG (argparser_arg(&argparser_state)) -static int arg_option(void) { +static int arg_option(int infile) { char *arg, *tmp; if(OPT("-q") || OPT("--slow-ui-updates")) update_delay = 2000; else if(OPT("--fast-ui-updates")) update_delay = 100; @@ -253,10 +253,14 @@ static int arg_option(void) { else if(OPT("--no-si")) si = 0; else if(OPT("-L") || OPT("--follow-symlinks")) follow_symlinks = 1; else if(OPT("--no-follow-symlinks")) follow_symlinks = 0; - else if(OPT("--exclude")) exclude_add(ARG); - else if(OPT("-X") || OPT("--exclude-from")) { - arg = ARG; + else if(OPT("--exclude")) { + arg = infile ? expanduser(ARG) : ARG; + exclude_add(arg); + if(infile) free(arg); + } else if(OPT("-X") || OPT("--exclude-from")) { + arg = infile ? expanduser(ARG) : ARG; if(exclude_addfile(arg)) die("Can't open %s: %s\n", arg, strerror(errno)); + if(infile) free(arg); } else if(OPT("--exclude-caches")) cachedir_tags = 1; else if(OPT("--include-caches")) cachedir_tags = 0; else if(OPT("--exclude-kernfs")) exclude_kernfs = 1; @@ -347,7 +351,7 @@ static void config_read(const char *fn) { argparser_state.argc = argslen; while((r = argparser_next(&argparser_state)) > 0) - if(r == 2 || !arg_option()) + if(r == 2 || !arg_option(1)) die("Unknown option in config file '%s': %s.\nRun with --ignore-config to skip reading config files.\n", fn, argparser_state.last); for(argsi=args; argsi && *argsi; argsi++) free(*argsi); @@ -394,7 +398,7 @@ static void argv_parse(int argc, char **argv) { else if(OPT("-o")) export = ARG; else if(OPT("-f")) import = ARG; else if(OPT("--ignore-config")) {} - else if(!arg_option()) die("Unknown option '%s'.\n", argparser_state.last); + else if(!arg_option(0)) die("Unknown option '%s'.\n", argparser_state.last); } #if !(HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS) diff --git a/src/util.c b/src/util.c index e387d74..6b36b9b 100644 --- a/src/util.c +++ b/src/util.c @@ -30,6 +30,8 @@ #include #include #include +#include + #ifdef HAVE_LOCALE_H #include #endif @@ -441,7 +443,7 @@ void addparentstats(struct dir *d, int64_t size, int64_t asize, uint64_t mtime, char buf[128];\ while((ptr = f) == NULL) {\ close_nc();\ - write(2, oom_msg, sizeof(oom_msg));\ + write(2, oom_msg, sizeof(oom_msg)-1);\ read(0, buf, sizeof(buf));\ }\ return ptr; @@ -455,3 +457,41 @@ char *xstrdup(const char *str) { strcpy(r, str); return r; } + + +/* Expands '~' and '~user' */ +char *expanduser(const char *path) { + size_t len, size; + struct passwd *pwd; + char *home = NULL, *tmp; + + if(path[0] != '~') return xstrdup(path); + len = strcspn(path+1, "/"); + + if(len == 0) { + home = getenv("HOME"); + if(!home) { + pwd = getpwuid(getuid()); + if(pwd) home = pwd->pw_dir; + } + } else { + tmp = xmalloc(len+1); + memcpy(tmp, path+1, len); + tmp[len] = 0; + pwd = getpwnam(tmp); + free(tmp); + if(pwd) home = pwd->pw_dir; + } + if(!home) return xstrdup(path); + + size = strlen(home); + while(size > 0 && home[size-1] == '/') size--; + home[size] = 0; + + if(size == 0 && path[len+1] == 0) return xstrdup("/"); + + size += strlen(path) - len; + tmp = xmalloc(size); + snprintf(tmp, size, "%s%s", home, path+1+len); + return tmp; +} diff --git a/src/util.h b/src/util.h index fe01dc6..2b03fd3 100644 --- a/src/util.h +++ b/src/util.h @@ -190,5 +190,7 @@ void *xrealloc(void *, size_t); char *xstrdup(const char *); +char *expanduser(const char *); + #endif