diff --git a/src/dir_scan.c b/src/dir_scan.c index f3688c64d90b9c25ad371506361a9ecf26840113..57f96b3d46a3757b663b3f9ffa61b0d8a028c1e2 100644 --- a/src/dir_scan.c +++ b/src/dir_scan.c @@ -196,6 +196,10 @@ static int dir_scan_item(struct dir *d) { if(!(d->flags & (FF_ERR|FF_EXL))) stat_to_dir(d, &st); + if(cachedir_tags && (d->flags & FF_DIR) && !(d->flags & (FF_ERR|FF_EXL|FF_OTHFS))) + if(has_cachedir_tag(d->name)) + d->flags |= FF_EXL; + /* Recurse into the dir or output the item */ if(d->flags & FF_DIR && !(d->flags & (FF_ERR|FF_EXL|FF_OTHFS))) fail = dir_scan_recurse(d); diff --git a/src/exclude.c b/src/exclude.c index ecf40a82567521a34804ee2a1b0ca41f410879ce..d7b679d81040af335cdfe6163b043866d15f822e 100644 --- a/src/exclude.c +++ b/src/exclude.c @@ -99,3 +99,26 @@ void exclude_clear() { excludes = NULL; } + +/* + * Exclusion of directories that contain only cached information. + * See http://www.brynosaurus.com/cachedir/ + */ +static const char cachedir_tag_signature[] = + "Signature: 8a477f597d28d172789f06886806bc55"; + +int has_cachedir_tag(const char *name) { + char buf[1024]; + FILE *f; + int match = 0; + const int signature_l = strlen(cachedir_tag_signature); + + snprintf(buf, sizeof(buf), "%s/CACHEDIR.TAG", name); + f = fopen(buf, "rb"); + if (f != NULL) { + match = ((fread(buf, 1, signature_l, f) == signature_l) && + !strncmp(buf, cachedir_tag_signature, signature_l)); + fclose(f); + } + return match; +} diff --git a/src/global.h b/src/global.h index d6eb2cb4a41ab45ca07cee5939973c63cc98de98..4bf0d55adda9ca8f6a8714231dd09abb9465b4d7 100644 --- a/src/global.h +++ b/src/global.h @@ -86,6 +86,8 @@ extern int pstate; extern int read_only; /* minimum screen update interval when calculating, in ms */ extern long update_delay; +/* filter directories with CACHEDIR.TAG */ +extern int cachedir_tags; /* handle input from keyboard and update display */ int input_handle(int); diff --git a/src/main.c b/src/main.c index 109f2a119b23585da1cff9997cff0c18a24581a8..54771b223fd212af9732b5b4a0dbb30be0cf8fb5 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ int pstate; int read_only = 0; long update_delay = 100; +int cachedir_tags = 0; static int min_rows = 17, min_cols = 60; static int ncurses_init = 0; @@ -125,6 +126,7 @@ static void argv_parse(int argc, char **argv) { { '2', 0, "-2" }, { 1, 1, "--exclude" }, { 'X', 1, "-X,--exclude-from" }, + { 'C', 0, "-C,--cachedir-tag" }, {0,0,NULL} }; @@ -146,6 +148,7 @@ static void argv_parse(int argc, char **argv) { printf(" -0,-1,-2 UI to use when scanning (0=none,2=full ncurses)\n"); printf(" --exclude PATTERN Exclude files that match PATTERN\n"); printf(" -X, --exclude-from FILE Exclude files that match any pattern in FILE\n"); + printf(" -C, --cachedir-tag Exclude directories containing CACHEDIR.TAG\n"); exit(0); case 'q': update_delay = 2000; break; case 'v': @@ -165,6 +168,9 @@ static void argv_parse(int argc, char **argv) { exit(1); } break; + case 'C': + cachedir_tags = 1; + break; case -2: printf("ncdu: %s.\n", val); exit(1);