| 1 | /* |
| 2 | * Disk usage by user |
| 3 | */ |
| 4 | |
| 5 | char *dargv[] = { |
| 6 | "/dev/rrp3", |
| 7 | 0 |
| 8 | }; |
| 9 | |
| 10 | #include <stdio.h> |
| 11 | #include <ctype.h> |
| 12 | #include <pwd.h> |
| 13 | #include <sys/param.h> |
| 14 | #include <sys/ino.h> |
| 15 | #include <sys/inode.h> |
| 16 | #include <sys/filsys.h> |
| 17 | |
| 18 | #define ITABSZ 256 |
| 19 | #define ISIZ (BSIZE/sizeof(struct dinode)) |
| 20 | #define NUID 1000 |
| 21 | struct filsys sblock; |
| 22 | struct dinode itab[ITABSZ]; |
| 23 | struct du |
| 24 | { |
| 25 | long blocks; |
| 26 | long nfiles; |
| 27 | int uid; |
| 28 | char *name; |
| 29 | } du[NUID]; |
| 30 | #define TSIZE 500 |
| 31 | int sizes[TSIZE]; |
| 32 | long overflow; |
| 33 | |
| 34 | int nflg; |
| 35 | int fflg; |
| 36 | int cflg; |
| 37 | |
| 38 | int fi; |
| 39 | unsigned ino; |
| 40 | unsigned nfiles; |
| 41 | |
| 42 | struct passwd *getpwent(); |
| 43 | char *malloc(); |
| 44 | char *copy(); |
| 45 | |
| 46 | main(argc, argv) |
| 47 | char **argv; |
| 48 | { |
| 49 | register int n; |
| 50 | register struct passwd *lp; |
| 51 | register char **p; |
| 52 | |
| 53 | for(n=0; n<NUID; n++) |
| 54 | du[n].uid = n; |
| 55 | while((lp=getpwent()) != 0) { |
| 56 | n = lp->pw_uid; |
| 57 | if (n>NUID) |
| 58 | continue; |
| 59 | if(du[n].name) |
| 60 | continue; |
| 61 | du[n].name = copy(lp->pw_name); |
| 62 | } |
| 63 | if (argc == 1) { |
| 64 | for (p = dargv; *p;) { |
| 65 | check(*p++); |
| 66 | report(); |
| 67 | } |
| 68 | return(0); |
| 69 | } |
| 70 | while (--argc) { |
| 71 | argv++; |
| 72 | if (argv[0][0]=='-') { |
| 73 | if (argv[0][1]=='n') |
| 74 | nflg++; |
| 75 | else if (argv[0][1]=='f') |
| 76 | fflg++; |
| 77 | else if (argv[0][1]=='c') |
| 78 | cflg++; |
| 79 | } else { |
| 80 | check(*argv); |
| 81 | report(); |
| 82 | } |
| 83 | } |
| 84 | return(0); |
| 85 | } |
| 86 | |
| 87 | check(file) |
| 88 | char *file; |
| 89 | { |
| 90 | register unsigned i, j; |
| 91 | register c; |
| 92 | |
| 93 | fi = open(file, 0); |
| 94 | if (fi < 0) { |
| 95 | printf("cannot open %s\n", file); |
| 96 | return; |
| 97 | } |
| 98 | printf("%s:\n", file); |
| 99 | sync(); |
| 100 | bread(1, (char *)&sblock, sizeof sblock); |
| 101 | nfiles = (sblock.s_isize-2)*(BSIZE/sizeof(struct dinode)); |
| 102 | ino = 0; |
| 103 | if (nflg) { |
| 104 | if (isdigit(c = getchar())) |
| 105 | ungetc(c, stdin); |
| 106 | else while (c!='\n' && c != EOF) |
| 107 | c = getchar(); |
| 108 | } |
| 109 | for(i=2; ino<nfiles; i += ITABSZ/ISIZ) { |
| 110 | bread(i, (char *)itab, sizeof itab); |
| 111 | for (j=0; j<ITABSZ && ino<nfiles; j++) { |
| 112 | ino++; |
| 113 | acct(&itab[j]); |
| 114 | } |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | acct(ip) |
| 119 | register struct dinode *ip; |
| 120 | { |
| 121 | register n; |
| 122 | register char *np; |
| 123 | static fino; |
| 124 | |
| 125 | if ((ip->di_mode&IFMT) == 0) |
| 126 | return; |
| 127 | if (cflg) { |
| 128 | if ((ip->di_mode&IFMT)!=IFDIR && (ip->di_mode&IFMT)!=IFREG) |
| 129 | return; |
| 130 | n = (ip->di_size+BSIZE-1)/BSIZE; |
| 131 | if (n >= TSIZE) { |
| 132 | overflow += n; |
| 133 | n = TSIZE-1; |
| 134 | } |
| 135 | sizes[n]++; |
| 136 | return; |
| 137 | } |
| 138 | if (ip->di_uid >= NUID) |
| 139 | return; |
| 140 | du[ip->di_uid].blocks += (ip->di_size+BSIZE-1)/BSIZE; |
| 141 | du[ip->di_uid].nfiles++; |
| 142 | if (nflg) { |
| 143 | tryagain: |
| 144 | if (fino==0) |
| 145 | if (scanf("%d", &fino)<=0) |
| 146 | return; |
| 147 | if (fino > ino) |
| 148 | return; |
| 149 | if (fino<ino) { |
| 150 | while ((n=getchar())!='\n' && n!=EOF) |
| 151 | ; |
| 152 | fino = 0; |
| 153 | goto tryagain; |
| 154 | } |
| 155 | if (np = du[ip->di_uid].name) |
| 156 | printf("%.7s ", np); |
| 157 | else |
| 158 | printf("%d ", ip->di_uid); |
| 159 | while ((n = getchar())==' ' || n=='\t') |
| 160 | ; |
| 161 | putchar(n); |
| 162 | while (n!=EOF && n!='\n') { |
| 163 | n = getchar(); |
| 164 | putchar(n); |
| 165 | } |
| 166 | fino = 0; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | bread(bno, buf, cnt) |
| 171 | unsigned bno; |
| 172 | char *buf; |
| 173 | { |
| 174 | |
| 175 | lseek(fi, (long)bno*BSIZE, 0); |
| 176 | if (read(fi, buf, cnt) != cnt) { |
| 177 | printf("read error %u\n", bno); |
| 178 | exit(1); |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | qcmp(p1, p2) |
| 183 | register struct du *p1, *p2; |
| 184 | { |
| 185 | if (p1->blocks > p2->blocks) |
| 186 | return(-1); |
| 187 | if (p1->blocks < p2->blocks) |
| 188 | return(1); |
| 189 | return(strcmp(p1->name, p2->name)); |
| 190 | } |
| 191 | |
| 192 | report() |
| 193 | { |
| 194 | register i; |
| 195 | |
| 196 | if (nflg) |
| 197 | return; |
| 198 | if (cflg) { |
| 199 | long t = 0; |
| 200 | for (i=0; i<TSIZE-1; i++) |
| 201 | if (sizes[i]) { |
| 202 | t += i*sizes[i]; |
| 203 | printf("%d %d %D\n", i, sizes[i], t); |
| 204 | } |
| 205 | printf("%d %d %D\n", TSIZE-1, sizes[TSIZE-1], overflow+t); |
| 206 | return; |
| 207 | } |
| 208 | qsort(du, NUID, sizeof(du[0]), qcmp); |
| 209 | for (i=0; i<NUID; i++) { |
| 210 | if (du[i].blocks==0) |
| 211 | return; |
| 212 | printf("%5D\t", du[i].blocks); |
| 213 | if (fflg) |
| 214 | printf("%5D\t", du[i].nfiles); |
| 215 | if (du[i].name) |
| 216 | printf("%s\n", du[i].name); |
| 217 | else |
| 218 | printf("#%d\n", du[i].uid); |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | char * |
| 223 | copy(s) |
| 224 | char *s; |
| 225 | { |
| 226 | register char *p; |
| 227 | register n; |
| 228 | |
| 229 | for(n=0; s[n]; n++) |
| 230 | ; |
| 231 | p = malloc((unsigned)n+1); |
| 232 | for(n=0; p[n] = s[n]; n++) |
| 233 | ; |
| 234 | return(p); |
| 235 | } |