Add '-I mask' cmdline flag to ignore/skip files and subdirectories

matching a specified shell-glob mask.

Reviewed by:	no serious objections on -arch and -audit over
		the last few months
MFC after:	1 month
This commit is contained in:
Peter Pentchev 2001-06-13 06:38:58 +00:00
parent 8b9959ada8
commit 4bb69e3542
2 changed files with 70 additions and 2 deletions

View File

@ -41,6 +41,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl H | L | P .Op Fl H | L | P
.Op Fl I Ar mask
.Op Fl a | s | d Ar depth .Op Fl a | s | d Ar depth
.Op Fl c .Op Fl c
.Op Fl h | k .Op Fl h | k
@ -69,6 +70,9 @@ Symbolic links on the command line are followed, symbolic links in file
hierarchies are not followed. hierarchies are not followed.
.It Fl L .It Fl L
Symbolic links on the command line and in file hierarchies are followed. 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 .It Fl P
No symbolic links are followed. No symbolic links are followed.
This is the default. This is the default.

View File

@ -50,10 +50,12 @@ static const char rcsid[] =
#include <sys/param.h> #include <sys/param.h>
#include <sys/queue.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
#include <fnmatch.h>
#include <fts.h> #include <fts.h>
#include <math.h> #include <math.h>
#include <stdio.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 }; 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 *)); int linkchk __P((FTSENT *));
static void usage __P((void)); static void usage __P((void));
void prthumanval __P((double)); void prthumanval __P((double));
unit_t unit_adjust __P((double *)); unit_t unit_adjust __P((double *));
void ignoreadd __P((const char *));
void ignoreclean __P((void));
int ignorep __P((FTSENT *));
int int
main(argc, argv) main(argc, argv)
@ -112,12 +123,16 @@ main(argc, argv)
save = argv; save = argv;
ftsoptions = 0; ftsoptions = 0;
depth = INT_MAX; 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) { switch (ch) {
case 'H': case 'H':
Hflag = 1; Hflag = 1;
break; break;
case 'I':
ignoreadd(optarg);
break;
case 'L': case 'L':
if (Pflag) if (Pflag)
usage(); usage();
@ -224,8 +239,13 @@ main(argc, argv)
while ((p = fts_read(fts)) != NULL) { while ((p = fts_read(fts)) != NULL) {
switch (p->fts_info) { switch (p->fts_info) {
case FTS_D: /* Ignore. */ case FTS_D: /* Ignore. */
if (ignorep(p))
fts_set(fts, p, FTS_SKIP);
break; break;
case FTS_DP: case FTS_DP:
if (ignorep(p))
break;
p->fts_parent->fts_number += p->fts_parent->fts_number +=
p->fts_number += p->fts_statp->st_blocks; p->fts_number += p->fts_statp->st_blocks;
@ -249,6 +269,9 @@ main(argc, argv)
rval = 1; rval = 1;
break; break;
default: default:
if (ignorep(p))
break;
if (p->fts_statp->st_nlink > 1 && linkchk(p)) if (p->fts_statp->st_nlink > 1 && linkchk(p))
break; break;
@ -281,6 +304,7 @@ main(argc, argv)
} }
} }
ignoreclean();
exit(rval); exit(rval);
} }
@ -366,6 +390,46 @@ static void
usage() usage()
{ {
(void)fprintf(stderr, (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); 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;
}