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 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 char copyright[] = 23 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 24 All rights reserved.\n"; 25 #endif /* not lint */ 26 27 #ifndef lint 28 static char sccsid[] = "@(#)du.c 5.5 (Berkeley) 05/15/90"; 29 #endif /* not lint */ 30 31 #include <sys/param.h> 32 #include <sys/stat.h> 33 #include <dirent.h> 34 #include <string.h> 35 #include <stdio.h> 36 37 typedef struct _ID { 38 dev_t dev; 39 ino_t inode; 40 } ID; 41 42 ID *files; 43 dev_t device; 44 int crossmounts, kvalue, listdirs, listfiles, maxfiles, numfiles; 45 char path[MAXPATHLEN + 1]; 46 47 main(argc, argv) 48 int argc; 49 char **argv; 50 { 51 extern int optind, errno; 52 int ch; 53 char *malloc(), top[MAXPATHLEN + 1]; 54 55 listdirs = crossmounts = 1; 56 while ((ch = getopt(argc, argv, "aksx")) != EOF) 57 switch(ch) { 58 case 'a': 59 listfiles = 1; 60 break; 61 case 'k': 62 kvalue = 1; 63 break; 64 case 's': 65 listfiles = listdirs = 0; 66 break; 67 case 'x': 68 crossmounts = 0; 69 break; 70 case '?': 71 default: 72 (void)fprintf(stderr, 73 "usage: du [-aksx] [name ...]\n"); 74 exit(1); 75 } 76 argv += optind; 77 78 files = (ID *)malloc((u_int)(sizeof(ID) * (maxfiles = 128))); 79 80 if (!*argv) 81 du("."); 82 else { 83 if (argv[1]) 84 (void)getwd(top); 85 for (;;) { 86 du(*argv); 87 if (!*++argv) 88 break; 89 if (chdir(top)) { 90 (void)fprintf(stderr, "du: %s: %s\n", 91 top, strerror(errno)); 92 exit(1); 93 } 94 } 95 } 96 exit(0); 97 } 98 99 struct stat info; 100 101 du(arg) 102 register char *arg; 103 { 104 extern int errno; 105 u_long total, descend(); 106 107 if (lstat(arg, &info)) { 108 (void)fprintf(stderr, "du: %s: %s\n", arg, strerror(errno)); 109 return; 110 } 111 if ((info.st_mode&S_IFMT) != S_IFDIR) { 112 (void)printf("%ld\t%s\n", kvalue ? 113 howmany(info.st_blocks, 2) : info.st_blocks, arg); 114 return; 115 } 116 device = info.st_dev; 117 (void)strcpy(path, arg); 118 total = descend(path); 119 if (!listfiles && !listdirs) 120 (void)printf("%lu\t%s\n", 121 kvalue ? howmany(total, 2) : total, path); 122 } 123 124 u_long 125 descend(endp) 126 register char *endp; 127 { 128 extern int errno; 129 register DIR *dir; 130 register ID *fp; 131 register struct dirent *dp; 132 u_long total; 133 char *realloc(); 134 135 if (info.st_nlink > 1) { 136 for (fp = files + numfiles - 1; fp >= files; --fp) 137 if (info.st_ino == fp->inode && 138 info.st_dev == fp->dev) 139 return(0L); 140 if (numfiles == maxfiles) 141 files = (ID *)realloc((char *)files, 142 (u_int)(sizeof(ID) * (maxfiles += 128))); 143 files[numfiles].inode = info.st_ino; 144 files[numfiles].dev = info.st_dev; 145 ++numfiles; 146 } 147 total = info.st_blocks; 148 if ((info.st_mode&S_IFMT) == S_IFDIR) { 149 if (info.st_dev != device && !crossmounts) 150 return(0L); 151 if (chdir(endp) || !(dir = opendir("."))) { 152 (void)fprintf(stderr, "du: %s: %s\n", 153 path, strerror(errno)); 154 return(total); 155 } 156 for (; *endp; ++endp); 157 if (endp[-1] != '/') 158 *endp++ = '/'; 159 while (dp = readdir(dir)) { 160 if (dp->d_name[0] == '.' && (!dp->d_name[1] || 161 dp->d_name[1] == '.' && !dp->d_name[2])) 162 continue; 163 bcopy(dp->d_name, endp, dp->d_namlen + 1); 164 if (lstat(dp->d_name, &info)) { 165 (void)fprintf(stderr, "du: %s: %s\n", path, 166 strerror(errno)); 167 continue; 168 } 169 total += descend(endp); 170 } 171 closedir(dir); 172 if (chdir("..")) { 173 (void)fprintf(stderr, "du: ..: %s\n", strerror(errno)); 174 exit(1); 175 } 176 *--endp = '\0'; 177 if (listdirs) 178 (void)printf("%lu\t%s\n", 179 kvalue ? howmany(total, 2) : total, path); 180 } 181 else if (listfiles) 182 (void)printf("%lu\t%s\n", 183 kvalue ? howmany(total, 2) : total, path); 184 return(total); 185 } 186