du.c revision 238817
1217309Snwhitehorn/* 2255852Sdteske * Copyright (c) 1989, 1993, 1994 3217309Snwhitehorn * The Regents of the University of California. All rights reserved. 4220749Snwhitehorn * 5217309Snwhitehorn * This code is derived from software contributed to Berkeley by 6255852Sdteske * Chris Newcomb. 7217309Snwhitehorn * 8217309Snwhitehorn * Redistribution and use in source and binary forms, with or without 9217309Snwhitehorn * modification, are permitted provided that the following conditions 10217309Snwhitehorn * are met: 11217309Snwhitehorn * 1. Redistributions of source code must retain the above copyright 12217309Snwhitehorn * notice, this list of conditions and the following disclaimer. 13217309Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 14217309Snwhitehorn * notice, this list of conditions and the following disclaimer in the 15217309Snwhitehorn * documentation and/or other materials provided with the distribution. 16217309Snwhitehorn * 4. Neither the name of the University nor the names of its contributors 17217309Snwhitehorn * may be used to endorse or promote products derived from this software 18217309Snwhitehorn * without specific prior written permission. 19217309Snwhitehorn * 20217309Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21217309Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22217309Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23217309Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24217309Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25217309Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26217309Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27217309Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28217309Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29217309Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30217309Snwhitehorn * SUCH DAMAGE. 31217309Snwhitehorn */ 32217309Snwhitehorn 33217309Snwhitehorn#ifndef lint 34217309Snwhitehornstatic const char copyright[] = 35217309Snwhitehorn"@(#) Copyright (c) 1989, 1993, 1994\n\ 36220749Snwhitehorn The Regents of the University of California. All rights reserved.\n"; 37217309Snwhitehorn#endif /* not lint */ 38224014Snwhitehorn 39224014Snwhitehorn#ifndef lint 40224014Snwhitehorn#if 0 41217309Snwhitehornstatic const char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95"; 42255852Sdteske#endif 43217309Snwhitehorn#endif /* not lint */ 44217309Snwhitehorn#include <sys/cdefs.h> 45217309Snwhitehorn__FBSDID("$FreeBSD: head/usr.bin/du/du.c 238817 2012-07-26 20:41:36Z pluknet $"); 46217309Snwhitehorn 47217309Snwhitehorn#include <sys/param.h> 48217309Snwhitehorn#include <sys/queue.h> 49217309Snwhitehorn#include <sys/stat.h> 50217309Snwhitehorn 51224014Snwhitehorn#include <err.h> 52224014Snwhitehorn#include <errno.h> 53217309Snwhitehorn#include <fnmatch.h> 54224014Snwhitehorn#include <fts.h> 55224014Snwhitehorn#include <libutil.h> 56224014Snwhitehorn#include <locale.h> 57224014Snwhitehorn#include <stdint.h> 58224014Snwhitehorn#include <stdio.h> 59224014Snwhitehorn#include <stdlib.h> 60224014Snwhitehorn#include <string.h> 61224014Snwhitehorn#include <sysexits.h> 62224014Snwhitehorn#include <unistd.h> 63224014Snwhitehorn 64224014Snwhitehornstatic SLIST_HEAD(ignhead, ignentry) ignores; 65224014Snwhitehornstruct ignentry { 66224014Snwhitehorn char *mask; 67224014Snwhitehorn SLIST_ENTRY(ignentry) next; 68224014Snwhitehorn}; 69224014Snwhitehorn 70224014Snwhitehornstatic int linkchk(FTSENT *); 71224014Snwhitehornstatic void usage(void); 72224014Snwhitehornstatic void prthumanval(int64_t); 73224014Snwhitehornstatic void ignoreadd(const char *); 74224014Snwhitehornstatic void ignoreclean(void); 75224014Snwhitehornstatic int ignorep(FTSENT *); 76224014Snwhitehornstatic void siginfo(int __unused); 77224014Snwhitehorn 78224014Snwhitehornstatic int nodumpflag = 0; 79224014Snwhitehornstatic int Aflag; 80224014Snwhitehornstatic long blocksize, cblocksize; 81224014Snwhitehornstatic volatile sig_atomic_t info; 82224014Snwhitehorn 83224014Snwhitehornint 84224014Snwhitehornmain(int argc, char *argv[]) 85224014Snwhitehorn{ 86224014Snwhitehorn FTS *fts; 87224014Snwhitehorn FTSENT *p; 88224014Snwhitehorn off_t savednumber, curblocks; 89217309Snwhitehorn off_t threshold, threshold_sign; 90217309Snwhitehorn int ftsoptions; 91217309Snwhitehorn int depth; 92217309Snwhitehorn int Hflag, Lflag, aflag, sflag, dflag, cflag; 93217309Snwhitehorn int hflag, lflag, ch, notused, rval; 94217309Snwhitehorn char **save; 95217309Snwhitehorn static char dot[] = "."; 96224014Snwhitehorn 97251843Sbapt setlocale(LC_ALL, ""); 98217309Snwhitehorn 99217309Snwhitehorn Hflag = Lflag = aflag = sflag = dflag = cflag = hflag = 100217309Snwhitehorn lflag = Aflag = 0; 101217309Snwhitehorn 102217309Snwhitehorn save = argv; 103217309Snwhitehorn ftsoptions = FTS_PHYSICAL; 104217309Snwhitehorn savednumber = 0; 105217309Snwhitehorn threshold = 0; 106217309Snwhitehorn threshold_sign = 1; 107217309Snwhitehorn cblocksize = DEV_BSIZE; 108217309Snwhitehorn blocksize = 0; 109217309Snwhitehorn depth = INT_MAX; 110217309Snwhitehorn SLIST_INIT(&ignores); 111217309Snwhitehorn 112217309Snwhitehorn while ((ch = getopt(argc, argv, "AB:HI:LPasd:cghklmnrt:x")) != -1) 113217309Snwhitehorn switch (ch) { 114217309Snwhitehorn case 'A': 115217309Snwhitehorn Aflag = 1; 116217309Snwhitehorn break; 117217309Snwhitehorn case 'B': 118217309Snwhitehorn errno = 0; 119217309Snwhitehorn cblocksize = atoi(optarg); 120217309Snwhitehorn if (errno == ERANGE || cblocksize <= 0) { 121217309Snwhitehorn warnx("invalid argument to option B: %s", 122217309Snwhitehorn optarg); 123217309Snwhitehorn usage(); 124220749Snwhitehorn } 125220749Snwhitehorn break; 126251843Sbapt case 'H': 127251843Sbapt Hflag = 1; 128217309Snwhitehorn Lflag = 0; 129220749Snwhitehorn break; 130217309Snwhitehorn case 'I': 131251843Sbapt ignoreadd(optarg); 132224014Snwhitehorn break; 133220749Snwhitehorn case 'L': 134217309Snwhitehorn Lflag = 1; 135251843Sbapt Hflag = 0; 136251843Sbapt break; 137251843Sbapt case 'P': 138251843Sbapt Hflag = Lflag = 0; 139251843Sbapt break; 140251843Sbapt case 'a': 141217309Snwhitehorn aflag = 1; 142220749Snwhitehorn break; 143220749Snwhitehorn case 's': 144251843Sbapt sflag = 1; 145220749Snwhitehorn break; 146220749Snwhitehorn case 'd': 147220749Snwhitehorn dflag = 1; 148251843Sbapt errno = 0; 149217309Snwhitehorn depth = atoi(optarg); 150220749Snwhitehorn if (errno == ERANGE || depth < 0) { 151220749Snwhitehorn warnx("invalid argument to option d: %s", 152217309Snwhitehorn optarg); 153220749Snwhitehorn usage(); 154220749Snwhitehorn } 155217309Snwhitehorn break; 156220749Snwhitehorn case 'c': 157220749Snwhitehorn cflag = 1; 158220749Snwhitehorn break; 159220749Snwhitehorn case 'g': 160220749Snwhitehorn hflag = 0; 161220749Snwhitehorn blocksize = 1073741824; 162251843Sbapt break; 163220749Snwhitehorn case 'h': 164220749Snwhitehorn hflag = 1; 165251843Sbapt break; 166217309Snwhitehorn case 'k': 167220749Snwhitehorn hflag = 0; 168220749Snwhitehorn blocksize = 1024; 169220749Snwhitehorn break; 170251843Sbapt case 'l': 171220749Snwhitehorn lflag = 1; 172220749Snwhitehorn break; 173220749Snwhitehorn case 'm': 174220749Snwhitehorn hflag = 0; 175220749Snwhitehorn blocksize = 1048576; 176220749Snwhitehorn break; 177217309Snwhitehorn case 'n': 178217309Snwhitehorn nodumpflag = 1; 179217309Snwhitehorn break; 180220749Snwhitehorn case 'r': /* Compatibility. */ 181220749Snwhitehorn break; 182217309Snwhitehorn case 't' : 183220749Snwhitehorn if (expand_number(optarg, &threshold) != 0 || 184220749Snwhitehorn threshold == 0) { 185217309Snwhitehorn warnx("invalid threshold: %s", optarg); 186251843Sbapt usage(); 187217309Snwhitehorn } else if (threshold < 0) 188220749Snwhitehorn threshold_sign = -1; 189220749Snwhitehorn break; 190220749Snwhitehorn case 'x': 191217309Snwhitehorn ftsoptions |= FTS_XDEV; 192217309Snwhitehorn break; 193217309Snwhitehorn case '?': 194217309Snwhitehorn default: 195217309Snwhitehorn usage(); 196217309Snwhitehorn /* NOTREACHED */ 197217309Snwhitehorn } 198217309Snwhitehorn 199217309Snwhitehorn argc -= optind; 200217309Snwhitehorn argv += optind; 201217309Snwhitehorn 202217309Snwhitehorn /* 203217309Snwhitehorn * XXX 204217309Snwhitehorn * Because of the way that fts(3) works, logical walks will not count 205217309Snwhitehorn * the blocks actually used by symbolic links. We rationalize this by 206217309Snwhitehorn * noting that users computing logical sizes are likely to do logical 207217309Snwhitehorn * copies, so not counting the links is correct. The real reason is 208217309Snwhitehorn * that we'd have to re-implement the kernel's symbolic link traversing 209217309Snwhitehorn * algorithm to get this right. If, for example, you have relative 210217309Snwhitehorn * symbolic links referencing other relative symbolic links, it gets 211217309Snwhitehorn * very nasty, very fast. The bottom line is that it's documented in 212217309Snwhitehorn * the man page, so it's a feature. 213217309Snwhitehorn */ 214217309Snwhitehorn 215217309Snwhitehorn if (Hflag) 216217309Snwhitehorn ftsoptions |= FTS_COMFOLLOW; 217217309Snwhitehorn if (Lflag) { 218217309Snwhitehorn ftsoptions &= ~FTS_PHYSICAL; 219217309Snwhitehorn ftsoptions |= FTS_LOGICAL; 220217309Snwhitehorn } 221217309Snwhitehorn 222217309Snwhitehorn if (!Aflag && (cblocksize % DEV_BSIZE) != 0) 223220749Snwhitehorn cblocksize = howmany(cblocksize, DEV_BSIZE) * DEV_BSIZE; 224220749Snwhitehorn 225224014Snwhitehorn if (aflag + dflag + sflag > 1) 226220749Snwhitehorn usage(); 227220749Snwhitehorn if (sflag) 228217309Snwhitehorn depth = 0; 229217309Snwhitehorn 230220749Snwhitehorn if (!*argv) { 231220749Snwhitehorn argv = save; 232220749Snwhitehorn argv[0] = dot; 233220749Snwhitehorn argv[1] = NULL; 234220749Snwhitehorn } 235220749Snwhitehorn 236220749Snwhitehorn if (blocksize == 0) 237220749Snwhitehorn (void)getbsize(¬used, &blocksize); 238217309Snwhitehorn 239217309Snwhitehorn if (!Aflag) { 240217309Snwhitehorn cblocksize /= DEV_BSIZE; 241217309Snwhitehorn blocksize /= DEV_BSIZE; 242217309Snwhitehorn } 243217309Snwhitehorn 244217309Snwhitehorn if (threshold != 0) 245217309Snwhitehorn threshold = howmany(threshold / DEV_BSIZE * cblocksize, 246220749Snwhitehorn blocksize); 247217309Snwhitehorn 248220749Snwhitehorn rval = 0; 249224014Snwhitehorn 250224014Snwhitehorn (void)signal(SIGINFO, siginfo); 251217309Snwhitehorn 252217309Snwhitehorn if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL) 253217309Snwhitehorn err(1, "fts_open"); 254217309Snwhitehorn 255217309Snwhitehorn while ((p = fts_read(fts)) != NULL) { 256217309Snwhitehorn switch (p->fts_info) { 257217309Snwhitehorn case FTS_D: /* Ignore. */ 258217309Snwhitehorn if (ignorep(p)) 259217309Snwhitehorn fts_set(fts, p, FTS_SKIP); 260217309Snwhitehorn break; 261217309Snwhitehorn case FTS_DP: 262217309Snwhitehorn if (ignorep(p)) 263224014Snwhitehorn break; 264224014Snwhitehorn 265217309Snwhitehorn curblocks = Aflag ? 266224014Snwhitehorn howmany(p->fts_statp->st_size, cblocksize) : 267224014Snwhitehorn howmany(p->fts_statp->st_blocks, cblocksize); 268224014Snwhitehorn p->fts_parent->fts_bignum += p->fts_bignum += 269217309Snwhitehorn curblocks; 270217309Snwhitehorn 271217309Snwhitehorn if (p->fts_level <= depth && threshold <= 272224014Snwhitehorn threshold_sign * howmany(p->fts_bignum * 273224014Snwhitehorn cblocksize, blocksize)) { 274224014Snwhitehorn if (hflag) { 275224014Snwhitehorn prthumanval(p->fts_bignum); 276255852Sdteske (void)printf("\t%s\n", p->fts_path); 277224014Snwhitehorn } else { 278255852Sdteske (void)printf("%jd\t%s\n", 279224014Snwhitehorn (intmax_t)howmany(p->fts_bignum * 280224014Snwhitehorn cblocksize, blocksize), 281224014Snwhitehorn p->fts_path); 282255852Sdteske } 283224014Snwhitehorn } 284224014Snwhitehorn if (info) { 285217309Snwhitehorn info = 0; 286255852Sdteske (void)printf("\t%s\n", p->fts_path); 287217309Snwhitehorn } 288224014Snwhitehorn break; 289255852Sdteske case FTS_DC: /* Ignore. */ 290255852Sdteske break; 291255852Sdteske case FTS_DNR: /* Warn, continue. */ 292255852Sdteske case FTS_ERR: 293255852Sdteske case FTS_NS: 294255852Sdteske warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); 295217309Snwhitehorn rval = 1; 296217309Snwhitehorn break; 297255852Sdteske default: 298255852Sdteske if (ignorep(p)) 299217309Snwhitehorn break; 300255852Sdteske 301217309Snwhitehorn if (lflag == 0 && p->fts_statp->st_nlink > 1 && 302217309Snwhitehorn linkchk(p)) 303255852Sdteske break; 304255852Sdteske 305255852Sdteske curblocks = Aflag ? 306255852Sdteske howmany(p->fts_statp->st_size, cblocksize) : 307217309Snwhitehorn howmany(p->fts_statp->st_blocks, cblocksize); 308255852Sdteske 309255852Sdteske if (aflag || p->fts_level == 0) { 310255852Sdteske if (hflag) { 311217309Snwhitehorn prthumanval(curblocks); 312255852Sdteske (void)printf("\t%s\n", p->fts_path); 313255852Sdteske } else { 314255852Sdteske (void)printf("%jd\t%s\n", 315255852Sdteske (intmax_t)howmany(curblocks * 316255852Sdteske cblocksize, blocksize), 317255852Sdteske p->fts_path); 318217309Snwhitehorn } 319255852Sdteske } 320255852Sdteske 321255852Sdteske p->fts_parent->fts_bignum += curblocks; 322255852Sdteske } 323255852Sdteske savednumber = p->fts_parent->fts_bignum; 324255852Sdteske } 325255852Sdteske 326217309Snwhitehorn if (errno) 327224014Snwhitehorn err(1, "fts_read"); 328224014Snwhitehorn 329224014Snwhitehorn if (cflag) { 330224014Snwhitehorn if (hflag) { 331224014Snwhitehorn prthumanval(savednumber); 332217309Snwhitehorn (void)printf("\ttotal\n"); 333255852Sdteske } else { 334255852Sdteske (void)printf("%jd\ttotal\n", (intmax_t)howmany( 335255852Sdteske savednumber * cblocksize, blocksize)); 336255852Sdteske } 337255852Sdteske } 338255852Sdteske 339255852Sdteske ignoreclean(); 340255852Sdteske exit(rval); 341255852Sdteske} 342224014Snwhitehorn 343224014Snwhitehornstatic int 344224014Snwhitehornlinkchk(FTSENT *p) 345224014Snwhitehorn{ 346224014Snwhitehorn struct links_entry { 347255852Sdteske struct links_entry *next; 348255852Sdteske struct links_entry *previous; 349255852Sdteske int links; 350255852Sdteske dev_t dev; 351255852Sdteske ino_t ino; 352224014Snwhitehorn }; 353255852Sdteske static const size_t links_hash_initial_size = 8192; 354224014Snwhitehorn static struct links_entry **buckets; 355224014Snwhitehorn static struct links_entry *free_list; 356224014Snwhitehorn static size_t number_buckets; 357255852Sdteske static unsigned long number_entries; 358255852Sdteske static char stop_allocating; 359255852Sdteske struct links_entry *le, **new_buckets; 360255852Sdteske struct stat *st; 361255852Sdteske size_t i, new_size; 362255852Sdteske int hash; 363255852Sdteske 364255852Sdteske st = p->fts_statp; 365255852Sdteske 366255852Sdteske /* If necessary, initialize the hash table. */ 367224014Snwhitehorn if (buckets == NULL) { 368224014Snwhitehorn number_buckets = links_hash_initial_size; 369224014Snwhitehorn buckets = malloc(number_buckets * sizeof(buckets[0])); 370224014Snwhitehorn if (buckets == NULL) 371224014Snwhitehorn errx(1, "No memory for hardlink detection"); 372224014Snwhitehorn for (i = 0; i < number_buckets; i++) 373224014Snwhitehorn buckets[i] = NULL; 374224014Snwhitehorn } 375224014Snwhitehorn 376224014Snwhitehorn /* If the hash table is getting too full, enlarge it. */ 377217309Snwhitehorn if (number_entries > number_buckets * 10 && !stop_allocating) { 378224014Snwhitehorn new_size = number_buckets * 2; 379217309Snwhitehorn new_buckets = malloc(new_size * sizeof(struct links_entry *)); 380224014Snwhitehorn 381224014Snwhitehorn /* Try releasing the free list to see if that helps. */ 382224014Snwhitehorn if (new_buckets == NULL && free_list != NULL) { 383224014Snwhitehorn while (free_list != NULL) { 384224014Snwhitehorn le = free_list; 385224014Snwhitehorn free_list = le->next; 386224014Snwhitehorn free(le); 387224014Snwhitehorn } 388224014Snwhitehorn new_buckets = malloc(new_size * 389224014Snwhitehorn sizeof(new_buckets[0])); 390224014Snwhitehorn } 391224014Snwhitehorn 392224014Snwhitehorn if (new_buckets == NULL) { 393224014Snwhitehorn stop_allocating = 1; 394224014Snwhitehorn warnx("No more memory for tracking hard links"); 395224014Snwhitehorn } else { 396224014Snwhitehorn memset(new_buckets, 0, 397224014Snwhitehorn new_size * sizeof(struct links_entry *)); 398224014Snwhitehorn for (i = 0; i < number_buckets; i++) { 399217309Snwhitehorn while (buckets[i] != NULL) { 400224014Snwhitehorn /* Remove entry from old bucket. */ 401224014Snwhitehorn le = buckets[i]; 402224014Snwhitehorn buckets[i] = le->next; 403251843Sbapt 404217309Snwhitehorn /* Add entry to new bucket. */ 405224014Snwhitehorn hash = (le->dev ^ le->ino) % new_size; 406217309Snwhitehorn 407217309Snwhitehorn if (new_buckets[hash] != NULL) 408224014Snwhitehorn new_buckets[hash]->previous = 409224014Snwhitehorn le; 410224014Snwhitehorn le->next = new_buckets[hash]; 411224014Snwhitehorn le->previous = NULL; 412224014Snwhitehorn new_buckets[hash] = le; 413224014Snwhitehorn } 414224014Snwhitehorn } 415224014Snwhitehorn free(buckets); 416224014Snwhitehorn buckets = new_buckets; 417224014Snwhitehorn number_buckets = new_size; 418224014Snwhitehorn } 419224014Snwhitehorn } 420224014Snwhitehorn 421224014Snwhitehorn /* Try to locate this entry in the hash table. */ 422224014Snwhitehorn hash = ( st->st_dev ^ st->st_ino ) % number_buckets; 423224014Snwhitehorn for (le = buckets[hash]; le != NULL; le = le->next) { 424217309Snwhitehorn if (le->dev == st->st_dev && le->ino == st->st_ino) { 425224014Snwhitehorn /* 426217309Snwhitehorn * Save memory by releasing an entry when we've seen 427224014Snwhitehorn * all of it's links. 428224014Snwhitehorn */ 429224014Snwhitehorn if (--le->links <= 0) { 430217309Snwhitehorn if (le->previous != NULL) 431217309Snwhitehorn le->previous->next = le->next; 432217309Snwhitehorn if (le->next != NULL) 433224014Snwhitehorn le->next->previous = le->previous; 434217309Snwhitehorn if (buckets[hash] == le) 435224014Snwhitehorn buckets[hash] = le->next; 436217309Snwhitehorn number_entries--; 437217309Snwhitehorn /* Recycle this node through the free list */ 438217309Snwhitehorn if (stop_allocating) { 439 free(le); 440 } else { 441 le->next = free_list; 442 free_list = le; 443 } 444 } 445 return (1); 446 } 447 } 448 449 if (stop_allocating) 450 return (0); 451 452 /* Add this entry to the links cache. */ 453 if (free_list != NULL) { 454 /* Pull a node from the free list if we can. */ 455 le = free_list; 456 free_list = le->next; 457 } else 458 /* Malloc one if we have to. */ 459 le = malloc(sizeof(struct links_entry)); 460 if (le == NULL) { 461 stop_allocating = 1; 462 warnx("No more memory for tracking hard links"); 463 return (0); 464 } 465 le->dev = st->st_dev; 466 le->ino = st->st_ino; 467 le->links = st->st_nlink - 1; 468 number_entries++; 469 le->next = buckets[hash]; 470 le->previous = NULL; 471 if (buckets[hash] != NULL) 472 buckets[hash]->previous = le; 473 buckets[hash] = le; 474 return (0); 475} 476 477static void 478prthumanval(int64_t bytes) 479{ 480 char buf[5]; 481 482 bytes *= cblocksize; 483 if (!Aflag) 484 bytes *= DEV_BSIZE; 485 486 humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE, 487 HN_B | HN_NOSPACE | HN_DECIMAL); 488 489 (void)printf("%4s", buf); 490} 491 492static void 493usage(void) 494{ 495 (void)fprintf(stderr, 496 "usage: du [-Aclnx] [-H | -L | -P] [-g | -h | -k | -m] " 497 "[-a | -s | -d depth] [-B blocksize] [-I mask] " 498 "[-t threshold] [file ...]\n"); 499 exit(EX_USAGE); 500} 501 502static void 503ignoreadd(const char *mask) 504{ 505 struct ignentry *ign; 506 507 ign = calloc(1, sizeof(*ign)); 508 if (ign == NULL) 509 errx(1, "cannot allocate memory"); 510 ign->mask = strdup(mask); 511 if (ign->mask == NULL) 512 errx(1, "cannot allocate memory"); 513 SLIST_INSERT_HEAD(&ignores, ign, next); 514} 515 516static void 517ignoreclean(void) 518{ 519 struct ignentry *ign; 520 521 while (!SLIST_EMPTY(&ignores)) { 522 ign = SLIST_FIRST(&ignores); 523 SLIST_REMOVE_HEAD(&ignores, next); 524 free(ign->mask); 525 free(ign); 526 } 527} 528 529static int 530ignorep(FTSENT *ent) 531{ 532 struct ignentry *ign; 533 534 if (nodumpflag && (ent->fts_statp->st_flags & UF_NODUMP)) 535 return 1; 536 SLIST_FOREACH(ign, &ignores, next) 537 if (fnmatch(ign->mask, ent->fts_name, 0) != FNM_NOMATCH) 538 return 1; 539 return 0; 540} 541 542static void 543siginfo(int sig __unused) 544{ 545 546 info = 1; 547} 548