du.c revision 128834
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1989, 1993, 1994 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Chris Newcomb. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 3. All advertising materials mentioning features or use of this software 171590Srgrimes * must display the following acknowledgement: 181590Srgrimes * This product includes software developed by the University of 191590Srgrimes * California, Berkeley and its contributors. 201590Srgrimes * 4. Neither the name of the University nor the names of its contributors 211590Srgrimes * may be used to endorse or promote products derived from this software 221590Srgrimes * without specific prior written permission. 231590Srgrimes * 241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341590Srgrimes * SUCH DAMAGE. 351590Srgrimes */ 361590Srgrimes 371590Srgrimes#ifndef lint 3841568Sarchiestatic const char copyright[] = 391590Srgrimes"@(#) Copyright (c) 1989, 1993, 1994\n\ 401590Srgrimes The Regents of the University of California. All rights reserved.\n"; 411590Srgrimes#endif /* not lint */ 421590Srgrimes 431590Srgrimes#ifndef lint 4456597Smharo#if 0 4541568Sarchiestatic const char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95"; 4656597Smharo#endif 471590Srgrimes#endif /* not lint */ 4899112Sobrien#include <sys/cdefs.h> 4999112Sobrien__FBSDID("$FreeBSD: head/usr.bin/du/du.c 128834 2004-05-02 17:54:57Z kientzle $"); 501590Srgrimes 511590Srgrimes#include <sys/param.h> 5278158Sroam#include <sys/queue.h> 531590Srgrimes#include <sys/stat.h> 541590Srgrimes 551590Srgrimes#include <err.h> 561590Srgrimes#include <errno.h> 5778158Sroam#include <fnmatch.h> 581590Srgrimes#include <fts.h> 5956597Smharo#include <math.h> 601590Srgrimes#include <stdio.h> 611590Srgrimes#include <stdlib.h> 621590Srgrimes#include <string.h> 6356597Smharo#include <sysexits.h> 6423693Speter#include <unistd.h> 651590Srgrimes 6656597Smharo#define KILO_SZ(n) (n) 6756597Smharo#define MEGA_SZ(n) ((n) * (n)) 6856597Smharo#define GIGA_SZ(n) ((n) * (n) * (n)) 6956597Smharo#define TERA_SZ(n) ((n) * (n) * (n) * (n)) 7056597Smharo#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n)) 7156597Smharo 7256597Smharo#define KILO_2_SZ (KILO_SZ(1024ULL)) 7356597Smharo#define MEGA_2_SZ (MEGA_SZ(1024ULL)) 7456597Smharo#define GIGA_2_SZ (GIGA_SZ(1024ULL)) 7556597Smharo#define TERA_2_SZ (TERA_SZ(1024ULL)) 7656597Smharo#define PETA_2_SZ (PETA_SZ(1024ULL)) 7756597Smharo 7856597Smharo#define KILO_SI_SZ (KILO_SZ(1000ULL)) 7956597Smharo#define MEGA_SI_SZ (MEGA_SZ(1000ULL)) 8056597Smharo#define GIGA_SI_SZ (GIGA_SZ(1000ULL)) 8156597Smharo#define TERA_SI_SZ (TERA_SZ(1000ULL)) 8256597Smharo#define PETA_SI_SZ (PETA_SZ(1000ULL)) 8356597Smharo 8456597Smharounsigned long long vals_si [] = {1, KILO_SI_SZ, MEGA_SI_SZ, GIGA_SI_SZ, TERA_SI_SZ, PETA_SI_SZ}; 8556597Smharounsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ}; 8656597Smharounsigned long long *valp; 8756597Smharo 8856597Smharotypedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t; 8956597Smharo 9056597Smharoint unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA }; 9156597Smharo 9278158SroamSLIST_HEAD(ignhead, ignentry) ignores; 9378158Sroamstruct ignentry { 9478158Sroam char *mask; 9578158Sroam SLIST_ENTRY(ignentry) next; 9678158Sroam}; 9778158Sroam 98128772Skientzlestatic int linkchk(FTSENT *); 9992920Simpstatic void usage(void); 10092920Simpvoid prthumanval(double); 10192920Simpunit_t unit_adjust(double *); 10292920Simpvoid ignoreadd(const char *); 10392920Simpvoid ignoreclean(void); 10492920Simpint ignorep(FTSENT *); 1051590Srgrimes 1061590Srgrimesint 107100822Sdwmalonemain(int argc, char *argv[]) 1081590Srgrimes{ 10932097Sjkh FTS *fts; 11032097Sjkh FTSENT *p; 11137952Sdes long blocksize, savednumber = 0; 11232097Sjkh int ftsoptions; 11332097Sjkh int listall; 11432097Sjkh int depth; 115108453Smike int Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag, hflag, ch, notused, rval; 11632097Sjkh char **save; 11787216Smarkm static char dot[] = "."; 1181590Srgrimes 11956597Smharo Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag = 0; 120128772Skientzle 1211590Srgrimes save = argv; 12232097Sjkh ftsoptions = 0; 12319120Sscrappy depth = INT_MAX; 12478158Sroam SLIST_INIT(&ignores); 125128772Skientzle 12678158Sroam while ((ch = getopt(argc, argv, "HI:LPasd:chkrx")) != -1) 1271590Srgrimes switch (ch) { 12832097Sjkh case 'H': 12932097Sjkh Hflag = 1; 13032097Sjkh break; 13178158Sroam case 'I': 13278158Sroam ignoreadd(optarg); 13378158Sroam break; 13432097Sjkh case 'L': 13532097Sjkh if (Pflag) 13632097Sjkh usage(); 13732097Sjkh Lflag = 1; 13832097Sjkh break; 13932097Sjkh case 'P': 14032097Sjkh if (Lflag) 14132097Sjkh usage(); 14232097Sjkh Pflag = 1; 14332097Sjkh break; 14432097Sjkh case 'a': 14532097Sjkh aflag = 1; 14632097Sjkh break; 14732097Sjkh case 's': 14832097Sjkh sflag = 1; 14932097Sjkh break; 15032097Sjkh case 'd': 15132097Sjkh dflag = 1; 15232097Sjkh errno = 0; 15332097Sjkh depth = atoi(optarg); 15432097Sjkh if (errno == ERANGE || depth < 0) { 15558601Scharnier warnx("invalid argument to option d: %s", optarg); 15632097Sjkh usage(); 15732097Sjkh } 15832097Sjkh break; 15932097Sjkh case 'c': 16032097Sjkh cflag = 1; 16132097Sjkh break; 16256597Smharo case 'h': 16356597Smharo putenv("BLOCKSIZE=512"); 16456597Smharo hflag = 1; 16556597Smharo valp = vals_base2; 16656597Smharo break; 16756597Smharo case 'k': 168112855Sobrien hflag = 0; 169112855Sobrien putenv("BLOCKSIZE=1024"); 17056597Smharo break; 17156597Smharo case 'r': /* Compatibility. */ 17256597Smharo break; 17356597Smharo case 'x': 17456597Smharo ftsoptions |= FTS_XDEV; 17556597Smharo break; 17632097Sjkh case '?': 17732097Sjkh default: 17819120Sscrappy usage(); 1791590Srgrimes } 18032097Sjkh 1811590Srgrimes argc -= optind; 1821590Srgrimes argv += optind; 1831590Srgrimes 1841590Srgrimes /* 1851590Srgrimes * XXX 1861590Srgrimes * Because of the way that fts(3) works, logical walks will not count 1871590Srgrimes * the blocks actually used by symbolic links. We rationalize this by 1881590Srgrimes * noting that users computing logical sizes are likely to do logical 1891590Srgrimes * copies, so not counting the links is correct. The real reason is 1901590Srgrimes * that we'd have to re-implement the kernel's symbolic link traversing 1911590Srgrimes * algorithm to get this right. If, for example, you have relative 1921590Srgrimes * symbolic links referencing other relative symbolic links, it gets 1931590Srgrimes * very nasty, very fast. The bottom line is that it's documented in 1941590Srgrimes * the man page, so it's a feature. 1951590Srgrimes */ 19632097Sjkh 19732097Sjkh if (Hflag + Lflag + Pflag > 1) 19832097Sjkh usage(); 19932097Sjkh 20032097Sjkh if (Hflag + Lflag + Pflag == 0) 20132097Sjkh Pflag = 1; /* -P (physical) is default */ 20232097Sjkh 2031590Srgrimes if (Hflag) 2041590Srgrimes ftsoptions |= FTS_COMFOLLOW; 20532097Sjkh 20632097Sjkh if (Lflag) 2071590Srgrimes ftsoptions |= FTS_LOGICAL; 2081590Srgrimes 20932097Sjkh if (Pflag) 21032097Sjkh ftsoptions |= FTS_PHYSICAL; 21132097Sjkh 21232097Sjkh listall = 0; 21332097Sjkh 2141590Srgrimes if (aflag) { 21519120Sscrappy if (sflag || dflag) 2161590Srgrimes usage(); 21732097Sjkh listall = 1; 21819120Sscrappy } else if (sflag) { 21919120Sscrappy if (dflag) 22019120Sscrappy usage(); 22132097Sjkh depth = 0; 2221590Srgrimes } 2231590Srgrimes 2241590Srgrimes if (!*argv) { 2251590Srgrimes argv = save; 22687216Smarkm argv[0] = dot; 2271590Srgrimes argv[1] = NULL; 2281590Srgrimes } 2291590Srgrimes 23032097Sjkh (void) getbsize(¬used, &blocksize); 2311590Srgrimes blocksize /= 512; 2321590Srgrimes 23332097Sjkh rval = 0; 234128772Skientzle 2351590Srgrimes if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL) 23632097Sjkh err(1, "fts_open"); 2371590Srgrimes 23832097Sjkh while ((p = fts_read(fts)) != NULL) { 2391590Srgrimes switch (p->fts_info) { 24032097Sjkh case FTS_D: /* Ignore. */ 24178158Sroam if (ignorep(p)) 24278158Sroam fts_set(fts, p, FTS_SKIP); 2431590Srgrimes break; 24432097Sjkh case FTS_DP: 24578158Sroam if (ignorep(p)) 24678158Sroam break; 24778158Sroam 24832097Sjkh p->fts_parent->fts_number += 24932097Sjkh p->fts_number += p->fts_statp->st_blocks; 250128772Skientzle 25158601Scharnier if (p->fts_level <= depth) { 25256597Smharo if (hflag) { 25358522Smharo (void) prthumanval(howmany(p->fts_number, blocksize)); 25456597Smharo (void) printf("\t%s\n", p->fts_path); 25556597Smharo } else { 25632097Sjkh (void) printf("%ld\t%s\n", 25732097Sjkh howmany(p->fts_number, blocksize), 25832097Sjkh p->fts_path); 25956597Smharo } 26058601Scharnier } 26132097Sjkh break; 26232097Sjkh case FTS_DC: /* Ignore. */ 26332097Sjkh break; 26432097Sjkh case FTS_DNR: /* Warn, continue. */ 26532097Sjkh case FTS_ERR: 26632097Sjkh case FTS_NS: 26732097Sjkh warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); 26832097Sjkh rval = 1; 26932097Sjkh break; 27032097Sjkh default: 27178158Sroam if (ignorep(p)) 27278158Sroam break; 27378158Sroam 27432097Sjkh if (p->fts_statp->st_nlink > 1 && linkchk(p)) 27532097Sjkh break; 276128772Skientzle 27758601Scharnier if (listall || p->fts_level == 0) { 27856597Smharo if (hflag) { 27956597Smharo (void) prthumanval(howmany(p->fts_statp->st_blocks, 28056597Smharo blocksize)); 28156597Smharo (void) printf("\t%s\n", p->fts_path); 28256597Smharo } else { 28356597Smharo (void) printf("%qd\t%s\n", 28490389Speter (long long)howmany(p->fts_statp->st_blocks, blocksize), 28556597Smharo p->fts_path); 28656597Smharo } 28758601Scharnier } 28832097Sjkh 28932097Sjkh p->fts_parent->fts_number += p->fts_statp->st_blocks; 2901590Srgrimes } 29139076Sdes savednumber = p->fts_parent->fts_number; 29232097Sjkh } 29332097Sjkh 2941590Srgrimes if (errno) 2951590Srgrimes err(1, "fts_read"); 29632097Sjkh 29758601Scharnier if (cflag) { 29856597Smharo if (hflag) { 29956597Smharo (void) prthumanval(howmany(savednumber, blocksize)); 30056597Smharo (void) printf("\ttotal\n"); 30156597Smharo } else { 30256597Smharo (void) printf("%ld\ttotal\n", howmany(savednumber, blocksize)); 30356597Smharo } 30458601Scharnier } 30532097Sjkh 30678158Sroam ignoreclean(); 30728891Swosch exit(rval); 3081590Srgrimes} 3091590Srgrimes 310128772Skientzlestatic int 311128772Skientzlelinkchk(FTSENT *p) 312128772Skientzle{ 313128772Skientzle struct links_entry { 314128806Skientzle struct links_entry *next; 315128806Skientzle struct links_entry *previous; 316128806Skientzle int links; 317128806Skientzle dev_t dev; 318128806Skientzle ino_t ino; 319128772Skientzle }; 320128806Skientzle static const size_t links_hash_initial_size = 8192; 321128806Skientzle static struct links_entry **buckets; 322128806Skientzle static struct links_entry *free_list; 323128806Skientzle static size_t number_buckets; 324128806Skientzle static unsigned long number_entries; 325128806Skientzle static char stop_allocating; 326128806Skientzle struct links_entry *le, **new_buckets; 327128806Skientzle struct stat *st; 328128806Skientzle size_t i, new_size; 329128834Skientzle int count, hash; 33032097Sjkh 331128772Skientzle st = p->fts_statp; 33232097Sjkh 333128772Skientzle /* If necessary, initialize the hash table. */ 334128772Skientzle if (buckets == NULL) { 335128772Skientzle number_buckets = links_hash_initial_size; 336128772Skientzle buckets = malloc(number_buckets * sizeof(buckets[0])); 337128772Skientzle if (buckets == NULL) 338128834Skientzle errx(1, "No memory for hardlink detection"); 339128772Skientzle for (i = 0; i < number_buckets; i++) 340128772Skientzle buckets[i] = NULL; 341128772Skientzle } 3421590Srgrimes 343128772Skientzle /* If the hash table is getting too full, enlarge it. */ 344128772Skientzle if (number_entries > number_buckets * 10 && !stop_allocating) { 345128772Skientzle new_size = number_buckets * 2; 346128772Skientzle new_buckets = malloc(new_size * sizeof(struct links_entry *)); 347128772Skientzle count = 0; 348128772Skientzle 349128772Skientzle /* Try releasing the free list to see if that helps. */ 350128772Skientzle if (new_buckets == NULL && free_list != NULL) { 351128772Skientzle while (free_list != NULL) { 352128772Skientzle le = free_list; 353128772Skientzle free_list = le->next; 354128772Skientzle free(le); 355128772Skientzle } 356128772Skientzle new_buckets = malloc(new_size * sizeof(new_buckets[0])); 357128772Skientzle } 358128772Skientzle 359128772Skientzle if (new_buckets == NULL) { 360128772Skientzle stop_allocating = 1; 361128834Skientzle warnx("No more memory for tracking hard links"); 362128772Skientzle } else { 363128772Skientzle memset(new_buckets, 0, 364128772Skientzle new_size * sizeof(struct links_entry *)); 365128772Skientzle for (i = 0; i < number_buckets; i++) { 366128772Skientzle while (buckets[i] != NULL) { 367128772Skientzle /* Remove entry from old bucket. */ 368128772Skientzle le = buckets[i]; 369128772Skientzle buckets[i] = le->next; 370128772Skientzle 371128772Skientzle /* Add entry to new bucket. */ 372128772Skientzle hash = (le->dev ^ le->ino) % new_size; 373128772Skientzle 374128772Skientzle if (new_buckets[hash] != NULL) 375128772Skientzle new_buckets[hash]->previous = 376128772Skientzle le; 377128772Skientzle le->next = new_buckets[hash]; 378128772Skientzle le->previous = NULL; 379128772Skientzle new_buckets[hash] = le; 380128772Skientzle } 381128772Skientzle } 382128772Skientzle free(buckets); 383128772Skientzle buckets = new_buckets; 384128772Skientzle number_buckets = new_size; 385128772Skientzle } 386128772Skientzle } 387128772Skientzle 388128772Skientzle /* Try to locate this entry in the hash table. */ 389128772Skientzle hash = ( st->st_dev ^ st->st_ino ) % number_buckets; 390128772Skientzle for (le = buckets[hash]; le != NULL; le = le->next) { 391128772Skientzle if (le->dev == st->st_dev && le->ino == st->st_ino) { 392128772Skientzle /* 393128772Skientzle * Save memory by releasing an entry when we've seen 394128772Skientzle * all of it's links. 395128772Skientzle */ 396128772Skientzle if (--le->links <= 0) { 397128772Skientzle if (le->previous != NULL) 398128772Skientzle le->previous->next = le->next; 399128772Skientzle if (le->next != NULL) 400128772Skientzle le->next->previous = le->previous; 401128772Skientzle if (buckets[hash] == le) 402128772Skientzle buckets[hash] = le->next; 403128772Skientzle number_entries--; 404128772Skientzle /* Recycle this node through the free list */ 405128772Skientzle if (stop_allocating) { 406128772Skientzle free(le); 407128772Skientzle } else { 408128772Skientzle le->next = free_list; 409128772Skientzle free_list = le; 410128772Skientzle } 411128772Skientzle } 412128772Skientzle return (1); 413128772Skientzle } 414128772Skientzle } 415128772Skientzle 416128772Skientzle if (stop_allocating) 417128772Skientzle return (0); 418128772Skientzle 419128772Skientzle /* Add this entry to the links cache. */ 420128772Skientzle if (free_list != NULL) { 421128772Skientzle /* Pull a node from the free list if we can. */ 422128772Skientzle le = free_list; 423128772Skientzle free_list = le->next; 424128772Skientzle } else 425128772Skientzle /* Malloc one if we have to. */ 426128772Skientzle le = malloc(sizeof(struct links_entry)); 427128772Skientzle if (le == NULL) { 428128772Skientzle stop_allocating = 1; 429128834Skientzle warnx("No more memory for tracking hard links"); 430128772Skientzle return (0); 431128772Skientzle } 432128772Skientzle le->dev = st->st_dev; 433128772Skientzle le->ino = st->st_ino; 434128772Skientzle le->links = st->st_nlink - 1; 435128772Skientzle number_entries++; 436128772Skientzle le->next = buckets[hash]; 437128772Skientzle le->previous = NULL; 438128772Skientzle if (buckets[hash] != NULL) 439128772Skientzle buckets[hash]->previous = le; 440128772Skientzle buckets[hash] = le; 4411590Srgrimes return (0); 4421590Srgrimes} 4431590Srgrimes 44456597Smharo/* 44556597Smharo * Output in "human-readable" format. Uses 3 digits max and puts 44656597Smharo * unit suffixes at the end. Makes output compact and easy to read, 44756597Smharo * especially on huge disks. 44856597Smharo * 44956597Smharo */ 45056597Smharounit_t 451100822Sdwmaloneunit_adjust(double *val) 45256597Smharo{ 45356597Smharo double abval; 45456597Smharo unit_t unit; 45556597Smharo unsigned int unit_sz; 45656597Smharo 45756597Smharo abval = fabs(*val); 45856597Smharo 45956597Smharo unit_sz = abval ? ilogb(abval) / 10 : 0; 46056597Smharo 46156597Smharo if (unit_sz >= UNIT_MAX) { 46256597Smharo unit = NONE; 46356597Smharo } else { 46456597Smharo unit = unitp[unit_sz]; 46556597Smharo *val /= (double)valp[unit_sz]; 46656597Smharo } 46756597Smharo 46856597Smharo return (unit); 46956597Smharo} 47056597Smharo 47156597Smharovoid 472100822Sdwmaloneprthumanval(double bytes) 47356597Smharo{ 47456597Smharo unit_t unit; 47556597Smharo 47656597Smharo bytes *= 512; 47756597Smharo unit = unit_adjust(&bytes); 47856597Smharo 47956597Smharo if (bytes == 0) 48056597Smharo (void)printf(" 0B"); 48156597Smharo else if (bytes > 10) 48256597Smharo (void)printf("%3.0f%c", bytes, "BKMGTPE"[unit]); 48356597Smharo else 48456597Smharo (void)printf("%3.1f%c", bytes, "BKMGTPE"[unit]); 48556597Smharo} 48656597Smharo 48727099Scharnierstatic void 488100822Sdwmaloneusage(void) 4891590Srgrimes{ 4901590Srgrimes (void)fprintf(stderr, 49178158Sroam "usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k] [-x] [-I mask] [file ...]\n"); 49256597Smharo exit(EX_USAGE); 4931590Srgrimes} 49478158Sroam 49578158Sroamvoid 496100822Sdwmaloneignoreadd(const char *mask) 49778158Sroam{ 49878158Sroam struct ignentry *ign; 49978158Sroam 50078158Sroam ign = calloc(1, sizeof(*ign)); 50178158Sroam if (ign == NULL) 50278158Sroam errx(1, "cannot allocate memory"); 50378158Sroam ign->mask = strdup(mask); 50478158Sroam if (ign->mask == NULL) 50578158Sroam errx(1, "cannot allocate memory"); 50678158Sroam SLIST_INSERT_HEAD(&ignores, ign, next); 50778158Sroam} 50878158Sroam 50978158Sroamvoid 510100822Sdwmaloneignoreclean(void) 51178158Sroam{ 51278158Sroam struct ignentry *ign; 51378158Sroam 51478158Sroam while (!SLIST_EMPTY(&ignores)) { 51578158Sroam ign = SLIST_FIRST(&ignores); 51678158Sroam SLIST_REMOVE_HEAD(&ignores, next); 51778158Sroam free(ign->mask); 51878158Sroam free(ign); 51978158Sroam } 52078158Sroam} 52178158Sroam 52278158Sroamint 523100822Sdwmaloneignorep(FTSENT *ent) 52478158Sroam{ 52578158Sroam struct ignentry *ign; 52678158Sroam 52778158Sroam SLIST_FOREACH(ign, &ignores, next) 52878158Sroam if (fnmatch(ign->mask, ent->fts_name, 0) != FNM_NOMATCH) 52978158Sroam return 1; 53078158Sroam return 0; 53178158Sroam} 532