diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-10-24 05:00:29 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-10-24 05:00:29 +0000 |
commit | bdfd0d78bc44e73d693510e70087857785b3b521 (patch) | |
tree | 153a573095afac8d8d0ea857759ecabd77fb28b7 /du.c | |
parent | 9260fc5552a3ee52eb95823aa6689d52a1ffd33c (diff) | |
download | busybox-w32-bdfd0d78bc44e73d693510e70087857785b3b521.tar.gz busybox-w32-bdfd0d78bc44e73d693510e70087857785b3b521.tar.bz2 busybox-w32-bdfd0d78bc44e73d693510e70087857785b3b521.zip |
Major rework of the directory structure and the entire build system.
-Erik
Diffstat (limited to 'du.c')
-rw-r--r-- | du.c | 257 |
1 files changed, 0 insertions, 257 deletions
@@ -1,257 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Mini du implementation for busybox | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 1999,2000,2001 by Lineo, inc. | ||
7 | * Written by John Beppu <beppu@lineo.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <sys/types.h> | ||
26 | #include <fcntl.h> | ||
27 | #include <dirent.h> | ||
28 | #include <stdio.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <getopt.h> | ||
31 | #include <string.h> | ||
32 | #include <errno.h> | ||
33 | #include "busybox.h" | ||
34 | |||
35 | |||
36 | #ifdef BB_FEATURE_HUMAN_READABLE | ||
37 | static unsigned long disp_hr = KILOBYTE; | ||
38 | #endif | ||
39 | |||
40 | typedef void (Display) (long, char *); | ||
41 | |||
42 | static int du_depth = 0; | ||
43 | static int count_hardlinks = 0; | ||
44 | |||
45 | static Display *print; | ||
46 | |||
47 | static void print_normal(long size, char *filename) | ||
48 | { | ||
49 | #ifdef BB_FEATURE_HUMAN_READABLE | ||
50 | printf("%s\t%s\n", make_human_readable_str(size<<10, 1, disp_hr), filename); | ||
51 | #else | ||
52 | printf("%ld\t%s\n", size, filename); | ||
53 | #endif | ||
54 | } | ||
55 | |||
56 | static void print_summary(long size, char *filename) | ||
57 | { | ||
58 | if (du_depth == 1) { | ||
59 | print_normal(size, filename); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | #define HASH_SIZE 311 /* Should be prime */ | ||
64 | #define hash_inode(i) ((i) % HASH_SIZE) | ||
65 | |||
66 | typedef struct ino_dev_hash_bucket_struct { | ||
67 | struct ino_dev_hash_bucket_struct *next; | ||
68 | ino_t ino; | ||
69 | dev_t dev; | ||
70 | char name[1]; | ||
71 | } ino_dev_hashtable_bucket_t; | ||
72 | |||
73 | static ino_dev_hashtable_bucket_t *ino_dev_hashtable[HASH_SIZE]; | ||
74 | |||
75 | /* | ||
76 | * Return 1 if statbuf->st_ino && statbuf->st_dev are recorded in | ||
77 | * `ino_dev_hashtable', else return 0 | ||
78 | * | ||
79 | * If NAME is a non-NULL pointer to a character pointer, and there is | ||
80 | * a match, then set *NAME to the value of the name slot in that | ||
81 | * bucket. | ||
82 | */ | ||
83 | static int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name) | ||
84 | { | ||
85 | ino_dev_hashtable_bucket_t *bucket; | ||
86 | |||
87 | bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)]; | ||
88 | while (bucket != NULL) { | ||
89 | if ((bucket->ino == statbuf->st_ino) && | ||
90 | (bucket->dev == statbuf->st_dev)) | ||
91 | { | ||
92 | if (name) *name = bucket->name; | ||
93 | return 1; | ||
94 | } | ||
95 | bucket = bucket->next; | ||
96 | } | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* Add statbuf to statbuf hash table */ | ||
101 | static void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) | ||
102 | { | ||
103 | int i; | ||
104 | size_t s; | ||
105 | ino_dev_hashtable_bucket_t *bucket; | ||
106 | |||
107 | i = hash_inode(statbuf->st_ino); | ||
108 | s = name ? strlen(name) : 0; | ||
109 | bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + s); | ||
110 | bucket->ino = statbuf->st_ino; | ||
111 | bucket->dev = statbuf->st_dev; | ||
112 | if (name) | ||
113 | strcpy(bucket->name, name); | ||
114 | else | ||
115 | bucket->name[0] = '\0'; | ||
116 | bucket->next = ino_dev_hashtable[i]; | ||
117 | ino_dev_hashtable[i] = bucket; | ||
118 | } | ||
119 | |||
120 | /* Clear statbuf hash table */ | ||
121 | static void reset_ino_dev_hashtable(void) | ||
122 | { | ||
123 | int i; | ||
124 | ino_dev_hashtable_bucket_t *bucket; | ||
125 | |||
126 | for (i = 0; i < HASH_SIZE; i++) { | ||
127 | while (ino_dev_hashtable[i] != NULL) { | ||
128 | bucket = ino_dev_hashtable[i]->next; | ||
129 | free(ino_dev_hashtable[i]); | ||
130 | ino_dev_hashtable[i] = bucket; | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | |||
135 | /* tiny recursive du */ | ||
136 | static long du(char *filename) | ||
137 | { | ||
138 | struct stat statbuf; | ||
139 | long sum; | ||
140 | |||
141 | if ((lstat(filename, &statbuf)) != 0) { | ||
142 | perror_msg("%s", filename); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | du_depth++; | ||
147 | sum = (statbuf.st_blocks >> 1); | ||
148 | |||
149 | /* Don't add in stuff pointed to by symbolic links */ | ||
150 | if (S_ISLNK(statbuf.st_mode)) { | ||
151 | sum = 0L; | ||
152 | if (du_depth == 1) { | ||
153 | } | ||
154 | } | ||
155 | if (S_ISDIR(statbuf.st_mode)) { | ||
156 | DIR *dir; | ||
157 | struct dirent *entry; | ||
158 | char *newfile; | ||
159 | |||
160 | dir = opendir(filename); | ||
161 | if (!dir) { | ||
162 | du_depth--; | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | newfile = last_char_is(filename, '/'); | ||
167 | if (newfile) | ||
168 | *newfile = '\0'; | ||
169 | |||
170 | while ((entry = readdir(dir))) { | ||
171 | char *name = entry->d_name; | ||
172 | |||
173 | if ((strcmp(name, "..") == 0) | ||
174 | || (strcmp(name, ".") == 0)) { | ||
175 | continue; | ||
176 | } | ||
177 | newfile = concat_path_file(filename, name); | ||
178 | sum += du(newfile); | ||
179 | free(newfile); | ||
180 | } | ||
181 | closedir(dir); | ||
182 | print(sum, filename); | ||
183 | } | ||
184 | else if (statbuf.st_nlink > 1 && !count_hardlinks) { | ||
185 | /* Add files with hard links only once */ | ||
186 | if (is_in_ino_dev_hashtable(&statbuf, NULL)) { | ||
187 | sum = 0L; | ||
188 | if (du_depth == 1) | ||
189 | print(sum, filename); | ||
190 | } | ||
191 | else { | ||
192 | add_to_ino_dev_hashtable(&statbuf, NULL); | ||
193 | } | ||
194 | } | ||
195 | du_depth--; | ||
196 | return sum; | ||
197 | } | ||
198 | |||
199 | int du_main(int argc, char **argv) | ||
200 | { | ||
201 | int status = EXIT_SUCCESS; | ||
202 | int i; | ||
203 | int c; | ||
204 | |||
205 | /* default behaviour */ | ||
206 | print = print_normal; | ||
207 | |||
208 | /* parse argv[] */ | ||
209 | while ((c = getopt(argc, argv, "sl" | ||
210 | #ifdef BB_FEATURE_HUMAN_READABLE | ||
211 | "hm" | ||
212 | #endif | ||
213 | "k")) != EOF) { | ||
214 | switch (c) { | ||
215 | case 's': | ||
216 | print = print_summary; | ||
217 | break; | ||
218 | case 'l': | ||
219 | count_hardlinks = 1; | ||
220 | break; | ||
221 | #ifdef BB_FEATURE_HUMAN_READABLE | ||
222 | case 'h': disp_hr = 0; break; | ||
223 | case 'm': disp_hr = MEGABYTE; break; | ||
224 | #endif | ||
225 | case 'k': break; | ||
226 | default: | ||
227 | show_usage(); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /* go through remaining args (if any) */ | ||
232 | if (optind >= argc) { | ||
233 | if (du(".") == 0) | ||
234 | status = EXIT_FAILURE; | ||
235 | } else { | ||
236 | long sum; | ||
237 | |||
238 | for (i=optind; i < argc; i++) { | ||
239 | sum = du(argv[i]); | ||
240 | if(is_directory(argv[i], FALSE, NULL)==FALSE) { | ||
241 | print_normal(sum, argv[i]); | ||
242 | } | ||
243 | reset_ino_dev_hashtable(); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | return status; | ||
248 | } | ||
249 | |||
250 | /* $Id: du.c,v 1.50 2001/06/30 17:54:20 andersen Exp $ */ | ||
251 | /* | ||
252 | Local Variables: | ||
253 | c-file-style: "linux" | ||
254 | c-basic-offset: 4 | ||
255 | tab-width: 4 | ||
256 | End: | ||
257 | */ | ||