From 5b57d28ffb6e1ef86b50f7d05d977826eae89bfe Mon Sep 17 00:00:00 2001 From: Kiyoshi Aman Date: Fri, 1 Feb 2019 22:55:37 +0000 Subject: initial population --- usr.bin/du/du.1 | 168 ++++++++++++++++++++++++++ usr.bin/du/du.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 530 insertions(+) create mode 100644 usr.bin/du/du.1 create mode 100644 usr.bin/du/du.c (limited to 'usr.bin/du') diff --git a/usr.bin/du/du.1 b/usr.bin/du/du.1 new file mode 100644 index 0000000..14bb436 --- /dev/null +++ b/usr.bin/du/du.1 @@ -0,0 +1,168 @@ +.\" $NetBSD: du.1,v 1.23 2012/05/14 21:14:14 wiz Exp $ +.\" +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)du.1 8.2 (Berkeley) 4/1/94 +.\" +.Dd May 14, 2012 +.Dt DU 1 +.Os +.Sh NAME +.Nm du +.Nd display disk usage statistics +.Sh SYNOPSIS +.Nm +.Op Fl H | Fl L | Fl P +.Op Fl a | Fl d Ar depth | Fl s +.Op Fl cghikmnrx +.Op Ar file ... +.Sh DESCRIPTION +The +.Nm +utility displays the file system usage for each file argument +and for each directory in the file hierarchy rooted in each directory +argument. +If no file is specified, the block usage of the hierarchy rooted in +the current directory is displayed. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl H +Symbolic links on the command line are followed. +(Symbolic links encountered in the tree traversal are not followed.) +.It Fl L +All symbolic links are followed. +.It Fl P +No symbolic links are followed. +.It Fl a +Display an entry for each file in the file hierarchy. +.It Fl c +Display the grand total after all the arguments have been processed. +.It Fl d +Display an entry files and directories +.Ar depth +directories deep. +.It Fl g +If the +.Fl g +flag is specified, the number displayed is the number of gigabyte +(1024*1024*1024 bytes) blocks. +.It Fl h +If the +.Fl h +flag is specified, the numbers will be displayed in "human-readable" +format. +Use unit suffixes: B (Byte), K (Kilobyte), M (Megabyte), G (Gigabyte), +T (Terabyte) and P (Petabyte). +.It Fl i +Output inode usage instead of blocks. +All "human-readable" options are ignored. +.It Fl k +By default, +.Nm +displays the number of blocks as returned by the +.Xr stat 2 +system call, i.e. 512-byte blocks. +If the +.Fl k +flag is specified, the number displayed is the number of kilobyte +(1024 bytes) blocks. +Partial numbers of blocks are rounded up. +.It Fl m +If the +.Fl m +flag is specified, the number displayed is the number of megabyte +(1024*1024 bytes) blocks. +.It Fl n +Ignore files and directories with user +.Qq nodump +flag +.Pq Dv UF_NODUMP +set. +.It Fl r +Generate warning messages about directories that cannot be read. +This is the default behaviour. +.It Fl s +Display only the grand total for the specified files. +.It Fl x +Filesystem mount points are not traversed. +.El +.Pp +.Nm +counts the storage used by symbolic links and not the files they +reference unless the +.Fl H +or +.Fl L +option is specified. +If either the +.Fl H +or +.Fl L +options are specified, storage used by any symbolic links which are +followed is not counted or displayed. +The +.Fl H , +.Fl L +and +.Fl P +options override each other and the command's actions are determined +by the last one specified. +.Pp +Files having multiple hard links are counted (and displayed) a single +time per +.Nm +execution. +.Sh ENVIRONMENT +.Bl -tag -width BLOCKSIZE +.It Ev BLOCKSIZE +If the environment variable +.Ev BLOCKSIZE +is set, and the +.Fl g , +.Fl h , +.Fl k , +and +.Fl m +options are not specified, the block counts will be displayed in units of that +size block. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr df 1 , +.Xr chflags 2 , +.Xr fts 3 , +.Xr getbsize 3 , +.Xr symlink 7 , +.Xr quot 8 +.Sh HISTORY +A +.Nm +command appeared in +.At v6 . diff --git a/usr.bin/du/du.c b/usr.bin/du/du.c new file mode 100644 index 0000000..5b13232 --- /dev/null +++ b/usr.bin/du/du.c @@ -0,0 +1,362 @@ +/* $NetBSD: du.c,v 1.36 2012/03/11 11:23:20 shattered Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Newcomb. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95"; +#else +__RCSID("$NetBSD: du.c,v 1.36 2012/03/11 11:23:20 shattered Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Count inodes or file size */ +#define COUNT (iflag ? 1 : p->fts_statp->st_blocks) + +static int linkchk(dev_t, ino_t); +static void prstat(const char *, int64_t); +__dead static void usage(void); + +static int hflag, iflag; +static long blocksize; + +int +main(int argc, char *argv[]) +{ + FTS *fts; + FTSENT *p; + int64_t totalblocks; + int ftsoptions, listfiles; + int depth; + int Hflag, Lflag, aflag, ch, cflag, dflag, gkmflag, nflag, rval, sflag; + const char *noargv[2]; + + Hflag = Lflag = aflag = cflag = dflag = gkmflag = nflag = sflag = 0; + totalblocks = 0; + ftsoptions = FTS_PHYSICAL; + depth = INT_MAX; + while ((ch = getopt(argc, argv, "HLPacd:ghikmnrsx")) != -1) + switch (ch) { + case 'H': + Hflag = 1; + Lflag = 0; + break; + case 'L': + Lflag = 1; + Hflag = 0; + break; + case 'P': + Hflag = Lflag = 0; + break; + case 'a': + aflag = 1; + break; + case 'c': + cflag = 1; + break; + case 'd': + dflag = 1; + depth = atoi(optarg); + if (depth < 0 || depth > SHRT_MAX) { + warnx("invalid argument to option d: %s", + optarg); + usage(); + } + break; + case 'g': + blocksize = 1024 * 1024 * 1024; + gkmflag = 1; + break; + case 'h': + hflag = 1; + break; + case 'i': + iflag = 1; + break; + case 'k': + blocksize = 1024; + gkmflag = 1; + break; + case 'm': + blocksize = 1024 * 1024; + gkmflag = 1; + break; + case 'n': + nflag = 1; + break; + case 'r': + break; + case 's': + sflag = 1; + break; + case 'x': + ftsoptions |= FTS_XDEV; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + /* + * XXX + * Because of the way that fts(3) works, logical walks will not count + * the blocks actually used by symbolic links. We rationalize this by + * noting that users computing logical sizes are likely to do logical + * copies, so not counting the links is correct. The real reason is + * that we'd have to re-implement the kernel's symbolic link traversing + * algorithm to get this right. If, for example, you have relative + * symbolic links referencing other relative symbolic links, it gets + * very nasty, very fast. The bottom line is that it's documented in + * the man page, so it's a feature. + */ + if (Hflag) + ftsoptions |= FTS_COMFOLLOW; + if (Lflag) { + ftsoptions &= ~FTS_PHYSICAL; + ftsoptions |= FTS_LOGICAL; + } + + listfiles = 0; + if (aflag) { + if (sflag || dflag) + usage(); + listfiles = 1; + } else if (sflag) { + if (dflag) + usage(); + depth = 0; + } + + if (!*argv) { + noargv[0] = "."; + noargv[1] = NULL; + argv = __UNCONST(noargv); + } + + if (!gkmflag) + (void)getbsize(NULL, &blocksize); + blocksize /= 512; + + if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL) + err(1, "fts_open `%s'", *argv); + + for (rval = 0; (p = fts_read(fts)) != NULL;) { + if (nflag) { + switch (p->fts_info) { + case FTS_NS: + case FTS_SLNONE: + /* nothing */ + break; + default: + if (p->fts_statp->st_flags & UF_NODUMP) { + fts_set(fts, p, FTS_SKIP); + continue; + } + } + } + switch (p->fts_info) { + case FTS_D: /* Ignore. */ + break; + case FTS_DP: + p->fts_parent->fts_number += + p->fts_number += COUNT; + if (cflag) + totalblocks += COUNT; + /* + * If listing each directory, or not listing files + * or directories and this is post-order of the + * root of a traversal, display the total. + */ + if (p->fts_level <= depth + || (!listfiles && !p->fts_level)) + prstat(p->fts_path, p->fts_number); + break; + case FTS_DC: /* Ignore. */ + break; + case FTS_DNR: /* Warn, continue. */ + case FTS_ERR: + case FTS_NS: + warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); + rval = 1; + break; + default: + if (p->fts_statp->st_nlink > 1 && + linkchk(p->fts_statp->st_dev, p->fts_statp->st_ino)) + break; + /* + * If listing each file, or a non-directory file was + * the root of a traversal, display the total. + */ + if (listfiles || !p->fts_level) + prstat(p->fts_path, COUNT); + p->fts_parent->fts_number += COUNT; + if (cflag) + totalblocks += COUNT; + } + } + if (errno) + err(1, "fts_read"); + if (cflag) + prstat("total", totalblocks); + exit(rval); +} + +static void +prstat(const char *fname, int64_t blocks) +{ + if (iflag) { + (void)printf("%" PRId64 "\t%s\n", blocks, fname); + return; + } + + if (hflag) { + char buf[5]; + int64_t sz = blocks * 512; + + humanize_number(buf, sizeof(buf), sz, "", HN_AUTOSCALE, + HN_B | HN_NOSPACE | HN_DECIMAL); + + (void)printf("%s\t%s\n", buf, fname); + } else + (void)printf("%" PRId64 "\t%s\n", + howmany(blocks, (int64_t)blocksize), + fname); +} + +static int +linkchk(dev_t dev, ino_t ino) +{ + static struct entry { + dev_t dev; + ino_t ino; + } *htable; + static int htshift; /* log(allocated size) */ + static int htmask; /* allocated size - 1 */ + static int htused; /* 2*number of insertions */ + static int sawzero; /* Whether zero is in table or not */ + int h, h2; + uint64_t tmp; + /* this constant is (1<<64)/((1+sqrt(5))/2) + * aka (word size)/(golden ratio) + */ + const uint64_t HTCONST = 11400714819323198485ULL; + const int HTBITS = CHAR_BIT * sizeof(tmp); + + /* Never store zero in hashtable */ + if (dev == 0 && ino == 0) { + h = sawzero; + sawzero = 1; + return h; + } + + /* Extend hash table if necessary, keep load under 0.5 */ + if (htused<<1 >= htmask) { + struct entry *ohtable; + + if (!htable) + htshift = 10; /* starting hashtable size */ + else + htshift++; /* exponential hashtable growth */ + + htmask = (1 << htshift) - 1; + htused = 0; + + ohtable = htable; + htable = calloc(htmask+1, sizeof(*htable)); + if (!htable) + err(1, "calloc"); + + /* populate newly allocated hashtable */ + if (ohtable) { + int i; + for (i = 0; i <= htmask>>1; i++) + if (ohtable[i].ino || ohtable[i].dev) + linkchk(ohtable[i].dev, ohtable[i].ino); + free(ohtable); + } + } + + /* multiplicative hashing */ + tmp = dev; + tmp <<= HTBITS>>1; + tmp |= ino; + tmp *= HTCONST; + h = tmp >> (HTBITS - htshift); + h2 = 1 | ( tmp >> (HTBITS - (htshift<<1) - 1)); /* must be odd */ + + /* open address hashtable search with double hash probing */ + while (htable[h].ino || htable[h].dev) { + if ((htable[h].ino == ino) && (htable[h].dev == dev)) + return 1; + h = (h + h2) & htmask; + } + + /* Insert the current entry into hashtable */ + htable[h].dev = dev; + htable[h].ino = ino; + htused++; + return 0; +} + +static void +usage(void) +{ + + (void)fprintf(stderr, + "usage: du [-H | -L | -P] [-a | -d depth | -s] [-cghikmnrx] [file ...]\n"); + exit(1); +} -- cgit v1.2.3-60-g2f50