Introduction
Introduction Statistics Contact Development Disclaimer Help
du.c - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
du.c (2902B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <sys/stat.h>
3 #include <sys/types.h>
4
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <limits.h>
8 #include <search.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <unistd.h>
13
14 #include "fs.h"
15 #include "util.h"
16
17 static size_t maxdepth = SIZE_MAX;
18 static size_t blksize = 512;
19
20 static int aflag = 0;
21 static int sflag = 0;
22 static int hflag = 0;
23
24 struct file {
25 dev_t devno;
26 ino_t inode;
27 };
28
29 static void
30 printpath(off_t n, const char *path)
31 {
32 if (hflag)
33 printf("%s\t%s\n", humansize(n * blksize), path);
34 else
35 printf("%jd\t%s\n", (intmax_t)n, path);
36 }
37
38 static off_t
39 nblks(blkcnt_t blocks)
40 {
41 return (512 * blocks + blksize - 1) / blksize;
42 }
43
44 static int
45 cmp(const void *p1, const void *p2)
46 {
47 const struct file *f1 = p1, *f2 = p2;
48
49 if (f1->devno > f2->devno)
50 return -1;
51 if (f1->devno < f2->devno)
52 return 1;
53
54 /* f1->devno == f2->devno */
55 if (f1->inode < f2->inode)
56 return -1;
57 if (f1->inode > f2->inode)
58 return 1;
59
60 return 0;
61 }
62
63 static int
64 duplicated(dev_t dev, ino_t ino)
65 {
66 static void *tree;
67 struct file **fpp, *fp, file = {dev, ino};
68
69 if ((fpp = tsearch(&file, &tree, cmp)) == NULL)
70 eprintf("%s:", argv0);
71
72 if (*fpp != &file)
73 return 1;
74
75 /* new file added */
76 fp = emalloc(sizeof(*fp));
77 *fp = file;
78 *fpp = fp;
79
80 return 0;
81 }
82
83 static void
84 du(int dirfd, const char *path, struct stat *st, void *data, struct recu…
85 {
86 off_t *total = data, subtotal;
87
88 subtotal = nblks(st->st_blocks);
89 if (S_ISDIR(st->st_mode)) {
90 recurse(dirfd, path, &subtotal, r);
91 } else if (r->follow != 'P' || st->st_nlink > 1) {
92 if (duplicated(st->st_dev, st->st_ino))
93 goto print;
94 }
95
96 *total += subtotal;
97
98 print:
99 if (!r->depth)
100 printpath(*total, r->path);
101 else if (!sflag && r->depth <= maxdepth && (S_ISDIR(st->st_mode)…
102 printpath(subtotal, r->path);
103 }
104
105 static void
106 usage(void)
107 {
108 eprintf("usage: %s [-a | -s] [-d depth] [-h] [-k] [-H | -L | -P]…
109 }
110
111 int
112 main(int argc, char *argv[])
113 {
114 struct recursor r = { .fn = du, .follow = 'P' };
115 off_t n = 0;
116 int kflag = 0, dflag = 0;
117 char *bsize;
118
119 ARGBEGIN {
120 case 'a':
121 aflag = 1;
122 break;
123 case 'd':
124 dflag = 1;
125 maxdepth = estrtonum(EARGF(usage()), 0, MIN(LLONG_MAX, S…
126 break;
127 case 'h':
128 hflag = 1;
129 break;
130 case 'k':
131 kflag = 1;
132 break;
133 case 's':
134 sflag = 1;
135 break;
136 case 'x':
137 r.flags |= SAMEDEV;
138 break;
139 case 'H':
140 case 'L':
141 case 'P':
142 r.follow = ARGC();
143 break;
144 default:
145 usage();
146 } ARGEND
147
148 if ((aflag && sflag) || (dflag && sflag))
149 usage();
150
151 bsize = getenv("BLOCKSIZE");
152 if (bsize)
153 blksize = estrtonum(bsize, 1, MIN(LLONG_MAX, SIZE_MAX));
154 if (kflag)
155 blksize = 1024;
156
157 if (!argc) {
158 recurse(AT_FDCWD, ".", &n, &r);
159 } else {
160 for (; *argv; argc--, argv++) {
161 n = 0;
162 recurse(AT_FDCWD, *argv, &n, &r);
163 }
164 }
165
166 return fshut(stdout, "<stdout>") || recurse_status;
167 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.