コード例 #1
0
int
main(int argc, char *argv[])
{
	FTS		*fts;
	FTSENT		*p;
	off_t		savednumber = 0;
	long		blocksize;
	int		ftsoptions;
	int		listall;
	int		depth;
	int		Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag, hflag, ch, notused, rval;
	char 		**save;
	static char	dot[] = ".";
	off_t           *ftsnum, *ftsparnum;

	setlocale(LC_ALL, "");

	Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag = 0;

	save = argv;
	ftsoptions = FTS_NOCHDIR;
	depth = INT_MAX;
	SLIST_INIT(&ignores);

	while ((ch = getopt(argc, argv, "HI:LPasd:cghkmrx")) != -1)
		switch (ch) {
			case 'H':
				Lflag = Pflag = 0;
				Hflag = 1;
				break;
			case 'I':
				ignoreadd(optarg);
				break;
			case 'L':
				Hflag = Pflag = 0;
				Lflag = 1;
				break;
			case 'P':
				Hflag = Lflag = 0;
				Pflag = 1;
				break;
			case 'a':
				aflag = 1;
				break;
			case 's':
				sflag = 1;
				break;
			case 'd':
				dflag = 1;
				errno = 0;
				depth = atoi(optarg);
				if (errno == ERANGE || depth < 0) {
					warnx("invalid argument to option d: %s", optarg);
					usage();
				}
				break;
			case 'c':
				cflag = 1;
				break;
			case 'h':
				putenv("BLOCKSIZE=512");
				hflag = 1;
				valp = vals_base2;
				break;
			case 'k':
				hflag = 0;
				putenv("BLOCKSIZE=1024");
				break;
			case 'm':
				hflag = 0;
				putenv("BLOCKSIZE=1048576");
				break;
			case 'g':
				hflag = 0;
				putenv("BLOCKSIZE=1g");
				break;
			case 'r':		 /* Compatibility. */
				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 + Lflag + Pflag > 1)
		usage();

	if (Hflag + Lflag + Pflag == 0)
		Pflag = 1;			/* -P (physical) is default */

	if (Hflag)
		ftsoptions |= FTS_COMFOLLOW;

	if (Lflag)
		ftsoptions |= FTS_LOGICAL;

	if (Pflag)
		ftsoptions |= FTS_PHYSICAL;

	listall = 0;

	if (aflag) {
		if (sflag || dflag)
			usage();
		listall = 1;
	} else if (sflag) {
		if (dflag)
			usage();
		depth = 0;
	}

	if (!*argv) {
		argv = save;
		argv[0] = dot;
		argv[1] = NULL;
	}

	(void) getbsize(&notused, &blocksize);
	blocksize /= 512;

	rval = 0;

	if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
		err(1, "fts_open");

	while ((p = fts_read(fts)) != NULL) {
		switch (p->fts_info) {
			case FTS_D:
				if (ignorep(p) || dirlinkchk(p))
					fts_set(fts, p, FTS_SKIP);
				break;
			case FTS_DP:
				if (ignorep(p))
					break;

				ftsparnum = (off_t *)&p->fts_parent->fts_number;
				ftsnum = (off_t *)&p->fts_number;
				if (p->fts_statp->st_size < TWO_TB) {
				    ftsparnum[0] += ftsnum[0] += p->fts_statp->st_blocks;
				} else {
				    ftsparnum[0] += ftsnum[0] += howmany(p->fts_statp->st_size, 512LL);
				}

				if (p->fts_level <= depth) {
					if (hflag) {
						(void) prthumanval(howmany(*ftsnum, blocksize));
						(void) printf("\t%s\n", p->fts_path);
					} else {
					(void) printf("%jd\t%s\n",
					    (intmax_t)howmany(*ftsnum, blocksize),
					    p->fts_path);
					}
				}
				break;
			case FTS_DC:			/* Ignore. */
				if (COMPAT_MODE("bin/du", "unix2003")) {
					errx(1, "Can't follow symlink cycle from %s to %s", p->fts_path, p->fts_cycle->fts_path);
				}
				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;
			case FTS_SLNONE:
				if (COMPAT_MODE("bin/du", "unix2003")) {
					struct stat sb;
					int rc = stat(p->fts_path, &sb);
					if (rc < 0 && errno == ELOOP) {
						errx(1, "Too many symlinks at %s", p->fts_path);
					}
				}
			default:
				if (ignorep(p))
					break;

				if (p->fts_statp->st_nlink > 1 && linkchk(p))
					break;

				if (listall || p->fts_level == 0) {
					if (hflag) {
					    if (p->fts_statp->st_size < TWO_TB) {
						(void) prthumanval(howmany(p->fts_statp->st_blocks,
							blocksize));
					    } else {
						(void) prthumanval(howmany(howmany(p->fts_statp->st_size, 512LL),
							blocksize));
					    }
						(void) printf("\t%s\n", p->fts_path);
					} else {
					    if (p->fts_statp->st_size < TWO_TB) {
						(void) printf("%jd\t%s\n",
							(intmax_t)howmany(p->fts_statp->st_blocks, blocksize),
							p->fts_path);
					    } else {
						(void) printf("%jd\t%s\n",
							(intmax_t)howmany(howmany(p->fts_statp->st_size, 512LL), blocksize),
							p->fts_path);
					    }
					}
				}

				ftsparnum = (off_t *)&p->fts_parent->fts_number;
				if (p->fts_statp->st_size < TWO_TB) {
				    ftsparnum[0] += p->fts_statp->st_blocks;
				} else {
				    ftsparnum[0] += p->fts_statp->st_size / 512LL;
				}
		}
		savednumber = ((off_t *)&p->fts_parent->fts_number)[0];
	}

	if (errno)
		err(1, "fts_read");

	if (cflag) {
		if (hflag) {
			(void) prthumanval(howmany(savednumber, blocksize));
			(void) printf("\ttotal\n");
		} else {
			(void) printf("%jd\ttotal\n", (intmax_t)howmany(savednumber, blocksize));
		}
	}

	ignoreclean();
	exit(rval);
}
コード例 #2
0
ファイル: du.c プロジェクト: edgar-pek/PerspicuOS
int
main(int argc, char *argv[])
{
	FTS		*fts;
	FTSENT		*p;
	off_t		savednumber, curblocks;
	off_t		threshold, threshold_sign;
	int		ftsoptions;
	int		listall;
	int		depth;
	int		Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag;
	int		hflag, lflag, ch, notused, rval;
	char 		**save;
	static char	dot[] = ".";

	setlocale(LC_ALL, "");

	Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag =
	    lflag = Aflag = 0;

	save = argv;
	ftsoptions = 0;
	savednumber = 0;
	threshold = 0;
	threshold_sign = 1;
	cblocksize = DEV_BSIZE;
	blocksize = 0;
	depth = INT_MAX;
	SLIST_INIT(&ignores);

	while ((ch = getopt(argc, argv, "AB:HI:LPasd:chklmnrt:x")) != -1)
		switch (ch) {
		case 'A':
			Aflag = 1;
			break;
		case 'B':
			errno = 0;
			cblocksize = atoi(optarg);
			if (errno == ERANGE || cblocksize <= 0) {
				warnx("invalid argument to option B: %s",
				    optarg);
				usage();
			}
			break;
		case 'H':
			Hflag = 1;
			break;
		case 'I':
			ignoreadd(optarg);
			break;
		case 'L':
			if (Pflag)
				usage();
			Lflag = 1;
			break;
		case 'P':
			if (Lflag)
				usage();
			Pflag = 1;
			break;
		case 'a':
			aflag = 1;
			break;
		case 's':
			sflag = 1;
			break;
		case 'd':
			dflag = 1;
			errno = 0;
			depth = atoi(optarg);
			if (errno == ERANGE || depth < 0) {
				warnx("invalid argument to option d: %s",
				    optarg);
				usage();
			}
			break;
		case 'c':
			cflag = 1;
			break;
		case 'h':
			hflag = 1;
			break;
		case 'k':
			hflag = 0;
			blocksize = 1024;
			break;
		case 'l':
			lflag = 1;
			break;
		case 'm':
			hflag = 0;
			blocksize = 1048576;
			break;
		case 'n':
			nodumpflag = 1;
			break;
		case 'r':		 /* Compatibility. */
			break;
		case 't' :
			if (expand_number(optarg, &threshold) != 0 ||
			    threshold == 0) {
				warnx("invalid threshold: %s", optarg);
				usage();
			} else if (threshold < 0)
				threshold_sign = -1;
			break;
		case 'x':
			ftsoptions |= FTS_XDEV;
			break;
		case '?':
		default:
			usage();
			/* NOTREACHED */
		}

	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 + Lflag + Pflag > 1)
		usage();

	if (Hflag + Lflag + Pflag == 0)
		Pflag = 1;			/* -P (physical) is default */

	if (Hflag)
		ftsoptions |= FTS_COMFOLLOW;

	if (Lflag)
		ftsoptions |= FTS_LOGICAL;

	if (Pflag)
		ftsoptions |= FTS_PHYSICAL;

	if (!Aflag && (cblocksize % DEV_BSIZE) != 0)
		cblocksize = howmany(cblocksize, DEV_BSIZE) * DEV_BSIZE;

	listall = 0;

	if (aflag) {
		if (sflag || dflag)
			usage();
		listall = 1;
	} else if (sflag) {
		if (dflag)
			usage();
		depth = 0;
	}

	if (!*argv) {
		argv = save;
		argv[0] = dot;
		argv[1] = NULL;
	}

	if (blocksize == 0)
		(void)getbsize(&notused, &blocksize);

	if (!Aflag) {
		cblocksize /= DEV_BSIZE;
		blocksize /= DEV_BSIZE;
	}

	if (threshold != 0)
		threshold = howmany(threshold / DEV_BSIZE * cblocksize,
		    blocksize);

	rval = 0;

	(void)signal(SIGINFO, siginfo);

	if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
		err(1, "fts_open");

	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;

			curblocks = Aflag ?
			    howmany(p->fts_statp->st_size, cblocksize) :
			    howmany(p->fts_statp->st_blocks, cblocksize);
			p->fts_parent->fts_bignum += p->fts_bignum +=
			    curblocks;

			if (p->fts_level <= depth && threshold <=
			    threshold_sign * howmany(p->fts_bignum *
			    cblocksize, blocksize)) {
				if (hflag) {
					prthumanval(p->fts_bignum);
					(void)printf("\t%s\n", p->fts_path);
				} else {
					(void)printf("%jd\t%s\n",
					    (intmax_t)howmany(p->fts_bignum *
					    cblocksize, blocksize),
					    p->fts_path);
				}
			}
			if (info) {
				info = 0;
				(void)printf("\t%s\n", p->fts_path);
			}
			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 (ignorep(p))
				break;

			if (lflag == 0 && p->fts_statp->st_nlink > 1 &&
			    linkchk(p))
				break;

			curblocks = Aflag ?
			    howmany(p->fts_statp->st_size, cblocksize) :
			    howmany(p->fts_statp->st_blocks, cblocksize);

			if (listall || p->fts_level == 0) {
				if (hflag) {
					prthumanval(curblocks);
					(void)printf("\t%s\n", p->fts_path);
				} else {
					(void)printf("%jd\t%s\n",
					    (intmax_t)howmany(curblocks *
					    cblocksize, blocksize),
					    p->fts_path);
				}
			}

			p->fts_parent->fts_bignum += curblocks;
		}
		savednumber = p->fts_parent->fts_bignum;
	}

	if (errno)
		err(1, "fts_read");

	if (cflag) {
		if (hflag) {
			prthumanval(savednumber);
			(void)printf("\ttotal\n");
		} else {
			(void)printf("%jd\ttotal\n", (intmax_t)howmany(
			    savednumber * cblocksize, blocksize));
		}
	}

	ignoreclean();
	exit(rval);
}