diff options
author | Saagar Jha <saagar@saagarjha.com> | 2020-05-07 16:09:17 -0700 |
---|---|---|
committer | Saagar Jha <saagar@saagarjha.com> | 2020-05-13 11:29:55 -0700 |
commit | c9ce16a63376389c6fdcdec01512754fd36fe12e (patch) | |
tree | 0774a27d46de66d6432069124dfa652c30e2285f | |
parent | 684e9e04ad437e26a785e46aca8740e6831343be (diff) |
Support excluding firmlinks on macOS
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | src/browser.c | 1 | ||||
-rw-r--r-- | src/dir_export.c | 4 | ||||
-rw-r--r-- | src/dir_import.c | 2 | ||||
-rw-r--r-- | src/dir_scan.c | 27 | ||||
-rw-r--r-- | src/global.h | 3 | ||||
-rw-r--r-- | src/main.c | 12 |
7 files changed, 51 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac index f238137..9cec626 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,11 @@ AC_CHECK_FUNCS( AC_CHECK_FUNCS(statfs) +AC_CHECK_HEADERS([sys/attr.h]) + +AC_CHECK_FUNCS([getattrlist]) + +AC_CHECK_DECLS([ATTR_CMNEXT_NOFIRMLINKPATH], [], [], [[#include <sys/attr.h>]]) # Look for ncurses library to link to ncurses=auto diff --git a/src/browser.c b/src/browser.c index 3a9971f..4306cbd 100644 --- a/src/browser.c +++ b/src/browser.c @@ -119,6 +119,7 @@ static void browse_draw_flag(struct dir *n, int *x) { n->flags & FF_SERR ? '.' : n->flags & FF_OTHFS ? '>' : n->flags & FF_KERNFS ? '^' : + n->flags & FF_FRMLNK ? 'F' : n->flags & FF_HLNKC ? 'H' : !(n->flags & FF_FILE || n->flags & FF_DIR) ? '@' : diff --git a/src/dir_export.c b/src/dir_export.c index f602421..dd96721 100644 --- a/src/dir_export.c +++ b/src/dir_export.c @@ -116,7 +116,7 @@ static void output_info(struct dir *d, const char *name, struct dir_ext *e) { if(d->flags & FF_ERR) fputs(",\"read_error\":true", stream); /* excluded/error'd files are "unknown" with respect to the "notreg" field. */ - if(!(d->flags & (FF_DIR|FF_FILE|FF_ERR|FF_EXL|FF_OTHFS|FF_KERNFS))) + if(!(d->flags & (FF_DIR|FF_FILE|FF_ERR|FF_EXL|FF_OTHFS|FF_KERNFS|FF_FRMLNK))) fputs(",\"notreg\":true", stream); if(d->flags & FF_EXL) fputs(",\"excluded\":\"pattern\"", stream); @@ -124,6 +124,8 @@ static void output_info(struct dir *d, const char *name, struct dir_ext *e) { fputs(",\"excluded\":\"othfs\"", stream); else if(d->flags & FF_KERNFS) fputs(",\"excluded\":\"kernfs\"", stream); + else if(d->flags & FF_FRMLNK) + fputs(",\"excluded\":\"frmlnk\"", stream); fputc('}', stream); } diff --git a/src/dir_import.c b/src/dir_import.c index b3aeb7b..142b5e4 100644 --- a/src/dir_import.c +++ b/src/dir_import.c @@ -482,6 +482,8 @@ static int iteminfo(void) { ctx->buf_dir->flags |= FF_OTHFS; else if(strcmp(ctx->val, "kernfs") == 0) ctx->buf_dir->flags |= FF_KERNFS; + else if(strcmp(ctx->val, "frmlnk") == 0) + ctx->buf_dir->flags |= FF_FRMLNK; else ctx->buf_dir->flags |= FF_EXL; } else if(strcmp(ctx->val, "notreg") == 0) { /* notreg */ diff --git a/src/dir_scan.c b/src/dir_scan.c index 74c123a..ea3c267 100644 --- a/src/dir_scan.c +++ b/src/dir_scan.c @@ -34,6 +34,10 @@ #include <sys/stat.h> #include <dirent.h> +#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH +#include <sys/attr.h> +#endif + #if HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS #include <sys/statfs.h> #include <linux/magic.h> @@ -241,6 +245,25 @@ static int dir_scan_item(const char *name) { } #endif +#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH + if(!follow_firmlinks) { + struct attrlist list = { + .bitmapcount = ATTR_BIT_MAP_COUNT, + .forkattr = ATTR_CMNEXT_NOFIRMLINKPATH, + }; + struct { + uint32_t length; + attrreference_t reference; + char extra[PATH_MAX]; + } __attribute__((aligned(4), packed)) attributes; + if (getattrlist(name, &list, &attributes, sizeof(attributes), FSOPT_ATTR_CMN_EXTENDED) == -1) { + buf_dir->flags |= FF_ERR; + dir_setlasterr(dir_curpath); + } else if (strcmp(dir_curpath, (char *)&attributes.reference + attributes.reference.attr_dataoffset)) + buf_dir->flags |= FF_FRMLNK; + } +#endif + if(!(buf_dir->flags & (FF_ERR|FF_EXL))) { if(follow_symlinks && S_ISLNK(st.st_mode) && !stat(name, &stl) && !S_ISDIR(stl.st_mode)) stat_to_dir(&stl); @@ -248,14 +271,14 @@ static int dir_scan_item(const char *name) { stat_to_dir(&st); } - if(cachedir_tags && (buf_dir->flags & FF_DIR) && !(buf_dir->flags & (FF_ERR|FF_EXL|FF_OTHFS|FF_KERNFS))) + if(cachedir_tags && (buf_dir->flags & FF_DIR) && !(buf_dir->flags & (FF_ERR|FF_EXL|FF_OTHFS|FF_KERNFS|FF_FRMLNK))) if(has_cachedir_tag(name)) { buf_dir->flags |= FF_EXL; buf_dir->size = buf_dir->asize = 0; } /* Recurse into the dir or output the item */ - if(buf_dir->flags & FF_DIR && !(buf_dir->flags & (FF_ERR|FF_EXL|FF_OTHFS|FF_KERNFS))) + if(buf_dir->flags & FF_DIR && !(buf_dir->flags & (FF_ERR|FF_EXL|FF_OTHFS|FF_KERNFS|FF_FRMLNK))) fail = dir_scan_recurse(name); else if(buf_dir->flags & FF_DIR) { if(dir_output.item(buf_dir, name, buf_ext) || dir_output.item(NULL, 0, NULL)) { diff --git a/src/global.h b/src/global.h index de7a9c2..afb9c5e 100644 --- a/src/global.h +++ b/src/global.h @@ -52,6 +52,7 @@ #define FF_BSEL 0x80 /* selected */ #define FF_EXT 0x100 /* extended struct available */ #define FF_KERNFS 0x200 /* excluded because it was a Linux pseudo filesystem */ +#define FF_FRMLNK 0x400 /* excluded because it was a firmlink */ /* Program states */ #define ST_CALC 0 @@ -106,6 +107,8 @@ extern int confirm_quit; extern int extended_info; /* flag whether we want to follow symlinks */ extern int follow_symlinks; +/* flag whether we want to follow firmlinks */ +extern int follow_firmlinks; /* handle input from keyboard and update display */ int input_handle(int); @@ -42,6 +42,7 @@ long update_delay = 100; int cachedir_tags = 0; int extended_info = 0; int follow_symlinks = 0; +int follow_firmlinks = 0; int confirm_quit = 0; static int min_rows = 17, min_cols = 60; @@ -138,6 +139,7 @@ static void argv_parse(int argc, char **argv) { { 'L', 0, "-L,--follow-symlinks" }, { 'C', 0, "--exclude-caches" }, { 2, 0, "--exclude-kernfs" }, + { 3, 0, "--follow-firmlinks" }, { 's', 0, "--si" }, { 'Q', 0, "--confirm-quit" }, { 'c', 1, "--color" }, @@ -170,6 +172,9 @@ static void argv_parse(int argc, char **argv) { #if HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS printf(" --exclude-kernfs Exclude Linux pseudo filesystems (procfs,sysfs,cgroup,...)\n"); #endif +#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH + printf(" --follow-firmlinks Follow firmlinks on macOS\n"); +#endif printf(" --confirm-quit Confirm quitting ncdu\n"); printf(" --color SCHEME Set color scheme (off/dark)\n"); exit(0); @@ -206,6 +211,13 @@ static void argv_parse(int argc, char **argv) { fprintf(stderr, "This feature is not supported on your platform\n"); exit(1); #endif + case 3 : +#if HAVE_SYS_ATTR_H && HAVE_GETATTRLIST && HAVE_DECL_ATTR_CMNEXT_NOFIRMLINKPATH + follow_firmlinks = 1; break; +#else + fprintf(stderr, "This feature is not supported on your platform\n"); + exit(1); +#endif case 'c': if(strcmp(val, "off") == 0) { uic_theme = 0; } else if(strcmp(val, "dark") == 0) { uic_theme = 1; } |