diff options
-rw-r--r-- | usr.bin/du/du.1 | 4 | ||||
-rw-r--r-- | usr.bin/du/du.c | 68 |
2 files changed, 70 insertions, 2 deletions
diff --git a/usr.bin/du/du.1 b/usr.bin/du/du.1 index f1e4fe9..9f69c5b 100644 --- a/usr.bin/du/du.1 +++ b/usr.bin/du/du.1 @@ -41,6 +41,7 @@ .Sh SYNOPSIS .Nm .Op Fl H | L | P +.Op Fl I Ar mask .Op Fl a | s | d Ar depth .Op Fl c .Op Fl h | k @@ -69,6 +70,9 @@ Symbolic links on the command line are followed, symbolic links in file hierarchies are not followed. .It Fl L Symbolic links on the command line and in file hierarchies are followed. +.It Fl I Ar mask +Ignore files and directories matching the specified +.Ar mask . .It Fl P No symbolic links are followed. This is the default. diff --git a/usr.bin/du/du.c b/usr.bin/du/du.c index f2f7ad4..c53665b 100644 --- a/usr.bin/du/du.c +++ b/usr.bin/du/du.c @@ -50,10 +50,12 @@ static const char rcsid[] = #include <sys/param.h> +#include <sys/queue.h> #include <sys/stat.h> #include <err.h> #include <errno.h> +#include <fnmatch.h> #include <fts.h> #include <math.h> #include <stdio.h> @@ -88,10 +90,19 @@ typedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t; int unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA }; +SLIST_HEAD(ignhead, ignentry) ignores; +struct ignentry { + char *mask; + SLIST_ENTRY(ignentry) next; +}; + int linkchk __P((FTSENT *)); static void usage __P((void)); void prthumanval __P((double)); unit_t unit_adjust __P((double *)); +void ignoreadd __P((const char *)); +void ignoreclean __P((void)); +int ignorep __P((FTSENT *)); int main(argc, argv) @@ -112,12 +123,16 @@ main(argc, argv) save = argv; ftsoptions = 0; depth = INT_MAX; + SLIST_INIT(&ignores); - while ((ch = getopt(argc, argv, "HLPasd:chkrx")) != -1) + while ((ch = getopt(argc, argv, "HI:LPasd:chkrx")) != -1) switch (ch) { case 'H': Hflag = 1; break; + case 'I': + ignoreadd(optarg); + break; case 'L': if (Pflag) usage(); @@ -224,8 +239,13 @@ main(argc, argv) while ((p = fts_read(fts)) != NULL) { switch (p->fts_info) { case FTS_D: /* Ignore. */ + if (ignorep(p)) + fts_set(fts, p, FTS_SKIP); break; case FTS_DP: + if (ignorep(p)) + break; + p->fts_parent->fts_number += p->fts_number += p->fts_statp->st_blocks; @@ -249,6 +269,9 @@ main(argc, argv) rval = 1; break; default: + if (ignorep(p)) + break; + if (p->fts_statp->st_nlink > 1 && linkchk(p)) break; @@ -281,6 +304,7 @@ main(argc, argv) } } + ignoreclean(); exit(rval); } @@ -366,6 +390,46 @@ static void usage() { (void)fprintf(stderr, - "usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k] [-x] [file ...]\n"); + "usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k] [-x] [-I mask] [file ...]\n"); exit(EX_USAGE); } + +void +ignoreadd(mask) + const char *mask; +{ + struct ignentry *ign; + + ign = calloc(1, sizeof(*ign)); + if (ign == NULL) + errx(1, "cannot allocate memory"); + ign->mask = strdup(mask); + if (ign->mask == NULL) + errx(1, "cannot allocate memory"); + SLIST_INSERT_HEAD(&ignores, ign, next); +} + +void +ignoreclean() +{ + struct ignentry *ign; + + while (!SLIST_EMPTY(&ignores)) { + ign = SLIST_FIRST(&ignores); + SLIST_REMOVE_HEAD(&ignores, next); + free(ign->mask); + free(ign); + } +} + +int +ignorep(ent) + FTSENT *ent; +{ + struct ignentry *ign; + + SLIST_FOREACH(ign, &ignores, next) + if (fnmatch(ign->mask, ent->fts_name, 0) != FNM_NOMATCH) + return 1; + return 0; +} |