2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 #pragma ident "%Z%%M% %I% %E% SMI"
30
31 /*
32 * du -- summarize disk usage
33 * du [-dorx] [-a|-s] [-h|-k|-m] [-H|-L] [file...]
34 */
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/avl.h>
39 #include <fcntl.h>
40 #include <dirent.h>
41 #include <limits.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <locale.h>
47 #include <libcmdutils.h>
48
49
50 static int aflg = 0;
51 static int rflg = 0;
52 static int sflg = 0;
53 static int kflg = 0;
54 static int mflg = 0;
55 static int oflg = 0;
56 static int dflg = 0;
57 static int hflg = 0;
58 static int Hflg = 0;
59 static int Lflg = 0;
60 static int cmdarg = 0; /* Command line argument */
61 static char *dot = ".";
62 static int level = 0; /* Level of recursion */
63
64 static char *base;
65 static char *name;
66 static size_t base_len = PATH_MAX + 1; /* # of chars for base */
67 static size_t name_len = PATH_MAX + 1; /* # of chars for name */
68
69 #define NUMBER_WIDTH 64
70 typedef char numbuf_t[NUMBER_WIDTH];
71
72 /*
73 * Output formats. Solaris uses a tab as separator, XPG4 a space.
74 */
75 #ifdef XPG4
76 #define FORMAT1 "%s %s\n"
77 #define FORMAT2 "%lld %s\n"
78 #else
79 #define FORMAT1 "%s\t%s\n"
80 #define FORMAT2 "%lld\t%s\n"
81 #endif
82
83 /*
84 * convert DEV_BSIZE blocks to K blocks
85 */
86 #define DEV_BSIZE 512
87 #define DEV_KSHIFT 1
88 #define DEV_MSHIFT 11
89 #define kb(n) (((u_longlong_t)(n)) >> DEV_KSHIFT)
90 #define mb(n) (((u_longlong_t)(n)) >> DEV_MSHIFT)
91
92 long wait();
93 static u_longlong_t descend(char *curname, int curfd, int *retcode,
100 int
101 main(int argc, char **argv)
102 {
103 blkcnt_t blocks = 0;
104 int c;
105 extern int optind;
106 char *np;
107 pid_t pid, wpid;
108 int status, retcode = 0;
109 setbuf(stderr, NULL);
110 (void) setlocale(LC_ALL, "");
111 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
112 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
113 #endif
114 (void) textdomain(TEXT_DOMAIN);
115
116 #ifdef XPG4
117 rflg++; /* "-r" is not an option but ON always */
118 #endif
119
120 while ((c = getopt(argc, argv, "adhHkLmorsx")) != EOF)
121 switch (c) {
122
123 case 'a':
124 aflg++;
125 continue;
126
127 case 'h':
128 hflg++;
129 kflg = 0;
130 mflg = 0;
131 continue;
132
133 case 'r':
134 rflg++;
135 continue;
136
137 case 's':
138 sflg++;
139 continue;
140
145 continue;
146
147 case 'm':
148 mflg++;
149 hflg = 0;
150 kflg = 0;
151 continue;
152
153 case 'o':
154 oflg++;
155 continue;
156
157 case 'd':
158 dflg++;
159 continue;
160
161 case 'x':
162 dflg++;
163 continue;
164
165 case 'H':
166 Hflg++;
167 /* -H and -L are mutually exclusive */
168 Lflg = 0;
169 cmdarg++;
170 continue;
171
172 case 'L':
173 Lflg++;
174 /* -H and -L are mutually exclusive */
175 Hflg = 0;
176 cmdarg = 0;
177 continue;
178 case '?':
179 (void) fprintf(stderr, gettext(
180 "usage: du [-dorx] [-a|-s] [-h|-k|-m] [-H|-L] "
181 "[file...]\n"));
182 exit(2);
183 }
184 if (optind == argc) {
185 argv = ˙
186 argc = 1;
187 optind = 0;
188 }
189
190 /* "-o" and "-s" don't make any sense together. */
191 if (oflg && sflg)
192 oflg = 0;
193
194 if ((base = (char *)calloc(base_len, sizeof (char))) == NULL) {
195 perror("du");
196 exit(1);
197 }
198 if ((name = (char *)calloc(name_len, sizeof (char))) == NULL) {
199 perror("du");
200 free(base);
362 int rc;
363 if ((rc = add_tnode(&tree, stb.st_dev, stb.st_ino)) != 1) {
364 if (rc == 0) {
365 /*
366 * This hierarchy, or file with multiple
367 * links, has already been visited/reported.
368 */
369 return (0);
370 } else {
371 /*
372 * An error occurred while trying to add the
373 * node to the tree.
374 */
375 if (rflg) {
376 perror("du");
377 }
378 exitdu(1);
379 }
380 }
381 }
382 blocks = stb.st_blocks;
383 /*
384 * If there are extended attributes on the current file, add their
385 * block usage onto the block count. Note: Since pathconf() always
386 * follows symlinks, only test for extended attributes using pathconf()
387 * if we are following symlinks or the current file is not a symlink.
388 */
389 if (curname && (follow_symlinks ||
390 ((stb.st_mode & S_IFMT) != S_IFLNK)) &&
391 pathconf(curname, _PC_XATTR_EXISTS) == 1) {
392 if ((fd = attropen(curname, ".", O_RDONLY)) < 0) {
393 if (rflg)
394 perror(gettext(
395 "du: can't access extended attributes"));
396 }
397 else
398 {
399 tmpflg = sflg;
400 sflg = 1;
401 blocks += descend(NULL, fd, retcode, device);
402 sflg = tmpflg;
578 while ((number >= scale) && (*uom != 'E')) {
579 uom++; /* next unit of measurement */
580 save = number;
581 number = (number + (scale / 2)) / scale;
582 }
583
584 /* check if we should output a decimal place after the point */
585 if (save && ((save / scale) < 10)) {
586 /* sprintf() will round for us */
587 float fnum = (float)save / scale;
588 (void) sprintf(buf, "%4.1f%c", fnum, *uom);
589 } else {
590 (void) sprintf(buf, "%4llu%c", number, *uom);
591 }
592 return (buf);
593 }
594
595 static void
596 printsize(blkcnt_t blocks, char *path)
597 {
598 if (hflg) {
599 numbuf_t numbuf;
600 unsigned long long scale = 1024L;
601 (void) printf(FORMAT1,
602 number_to_scaled_string(numbuf, blocks, DEV_BSIZE, scale),
603 path);
604 } else if (kflg) {
605 (void) printf(FORMAT2, (long long)kb(blocks), path);
606 } else if (mflg) {
607 (void) printf(FORMAT2, (long long)mb(blocks), path);
608 } else {
609 (void) printf(FORMAT2, (long long)blocks, path);
610 }
611 }
612
613 static void
614 exitdu(int exitcode)
615 {
616 free(base);
617 free(name);
618 exit(exitcode);
619 }
|
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * du -- summarize disk usage
32 * du [-Adorx] [-a|-s] [-h|-k|-m] [-H|-L] [file...]
33 */
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/avl.h>
38 #include <fcntl.h>
39 #include <dirent.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <locale.h>
46 #include <libcmdutils.h>
47
48
49 static int aflg = 0;
50 static int rflg = 0;
51 static int sflg = 0;
52 static int kflg = 0;
53 static int mflg = 0;
54 static int oflg = 0;
55 static int dflg = 0;
56 static int hflg = 0;
57 static int Aflg = 0;
58 static int Hflg = 0;
59 static int Lflg = 0;
60 static int cmdarg = 0; /* Command line argument */
61 static char *dot = ".";
62 static int level = 0; /* Level of recursion */
63
64 static char *base;
65 static char *name;
66 static size_t base_len = PATH_MAX + 1; /* # of chars for base */
67 static size_t name_len = PATH_MAX + 1; /* # of chars for name */
68
69 #define NUMBER_WIDTH 64
70 typedef char numbuf_t[NUMBER_WIDTH];
71
72 /*
73 * Output formats. illumos uses a tab as separator, XPG4 a space.
74 */
75 #ifdef XPG4
76 #define FORMAT1 "%s %s\n"
77 #define FORMAT2 "%lld %s\n"
78 #else
79 #define FORMAT1 "%s\t%s\n"
80 #define FORMAT2 "%lld\t%s\n"
81 #endif
82
83 /*
84 * convert DEV_BSIZE blocks to K blocks
85 */
86 #define DEV_BSIZE 512
87 #define DEV_KSHIFT 1
88 #define DEV_MSHIFT 11
89 #define kb(n) (((u_longlong_t)(n)) >> DEV_KSHIFT)
90 #define mb(n) (((u_longlong_t)(n)) >> DEV_MSHIFT)
91
92 long wait();
93 static u_longlong_t descend(char *curname, int curfd, int *retcode,
100 int
101 main(int argc, char **argv)
102 {
103 blkcnt_t blocks = 0;
104 int c;
105 extern int optind;
106 char *np;
107 pid_t pid, wpid;
108 int status, retcode = 0;
109 setbuf(stderr, NULL);
110 (void) setlocale(LC_ALL, "");
111 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
112 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
113 #endif
114 (void) textdomain(TEXT_DOMAIN);
115
116 #ifdef XPG4
117 rflg++; /* "-r" is not an option but ON always */
118 #endif
119
120 while ((c = getopt(argc, argv, "aAdhHkLmorsx")) != EOF)
121 switch (c) {
122
123 case 'a':
124 aflg++;
125 continue;
126
127 case 'h':
128 hflg++;
129 kflg = 0;
130 mflg = 0;
131 continue;
132
133 case 'r':
134 rflg++;
135 continue;
136
137 case 's':
138 sflg++;
139 continue;
140
145 continue;
146
147 case 'm':
148 mflg++;
149 hflg = 0;
150 kflg = 0;
151 continue;
152
153 case 'o':
154 oflg++;
155 continue;
156
157 case 'd':
158 dflg++;
159 continue;
160
161 case 'x':
162 dflg++;
163 continue;
164
165 case 'A':
166 Aflg++;
167 continue;
168
169 case 'H':
170 Hflg++;
171 /* -H and -L are mutually exclusive */
172 Lflg = 0;
173 cmdarg++;
174 continue;
175
176 case 'L':
177 Lflg++;
178 /* -H and -L are mutually exclusive */
179 Hflg = 0;
180 cmdarg = 0;
181 continue;
182 case '?':
183 (void) fprintf(stderr, gettext(
184 "usage: du [-Adorx] [-a|-s] [-h|-k|-m] [-H|-L] "
185 "[file...]\n"));
186 exit(2);
187 }
188 if (optind == argc) {
189 argv = ˙
190 argc = 1;
191 optind = 0;
192 }
193
194 /* "-o" and "-s" don't make any sense together. */
195 if (oflg && sflg)
196 oflg = 0;
197
198 if ((base = (char *)calloc(base_len, sizeof (char))) == NULL) {
199 perror("du");
200 exit(1);
201 }
202 if ((name = (char *)calloc(name_len, sizeof (char))) == NULL) {
203 perror("du");
204 free(base);
366 int rc;
367 if ((rc = add_tnode(&tree, stb.st_dev, stb.st_ino)) != 1) {
368 if (rc == 0) {
369 /*
370 * This hierarchy, or file with multiple
371 * links, has already been visited/reported.
372 */
373 return (0);
374 } else {
375 /*
376 * An error occurred while trying to add the
377 * node to the tree.
378 */
379 if (rflg) {
380 perror("du");
381 }
382 exitdu(1);
383 }
384 }
385 }
386 blocks = Aflg ? stb.st_size : stb.st_blocks;
387
388 /*
389 * If there are extended attributes on the current file, add their
390 * block usage onto the block count. Note: Since pathconf() always
391 * follows symlinks, only test for extended attributes using pathconf()
392 * if we are following symlinks or the current file is not a symlink.
393 */
394 if (curname && (follow_symlinks ||
395 ((stb.st_mode & S_IFMT) != S_IFLNK)) &&
396 pathconf(curname, _PC_XATTR_EXISTS) == 1) {
397 if ((fd = attropen(curname, ".", O_RDONLY)) < 0) {
398 if (rflg)
399 perror(gettext(
400 "du: can't access extended attributes"));
401 }
402 else
403 {
404 tmpflg = sflg;
405 sflg = 1;
406 blocks += descend(NULL, fd, retcode, device);
407 sflg = tmpflg;
583 while ((number >= scale) && (*uom != 'E')) {
584 uom++; /* next unit of measurement */
585 save = number;
586 number = (number + (scale / 2)) / scale;
587 }
588
589 /* check if we should output a decimal place after the point */
590 if (save && ((save / scale) < 10)) {
591 /* sprintf() will round for us */
592 float fnum = (float)save / scale;
593 (void) sprintf(buf, "%4.1f%c", fnum, *uom);
594 } else {
595 (void) sprintf(buf, "%4llu%c", number, *uom);
596 }
597 return (buf);
598 }
599
600 static void
601 printsize(blkcnt_t blocks, char *path)
602 {
603 u_longlong_t bsize;
604
605 bsize = Aflg ? 1 : DEV_BSIZE;
606
607 if (hflg) {
608 numbuf_t numbuf;
609 unsigned long long scale = 1024L;
610 (void) printf(FORMAT1,
611 number_to_scaled_string(numbuf, blocks, bsize, scale),
612 path);
613 } else if (kflg) {
614 (void) printf(FORMAT2, (long long)kb(blocks), path);
615 } else if (mflg) {
616 (void) printf(FORMAT2, (long long)mb(blocks), path);
617 } else {
618 (void) printf(FORMAT2, (long long)blocks, path);
619 }
620 }
621
622 static void
623 exitdu(int exitcode)
624 {
625 free(base);
626 free(name);
627 exit(exitcode);
628 }
|