Commit | Line | Data |
---|---|---|
20ff9060 KB |
1 | /* |
2 | * Copyright (c) 1989 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Chris Newcomb. | |
7 | * | |
f15db449 | 8 | * %sccs.include.redist.c% |
20ff9060 KB |
9 | */ |
10 | ||
fbdb528f | 11 | #ifndef lint |
20ff9060 KB |
12 | char copyright[] = |
13 | "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ | |
14 | All rights reserved.\n"; | |
15 | #endif /* not lint */ | |
16 | ||
17 | #ifndef lint | |
f15db449 | 18 | static char sccsid[] = "@(#)du.c 5.6 (Berkeley) %G%"; |
20ff9060 | 19 | #endif /* not lint */ |
fbdb528f | 20 | |
ca4a89e1 BJ |
21 | #include <sys/param.h> |
22 | #include <sys/stat.h> | |
20ff9060 | 23 | #include <dirent.h> |
38dde0cd | 24 | #include <string.h> |
20ff9060 | 25 | #include <stdio.h> |
fbdb528f | 26 | |
20ff9060 KB |
27 | typedef struct _ID { |
28 | dev_t dev; | |
29 | ino_t inode; | |
30 | } ID; | |
e29a75fd | 31 | |
20ff9060 KB |
32 | ID *files; |
33 | dev_t device; | |
3f900164 | 34 | int crossmounts, kvalue, listdirs, listfiles, maxfiles, numfiles; |
20ff9060 | 35 | char path[MAXPATHLEN + 1]; |
905d30b9 | 36 | |
ca4a89e1 | 37 | main(argc, argv) |
e29a75fd BJ |
38 | int argc; |
39 | char **argv; | |
ca4a89e1 | 40 | { |
20ff9060 | 41 | extern int optind, errno; |
17372837 | 42 | int ch; |
20ff9060 | 43 | char *malloc(), top[MAXPATHLEN + 1]; |
ca4a89e1 | 44 | |
20ff9060 | 45 | listdirs = crossmounts = 1; |
3f900164 | 46 | while ((ch = getopt(argc, argv, "aksx")) != EOF) |
20ff9060 KB |
47 | switch(ch) { |
48 | case 'a': | |
49 | listfiles = 1; | |
50 | break; | |
3f900164 KB |
51 | case 'k': |
52 | kvalue = 1; | |
53 | break; | |
20ff9060 KB |
54 | case 's': |
55 | listfiles = listdirs = 0; | |
56 | break; | |
57 | case 'x': | |
58 | crossmounts = 0; | |
59 | break; | |
60 | case '?': | |
61 | default: | |
3f900164 KB |
62 | (void)fprintf(stderr, |
63 | "usage: du [-aksx] [name ...]\n"); | |
20ff9060 | 64 | exit(1); |
dd610901 | 65 | } |
20ff9060 KB |
66 | argv += optind; |
67 | ||
68 | files = (ID *)malloc((u_int)(sizeof(ID) * (maxfiles = 128))); | |
69 | ||
70 | if (!*argv) | |
71 | du("."); | |
72 | else { | |
73 | if (argv[1]) | |
74 | (void)getwd(top); | |
17372837 | 75 | for (;;) { |
20ff9060 | 76 | du(*argv); |
17372837 KB |
77 | if (!*++argv) |
78 | break; | |
79 | if (chdir(top)) { | |
20ff9060 KB |
80 | (void)fprintf(stderr, "du: %s: %s\n", |
81 | top, strerror(errno)); | |
dd610901 | 82 | exit(1); |
20ff9060 | 83 | } |
dd610901 | 84 | } |
20ff9060 | 85 | } |
ca4a89e1 BJ |
86 | exit(0); |
87 | } | |
88 | ||
20ff9060 | 89 | struct stat info; |
e29a75fd | 90 | |
20ff9060 KB |
91 | du(arg) |
92 | register char *arg; | |
ca4a89e1 | 93 | { |
20ff9060 KB |
94 | extern int errno; |
95 | u_long total, descend(); | |
ca4a89e1 | 96 | |
20ff9060 | 97 | if (lstat(arg, &info)) { |
ee63d32b | 98 | (void)fprintf(stderr, "du: %s: %s\n", arg, strerror(errno)); |
20ff9060 | 99 | return; |
ca4a89e1 | 100 | } |
20ff9060 | 101 | if ((info.st_mode&S_IFMT) != S_IFDIR) { |
3f900164 KB |
102 | (void)printf("%ld\t%s\n", kvalue ? |
103 | howmany(info.st_blocks, 2) : info.st_blocks, arg); | |
20ff9060 | 104 | return; |
fbdb528f | 105 | } |
20ff9060 KB |
106 | device = info.st_dev; |
107 | (void)strcpy(path, arg); | |
108 | total = descend(path); | |
109 | if (!listfiles && !listdirs) | |
3f900164 KB |
110 | (void)printf("%lu\t%s\n", |
111 | kvalue ? howmany(total, 2) : total, path); | |
20ff9060 KB |
112 | } |
113 | ||
114 | u_long | |
115 | descend(endp) | |
116 | register char *endp; | |
117 | { | |
118 | extern int errno; | |
119 | register DIR *dir; | |
120 | register ID *fp; | |
121 | register struct dirent *dp; | |
122 | u_long total; | |
123 | char *realloc(); | |
124 | ||
125 | if (info.st_nlink > 1) { | |
126 | for (fp = files + numfiles - 1; fp >= files; --fp) | |
127 | if (info.st_ino == fp->inode && | |
128 | info.st_dev == fp->dev) | |
129 | return(0L); | |
130 | if (numfiles == maxfiles) | |
131 | files = (ID *)realloc((char *)files, | |
132 | (u_int)(sizeof(ID) * (maxfiles += 128))); | |
133 | files[numfiles].inode = info.st_ino; | |
134 | files[numfiles].dev = info.st_dev; | |
135 | ++numfiles; | |
a1a73cfc | 136 | } |
20ff9060 KB |
137 | total = info.st_blocks; |
138 | if ((info.st_mode&S_IFMT) == S_IFDIR) { | |
139 | if (info.st_dev != device && !crossmounts) | |
140 | return(0L); | |
141 | if (chdir(endp) || !(dir = opendir("."))) { | |
3f900164 KB |
142 | (void)fprintf(stderr, "du: %s: %s\n", |
143 | path, strerror(errno)); | |
20ff9060 KB |
144 | return(total); |
145 | } | |
146 | for (; *endp; ++endp); | |
147 | if (endp[-1] != '/') | |
148 | *endp++ = '/'; | |
149 | while (dp = readdir(dir)) { | |
150 | if (dp->d_name[0] == '.' && (!dp->d_name[1] || | |
151 | dp->d_name[1] == '.' && !dp->d_name[2])) | |
152 | continue; | |
153 | bcopy(dp->d_name, endp, dp->d_namlen + 1); | |
154 | if (lstat(dp->d_name, &info)) { | |
155 | (void)fprintf(stderr, "du: %s: %s\n", path, | |
156 | strerror(errno)); | |
157 | continue; | |
a1a73cfc | 158 | } |
20ff9060 | 159 | total += descend(endp); |
ca4a89e1 | 160 | } |
20ff9060 KB |
161 | closedir(dir); |
162 | if (chdir("..")) { | |
3f900164 | 163 | (void)fprintf(stderr, "du: ..: %s\n", strerror(errno)); |
20ff9060 KB |
164 | exit(1); |
165 | } | |
166 | *--endp = '\0'; | |
167 | if (listdirs) | |
3f900164 KB |
168 | (void)printf("%lu\t%s\n", |
169 | kvalue ? howmany(total, 2) : total, path); | |
ca4a89e1 | 170 | } |
20ff9060 | 171 | else if (listfiles) |
3f900164 KB |
172 | (void)printf("%lu\t%s\n", |
173 | kvalue ? howmany(total, 2) : total, path); | |
20ff9060 | 174 | return(total); |
ca4a89e1 | 175 | } |