]>
Commit | Line | Data |
---|---|---|
c1ddfbcb | 1 | diff -Nur busybox-1.00/AUTHORS busybox/AUTHORS |
2 | --- busybox-1.00/AUTHORS 2004-07-26 20:57:49.000000000 +0200 | |
3 | +++ busybox/AUTHORS 2005-06-04 08:20:22.000000000 +0200 | |
4 | @@ -2,12 +2,15 @@ | |
5 | ||
6 | If you have code in BusyBox, you should be listed here. If you should be | |
7 | listed, or the description of what you have done needs more detail, or is | |
8 | -incorect, _please_ let me know. | |
9 | +incorrect, _please_ let me know. | |
10 | ||
11 | -Erik | |
12 | ||
13 | ----------- | |
14 | ||
15 | +Peter Willis <psyphreak@phreaker.net> | |
16 | + eject | |
17 | + | |
18 | Emanuele Aina <emanuele.aina@tiscali.it> | |
19 | run-parts | |
20 | ||
21 | @@ -29,6 +32,9 @@ | |
22 | John Beppu <beppu@codepoet.org> | |
23 | du, nslookup, sort | |
24 | ||
25 | +David Brownell <dbrownell@users.sourceforge.net> | |
26 | + zcip | |
27 | + | |
28 | Brian Candler <B.Candler@pobox.com> | |
29 | tiny-ls(ls) | |
30 | ||
31 | @@ -69,6 +75,12 @@ | |
32 | Matt Kraai <kraai@alumni.cmu.edu> | |
33 | documentation, bugfixes, test suite | |
34 | ||
35 | +Rob Landley <rob@landley.net> | |
36 | + sed (major rewrite in 2003, and I now maintain the thing). | |
37 | + bunzip2 (complete from-scratch rewrite, then mjn3 optimized the result.) | |
38 | + sort (more or less from scratch rewrite in 2004, I now maintain it). | |
39 | + I've patched lots of other applets, but don't maintain 'em. | |
40 | + | |
41 | Stephan Linz <linz@li-pro.net> | |
42 | ipcalc, Red Hat equivalence | |
43 | ||
44 | @@ -76,13 +88,14 @@ | |
45 | tr | |
46 | ||
47 | Glenn McGrath <bug1@iinet.net.au> | |
48 | - Common unarchving code and unarchiving applets, ifupdown, ftpgetput, | |
49 | - nameif, sed, patch, fold, install, uudecode. | |
50 | - Various bugfixes, review and apply numerous patches. | |
51 | + Common unarchiving code and unarchiving applets, ifupdown, ftpgetput, | |
52 | + nameif, sed, patch, fold, install, uudecode. | |
53 | + Various bugfixes, review and apply numerous patches. | |
54 | ||
55 | Manuel Novoa III <mjn3@codepoet.org> | |
56 | cat, head, mkfifo, mknod, rmdir, sleep, tee, tty, uniq, usleep, wc, yes, | |
57 | - mesg, vconfig, make_directory, parse_mode, dirname, mode_string, | |
58 | + mesg, vconfig, nice, renice, | |
59 | + make_directory, parse_mode, dirname, mode_string, | |
60 | get_last_path_component, simplify_path, and a number trivial libbb routines | |
61 | ||
62 | also bug fixes, partial rewrites, and size optimizations in | |
63 | @@ -115,6 +128,9 @@ | |
64 | Gyepi Sam <gyepi@praxis-sw.com> | |
65 | Remote logging feature for syslogd | |
66 | ||
67 | +Rob Sullivan <cogito.ergo.cogito@gmail.com> | |
68 | + comm | |
69 | + | |
70 | Linus Torvalds <torvalds@transmeta.com> | |
71 | mkswap, fsck.minix, mkfs.minix | |
72 | ||
73 | @@ -129,5 +145,6 @@ | |
74 | tarcat (since removed), loadkmap, various fixes, Debian maintenance | |
75 | ||
76 | Tito Ragusa <farmatito@tiscali.it> | |
77 | - devfsd and size optimizations in strings, openvt, chvt, deallocvt, hdparm and fdformat. | |
78 | + devfsd and size optimizations in strings, openvt, chvt, deallocvt, hdparm, | |
79 | + fdformat, lsattr, chattr, id and eject. | |
80 | ||
81 | diff -Nur busybox-1.00/Makefile busybox/Makefile | |
82 | --- busybox-1.00/Makefile 2004-10-08 09:45:08.000000000 +0200 | |
83 | +++ busybox/Makefile 2005-06-04 08:20:22.000000000 +0200 | |
84 | @@ -22,7 +22,7 @@ | |
85 | #-------------------------------------------------------------- | |
86 | noconfig_targets := menuconfig config oldconfig randconfig \ | |
87 | defconfig allyesconfig allnoconfig clean distclean \ | |
88 | - release tags | |
89 | + release tags | |
90 | ||
91 | ifndef TOPDIR | |
92 | TOPDIR=$(CURDIR)/ | |
93 | @@ -42,13 +42,12 @@ | |
94 | DIRS:=applets archival archival/libunarchive coreutils console-tools \ | |
95 | debianutils editors findutils init miscutils modutils networking \ | |
96 | networking/libiproute networking/udhcp procps loginutils shell \ | |
97 | - sysklogd util-linux libpwdgrp coreutils/libcoreutils libbb | |
98 | + sysklogd util-linux e2fsprogs libpwdgrp coreutils/libcoreutils libbb | |
99 | ||
100 | SRC_DIRS:=$(patsubst %,$(top_srcdir)/%,$(DIRS)) | |
101 | ||
102 | ifeq ($(strip $(CONFIG_SELINUX)),y) | |
103 | -CFLAGS += -I/usr/include/selinux | |
104 | -LIBRARIES += -lsecure | |
105 | +LIBRARIES += -lselinux | |
106 | endif | |
107 | ||
108 | CONFIG_CONFIG_IN = $(top_srcdir)/sysdeps/$(TARGET_OS)/Config.in | |
109 | @@ -130,7 +129,7 @@ | |
110 | busybox.links: $(top_srcdir)/applets/busybox.mkll include/config.h $(top_srcdir)/include/applets.h | |
111 | - $(SHELL) $^ >$@ | |
112 | ||
113 | -install: applets/install.sh busybox busybox.links | |
114 | +install: $(top_srcdir)/applets/install.sh busybox busybox.links | |
115 | $(SHELL) $< $(PREFIX) | |
116 | ifeq ($(strip $(CONFIG_FEATURE_SUID)),y) | |
117 | @echo | |
118 | @@ -147,7 +146,7 @@ | |
119 | rm -f $(PREFIX)/bin/busybox | |
120 | for i in `cat busybox.links` ; do rm -f $(PREFIX)$$i; done | |
121 | ||
122 | -install-hardlinks: applets/install.sh busybox busybox.links | |
123 | +install-hardlinks: $(top_srcdir)/applets/install.sh busybox busybox.links | |
124 | $(SHELL) $< $(PREFIX) --hardlinks | |
125 | ||
126 | check: busybox | |
127 | diff -Nur busybox-1.00/TODO busybox/TODO | |
128 | --- busybox-1.00/TODO 2004-05-01 02:49:49.000000000 +0200 | |
129 | +++ busybox/TODO 2005-06-04 08:20:22.000000000 +0200 | |
130 | @@ -2,10 +2,106 @@ | |
131 | ||
132 | Stuff that needs to be done | |
133 | ||
134 | ----- | |
135 | -tr - missing SuS3 features in busybox 1.0pre10 | |
136 | +tr - missing SuS3 features in busybox 1.0pre10 | |
137 | ||
138 | tr doesnt support [:blank:], [:digit:] or other predefined classes, [=equiv=] | |
139 | support is also missing. | |
140 | ---- | |
141 | - | |
142 | +find | |
143 | + doesn't understand () or -exec, and these are actually used out in the real | |
144 | + world. The "make uninstall" of lots of things (including busybox itself) | |
145 | + breaks because of this, and sometimes even "make install" (like udev). | |
146 | +---- | |
147 | +comm | |
148 | + Perl needs "comm" to build. It's small and simple, but we haven't got it. | |
149 | +--- | |
150 | +sh | |
151 | + The command shell situation is a big mess. We have three or four different | |
152 | + shells that don't really share any code, and the "standalone shell" doesn't | |
153 | + work all that well (especially not in a chroot environment), due to apps not | |
154 | + being reentrant. Unifying the various shells and figuring out a configurable | |
155 | + way of adding the minimal set of bash features a given script uses is a big | |
156 | + job, but it be a big improvement. | |
157 | +--- | |
158 | +gzip | |
159 | + Can't handle compressing multiple files at once. (I don't mean making a | |
160 | + multiple file archive, I mean compressing more than one file at a time.) | |
161 | + Some global variables aren't re-initialized between runs. | |
162 | +--- | |
163 | +gunzip | |
164 | + same problem as gzip. "gunzip one.gz two.gz three.gz" doesn't work for | |
165 | + two.gz and three.gz due to global variables not getting reset. | |
166 | +--- | |
167 | +diff | |
168 | + We should have a diff -u command. We have patch, we should have diff | |
169 | + (we only need to support unified diffs though). | |
170 | +--- | |
171 | +patch | |
172 | + should have -i support, and simple fuzz factor support to apply patches | |
173 | + at an offset shouldn't take up too much space. | |
174 | +--- | |
175 | +man | |
176 | + It would be nice to have a man command. Not one that handles troff or | |
177 | + anything, just one that can handle preformatted ascii man pages, possibly | |
178 | + compressed. This could probably be a script in the extras directory that | |
179 | + calls cat/zcatbzcat | more | |
180 | +--- | |
181 | +less | |
182 | + More sucks if you're used to less. A tiny less implementation would be | |
183 | + very nice. | |
184 | +--- | |
185 | +bzip2 | |
186 | + Compression-side support. | |
187 | + | |
188 | + | |
189 | +Architectural issues: | |
190 | + | |
191 | +Do a SUSv3 audit | |
192 | + Look at the full Single Unix Specification version 3 (available online at | |
193 | + "http://www.opengroup.org/onlinepubs/009695399/nfindex.html") and | |
194 | + figure out which of our apps are compliant, and what we're missing that | |
195 | + we might actually care about. | |
196 | + | |
197 | + Even better would be some kind of automated compliance test harness that | |
198 | + exercises each command line option and the various corner cases. | |
199 | +-- | |
200 | +Unify archivers | |
201 | + Lots of archivers have the same general infrastructure. The directory | |
202 | + traversal code should be factored out, and the guts of each archiver could | |
203 | + be some setup code and a series of callbacks for "add this file", | |
204 | + "add this directory", "add this symlink" and so on. | |
205 | + | |
206 | + This could clean up tar and zip, and make it cheaper to add cpio and ar | |
207 | + write support, and possibly even cheaply add things like mkisofs someday, | |
208 | + if it becomes relevant. | |
209 | +--- | |
210 | +Text buffer support. | |
211 | + Several existing applets and potential additions (sort, vi, less...) read | |
212 | + a whole file into memory and act on it. There might be an opportunity | |
213 | + for shared code in there that could be moved into libbb... | |
214 | +--- | |
215 | +Individual compilation of applets. | |
216 | + It would be nice if busybox had the option to compile to individual applets, | |
217 | + for people who want an alternate implementation less bloated than the gnu | |
218 | + utils (or simply with less political baggage), but without it being one big | |
219 | + executable. | |
220 | + | |
221 | + Turning libbb into a real dll is another possibility, especially if libbb | |
222 | + could export some of the other library interfaces we've already more or less | |
223 | + got the code for (like zlib). | |
224 | +--- | |
225 | +buildroot - Make a "dogfood" option | |
226 | + Busybox is now capable of replacing most gnu packages for real world use, | |
227 | + such as developing software or in a live CD. A system built from busybox | |
228 | + (1.00 with updated sort.c), uclibc 0.9.27, gcc, binutils, make, and a few | |
229 | + other development tools (http://www.landley.net/code/firmware has an example | |
230 | + system using autoconf, automake, bison, flex, libtools, m4, zlib, | |
231 | + and groff: dunno what subset of that is actually necessary) is capable of | |
232 | + rebuilding itself, from scratch, under itself. | |
233 | + | |
234 | + It would be a good "eating our own dogfood" test if buildroot had the option | |
235 | + of using busybox instead of bzip2, coreutils, file, findutils, gawk, grep, | |
236 | + inetutils, modutils, net-tools, procps, sed, shadow, sysklogd, sysvinit, tar, | |
237 | + util-linux, and vim. Anything that's wrong with the resulting system, we | |
238 | + can fix. (It would be nice to be able to upgrade busybox to be able to | |
239 | + replace bash, diffutils, gzip, less, and patch as well.) | |
240 | diff -Nur busybox-1.00/applets/busybox.c busybox/applets/busybox.c | |
241 | --- busybox-1.00/applets/busybox.c 2004-03-15 09:28:15.000000000 +0100 | |
242 | +++ busybox/applets/busybox.c 2005-06-04 08:20:20.000000000 +0200 | |
243 | @@ -144,25 +144,25 @@ | |
244 | output_width -= 20; | |
245 | #endif | |
246 | ||
247 | - fprintf(stderr, "%s\n\n" | |
248 | - "Usage: busybox [function] [arguments]...\n" | |
249 | - " or: [function] [arguments]...\n\n" | |
250 | - "\tBusyBox is a multi-call binary that combines many common Unix\n" | |
251 | - "\tutilities into a single executable. Most people will create a\n" | |
252 | - "\tlink to busybox for each function they wish to use, and BusyBox\n" | |
253 | - "\twill act like whatever it was invoked as.\n" | |
254 | - "\nCurrently defined functions:\n", bb_msg_full_version); | |
255 | + printf("%s\n\n" | |
256 | + "Usage: busybox [function] [arguments]...\n" | |
257 | + " or: [function] [arguments]...\n\n" | |
258 | + "\tBusyBox is a multi-call binary that combines many common Unix\n" | |
259 | + "\tutilities into a single executable. Most people will create a\n" | |
260 | + "\tlink to busybox for each function they wish to use and BusyBox\n" | |
261 | + "\twill act like whatever it was invoked as!\n" | |
262 | + "\nCurrently defined functions:\n", bb_msg_full_version); | |
263 | ||
264 | while (a->name != 0) { | |
265 | col += | |
266 | - fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "), | |
267 | - (a++)->name); | |
268 | + printf("%s%s", ((col == 0) ? "\t" : ", "), | |
269 | + (a++)->name); | |
270 | if (col > output_width && a->name != 0) { | |
271 | - fprintf(stderr, ",\n"); | |
272 | + printf(",\n"); | |
273 | col = 0; | |
274 | } | |
275 | } | |
276 | - fprintf(stderr, "\n\n"); | |
277 | + printf("\n\n"); | |
278 | exit(0); | |
279 | } | |
280 | ||
281 | diff -Nur busybox-1.00/archival/ar.c busybox/archival/ar.c | |
282 | --- busybox-1.00/archival/ar.c 2004-10-07 02:35:59.000000000 +0200 | |
283 | +++ busybox/archival/ar.c 2005-06-04 08:20:08.000000000 +0200 | |
284 | @@ -56,19 +56,21 @@ | |
285 | #define AR_OPT_PRESERVE_DATE 0x08 | |
286 | #define AR_OPT_VERBOSE 0x10 | |
287 | #define AR_OPT_CREATE 0x20 | |
288 | +#define AR_OPT_INSERT 0x40 | |
289 | ||
290 | extern int ar_main(int argc, char **argv) | |
291 | { | |
292 | archive_handle_t *archive_handle; | |
293 | unsigned long opt; | |
294 | + char *msg_unsupported_err = "Archive %s not supported. Install binutils 'ar'."; | |
295 | char magic[8]; | |
296 | ||
297 | archive_handle = init_handle(); | |
298 | ||
299 | bb_opt_complementaly = "p~tx:t~px:x~pt"; | |
300 | - opt = bb_getopt_ulflags(argc, argv, "ptxovc"); | |
301 | + opt = bb_getopt_ulflags(argc, argv, "ptxovcr"); | |
302 | ||
303 | - if ((opt & 0x80000000UL) || (optind == argc)) { | |
304 | + if ((opt & BB_GETOPT_ERROR) || (opt == 0) || (optind == argc)) { | |
305 | bb_show_usage(); | |
306 | } | |
307 | ||
308 | @@ -88,7 +90,10 @@ | |
309 | archive_handle->action_header = header_verbose_list_ar; | |
310 | } | |
311 | if (opt & AR_OPT_CREATE) { | |
312 | - bb_error_msg_and_die("Archive creation not supported. Install binutils 'ar'."); | |
313 | + bb_error_msg_and_die(msg_unsupported_err, "creation"); | |
314 | + } | |
315 | + if (opt & AR_OPT_INSERT) { | |
316 | + bb_error_msg_and_die(msg_unsupported_err, "insertion"); | |
317 | } | |
318 | ||
319 | archive_handle->src_fd = bb_xopen(argv[optind++], O_RDONLY); | |
320 | diff -Nur busybox-1.00/archival/dpkg.c busybox/archival/dpkg.c | |
321 | --- busybox-1.00/archival/dpkg.c 2004-04-14 19:51:08.000000000 +0200 | |
322 | +++ busybox/archival/dpkg.c 2005-06-04 08:20:08.000000000 +0200 | |
323 | @@ -58,7 +58,7 @@ | |
324 | * I estimate it should be at least 50% bigger than PACKAGE_HASH_PRIME, | |
325 | * as there a lot of duplicate version numbers */ | |
326 | #define NAME_HASH_PRIME 16381 | |
327 | -char *name_hashtable[NAME_HASH_PRIME + 1]; | |
328 | +static char *name_hashtable[NAME_HASH_PRIME + 1]; | |
329 | ||
330 | /* PACKAGE_HASH_PRIME, Maximum number of unique packages, | |
331 | * It must not be smaller than STATUS_HASH_PRIME, | |
332 | @@ -82,7 +82,7 @@ | |
333 | unsigned int num_of_edges:14; | |
334 | edge_t **edge; | |
335 | } common_node_t; | |
336 | -common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1]; | |
337 | +static common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1]; | |
338 | ||
339 | /* Currently it doesnt store packages that have state-status of not-installed | |
340 | * So it only really has to be the size of the maximum number of packages | |
341 | @@ -92,7 +92,7 @@ | |
342 | unsigned int package:14; /* has to fit PACKAGE_HASH_PRIME */ | |
343 | unsigned int status:14; /* has to fit STATUS_HASH_PRIME */ | |
344 | } status_node_t; | |
345 | -status_node_t *status_hashtable[STATUS_HASH_PRIME + 1]; | |
346 | +static status_node_t *status_hashtable[STATUS_HASH_PRIME + 1]; | |
347 | ||
348 | /* Even numbers are for 'extras', like ored dependencies or null */ | |
349 | enum edge_type_e { | |
350 | @@ -137,7 +137,7 @@ | |
351 | } deb_file_t; | |
352 | ||
353 | ||
354 | -void make_hash(const char *key, unsigned int *start, unsigned int *decrement, const int hash_prime) | |
355 | +static void make_hash(const char *key, unsigned int *start, unsigned int *decrement, const int hash_prime) | |
356 | { | |
357 | unsigned long int hash_num = key[0]; | |
358 | int len = strlen(key); | |
359 | @@ -157,7 +157,7 @@ | |
360 | } | |
361 | ||
362 | /* this adds the key to the hash table */ | |
363 | -int search_name_hashtable(const char *key) | |
364 | +static int search_name_hashtable(const char *key) | |
365 | { | |
366 | unsigned int probe_address = 0; | |
367 | unsigned int probe_decrement = 0; | |
368 | @@ -181,7 +181,7 @@ | |
369 | /* this DOESNT add the key to the hashtable | |
370 | * TODO make it consistent with search_name_hashtable | |
371 | */ | |
372 | -unsigned int search_status_hashtable(const char *key) | |
373 | +static unsigned int search_status_hashtable(const char *key) | |
374 | { | |
375 | unsigned int probe_address = 0; | |
376 | unsigned int probe_decrement = 0; | |
377 | @@ -201,7 +201,7 @@ | |
378 | } | |
379 | ||
380 | /* Need to rethink version comparison, maybe the official dpkg has something i can use ? */ | |
381 | -int version_compare_part(const char *version1, const char *version2) | |
382 | +static int version_compare_part(const char *version1, const char *version2) | |
383 | { | |
384 | int upstream_len1 = 0; | |
385 | int upstream_len2 = 0; | |
386 | @@ -268,7 +268,7 @@ | |
387 | * if ver1 = ver2 return 0, | |
388 | * if ver1 > ver2 return 1, | |
389 | */ | |
390 | -int version_compare(const unsigned int ver1, const unsigned int ver2) | |
391 | +static int version_compare(const unsigned int ver1, const unsigned int ver2) | |
392 | { | |
393 | char *ch_ver1 = name_hashtable[ver1]; | |
394 | char *ch_ver2 = name_hashtable[ver2]; | |
395 | @@ -330,7 +330,7 @@ | |
396 | return(version_compare_part(deb_ver1, deb_ver2)); | |
397 | } | |
398 | ||
399 | -int test_version(const unsigned int version1, const unsigned int version2, const unsigned int operator) | |
400 | +static int test_version(const unsigned int version1, const unsigned int version2, const unsigned int operator) | |
401 | { | |
402 | const int version_result = version_compare(version1, version2); | |
403 | switch(operator) { | |
404 | @@ -366,7 +366,7 @@ | |
405 | } | |
406 | ||
407 | ||
408 | -int search_package_hashtable(const unsigned int name, const unsigned int version, const unsigned int operator) | |
409 | +static int search_package_hashtable(const unsigned int name, const unsigned int version, const unsigned int operator) | |
410 | { | |
411 | unsigned int probe_address = 0; | |
412 | unsigned int probe_decrement = 0; | |
413 | @@ -405,7 +405,7 @@ | |
414 | * FIXME: I don't think this is very efficient, but I thought I'd keep | |
415 | * it simple for now until it proves to be a problem. | |
416 | */ | |
417 | -int search_for_provides(int needle, int start_at) { | |
418 | +static int search_for_provides(int needle, int start_at) { | |
419 | int i, j; | |
420 | common_node_t *p; | |
421 | for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) { | |
422 | @@ -421,7 +421,7 @@ | |
423 | /* | |
424 | * Add an edge to a node | |
425 | */ | |
426 | -void add_edge_to_node(common_node_t *node, edge_t *edge) | |
427 | +static void add_edge_to_node(common_node_t *node, edge_t *edge) | |
428 | { | |
429 | node->num_of_edges++; | |
430 | node->edge = xrealloc(node->edge, sizeof(edge_t) * (node->num_of_edges + 1)); | |
431 | @@ -438,7 +438,7 @@ | |
432 | * field contains the number of EDGE nodes which follow as part of | |
433 | * this alternative. | |
434 | */ | |
435 | -void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type) | |
436 | +static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type) | |
437 | { | |
438 | char *line = bb_xstrdup(whole_line); | |
439 | char *line2; | |
440 | @@ -537,7 +537,7 @@ | |
441 | return; | |
442 | } | |
443 | ||
444 | -void free_package(common_node_t *node) | |
445 | +static void free_package(common_node_t *node) | |
446 | { | |
447 | unsigned short i; | |
448 | if (node) { | |
449 | @@ -550,7 +550,7 @@ | |
450 | } | |
451 | } | |
452 | ||
453 | -unsigned int fill_package_struct(char *control_buffer) | |
454 | +static unsigned int fill_package_struct(char *control_buffer) | |
455 | { | |
456 | common_node_t *new_node = (common_node_t *) xcalloc(1, sizeof(common_node_t)); | |
457 | const char *field_names[] = { "Package", "Version", "Pre-Depends", "Depends", | |
458 | @@ -624,7 +624,7 @@ | |
459 | } | |
460 | ||
461 | /* if num = 1, it returns the want status, 2 returns flag, 3 returns status */ | |
462 | -unsigned int get_status(const unsigned int status_node, const int num) | |
463 | +static unsigned int get_status(const unsigned int status_node, const int num) | |
464 | { | |
465 | char *status_string = name_hashtable[status_hashtable[status_node]->status]; | |
466 | char *state_sub_string; | |
467 | @@ -646,7 +646,7 @@ | |
468 | return(state_sub_num); | |
469 | } | |
470 | ||
471 | -void set_status(const unsigned int status_node_num, const char *new_value, const int position) | |
472 | +static void set_status(const unsigned int status_node_num, const char *new_value, const int position) | |
473 | { | |
474 | const unsigned int new_value_len = strlen(new_value); | |
475 | const unsigned int new_value_num = search_name_hashtable(new_value); | |
476 | @@ -682,7 +682,7 @@ | |
477 | return; | |
478 | } | |
479 | ||
480 | -const char *describe_status(int status_num) { | |
481 | +static const char *describe_status(int status_num) { | |
482 | int status_want, status_state ; | |
483 | if ( status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0 ) | |
484 | return "is not installed or flagged to be installed\n"; | |
485 | @@ -707,7 +707,7 @@ | |
486 | } | |
487 | ||
488 | ||
489 | -void index_status_file(const char *filename) | |
490 | +static void index_status_file(const char *filename) | |
491 | { | |
492 | FILE *status_file; | |
493 | char *control_buffer; | |
494 | @@ -812,7 +812,7 @@ | |
495 | } | |
496 | #endif | |
497 | ||
498 | -void write_buffer_no_status(FILE *new_status_file, const char *control_buffer) | |
499 | +static void write_buffer_no_status(FILE *new_status_file, const char *control_buffer) | |
500 | { | |
501 | char *name; | |
502 | char *value; | |
503 | @@ -830,7 +830,7 @@ | |
504 | } | |
505 | ||
506 | /* This could do with a cleanup */ | |
507 | -void write_status_file(deb_file_t **deb_file) | |
508 | +static void write_status_file(deb_file_t **deb_file) | |
509 | { | |
510 | FILE *old_status_file = bb_xfopen("/var/lib/dpkg/status", "r"); | |
511 | FILE *new_status_file = bb_xfopen("/var/lib/dpkg/status.udeb", "w"); | |
512 | @@ -978,7 +978,7 @@ | |
513 | * which a regular depends can be satisfied by a package which we want | |
514 | * to install. | |
515 | */ | |
516 | -int package_satisfies_dependency(int package, int depend_type) | |
517 | +static int package_satisfies_dependency(int package, int depend_type) | |
518 | { | |
519 | int status_num = search_status_hashtable(name_hashtable[package_hashtable[package]->name]); | |
520 | ||
521 | @@ -995,7 +995,7 @@ | |
522 | return 0; | |
523 | } | |
524 | ||
525 | -int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count) | |
526 | +static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count) | |
527 | { | |
528 | int *conflicts = NULL; | |
529 | int conflicts_num = 0; | |
530 | @@ -1204,7 +1204,7 @@ | |
531 | return(TRUE); | |
532 | } | |
533 | ||
534 | -char **create_list(const char *filename) | |
535 | +static char **create_list(const char *filename) | |
536 | { | |
537 | FILE *list_stream; | |
538 | char **file_list = NULL; | |
539 | @@ -1233,7 +1233,7 @@ | |
540 | } | |
541 | ||
542 | /* maybe i should try and hook this into remove_file.c somehow */ | |
543 | -int remove_file_array(char **remove_names, char **exclude_names) | |
544 | +static int remove_file_array(char **remove_names, char **exclude_names) | |
545 | { | |
546 | struct stat path_stat; | |
547 | int match_flag; | |
548 | @@ -1271,7 +1271,7 @@ | |
549 | return(remove_flag); | |
550 | } | |
551 | ||
552 | -int run_package_script(const char *package_name, const char *script_type) | |
553 | +static int run_package_script(const char *package_name, const char *script_type) | |
554 | { | |
555 | struct stat path_stat; | |
556 | char *script_path; | |
557 | @@ -1290,10 +1290,10 @@ | |
558 | return(result); | |
559 | } | |
560 | ||
561 | -const char *all_control_files[] = {"preinst", "postinst", "prerm", "postrm", | |
562 | +static const char *all_control_files[] = {"preinst", "postinst", "prerm", "postrm", | |
563 | "list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL }; | |
564 | ||
565 | -char **all_control_list(const char *package_name) | |
566 | +static char **all_control_list(const char *package_name) | |
567 | { | |
568 | unsigned short i = 0; | |
569 | char **remove_files; | |
570 | @@ -1310,7 +1310,7 @@ | |
571 | return(remove_files); | |
572 | } | |
573 | ||
574 | -void free_array(char **array) | |
575 | +static void free_array(char **array) | |
576 | { | |
577 | ||
578 | if (array) { | |
579 | @@ -1327,7 +1327,7 @@ | |
580 | * the status_hashtable to retrieve the info. This results in smaller code than | |
581 | * scanning the status file. The resulting list, however, is unsorted. | |
582 | */ | |
583 | -void list_packages(void) | |
584 | +static void list_packages(void) | |
585 | { | |
586 | int i; | |
587 | ||
588 | @@ -1364,7 +1364,7 @@ | |
589 | } | |
590 | } | |
591 | ||
592 | -void remove_package(const unsigned int package_num, int noisy) | |
593 | +static void remove_package(const unsigned int package_num, int noisy) | |
594 | { | |
595 | const char *package_name = name_hashtable[package_hashtable[package_num]->name]; | |
596 | const char *package_version = name_hashtable[package_hashtable[package_num]->version]; | |
597 | @@ -1418,7 +1418,7 @@ | |
598 | set_status(status_num, "config-files", 3); | |
599 | } | |
600 | ||
601 | -void purge_package(const unsigned int package_num) | |
602 | +static void purge_package(const unsigned int package_num) | |
603 | { | |
604 | const char *package_name = name_hashtable[package_hashtable[package_num]->name]; | |
605 | const char *package_version = name_hashtable[package_hashtable[package_num]->version]; | |
606 | @@ -1614,7 +1614,7 @@ | |
607 | free(info_prefix); | |
608 | } | |
609 | ||
610 | -void configure_package(deb_file_t *deb_file) | |
611 | +static void configure_package(deb_file_t *deb_file) | |
612 | { | |
613 | const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name]; | |
614 | const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version]; | |
615 | diff -Nur busybox-1.00/archival/dpkg_deb.c busybox/archival/dpkg_deb.c | |
616 | --- busybox-1.00/archival/dpkg_deb.c 2004-03-15 09:28:16.000000000 +0100 | |
617 | +++ busybox/archival/dpkg_deb.c 2005-06-04 08:20:08.000000000 +0200 | |
618 | @@ -88,7 +88,7 @@ | |
619 | argcount = 2; | |
620 | } | |
621 | ||
622 | - if ((optind + argcount != argc) || (opt & 0x80000000UL)) { | |
623 | + if ((optind + argcount != argc) || (opt & BB_GETOPT_ERROR)) { | |
624 | bb_show_usage(); | |
625 | } | |
626 | ||
627 | diff -Nur busybox-1.00/archival/gzip.c busybox/archival/gzip.c | |
628 | --- busybox-1.00/archival/gzip.c 2004-04-14 19:51:08.000000000 +0200 | |
629 | +++ busybox/archival/gzip.c 2005-06-04 08:20:08.000000000 +0200 | |
630 | @@ -51,12 +51,6 @@ | |
631 | #include <time.h> | |
632 | #include "busybox.h" | |
633 | ||
634 | -#define memzero(s, n) memset ((void *)(s), 0, (n)) | |
635 | - | |
636 | -#ifndef RETSIGTYPE | |
637 | -# define RETSIGTYPE void | |
638 | -#endif | |
639 | - | |
640 | typedef unsigned char uch; | |
641 | typedef unsigned short ush; | |
642 | typedef unsigned long ulg; | |
643 | @@ -214,9 +208,6 @@ | |
644 | static int zip(int in, int out); | |
645 | static int file_read(char *buf, unsigned size); | |
646 | ||
647 | - /* from gzip.c */ | |
648 | -static RETSIGTYPE abort_gzip(void); | |
649 | - | |
650 | /* from deflate.c */ | |
651 | static void lm_init(ush * flags); | |
652 | static ulg deflate(void); | |
653 | @@ -335,7 +326,7 @@ | |
654 | /* ======================================================================== | |
655 | * Signal and error handler. | |
656 | */ | |
657 | -static void abort_gzip() | |
658 | +static void abort_gzip(int ignored) | |
659 | { | |
660 | exit(ERROR); | |
661 | } | |
662 | @@ -350,13 +341,6 @@ | |
663 | bytes_in = 0L; | |
664 | } | |
665 | ||
666 | -static void write_bb_error_msg(void) | |
667 | -{ | |
668 | - fputc('\n', stderr); | |
669 | - bb_perror_nomsg(); | |
670 | - abort_gzip(); | |
671 | -} | |
672 | - | |
673 | /* =========================================================================== | |
674 | * Does the same as write(), but also handles partial pipe writes and checks | |
675 | * for error return. | |
676 | @@ -366,9 +350,7 @@ | |
677 | unsigned n; | |
678 | ||
679 | while ((n = write(fd, buf, cnt)) != cnt) { | |
680 | - if (n == (unsigned) (-1)) { | |
681 | - write_bb_error_msg(); | |
682 | - } | |
683 | + if (n == (unsigned) (-1)) bb_error_msg_and_die("can't write"); | |
684 | cnt -= n; | |
685 | buf = (void *) ((char *) buf + n); | |
686 | } | |
687 | @@ -559,7 +541,7 @@ | |
688 | /* =========================================================================== | |
689 | * Write out any remaining bits in an incomplete byte. | |
690 | */ | |
691 | -static void bi_windup() | |
692 | +static void bi_windup(void) | |
693 | { | |
694 | if (bi_valid > 8) { | |
695 | put_short(bi_buf); | |
696 | @@ -846,7 +828,7 @@ | |
697 | register unsigned j; | |
698 | ||
699 | /* Initialize the hash table. */ | |
700 | - memzero((char *) head, HASH_SIZE * sizeof(*head)); | |
701 | + memset(head, 0, HASH_SIZE * sizeof(*head)); | |
702 | /* prev will be initialized on the fly */ | |
703 | ||
704 | *flags |= SLOW; | |
705 | @@ -996,7 +978,7 @@ | |
706 | * file reads are performed for at least two bytes (required for the | |
707 | * translate_eol option). | |
708 | */ | |
709 | -static void fill_window() | |
710 | +static void fill_window(void) | |
711 | { | |
712 | register unsigned n, m; | |
713 | unsigned more = | |
714 | @@ -1060,7 +1042,7 @@ | |
715 | * evaluation for matches: a match is finally adopted only if there is | |
716 | * no better match at the next window position. | |
717 | */ | |
718 | -static ulg deflate() | |
719 | +static ulg deflate(void) | |
720 | { | |
721 | IPos hash_head; /* head of hash chain */ | |
722 | IPos prev_match; /* previous match */ | |
723 | @@ -1188,8 +1170,6 @@ | |
724 | ||
725 | typedef struct dirent dir_type; | |
726 | ||
727 | -typedef RETSIGTYPE(*sig_type) (int); | |
728 | - | |
729 | /* ======================================================================== */ | |
730 | int gzip_main(int argc, char **argv) | |
731 | { | |
732 | @@ -1235,16 +1215,16 @@ | |
733 | ||
734 | foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; | |
735 | if (foreground) { | |
736 | - (void) signal(SIGINT, (sig_type) abort_gzip); | |
737 | + (void) signal(SIGINT, abort_gzip); | |
738 | } | |
739 | #ifdef SIGTERM | |
740 | if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { | |
741 | - (void) signal(SIGTERM, (sig_type) abort_gzip); | |
742 | + (void) signal(SIGTERM, abort_gzip); | |
743 | } | |
744 | #endif | |
745 | #ifdef SIGHUP | |
746 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { | |
747 | - (void) signal(SIGHUP, (sig_type) abort_gzip); | |
748 | + (void) signal(SIGHUP, abort_gzip); | |
749 | } | |
750 | #endif | |
751 | ||
752 | @@ -1271,6 +1251,7 @@ | |
753 | for (i = optind; i < argc; i++) { | |
754 | char *path = NULL; | |
755 | ||
756 | + clear_bufs(); | |
757 | if (strcmp(argv[i], "-") == 0) { | |
758 | time_stamp = 0; | |
759 | ifile_size = -1L; | |
760 | @@ -1749,7 +1730,7 @@ | |
761 | /* =========================================================================== | |
762 | * Initialize a new block. | |
763 | */ | |
764 | -static void init_block() | |
765 | +static void init_block(void) | |
766 | { | |
767 | int n; /* iterates over tree elements */ | |
768 | ||
769 | @@ -2162,7 +2143,7 @@ | |
770 | * Construct the Huffman tree for the bit lengths and return the index in | |
771 | * bl_order of the last bit length code to send. | |
772 | */ | |
773 | -static const int build_bl_tree() | |
774 | +static int build_bl_tree(void) | |
775 | { | |
776 | int max_blindex; /* index of last bit length code of non zero freq */ | |
777 | ||
778 | @@ -2425,7 +2406,7 @@ | |
779 | * IN assertion: the fields freq of dyn_ltree are set and the total of all | |
780 | * frequencies does not exceed 64K (to fit in an int on 16 bit machines). | |
781 | */ | |
782 | -static void set_file_type() | |
783 | +static void set_file_type(void) | |
784 | { | |
785 | int n = 0; | |
786 | unsigned ascii_freq = 0; | |
787 | @@ -2538,7 +2519,7 @@ | |
788 | * Write the output buffer outbuf[0..outcnt-1] and update bytes_out. | |
789 | * (used for the compressed data only) | |
790 | */ | |
791 | -static void flush_outbuf() | |
792 | +static void flush_outbuf(void) | |
793 | { | |
794 | if (outcnt == 0) | |
795 | return; | |
796 | diff -Nur busybox-1.00/archival/libunarchive/archive_xread_all_eof.c busybox/archival/libunarchive/archive_xread_all_eof.c | |
797 | --- busybox-1.00/archival/libunarchive/archive_xread_all_eof.c 2003-11-21 23:24:48.000000000 +0100 | |
798 | +++ busybox/archival/libunarchive/archive_xread_all_eof.c 2005-06-04 08:20:08.000000000 +0200 | |
799 | @@ -26,7 +26,7 @@ | |
800 | ||
801 | size = bb_full_read(archive_handle->src_fd, buf, count); | |
802 | if ((size != 0) && (size != count)) { | |
803 | - bb_perror_msg_and_die("Short read, read %d of %d", size, count); | |
804 | + bb_perror_msg_and_die("Short read, read %ld of %ld", (long)size, (long)count); | |
805 | } | |
806 | return(size); | |
807 | } | |
808 | diff -Nur busybox-1.00/archival/libunarchive/check_header_gzip.c busybox/archival/libunarchive/check_header_gzip.c | |
809 | --- busybox-1.00/archival/libunarchive/check_header_gzip.c 2003-03-19 10:11:25.000000000 +0100 | |
810 | +++ busybox/archival/libunarchive/check_header_gzip.c 2005-06-04 08:20:08.000000000 +0200 | |
811 | @@ -1,6 +1,7 @@ | |
812 | #include <stdlib.h> | |
813 | #include <unistd.h> | |
814 | #include "libbb.h" | |
815 | +#include "unarchive.h" /* for external decl of check_header_gzip */ | |
816 | ||
817 | extern void check_header_gzip(int src_fd) | |
818 | { | |
819 | diff -Nur busybox-1.00/archival/libunarchive/decompress_bunzip2.c busybox/archival/libunarchive/decompress_bunzip2.c | |
820 | --- busybox-1.00/archival/libunarchive/decompress_bunzip2.c 2004-08-28 02:43:05.000000000 +0200 | |
821 | +++ busybox/archival/libunarchive/decompress_bunzip2.c 2005-06-04 08:20:08.000000000 +0200 | |
822 | @@ -134,8 +134,6 @@ | |
823 | ||
824 | static int get_next_block(bunzip_data *bd) | |
825 | { | |
826 | - /* Note: Ignore the warning about hufGroup, base and limit being used uninitialized. | |
827 | - * They will be initialized on the fist pass of the loop. */ | |
828 | struct group_data *hufGroup; | |
829 | int dbufCount,nextSym,dbufSize,groupCount,*base,*limit,selector, | |
830 | i,j,k,t,runPos,symCount,symTotal,nSelectors,byteCount[256]; | |
831 | @@ -286,16 +284,15 @@ | |
832 | mtfSymbol[i]=(unsigned char)i; | |
833 | } | |
834 | /* Loop through compressed symbols. */ | |
835 | - runPos=dbufCount=symCount=selector=0; | |
836 | + runPos=dbufCount=selector=0; | |
837 | for(;;) { | |
838 | - /* Determine which Huffman coding group to use. */ | |
839 | - if(!(symCount--)) { | |
840 | - symCount=GROUP_SIZE-1; | |
841 | - if(selector>=nSelectors) return RETVAL_DATA_ERROR; | |
842 | - hufGroup=bd->groups+selectors[selector++]; | |
843 | - base=hufGroup->base-1; | |
844 | - limit=hufGroup->limit-1; | |
845 | - } | |
846 | + /* fetch next Huffman coding group from list. */ | |
847 | + symCount=GROUP_SIZE-1; | |
848 | + if(selector>=nSelectors) return RETVAL_DATA_ERROR; | |
849 | + hufGroup=bd->groups+selectors[selector++]; | |
850 | + base=hufGroup->base-1; | |
851 | + limit=hufGroup->limit-1; | |
852 | +continue_this_group: | |
853 | /* Read next Huffman-coded symbol. */ | |
854 | /* Note: It is far cheaper to read maxLen bits and back up than it is | |
855 | to read minLen bits and then an additional bit at a time, testing | |
856 | @@ -346,7 +343,7 @@ | |
857 | context). Thus space is saved. */ | |
858 | t += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */ | |
859 | runPos <<= 1; | |
860 | - continue; | |
861 | + goto end_of_huffman_loop; | |
862 | } | |
863 | /* When we hit the first non-run symbol after a run, we now know | |
864 | how many times to repeat the last literal, so append that many | |
865 | @@ -384,6 +381,10 @@ | |
866 | /* We have our literal byte. Save it into dbuf. */ | |
867 | byteCount[uc]++; | |
868 | dbuf[dbufCount++] = (unsigned int)uc; | |
869 | + /* Skip group initialization if we're not done with this group. Done this | |
870 | + * way to avoid compiler warning. */ | |
871 | +end_of_huffman_loop: | |
872 | + if(symCount--) goto continue_this_group; | |
873 | } | |
874 | /* At this point, we've read all the Huffman-coded symbols (and repeated | |
875 | runs) for this block from the input stream, and decoded them into the | |
876 | diff -Nur busybox-1.00/archival/libunarchive/decompress_uncompress.c busybox/archival/libunarchive/decompress_uncompress.c | |
877 | --- busybox-1.00/archival/libunarchive/decompress_uncompress.c 2004-04-14 19:51:08.000000000 +0200 | |
878 | +++ busybox/archival/libunarchive/decompress_uncompress.c 2005-06-04 08:20:08.000000000 +0200 | |
879 | @@ -65,23 +65,23 @@ | |
880 | #define MAXCODE(n) (1L << (n)) | |
881 | ||
882 | /* Block compress mode -C compatible with 2.0 */ | |
883 | -int block_mode = BLOCK_MODE; | |
884 | +static int block_mode = BLOCK_MODE; | |
885 | ||
886 | /* user settable max # bits/code */ | |
887 | -int maxbits = BITS; | |
888 | +static int maxbits = BITS; | |
889 | ||
890 | /* Exitcode of compress (-1 no file compressed) */ | |
891 | -int exit_code = -1; | |
892 | +static int exit_code = -1; | |
893 | ||
894 | /* Input buffer */ | |
895 | -unsigned char inbuf[IBUFSIZ + 64]; | |
896 | +static unsigned char inbuf[IBUFSIZ + 64]; | |
897 | ||
898 | /* Output buffer */ | |
899 | -unsigned char outbuf[OBUFSIZ + 2048]; | |
900 | +static unsigned char outbuf[OBUFSIZ + 2048]; | |
901 | ||
902 | ||
903 | -long int htab[HSIZE]; | |
904 | -unsigned short codetab[HSIZE]; | |
905 | +static long int htab[HSIZE]; | |
906 | +static unsigned short codetab[HSIZE]; | |
907 | ||
908 | #define htabof(i) htab[i] | |
909 | #define codetabof(i) codetab[i] | |
910 | diff -Nur busybox-1.00/archival/libunarchive/decompress_unzip.c busybox/archival/libunarchive/decompress_unzip.c | |
911 | --- busybox-1.00/archival/libunarchive/decompress_unzip.c 2004-04-25 07:11:13.000000000 +0200 | |
912 | +++ busybox/archival/libunarchive/decompress_unzip.c 2005-06-04 08:20:08.000000000 +0200 | |
913 | @@ -151,7 +151,10 @@ | |
914 | /* Leave the first 4 bytes empty so we can always unwind the bitbuffer | |
915 | * to the front of the bytebuffer, leave 4 bytes free at end of tail | |
916 | * so we can easily top up buffer in check_trailer_gzip() */ | |
917 | - bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8); | |
918 | + if (!(bytebuffer_size = bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8))) { | |
919 | + bb_error_msg_and_die("unexpected end of file"); | |
920 | + } | |
921 | + bytebuffer_size += 4; | |
922 | bytebuffer_offset = 4; | |
923 | } | |
924 | bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current; | |
925 | diff -Nur busybox-1.00/archival/rpm.c busybox/archival/rpm.c | |
926 | --- busybox-1.00/archival/rpm.c 2004-03-15 09:28:16.000000000 +0100 | |
927 | +++ busybox/archival/rpm.c 2005-06-04 08:20:08.000000000 +0200 | |
928 | @@ -260,12 +260,16 @@ | |
929 | int bsearch_rpmtag(const void *key, const void *item) | |
930 | { | |
931 | rpm_index **tmp = (rpm_index **) item; | |
932 | + /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... | |
933 | + * it's ok to ignore it because this isn't a 'real' pointer */ | |
934 | return ((int) key - tmp[0]->tag); | |
935 | } | |
936 | ||
937 | int rpm_getcount(int tag) | |
938 | { | |
939 | rpm_index **found; | |
940 | + /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... | |
941 | + * it's ok to ignore it because tag won't be used as a pointer */ | |
942 | found = bsearch((void *) tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | |
943 | if (!found) return 0; | |
944 | else return found[0]->count; | |
945 | @@ -274,6 +278,8 @@ | |
946 | char *rpm_getstring(int tag, int itemindex) | |
947 | { | |
948 | rpm_index **found; | |
949 | + /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... | |
950 | + * it's ok to ignore it because tag won't be used as a pointer */ | |
951 | found = bsearch((void *) tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | |
952 | if (!found || itemindex >= found[0]->count) return NULL; | |
953 | if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) { | |
954 | @@ -288,6 +294,8 @@ | |
955 | { | |
956 | rpm_index **found; | |
957 | int n, *tmpint; | |
958 | + /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... | |
959 | + * it's ok to ignore it because tag won't be used as a pointer */ | |
960 | found = bsearch((void *) tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | |
961 | if (!found || itemindex >= found[0]->count) return -1; | |
962 | tmpint = (int *) (map + found[0]->offset); | |
963 | diff -Nur busybox-1.00/archival/rpm2cpio.c busybox/archival/rpm2cpio.c | |
964 | --- busybox-1.00/archival/rpm2cpio.c 2004-03-27 11:02:41.000000000 +0100 | |
965 | +++ busybox/archival/rpm2cpio.c 2005-06-04 08:20:08.000000000 +0200 | |
966 | @@ -48,7 +48,7 @@ | |
967 | uint32_t size; /* Size of store (4 bytes) */ | |
968 | }; | |
969 | ||
970 | -void skip_header(int rpm_fd) | |
971 | +static void skip_header(int rpm_fd) | |
972 | { | |
973 | struct rpm_header header; | |
974 | ||
975 | diff -Nur busybox-1.00/archival/tar.c busybox/archival/tar.c | |
976 | --- busybox-1.00/archival/tar.c 2004-08-27 00:18:56.000000000 +0200 | |
977 | +++ busybox/archival/tar.c 2005-06-04 08:20:08.000000000 +0200 | |
978 | @@ -724,7 +724,7 @@ | |
979 | ); | |
980 | ||
981 | /* Check one and only one context option was given */ | |
982 | - if(opt & 0x80000000UL) { | |
983 | + if(opt & BB_GETOPT_ERROR) { | |
984 | bb_show_usage(); | |
985 | } | |
986 | #ifdef CONFIG_FEATURE_TAR_CREATE | |
987 | diff -Nur busybox-1.00/coreutils/Config.in busybox/coreutils/Config.in | |
988 | --- busybox-1.00/coreutils/Config.in 2004-08-11 04:45:47.000000000 +0200 | |
989 | +++ busybox/coreutils/Config.in 2005-06-04 08:20:13.000000000 +0200 | |
990 | @@ -59,6 +59,13 @@ | |
991 | cmp is used to compare two files and returns the result | |
992 | to standard output. | |
993 | ||
994 | +config CONFIG_COMM | |
995 | + bool "comm" | |
996 | + default n | |
997 | + help | |
998 | + comm is used to compare two files line by line and return | |
999 | + a three-column output. | |
1000 | + | |
1001 | config CONFIG_CP | |
1002 | bool "cp" | |
1003 | default n | |
1004 | @@ -164,6 +171,12 @@ | |
1005 | a command; without options it displays the current | |
1006 | environment. | |
1007 | ||
1008 | +config CONFIG_PRINTENV | |
1009 | + bool "printenv" | |
1010 | + default n | |
1011 | + help | |
1012 | + printenv is used to print all or part of environment. | |
1013 | + | |
1014 | config CONFIG_EXPR | |
1015 | bool "expr" | |
1016 | default n | |
1017 | @@ -329,6 +342,12 @@ | |
1018 | help | |
1019 | mv is used to move or rename files or directories. | |
1020 | ||
1021 | +config CONFIG_NICE | |
1022 | + bool "nice" | |
1023 | + default n | |
1024 | + help | |
1025 | + nice runs a program with modified scheduling priority. | |
1026 | + | |
1027 | config CONFIG_OD | |
1028 | bool "od" | |
1029 | default n | |
1030 | @@ -398,12 +417,45 @@ | |
1031 | help | |
1032 | sort is used to sort lines of text in specified files. | |
1033 | ||
1034 | +config CONFIG_SORT_BIG | |
1035 | + bool " full SuSv3 compliant sort (Support -ktcsbdfiozgM)" | |
1036 | + default y | |
1037 | + depends on CONFIG_SORT | |
1038 | + help | |
1039 | + Without this, sort only supports -r, -u, and an integer version | |
1040 | + of -n. Selecting this adds sort keys, floating point support, and | |
1041 | + more. This adds a little over 3k to a nonstatic build on x86. | |
1042 | + | |
1043 | + The SuSv3 sort standard is available at: | |
1044 | + http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html | |
1045 | + | |
1046 | +config CONFIG_STAT | |
1047 | + bool "stat" | |
1048 | + default n | |
1049 | + help | |
1050 | + display file or filesystem status. | |
1051 | + | |
1052 | +config CONFIG_FEATURE_STAT_FORMAT | |
1053 | + bool " Enable custom formats (-c)" | |
1054 | + default n | |
1055 | + depends on CONFIG_STAT | |
1056 | + help | |
1057 | + Without this, stat will not support the '-c format' option where | |
1058 | + users can pass a custom format string for output. This adds about | |
1059 | + 7k to a nonstatic build on amd64. | |
1060 | + | |
1061 | config CONFIG_STTY | |
1062 | bool "stty" | |
1063 | default n | |
1064 | help | |
1065 | stty is used to change and print terminal line settings. | |
1066 | ||
1067 | +config CONFIG_SUM | |
1068 | + bool "sum" | |
1069 | + default n | |
1070 | + help | |
1071 | + checksum and count the blocks in a file | |
1072 | + | |
1073 | config CONFIG_SYNC | |
1074 | bool "sync" | |
1075 | default n | |
1076 | diff -Nur busybox-1.00/coreutils/Makefile.in busybox/coreutils/Makefile.in | |
1077 | --- busybox-1.00/coreutils/Makefile.in 2004-10-08 09:45:14.000000000 +0200 | |
1078 | +++ busybox/coreutils/Makefile.in 2005-06-04 08:20:13.000000000 +0200 | |
1079 | @@ -24,69 +24,74 @@ | |
1080 | srcdir=$(top_srcdir)/coreutils | |
1081 | ||
1082 | COREUTILS-y:= | |
1083 | -COREUTILS-$(CONFIG_BASENAME) += basename.o | |
1084 | -COREUTILS-$(CONFIG_CAL) += cal.o | |
1085 | -COREUTILS-$(CONFIG_CAT) += cat.o | |
1086 | -COREUTILS-$(CONFIG_CHGRP) += chgrp.o | |
1087 | -COREUTILS-$(CONFIG_CHMOD) += chmod.o | |
1088 | -COREUTILS-$(CONFIG_CHOWN) += chown.o | |
1089 | -COREUTILS-$(CONFIG_CHROOT) += chroot.o | |
1090 | -COREUTILS-$(CONFIG_CMP) += cmp.o | |
1091 | -COREUTILS-$(CONFIG_CP) += cp.o | |
1092 | -COREUTILS-$(CONFIG_CUT) += cut.o | |
1093 | -COREUTILS-$(CONFIG_DATE) += date.o | |
1094 | -COREUTILS-$(CONFIG_DD) += dd.o | |
1095 | -COREUTILS-$(CONFIG_DF) += df.o | |
1096 | -COREUTILS-$(CONFIG_DIRNAME) += dirname.o | |
1097 | -COREUTILS-$(CONFIG_DOS2UNIX) += dos2unix.o | |
1098 | -COREUTILS-$(CONFIG_DU) += du.o | |
1099 | -COREUTILS-$(CONFIG_ECHO) += echo.o | |
1100 | -COREUTILS-$(CONFIG_ENV) += env.o | |
1101 | -COREUTILS-$(CONFIG_EXPR) += expr.o | |
1102 | -COREUTILS-$(CONFIG_FALSE) += false.o | |
1103 | -COREUTILS-$(CONFIG_FOLD) += fold.o | |
1104 | -COREUTILS-$(CONFIG_HEAD) += head.o | |
1105 | -COREUTILS-$(CONFIG_HOSTID) += hostid.o | |
1106 | -COREUTILS-$(CONFIG_ID) += id.o | |
1107 | -COREUTILS-$(CONFIG_INSTALL) += install.o | |
1108 | -COREUTILS-$(CONFIG_LENGTH) += length.o | |
1109 | -COREUTILS-$(CONFIG_LN) += ln.o | |
1110 | -COREUTILS-$(CONFIG_LOGNAME) += logname.o | |
1111 | -COREUTILS-$(CONFIG_LS) += ls.o | |
1112 | -COREUTILS-$(CONFIG_MD5SUM) += md5_sha1_sum.o | |
1113 | -COREUTILS-$(CONFIG_MKDIR) += mkdir.o | |
1114 | -COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o | |
1115 | -COREUTILS-$(CONFIG_MKNOD) += mknod.o | |
1116 | -COREUTILS-$(CONFIG_MV) += mv.o | |
1117 | -COREUTILS-$(CONFIG_OD) += od.o | |
1118 | -COREUTILS-$(CONFIG_PRINTF) += printf.o | |
1119 | -COREUTILS-$(CONFIG_PWD) += pwd.o | |
1120 | -COREUTILS-$(CONFIG_REALPATH) += realpath.o | |
1121 | -COREUTILS-$(CONFIG_RM) += rm.o | |
1122 | -COREUTILS-$(CONFIG_RMDIR) += rmdir.o | |
1123 | -COREUTILS-$(CONFIG_SEQ) += seq.o | |
1124 | -COREUTILS-$(CONFIG_SHA1SUM) += md5_sha1_sum.o | |
1125 | -COREUTILS-$(CONFIG_SLEEP) += sleep.o | |
1126 | -COREUTILS-$(CONFIG_SORT) += sort.o | |
1127 | -COREUTILS-$(CONFIG_STTY) += stty.o | |
1128 | -COREUTILS-$(CONFIG_SYNC) += sync.o | |
1129 | -COREUTILS-$(CONFIG_TAIL) += tail.o | |
1130 | -COREUTILS-$(CONFIG_TEE) += tee.o | |
1131 | -COREUTILS-$(CONFIG_TEST) += test.o | |
1132 | -COREUTILS-$(CONFIG_TOUCH) += touch.o | |
1133 | -COREUTILS-$(CONFIG_TR) += tr.o | |
1134 | -COREUTILS-$(CONFIG_TRUE) += true.o | |
1135 | -COREUTILS-$(CONFIG_TTY) += tty.o | |
1136 | -COREUTILS-$(CONFIG_UNAME) += uname.o | |
1137 | -COREUTILS-$(CONFIG_UNIQ) += uniq.o | |
1138 | -COREUTILS-$(CONFIG_USLEEP) += usleep.o | |
1139 | -COREUTILS-$(CONFIG_UUDECODE) += uudecode.o | |
1140 | -COREUTILS-$(CONFIG_UUENCODE) += uuencode.o | |
1141 | -COREUTILS-$(CONFIG_WATCH) += watch.o | |
1142 | -COREUTILS-$(CONFIG_WC) += wc.o | |
1143 | -COREUTILS-$(CONFIG_WHO) += who.o | |
1144 | -COREUTILS-$(CONFIG_WHOAMI) += whoami.o | |
1145 | -COREUTILS-$(CONFIG_YES) += yes.o | |
1146 | +COREUTILS-$(CONFIG_BASENAME) += basename.o | |
1147 | +COREUTILS-$(CONFIG_CAL) += cal.o | |
1148 | +COREUTILS-$(CONFIG_CAT) += cat.o | |
1149 | +COREUTILS-$(CONFIG_CHGRP) += chgrp.o | |
1150 | +COREUTILS-$(CONFIG_CHMOD) += chmod.o | |
1151 | +COREUTILS-$(CONFIG_CHOWN) += chown.o | |
1152 | +COREUTILS-$(CONFIG_CHROOT) += chroot.o | |
1153 | +COREUTILS-$(CONFIG_CMP) += cmp.o | |
1154 | +COREUTILS-$(CONFIG_COMM) += comm.o | |
1155 | +COREUTILS-$(CONFIG_CP) += cp.o | |
1156 | +COREUTILS-$(CONFIG_CUT) += cut.o | |
1157 | +COREUTILS-$(CONFIG_DATE) += date.o | |
1158 | +COREUTILS-$(CONFIG_DD) += dd.o | |
1159 | +COREUTILS-$(CONFIG_DF) += df.o | |
1160 | +COREUTILS-$(CONFIG_DIRNAME) += dirname.o | |
1161 | +COREUTILS-$(CONFIG_DOS2UNIX) += dos2unix.o | |
1162 | +COREUTILS-$(CONFIG_DU) += du.o | |
1163 | +COREUTILS-$(CONFIG_ECHO) += echo.o | |
1164 | +COREUTILS-$(CONFIG_ENV) += env.o | |
1165 | +COREUTILS-$(CONFIG_EXPR) += expr.o | |
1166 | +COREUTILS-$(CONFIG_FALSE) += false.o | |
1167 | +COREUTILS-$(CONFIG_FOLD) += fold.o | |
1168 | +COREUTILS-$(CONFIG_HEAD) += head.o | |
1169 | +COREUTILS-$(CONFIG_HOSTID) += hostid.o | |
1170 | +COREUTILS-$(CONFIG_ID) += id.o | |
1171 | +COREUTILS-$(CONFIG_INSTALL) += install.o | |
1172 | +COREUTILS-$(CONFIG_LENGTH) += length.o | |
1173 | +COREUTILS-$(CONFIG_LN) += ln.o | |
1174 | +COREUTILS-$(CONFIG_LOGNAME) += logname.o | |
1175 | +COREUTILS-$(CONFIG_LS) += ls.o | |
1176 | +COREUTILS-$(CONFIG_MD5SUM) += md5_sha1_sum.o | |
1177 | +COREUTILS-$(CONFIG_MKDIR) += mkdir.o | |
1178 | +COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o | |
1179 | +COREUTILS-$(CONFIG_MKNOD) += mknod.o | |
1180 | +COREUTILS-$(CONFIG_MV) += mv.o | |
1181 | +COREUTILS-$(CONFIG_NICE) += nice.o | |
1182 | +COREUTILS-$(CONFIG_OD) += od.o | |
1183 | +COREUTILS-$(CONFIG_PRINTENV) += printenv.o | |
1184 | +COREUTILS-$(CONFIG_PRINTF) += printf.o | |
1185 | +COREUTILS-$(CONFIG_PWD) += pwd.o | |
1186 | +COREUTILS-$(CONFIG_REALPATH) += realpath.o | |
1187 | +COREUTILS-$(CONFIG_RM) += rm.o | |
1188 | +COREUTILS-$(CONFIG_RMDIR) += rmdir.o | |
1189 | +COREUTILS-$(CONFIG_SEQ) += seq.o | |
1190 | +COREUTILS-$(CONFIG_SHA1SUM) += md5_sha1_sum.o | |
1191 | +COREUTILS-$(CONFIG_SLEEP) += sleep.o | |
1192 | +COREUTILS-$(CONFIG_SORT) += sort.o | |
1193 | +COREUTILS-$(CONFIG_STAT) += stat.o | |
1194 | +COREUTILS-$(CONFIG_STTY) += stty.o | |
1195 | +COREUTILS-$(CONFIG_SUM) += sum.o | |
1196 | +COREUTILS-$(CONFIG_SYNC) += sync.o | |
1197 | +COREUTILS-$(CONFIG_TAIL) += tail.o | |
1198 | +COREUTILS-$(CONFIG_TEE) += tee.o | |
1199 | +COREUTILS-$(CONFIG_TEST) += test.o | |
1200 | +COREUTILS-$(CONFIG_TOUCH) += touch.o | |
1201 | +COREUTILS-$(CONFIG_TR) += tr.o | |
1202 | +COREUTILS-$(CONFIG_TRUE) += true.o | |
1203 | +COREUTILS-$(CONFIG_TTY) += tty.o | |
1204 | +COREUTILS-$(CONFIG_UNAME) += uname.o | |
1205 | +COREUTILS-$(CONFIG_UNIQ) += uniq.o | |
1206 | +COREUTILS-$(CONFIG_USLEEP) += usleep.o | |
1207 | +COREUTILS-$(CONFIG_UUDECODE) += uudecode.o | |
1208 | +COREUTILS-$(CONFIG_UUENCODE) += uuencode.o | |
1209 | +COREUTILS-$(CONFIG_WATCH) += watch.o | |
1210 | +COREUTILS-$(CONFIG_WC) += wc.o | |
1211 | +COREUTILS-$(CONFIG_WHO) += who.o | |
1212 | +COREUTILS-$(CONFIG_WHOAMI) += whoami.o | |
1213 | +COREUTILS-$(CONFIG_YES) += yes.o | |
1214 | ||
1215 | libraries-y+=$(COREUTILS_DIR)$(COREUTILS_AR) | |
1216 | ||
1217 | @@ -95,4 +100,3 @@ | |
1218 | ||
1219 | $(COREUTILS_DIR)%.o: $(srcdir)/%.c | |
1220 | $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< | |
1221 | - | |
1222 | diff -Nur busybox-1.00/coreutils/comm.c busybox/coreutils/comm.c | |
1223 | --- busybox-1.00/coreutils/comm.c 1970-01-01 01:00:00.000000000 +0100 | |
1224 | +++ busybox/coreutils/comm.c 2005-06-04 08:20:13.000000000 +0200 | |
1225 | @@ -0,0 +1,144 @@ | |
1226 | +/* vi: set sw=4 ts=4: */ | |
1227 | +/* | |
1228 | + * Mini comm implementation for busybox | |
1229 | + * | |
1230 | + * Copyright (C) 2005 by Robert Sullivan <cogito.ergo.cogito@gmail.com> | |
1231 | + * | |
1232 | + * This program is free software; you can redistribute it and/or modify | |
1233 | + * it under the terms of the GNU General Public License as published by | |
1234 | + * the Free Software Foundation; either version 2 of the License, or | |
1235 | + * (at your option) any later version. | |
1236 | + * | |
1237 | + * This program is distributed in the hope that it will be useful, | |
1238 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1239 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1240 | + * General Public License for more details. | |
1241 | + * | |
1242 | + * You should have received a copy of the GNU General Public License | |
1243 | + * along with this program; if not, write to the Free Software | |
1244 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
1245 | + * 02111-1307 USA | |
1246 | + * | |
1247 | + */ | |
1248 | + | |
1249 | +#include <stdio.h> | |
1250 | +#include <stdlib.h> | |
1251 | +#include <string.h> | |
1252 | +#include <unistd.h> | |
1253 | +#include "busybox.h" | |
1254 | + | |
1255 | +#define COMM_OPT_1 0x01 | |
1256 | +#define COMM_OPT_2 0x02 | |
1257 | +#define COMM_OPT_3 0x04 | |
1258 | + | |
1259 | +/* These three variables control behaviour if non-zero */ | |
1260 | + | |
1261 | +static int only_file_1; | |
1262 | +static int only_file_2; | |
1263 | +static int both; | |
1264 | + | |
1265 | +/* writeline outputs the input given, appropriately aligned according to class */ | |
1266 | +static void writeline(char *line, int class) | |
1267 | +{ | |
1268 | + if (class == 0) { | |
1269 | + if (!only_file_1) | |
1270 | + return; | |
1271 | + } else if (class == 1) { | |
1272 | + if (!only_file_2) | |
1273 | + return; | |
1274 | + if (only_file_1) | |
1275 | + putchar('\t'); | |
1276 | + } | |
1277 | + else /*if (class == 2)*/ { | |
1278 | + if (!both) | |
1279 | + return; | |
1280 | + if (only_file_1) | |
1281 | + putchar('\t'); | |
1282 | + if (only_file_2) | |
1283 | + putchar('\t'); | |
1284 | + } | |
1285 | + fputs(line, stdout); | |
1286 | +} | |
1287 | + | |
1288 | +/* This is the real core of the program - lines are compared here */ | |
1289 | +static void cmp_files(char **infiles) | |
1290 | +{ | |
1291 | +#define LINE_LEN 100 | |
1292 | +#define BB_EOF_0 0x1 | |
1293 | +#define BB_EOF_1 0x2 | |
1294 | + char thisline[2][LINE_LEN]; | |
1295 | + FILE *streams[2]; | |
1296 | + int i; | |
1297 | + | |
1298 | + for (i = 0; i < 2; ++i) { | |
1299 | + streams[i] = ((infiles[i][0] == '=' && infiles[i][1]) ? stdin : bb_xfopen(infiles[i], "r")); | |
1300 | + fgets(thisline[i], LINE_LEN, streams[i]); | |
1301 | + } | |
1302 | + | |
1303 | + while (thisline[0] || thisline[1]) { | |
1304 | + int order = 0; | |
1305 | + | |
1306 | + i = 0; | |
1307 | + if (feof(streams[0])) i |= BB_EOF_0; | |
1308 | + if (feof(streams[1])) i |= BB_EOF_1; | |
1309 | + | |
1310 | + if (!thisline[0]) | |
1311 | + order = 1; | |
1312 | + else if (!thisline[1]) | |
1313 | + order = -1; | |
1314 | + else { | |
1315 | + int tl0_len, tl1_len; | |
1316 | + tl0_len = strlen(thisline[0]); | |
1317 | + tl1_len = strlen(thisline[1]); | |
1318 | + order = memcmp(thisline[0], thisline[1], tl0_len < tl1_len ? tl0_len : tl1_len); | |
1319 | + if (!order) | |
1320 | + order = tl0_len < tl1_len ? -1 : tl0_len != tl1_len; | |
1321 | + } | |
1322 | + | |
1323 | + if (order == 0 && !i) | |
1324 | + writeline(thisline[1], 2); | |
1325 | + else if (order > 0 && !(i & BB_EOF_1)) | |
1326 | + writeline(thisline[1], 1); | |
1327 | + else if (order < 0 && !(i & BB_EOF_0)) | |
1328 | + writeline(thisline[0], 0); | |
1329 | + | |
1330 | + if (i & BB_EOF_0 & BB_EOF_1) { | |
1331 | + break; | |
1332 | + | |
1333 | + } else if (i) { | |
1334 | + i = (i & BB_EOF_0 ? 1 : 0); | |
1335 | + while (!feof(streams[i])) { | |
1336 | + if ((order < 0 && i) || (order > 0 && !i)) | |
1337 | + writeline(thisline[i], i); | |
1338 | + fgets(thisline[i], LINE_LEN, streams[i]); | |
1339 | + } | |
1340 | + break; | |
1341 | + | |
1342 | + } else { | |
1343 | + if (order >= 0) | |
1344 | + fgets(thisline[1], LINE_LEN, streams[1]); | |
1345 | + if (order <= 0) | |
1346 | + fgets(thisline[0], LINE_LEN, streams[0]); | |
1347 | + } | |
1348 | + } | |
1349 | + | |
1350 | + fclose(streams[0]); | |
1351 | + fclose(streams[1]); | |
1352 | +} | |
1353 | + | |
1354 | +int comm_main(int argc, char **argv) | |
1355 | +{ | |
1356 | + unsigned long flags; | |
1357 | + | |
1358 | + flags = bb_getopt_ulflags(argc, argv, "123"); | |
1359 | + | |
1360 | + if (optind + 2 != argc) | |
1361 | + bb_show_usage(); | |
1362 | + | |
1363 | + only_file_1 = !(flags & COMM_OPT_1); | |
1364 | + only_file_2 = !(flags & COMM_OPT_2); | |
1365 | + both = !(flags & COMM_OPT_3); | |
1366 | + | |
1367 | + cmp_files(argv + optind); | |
1368 | + exit(EXIT_SUCCESS); | |
1369 | +} | |
1370 | diff -Nur busybox-1.00/coreutils/cp.c busybox/coreutils/cp.c | |
1371 | --- busybox-1.00/coreutils/cp.c 2004-01-25 06:50:28.000000000 +0100 | |
1372 | +++ busybox/coreutils/cp.c 2005-06-04 08:20:13.000000000 +0200 | |
1373 | @@ -42,7 +42,7 @@ | |
1374 | #include "libcoreutils/coreutils.h" | |
1375 | ||
1376 | /* WARNING!! ORDER IS IMPORTANT!! */ | |
1377 | -static const char cp_opts[] = "pdRfiar"; | |
1378 | +static const char cp_opts[] = "pdRfiarPHL"; | |
1379 | ||
1380 | extern int cp_main(int argc, char **argv) | |
1381 | { | |
1382 | @@ -70,9 +70,23 @@ | |
1383 | if (flags & 64) { | |
1384 | /* Make -r a synonym for -R, | |
1385 | * -r was marked as obsolete in SUSv3, but is included for compatability | |
1386 | - */ | |
1387 | + */ | |
1388 | flags |= FILEUTILS_RECUR; | |
1389 | } | |
1390 | + if (flags & 128) { | |
1391 | + /* Make -P a synonym for -d, | |
1392 | + * -d is the GNU option while -P is the POSIX 2003 option | |
1393 | + */ | |
1394 | + flags |= FILEUTILS_DEREFERENCE; | |
1395 | + } | |
1396 | + /* Default behavior of cp is to dereference, so we don't have to do | |
1397 | + * anything special when we are given -L. | |
1398 | + * The behavior of -H is *almost* like -L, but not quite, so let's | |
1399 | + * just ignore it too for fun. | |
1400 | + if (flags & 256 || flags & 512) { | |
1401 | + ; | |
1402 | + } | |
1403 | + */ | |
1404 | ||
1405 | flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */ | |
1406 | ||
1407 | @@ -86,7 +100,7 @@ | |
1408 | /* If there are only two arguments and... */ | |
1409 | if (optind + 2 == argc) { | |
1410 | s_flags = cp_mv_stat2(*argv, &source_stat, | |
1411 | - (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); | |
1412 | + (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); | |
1413 | if ((s_flags < 0) || ((d_flags = cp_mv_stat(last, &dest_stat)) < 0)) { | |
1414 | exit(EXIT_FAILURE); | |
1415 | } | |
1416 | @@ -98,8 +112,8 @@ | |
1417 | ((((flags & FILEUTILS_RECUR) >> 1) & s_flags) && !d_flags) | |
1418 | ) { | |
1419 | /* ...do a simple copy. */ | |
1420 | - dest = last; | |
1421 | - goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */ | |
1422 | + dest = last; | |
1423 | + goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */ | |
1424 | } | |
1425 | } | |
1426 | ||
1427 | diff -Nur busybox-1.00/coreutils/cut.c busybox/coreutils/cut.c | |
1428 | --- busybox-1.00/coreutils/cut.c 2004-04-14 19:51:09.000000000 +0200 | |
1429 | +++ busybox/coreutils/cut.c 2005-06-04 08:20:13.000000000 +0200 | |
1430 | @@ -300,7 +300,7 @@ | |
1431 | part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS); | |
1432 | if(part == 0) | |
1433 | bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); | |
1434 | - if(opt & 0x80000000UL) | |
1435 | + if(opt & BB_GETOPT_ERROR) | |
1436 | bb_error_msg_and_die("only one type of list may be specified"); | |
1437 | parse_lists(sopt); | |
1438 | if((opt & (OPT_DELIM_FLGS))) { | |
1439 | diff -Nur busybox-1.00/coreutils/date.c busybox/coreutils/date.c | |
1440 | --- busybox-1.00/coreutils/date.c 2004-10-11 22:52:16.000000000 +0200 | |
1441 | +++ busybox/coreutils/date.c 2005-06-04 08:20:13.000000000 +0200 | |
1442 | @@ -136,7 +136,6 @@ | |
1443 | { | |
1444 | char *date_str = NULL; | |
1445 | char *date_fmt = NULL; | |
1446 | - char *t_buff; | |
1447 | int set_time; | |
1448 | int utc; | |
1449 | int use_arg = 0; | |
1450 | @@ -166,7 +165,7 @@ | |
1451 | bb_error_msg_and_die(bb_msg_memory_exhausted); | |
1452 | } | |
1453 | use_arg = opt & DATE_OPT_DATE; | |
1454 | - if(opt & 0x80000000UL) | |
1455 | + if(opt & BB_GETOPT_ERROR) | |
1456 | bb_show_usage(); | |
1457 | #ifdef CONFIG_FEATURE_DATE_ISOFMT | |
1458 | if(opt & DATE_OPT_TIMESPEC) { | |
1459 | @@ -283,10 +282,13 @@ | |
1460 | date_fmt = "%Y.%m.%d-%H:%M:%S"; | |
1461 | } | |
1462 | ||
1463 | - /* Print OUTPUT (after ALL that!) */ | |
1464 | - t_buff = xmalloc(201); | |
1465 | - strftime(t_buff, 200, date_fmt, &tm_time); | |
1466 | - puts(t_buff); | |
1467 | + { | |
1468 | + /* Print OUTPUT (after ALL that!) */ | |
1469 | + RESERVE_CONFIG_BUFFER(t_buff, 201); | |
1470 | + strftime(t_buff, 200, date_fmt, &tm_time); | |
1471 | + puts(t_buff); | |
1472 | + RELEASE_CONFIG_BUFFER(t_buff); | |
1473 | + } | |
1474 | ||
1475 | return EXIT_SUCCESS; | |
1476 | } | |
1477 | diff -Nur busybox-1.00/coreutils/expr.c busybox/coreutils/expr.c | |
1478 | --- busybox-1.00/coreutils/expr.c 2004-04-14 19:51:09.000000000 +0200 | |
1479 | +++ busybox/coreutils/expr.c 2005-06-04 08:20:13.000000000 +0200 | |
1480 | @@ -245,10 +245,9 @@ | |
1481 | static VALUE *docolon (VALUE *sv, VALUE *pv) | |
1482 | { | |
1483 | VALUE *v; | |
1484 | - const char *errmsg; | |
1485 | - struct re_pattern_buffer re_buffer; | |
1486 | - struct re_registers re_regs; | |
1487 | - int len; | |
1488 | + regex_t re_buffer; | |
1489 | + const int NMATCH = 2; | |
1490 | + regmatch_t re_regs[NMATCH]; | |
1491 | ||
1492 | tostring (sv); | |
1493 | tostring (pv); | |
1494 | @@ -260,27 +259,22 @@ | |
1495 | pv->u.s); | |
1496 | } | |
1497 | ||
1498 | - len = strlen (pv->u.s); | |
1499 | memset (&re_buffer, 0, sizeof (re_buffer)); | |
1500 | - memset (&re_regs, 0, sizeof (re_regs)); | |
1501 | - re_buffer.allocated = 2 * len; | |
1502 | - re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated); | |
1503 | - re_buffer.translate = 0; | |
1504 | - re_syntax_options = RE_SYNTAX_POSIX_BASIC; | |
1505 | - errmsg = re_compile_pattern (pv->u.s, len, &re_buffer); | |
1506 | - if (errmsg) { | |
1507 | - bb_error_msg_and_die("%s", errmsg); | |
1508 | - } | |
1509 | - | |
1510 | - len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs); | |
1511 | - if (len >= 0) { | |
1512 | + memset (re_regs, 0, sizeof (*re_regs)); | |
1513 | + if( regcomp (&re_buffer, pv->u.s, 0) != 0 ) | |
1514 | + bb_error_msg_and_die("Invalid regular expression"); | |
1515 | + | |
1516 | + /* expr uses an anchored pattern match, so check that there was a | |
1517 | + * match and that the match starts at offset 0. */ | |
1518 | + if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && | |
1519 | + re_regs[0].rm_so == 0) { | |
1520 | /* Were \(...\) used? */ | |
1521 | - if (re_buffer.re_nsub > 0) { /* was (re_regs.start[1] >= 0) */ | |
1522 | - sv->u.s[re_regs.end[1]] = '\0'; | |
1523 | - v = str_value (sv->u.s + re_regs.start[1]); | |
1524 | + if (re_buffer.re_nsub > 0) { | |
1525 | + sv->u.s[re_regs[1].rm_eo] = '\0'; | |
1526 | + v = str_value (sv->u.s + re_regs[1].rm_so); | |
1527 | } | |
1528 | else | |
1529 | - v = int_value (len); | |
1530 | + v = int_value (re_regs[0].rm_eo); | |
1531 | } | |
1532 | else { | |
1533 | /* Match failed -- return the right kind of null. */ | |
1534 | @@ -289,7 +283,6 @@ | |
1535 | else | |
1536 | v = int_value (0); | |
1537 | } | |
1538 | - free (re_buffer.buffer); | |
1539 | return v; | |
1540 | } | |
1541 | ||
1542 | diff -Nur busybox-1.00/coreutils/id.c busybox/coreutils/id.c | |
1543 | --- busybox-1.00/coreutils/id.c 2004-09-15 05:04:07.000000000 +0200 | |
1544 | +++ busybox/coreutils/id.c 2005-06-04 08:20:13.000000000 +0200 | |
1545 | @@ -32,8 +32,7 @@ | |
1546 | #include <sys/types.h> | |
1547 | ||
1548 | #ifdef CONFIG_SELINUX | |
1549 | -#include <proc_secure.h> | |
1550 | -#include <flask_util.h> | |
1551 | +#include <selinux/selinux.h> /* for is_selinux_enabled() */ | |
1552 | #endif | |
1553 | ||
1554 | #define PRINT_REAL 1 | |
1555 | @@ -61,14 +60,11 @@ | |
1556 | gid_t gid; | |
1557 | unsigned long flags; | |
1558 | short status; | |
1559 | -#ifdef CONFIG_SELINUX | |
1560 | - int is_flask_enabled_flag = is_flask_enabled(); | |
1561 | -#endif | |
1562 | ||
1563 | bb_opt_complementaly = "u~g:g~u"; | |
1564 | flags = bb_getopt_ulflags(argc, argv, "rnug"); | |
1565 | ||
1566 | - if ((flags & 0x80000000UL) | |
1567 | + if ((flags & BB_GETOPT_ERROR) | |
1568 | /* Don't allow -n -r -nr */ | |
1569 | || (flags <= 3 && flags > 0) | |
1570 | /* Don't allow more than one username */ | |
1571 | @@ -109,17 +105,26 @@ | |
1572 | putchar(' '); | |
1573 | /* my_getgrgid doesn't exit on failure here */ | |
1574 | status|=printf_full(gid, my_getgrgid(NULL, gid, 0), 'g'); | |
1575 | + | |
1576 | #ifdef CONFIG_SELINUX | |
1577 | - if(is_flask_enabled_flag) { | |
1578 | - security_id_t mysid = getsecsid(); | |
1579 | - char context[80]; | |
1580 | - int len = sizeof(context); | |
1581 | - context[0] = '\0'; | |
1582 | - if(security_sid_to_context(mysid, context, &len)) | |
1583 | - strcpy(context, "unknown"); | |
1584 | + if ( is_selinux_enabled() ) { | |
1585 | + security_context_t mysid; | |
1586 | + char context[80]; | |
1587 | + int len = sizeof(context); | |
1588 | + | |
1589 | + getcon(&mysid); | |
1590 | + context[0] = '\0'; | |
1591 | + if (mysid) { | |
1592 | + len = strlen(mysid)+1; | |
1593 | + safe_strncpy(context, mysid, len); | |
1594 | + freecon(mysid); | |
1595 | + }else{ | |
1596 | + safe_strncpy(context, "unknown",8); | |
1597 | + } | |
1598 | bb_printf(" context=%s", context); | |
1599 | } | |
1600 | #endif | |
1601 | + | |
1602 | putchar('\n'); | |
1603 | bb_fflush_stdout_and_exit(status); | |
1604 | } | |
1605 | diff -Nur busybox-1.00/coreutils/install.c busybox/coreutils/install.c | |
1606 | --- busybox-1.00/coreutils/install.c 2004-04-25 07:11:14.000000000 +0200 | |
1607 | +++ busybox/coreutils/install.c 2005-06-04 08:20:13.000000000 +0200 | |
1608 | @@ -69,7 +69,7 @@ | |
1609 | flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */ | |
1610 | ||
1611 | /* Check valid options were given */ | |
1612 | - if(flags & 0x80000000UL) { | |
1613 | + if(flags & BB_GETOPT_ERROR) { | |
1614 | bb_show_usage(); | |
1615 | } | |
1616 | ||
1617 | diff -Nur busybox-1.00/coreutils/ln.c busybox/coreutils/ln.c | |
1618 | --- busybox-1.00/coreutils/ln.c 2004-03-15 09:28:20.000000000 +0100 | |
1619 | +++ busybox/coreutils/ln.c 2005-06-04 08:20:13.000000000 +0200 | |
1620 | @@ -21,21 +21,20 @@ | |
1621 | */ | |
1622 | ||
1623 | /* BB_AUDIT SUSv3 compliant */ | |
1624 | -/* BB_AUDIT GNU options missing: -b, -d, -F, -i, -S, and -v. */ | |
1625 | +/* BB_AUDIT GNU options missing: -d, -F, -i, and -v. */ | |
1626 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */ | |
1627 | ||
1628 | -/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | |
1629 | - * | |
1630 | - * Fixed bug involving -n option. Essentially, -n was always in effect. | |
1631 | - */ | |
1632 | - | |
1633 | +#include <stdio.h> | |
1634 | #include <stdlib.h> | |
1635 | #include <unistd.h> | |
1636 | +#include <errno.h> | |
1637 | #include "busybox.h" | |
1638 | ||
1639 | #define LN_SYMLINK 1 | |
1640 | #define LN_FORCE 2 | |
1641 | #define LN_NODEREFERENCE 4 | |
1642 | +#define LN_BACKUP 8 | |
1643 | +#define LN_SUFFIX 16 | |
1644 | ||
1645 | extern int ln_main(int argc, char **argv) | |
1646 | { | |
1647 | @@ -44,10 +43,11 @@ | |
1648 | char *last; | |
1649 | char *src_name; | |
1650 | char *src; | |
1651 | + char *suffix = "~"; | |
1652 | struct stat statbuf; | |
1653 | int (*link_func)(const char *, const char *); | |
1654 | ||
1655 | - flag = bb_getopt_ulflags(argc, argv, "sfn"); | |
1656 | + flag = bb_getopt_ulflags(argc, argv, "sfnbS:", &suffix); | |
1657 | ||
1658 | if (argc == optind) { | |
1659 | bb_show_usage(); | |
1660 | @@ -80,7 +80,23 @@ | |
1661 | continue; | |
1662 | } | |
1663 | ||
1664 | - if (flag & LN_FORCE) { | |
1665 | + if (flag & LN_BACKUP) { | |
1666 | + char *backup = NULL; | |
1667 | + bb_xasprintf(&backup, "%s%s", src, suffix); | |
1668 | + if (rename(src, backup) < 0 && errno != ENOENT) { | |
1669 | + bb_perror_msg(src); | |
1670 | + status = EXIT_FAILURE; | |
1671 | + free(backup); | |
1672 | + continue; | |
1673 | + } | |
1674 | + free(backup); | |
1675 | + /* | |
1676 | + * When the source and dest are both hard links to the same | |
1677 | + * inode, a rename may succeed even though nothing happened. | |
1678 | + * Therefore, always unlink(). | |
1679 | + */ | |
1680 | + unlink(src); | |
1681 | + } else if (flag & LN_FORCE) { | |
1682 | unlink(src); | |
1683 | } | |
1684 | ||
1685 | diff -Nur busybox-1.00/coreutils/ls.c busybox/coreutils/ls.c | |
1686 | --- busybox-1.00/coreutils/ls.c 2004-09-24 04:04:13.000000000 +0200 | |
1687 | +++ busybox/coreutils/ls.c 2005-06-04 08:20:13.000000000 +0200 | |
1688 | @@ -64,9 +64,7 @@ | |
1689 | #include <sys/sysmacros.h> /* major() and minor() */ | |
1690 | #include "busybox.h" | |
1691 | #ifdef CONFIG_SELINUX | |
1692 | -#include <fs_secure.h> | |
1693 | -#include <flask_util.h> | |
1694 | -#include <ss.h> | |
1695 | +#include <selinux/selinux.h> /* for is_selinux_enabled() */ | |
1696 | #endif | |
1697 | ||
1698 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS | |
1699 | @@ -182,7 +180,7 @@ | |
1700 | char *fullname; /* the dir entry name */ | |
1701 | struct stat dstat; /* the file stat info */ | |
1702 | #ifdef CONFIG_SELINUX | |
1703 | - security_id_t sid; | |
1704 | + security_context_t sid; | |
1705 | #endif | |
1706 | struct dnode *next; /* point at the next node */ | |
1707 | }; | |
1708 | @@ -195,7 +193,7 @@ | |
1709 | static unsigned int all_fmt; | |
1710 | ||
1711 | #ifdef CONFIG_SELINUX | |
1712 | -static int is_flask_enabled_flag; | |
1713 | +static int selinux_enabled= 0; | |
1714 | #endif | |
1715 | ||
1716 | #ifdef CONFIG_FEATURE_AUTOWIDTH | |
1717 | @@ -213,18 +211,19 @@ | |
1718 | struct stat dstat; | |
1719 | struct dnode *cur; | |
1720 | #ifdef CONFIG_SELINUX | |
1721 | - security_id_t sid; | |
1722 | + security_context_t sid=NULL; | |
1723 | #endif | |
1724 | int rc; | |
1725 | ||
1726 | #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS | |
1727 | if (all_fmt & FOLLOW_LINKS) { | |
1728 | #ifdef CONFIG_SELINUX | |
1729 | - if(is_flask_enabled_flag) | |
1730 | - rc = stat_secure(fullname, &dstat, &sid); | |
1731 | - else | |
1732 | + if (is_selinux_enabled()) { | |
1733 | + rc=0; /* Set the number which means success before hand. */ | |
1734 | + rc = getfilecon(fullname,&sid); | |
1735 | + } | |
1736 | #endif | |
1737 | - rc = stat(fullname, &dstat); | |
1738 | + rc = stat(fullname, &dstat); | |
1739 | if(rc) | |
1740 | { | |
1741 | bb_perror_msg("%s", fullname); | |
1742 | @@ -235,11 +234,12 @@ | |
1743 | #endif | |
1744 | { | |
1745 | #ifdef CONFIG_SELINUX | |
1746 | - if(is_flask_enabled_flag) | |
1747 | - rc = lstat_secure(fullname, &dstat, &sid); | |
1748 | - else | |
1749 | + if (is_selinux_enabled()) { | |
1750 | + rc=0; /* Set the number which means success before hand. */ | |
1751 | + rc = lgetfilecon(fullname,&sid); | |
1752 | + } | |
1753 | #endif | |
1754 | - rc = lstat(fullname, &dstat); | |
1755 | + rc = lstat(fullname, &dstat); | |
1756 | if(rc) | |
1757 | { | |
1758 | bb_perror_msg("%s", fullname); | |
1759 | @@ -736,12 +736,16 @@ | |
1760 | #ifdef CONFIG_SELINUX | |
1761 | case LIST_CONTEXT: | |
1762 | { | |
1763 | - char context[64]; | |
1764 | - int len = sizeof(context); | |
1765 | - if(security_sid_to_context(dn->sid, context, &len)) | |
1766 | - { | |
1767 | - strcpy(context, "unknown"); | |
1768 | - len = 7; | |
1769 | + char context[80]; | |
1770 | + int len; | |
1771 | + | |
1772 | + if (dn->sid) { | |
1773 | + /* I assume sid initilized with NULL */ | |
1774 | + len = strlen(dn->sid)+1; | |
1775 | + safe_strncpy(context, dn->sid, len); | |
1776 | + freecon(dn->sid); | |
1777 | + }else { | |
1778 | + safe_strncpy(context, "unknown",8); | |
1779 | } | |
1780 | printf("%-32s ", context); | |
1781 | column += MAX(33, len); | |
1782 | @@ -963,10 +967,6 @@ | |
1783 | char *terminal_width_str = NULL; | |
1784 | #endif | |
1785 | ||
1786 | -#ifdef CONFIG_SELINUX | |
1787 | - is_flask_enabled_flag = is_flask_enabled(); | |
1788 | -#endif | |
1789 | - | |
1790 | all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO | |
1791 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS | |
1792 | | TIME_MOD | |
1793 | diff -Nur busybox-1.00/coreutils/md5_sha1_sum.c busybox/coreutils/md5_sha1_sum.c | |
1794 | --- busybox-1.00/coreutils/md5_sha1_sum.c 2004-04-14 19:51:09.000000000 +0200 | |
1795 | +++ busybox/coreutils/md5_sha1_sum.c 2005-06-04 08:20:13.000000000 +0200 | |
1796 | @@ -49,38 +49,25 @@ | |
1797 | ||
1798 | static uint8_t *hash_file(const char *filename, uint8_t hash_algo) | |
1799 | { | |
1800 | - uint8_t *hash_value_bin; | |
1801 | - uint8_t *hash_value = NULL; | |
1802 | - uint8_t hash_length; | |
1803 | - int src_fd; | |
1804 | - | |
1805 | - if (strcmp(filename, "-") == 0) { | |
1806 | - src_fd = STDIN_FILENO; | |
1807 | - } else { | |
1808 | - src_fd = open(filename, O_RDONLY); | |
1809 | - } | |
1810 | - | |
1811 | - if (hash_algo == HASH_MD5) { | |
1812 | - hash_length = 16; | |
1813 | - } else { | |
1814 | - hash_length = 20; | |
1815 | - } | |
1816 | - | |
1817 | - hash_value_bin = xmalloc(hash_length); | |
1818 | - | |
1819 | - if ((src_fd != -1) && (hash_fd(src_fd, -1, hash_algo, hash_value_bin) != -2)) { | |
1820 | - hash_value = hash_bin_to_hex(hash_value_bin, hash_length); | |
1821 | - } else { | |
1822 | + int src_fd = strcmp(filename, "-") == 0 ? STDIN_FILENO : | |
1823 | + open(filename, O_RDONLY); | |
1824 | + if (src_fd == -1) { | |
1825 | bb_perror_msg("%s", filename); | |
1826 | + return NULL; | |
1827 | + } else { | |
1828 | + uint8_t *hash_value; | |
1829 | + RESERVE_CONFIG_UBUFFER(hash_value_bin, 20); | |
1830 | + hash_value = hash_fd(src_fd, -1, hash_algo, hash_value_bin) != -2 ? | |
1831 | + hash_bin_to_hex(hash_value_bin, hash_algo == HASH_MD5 ? 16 : 20) : | |
1832 | + NULL; | |
1833 | + RELEASE_CONFIG_BUFFER(hash_value_bin); | |
1834 | + close(src_fd); | |
1835 | + return hash_value; | |
1836 | } | |
1837 | - | |
1838 | - close(src_fd); | |
1839 | - | |
1840 | - return(hash_value); | |
1841 | } | |
1842 | ||
1843 | /* This could become a common function for md5 as well, by using md5_stream */ | |
1844 | -extern int hash_files(int argc, char **argv, const uint8_t hash_algo) | |
1845 | +static int hash_files(int argc, char **argv, const uint8_t hash_algo) | |
1846 | { | |
1847 | int return_value = EXIT_SUCCESS; | |
1848 | uint8_t *hash_value; | |
1849 | diff -Nur busybox-1.00/coreutils/nice.c busybox/coreutils/nice.c | |
1850 | --- busybox-1.00/coreutils/nice.c 1970-01-01 01:00:00.000000000 +0100 | |
1851 | +++ busybox/coreutils/nice.c 2005-06-04 08:20:13.000000000 +0200 | |
1852 | @@ -0,0 +1,86 @@ | |
1853 | +/* vi: set sw=4 ts=4: */ | |
1854 | +/* | |
1855 | + * nice implementation for busybox | |
1856 | + * | |
1857 | + * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> | |
1858 | + * | |
1859 | + * This program is free software; you can redistribute it and/or modify | |
1860 | + * it under the terms of the GNU General Public License as published by | |
1861 | + * the Free Software Foundation; either version 2 of the License, or | |
1862 | + * (at your option) any later version. | |
1863 | + * | |
1864 | + * This program is distributed in the hope that it will be useful, | |
1865 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1866 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1867 | + * General Public License for more details. | |
1868 | + * | |
1869 | + * You should have received a copy of the GNU General Public License | |
1870 | + * along with this program; if not, write to the Free Software | |
1871 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
1872 | + * | |
1873 | + */ | |
1874 | + | |
1875 | +#include <stdio.h> | |
1876 | +#include <stdlib.h> | |
1877 | +#include <string.h> | |
1878 | +#include <limits.h> | |
1879 | +#include <errno.h> | |
1880 | +#include <unistd.h> | |
1881 | +#include <sys/time.h> | |
1882 | +#include <sys/resource.h> | |
1883 | +#include "busybox.h" | |
1884 | + | |
1885 | +static inline int int_add_no_wrap(int a, int b) | |
1886 | +{ | |
1887 | + int s = a + b; | |
1888 | + | |
1889 | + if (b < 0) { | |
1890 | + if (s > a) s = INT_MIN; | |
1891 | + } else { | |
1892 | + if (s < a) s = INT_MAX; | |
1893 | + } | |
1894 | + | |
1895 | + return s; | |
1896 | +} | |
1897 | + | |
1898 | +int nice_main(int argc, char **argv) | |
1899 | +{ | |
1900 | + static const char Xetpriority_msg[] = "cannot %cet priority"; | |
1901 | + | |
1902 | + int old_priority, adjustment; | |
1903 | + | |
1904 | + errno = 0; /* Needed for getpriority error detection. */ | |
1905 | + old_priority = getpriority(PRIO_PROCESS, 0); | |
1906 | + if (errno) { | |
1907 | + bb_perror_msg_and_die(Xetpriority_msg, 'g'); | |
1908 | + } | |
1909 | + | |
1910 | + if (!*++argv) { /* No args, so (GNU) output current nice value. */ | |
1911 | + bb_printf("%d\n", old_priority); | |
1912 | + bb_fflush_stdout_and_exit(EXIT_SUCCESS); | |
1913 | + } | |
1914 | + | |
1915 | + adjustment = 10; /* Set default adjustment. */ | |
1916 | + | |
1917 | + if ((argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) { /* "-n" */ | |
1918 | + if (argc < 4) { /* Missing priority and/or utility! */ | |
1919 | + bb_show_usage(); | |
1920 | + } | |
1921 | + adjustment = bb_xgetlarg(argv[1], 10, INT_MIN, INT_MAX); | |
1922 | + argv += 2; | |
1923 | + } | |
1924 | + | |
1925 | + { /* Set our priority. Handle integer wrapping for old + adjust. */ | |
1926 | + int new_priority = int_add_no_wrap(old_priority, adjustment); | |
1927 | + | |
1928 | + if (setpriority(PRIO_PROCESS, 0, new_priority) < 0) { | |
1929 | + bb_perror_msg_and_die(Xetpriority_msg, 's'); | |
1930 | + } | |
1931 | + } | |
1932 | + | |
1933 | + execvp(*argv, argv); /* Now exec the desired program. */ | |
1934 | + | |
1935 | + /* The exec failed... */ | |
1936 | + bb_default_error_retval = (errno == ENOENT) ? 127 : 126; /* SUSv3 */ | |
1937 | + bb_perror_msg_and_die("%s", *argv); | |
1938 | +} | |
1939 | diff -Nur busybox-1.00/coreutils/printenv.c busybox/coreutils/printenv.c | |
1940 | --- busybox-1.00/coreutils/printenv.c 1970-01-01 01:00:00.000000000 +0100 | |
1941 | +++ busybox/coreutils/printenv.c 2005-06-04 08:20:13.000000000 +0200 | |
1942 | @@ -0,0 +1,53 @@ | |
1943 | +/* | |
1944 | + * printenv implementation for busybox | |
1945 | + * | |
1946 | + * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org> | |
1947 | + * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org> | |
1948 | + * | |
1949 | + * This program is free software; you can redistribute it and/or modify | |
1950 | + * it under the terms of the GNU General Public License as published by | |
1951 | + * the Free Software Foundation; either version 2 of the License, or | |
1952 | + * (at your option) any later version. | |
1953 | + * | |
1954 | + * This program is distributed in the hope that it will be useful, | |
1955 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1956 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1957 | + * General Public License for more details. | |
1958 | + * | |
1959 | + * You should have received a copy of the GNU General Public License | |
1960 | + * along with this program; if not, write to the Free Software | |
1961 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
1962 | + * | |
1963 | + */ | |
1964 | + | |
1965 | +#include <stdio.h> | |
1966 | +#include <string.h> | |
1967 | +#include <stdlib.h> | |
1968 | +#include "busybox.h" | |
1969 | + | |
1970 | +int printenv_main(int argc, char **argv) | |
1971 | +{ | |
1972 | + extern char **environ; | |
1973 | + int e = 0; | |
1974 | + | |
1975 | + /* no variables specified, show whole env */ | |
1976 | + if (argc == 1) | |
1977 | + while (environ[e]) | |
1978 | + puts(environ[e++]); | |
1979 | + | |
1980 | + /* search for specified variables and print them out if found */ | |
1981 | + else { | |
1982 | + int i; | |
1983 | + size_t l; | |
1984 | + char *arg, *env; | |
1985 | + | |
1986 | + for (i=1; (arg = argv[i]); ++i) | |
1987 | + for (; (env = environ[e]); ++e) { | |
1988 | + l = strlen(arg); | |
1989 | + if (!strncmp(env, arg, l) && env[l] == '=') | |
1990 | + puts(env + l + 1); | |
1991 | + } | |
1992 | + } | |
1993 | + | |
1994 | + bb_fflush_stdout_and_exit(0); | |
1995 | +} | |
1996 | diff -Nur busybox-1.00/coreutils/sort.c busybox/coreutils/sort.c | |
1997 | --- busybox-1.00/coreutils/sort.c 2003-03-19 10:11:34.000000000 +0100 | |
1998 | +++ busybox/coreutils/sort.c 2005-06-04 08:20:13.000000000 +0200 | |
1999 | @@ -1,8 +1,8 @@ | |
2000 | /* vi: set sw=4 ts=4: */ | |
2001 | /* | |
2002 | - * Mini sort implementation for busybox | |
2003 | + * SuS3 compliant sort implementation for busybox | |
2004 | * | |
2005 | - * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> | |
2006 | + * Copyright (C) 2004 by Rob Landley <rob@landley.net> | |
2007 | * | |
2008 | * This program is free software; you can redistribute it and/or modify | |
2009 | * it under the terms of the GNU General Public License as published by | |
2010 | @@ -18,83 +18,321 @@ | |
2011 | * along with this program; if not, write to the Free Software | |
2012 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
2013 | * | |
2014 | + * See SuS3 sort standard at: | |
2015 | + * http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html | |
2016 | */ | |
2017 | ||
2018 | -/* BB_AUDIT SUSv3 _NOT_ compliant -- a number of options are not supported. */ | |
2019 | -/* http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html */ | |
2020 | - | |
2021 | -/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | |
2022 | - * | |
2023 | - * Now does proper error checking on i/o. Plus some space savings. | |
2024 | - */ | |
2025 | - | |
2026 | +#include <ctype.h> | |
2027 | +#include <math.h> | |
2028 | #include <stdio.h> | |
2029 | #include <stdlib.h> | |
2030 | #include <string.h> | |
2031 | +#include <time.h> | |
2032 | #include <unistd.h> | |
2033 | #include "busybox.h" | |
2034 | -#include "libcoreutils/coreutils.h" | |
2035 | ||
2036 | -static int compare_ascii(const void *x, const void *y) | |
2037 | +static int global_flags; | |
2038 | + | |
2039 | +/* | |
2040 | + sort [-m][-o output][-bdfinru][-t char][-k keydef]... [file...] | |
2041 | + sort -c [-bdfinru][-t char][-k keydef][file] | |
2042 | +*/ | |
2043 | + | |
2044 | +/* These are sort types */ | |
2045 | +#define FLAG_n 1 /* Numeric sort */ | |
2046 | +#define FLAG_g 2 /* Sort using strtod() */ | |
2047 | +#define FLAG_M 4 /* Sort date */ | |
2048 | +/* ucsz apply to root level only, not keys. b at root level implies bb */ | |
2049 | +#define FLAG_u 8 /* Unique */ | |
2050 | +#define FLAG_c 16 /* Check: no output, exit(!ordered) */ | |
2051 | +#define FLAG_s 32 /* Stable sort, no ascii fallback at end */ | |
2052 | +#define FLAG_z 64 /* Input is null terminated, not \n */ | |
2053 | +/* These can be applied to search keys, the previous four can't */ | |
2054 | +#define FLAG_b 128 /* Ignore leading blanks */ | |
2055 | +#define FLAG_r 256 /* Reverse */ | |
2056 | +#define FLAG_d 512 /* Ignore !(isalnum()|isspace()) */ | |
2057 | +#define FLAG_f 1024 /* Force uppercase */ | |
2058 | +#define FLAG_i 2048 /* Ignore !isprint() */ | |
2059 | +#define FLAG_bb 32768 /* Ignore trailing blanks */ | |
2060 | + | |
2061 | + | |
2062 | +#ifdef CONFIG_SORT_BIG | |
2063 | +static char key_separator; | |
2064 | + | |
2065 | +static struct sort_key | |
2066 | { | |
2067 | - return strcmp(*(char **)x, *(char **)y); | |
2068 | -} | |
2069 | + struct sort_key *next_key; /* linked list */ | |
2070 | + unsigned short range[4]; /* start word, start char, end word, end char */ | |
2071 | + int flags; | |
2072 | +} *key_list; | |
2073 | ||
2074 | -static int compare_numeric(const void *x, const void *y) | |
2075 | +static char *get_key(char *str, struct sort_key *key, int flags) | |
2076 | { | |
2077 | - int z = atoi(*(char **)x) - atoi(*(char **)y); | |
2078 | - return z ? z : strcmp(*(char **)x, *(char **)y); | |
2079 | + int start=0,end,len,i,j; | |
2080 | + | |
2081 | + /* Special case whole string, so we don't have to make a copy */ | |
2082 | + if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3] | |
2083 | + && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str; | |
2084 | + /* Find start of key on first pass, end on second pass*/ | |
2085 | + len=strlen(str); | |
2086 | + | |
2087 | + for(j=0;j<2;j++) { | |
2088 | + if(!key->range[2*j]) end=len; | |
2089 | + /* Loop through fields */ | |
2090 | + else { | |
2091 | + end=0; | |
2092 | + for(i=1;i<key->range[2*j]+j;i++) { | |
2093 | + /* Skip leading blanks or first separator */ | |
2094 | + if(str[end]) { | |
2095 | + if(key_separator) { | |
2096 | + if(str[end]==key_separator) end++; | |
2097 | + } else if(isspace(str[end])) | |
2098 | + while(isspace(str[end])) end++; | |
2099 | + } | |
2100 | + /* Skip body of key */ | |
2101 | + for(;str[end];end++) { | |
2102 | + if(key_separator) { | |
2103 | + if(str[end]==key_separator) break; | |
2104 | + } else if(isspace(str[end])) break; | |
2105 | + } | |
2106 | + } | |
2107 | + } | |
2108 | + if(!j) start=end; | |
2109 | + } | |
2110 | + /* Key with explicit separator starts after separator */ | |
2111 | + if(key_separator && str[start]==key_separator) start++; | |
2112 | + /* Strip leading whitespace if necessary */ | |
2113 | + if(flags&FLAG_b) while(isspace(str[start])) start++; | |
2114 | + /* Strip trailing whitespace if necessary */ | |
2115 | + if(flags&FLAG_bb) while(end>start && isspace(str[end-1])) end--; | |
2116 | + /* Handle offsets on start and end */ | |
2117 | + if(key->range[3]) { | |
2118 | + end+=key->range[3]-1; | |
2119 | + if(end>len) end=len; | |
2120 | + } | |
2121 | + if(key->range[1]) { | |
2122 | + start+=key->range[1]-1; | |
2123 | + if(start>len) start=len; | |
2124 | + } | |
2125 | + /* Make the copy */ | |
2126 | + if(end<start) end=start; | |
2127 | + str=bb_xstrndup(str+start,end-start); | |
2128 | + /* Handle -d */ | |
2129 | + if(flags&FLAG_d) { | |
2130 | + for(start=end=0;str[end];end++) | |
2131 | + if(isspace(str[end]) || isalnum(str[end])) str[start++]=str[end]; | |
2132 | + str[start]=0; | |
2133 | + } | |
2134 | + /* Handle -i */ | |
2135 | + if(flags&FLAG_i) { | |
2136 | + for(start=end=0;str[end];end++) | |
2137 | + if(isprint(str[end])) str[start++]=str[end]; | |
2138 | + str[start]=0; | |
2139 | + } | |
2140 | + /* Handle -f */ | |
2141 | + if(flags*FLAG_f) for(i=0;str[i];i++) str[i]=toupper(str[i]); | |
2142 | + | |
2143 | + return str; | |
2144 | } | |
2145 | ||
2146 | -int sort_main(int argc, char **argv) | |
2147 | +static struct sort_key *add_key(void) | |
2148 | { | |
2149 | - FILE *fp; | |
2150 | - char *line, **lines = NULL; | |
2151 | - int i, nlines = 0, inc; | |
2152 | - int (*compare)(const void *, const void *) = compare_ascii; | |
2153 | + struct sort_key **pkey=&key_list; | |
2154 | + while(*pkey) pkey=&((*pkey)->next_key); | |
2155 | + return *pkey=xcalloc(1,sizeof(struct sort_key)); | |
2156 | +} | |
2157 | ||
2158 | - int flags; | |
2159 | +#define GET_LINE(fp) (global_flags&FLAG_z) ? bb_get_chunk_from_file(fp) \ | |
2160 | + : bb_get_chomped_line_from_file(fp) | |
2161 | +#else | |
2162 | +#define GET_LINE(fp) bb_get_chomped_line_from_file(fp) | |
2163 | +#endif | |
2164 | ||
2165 | - bb_default_error_retval = 2; | |
2166 | +/* Iterate through keys list and perform comparisons */ | |
2167 | +static int compare_keys(const void *xarg, const void *yarg) | |
2168 | +{ | |
2169 | + int flags=global_flags,retval=0; | |
2170 | + char *x,*y; | |
2171 | ||
2172 | - flags = bb_getopt_ulflags(argc, argv, "nru"); | |
2173 | - if (flags & 1) { | |
2174 | - compare = compare_numeric; | |
2175 | +#ifdef CONFIG_SORT_BIG | |
2176 | + struct sort_key *key; | |
2177 | + | |
2178 | + for(key=key_list;!retval && key;key=key->next_key) { | |
2179 | + flags=(key->flags) ? key->flags : global_flags; | |
2180 | + /* Chop out and modify key chunks, handling -dfib */ | |
2181 | + x=get_key(*(char **)xarg,key,flags); | |
2182 | + y=get_key(*(char **)yarg,key,flags); | |
2183 | +#else | |
2184 | + /* This curly bracket serves no purpose but to match the nesting | |
2185 | + level of the for() loop we're not using */ | |
2186 | + { | |
2187 | + x=*(char **)xarg; | |
2188 | + y=*(char **)yarg; | |
2189 | +#endif | |
2190 | + /* Perform actual comparison */ | |
2191 | + switch(flags&7) { | |
2192 | + default: | |
2193 | + bb_error_msg_and_die("Unknown sort type."); | |
2194 | + break; | |
2195 | + /* Ascii sort */ | |
2196 | + case 0: | |
2197 | + retval=strcmp(x,y); | |
2198 | + break; | |
2199 | +#ifdef CONFIG_SORT_BIG | |
2200 | + case FLAG_g: | |
2201 | + { | |
2202 | + char *xx,*yy; | |
2203 | + double dx=strtod(x,&xx), dy=strtod(y,&yy); | |
2204 | + /* not numbers < NaN < -infinity < numbers < +infinity) */ | |
2205 | + if(x==xx) retval=(y==yy ? 0 : -1); | |
2206 | + else if(y==yy) retval=1; | |
2207 | + else if(isnan(dx)) retval=isnan(dy) ? 0 : -1; | |
2208 | + else if(isnan(dy)) retval=1; | |
2209 | + else if(isinf(dx)) { | |
2210 | + if(dx<0) retval=((isinf(dy) && dy<0) ? 0 : -1); | |
2211 | + else retval=((isinf(dy) && dy>0) ? 0 : 1); | |
2212 | + } else if(isinf(dy)) retval=dy<0 ? 1 : -1; | |
2213 | + else retval=dx>dy ? 1 : (dx<dy ? -1 : 0); | |
2214 | + break; | |
2215 | + } | |
2216 | + case FLAG_M: | |
2217 | + { | |
2218 | + struct tm thyme; | |
2219 | + int dx; | |
2220 | + char *xx,*yy; | |
2221 | + | |
2222 | + xx=strptime(x,"%b",&thyme); | |
2223 | + dx=thyme.tm_mon; | |
2224 | + yy=strptime(y,"%b",&thyme); | |
2225 | + if(!xx) retval=(!yy ? 0 : -1); | |
2226 | + else if(!yy) retval=1; | |
2227 | + else retval=(dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon); | |
2228 | + break; | |
2229 | + } | |
2230 | + /* Full floating point version of -n */ | |
2231 | + case FLAG_n: | |
2232 | + { | |
2233 | + double dx=atof(x),dy=atof(y); | |
2234 | + retval=dx>dy ? 1 : (dx<dy ? -1 : 0); | |
2235 | + break; | |
2236 | + } | |
2237 | + } | |
2238 | + /* Free key copies. */ | |
2239 | + if(x!=*(char **)xarg) free(x); | |
2240 | + if(y!=*(char **)yarg) free(y); | |
2241 | + if(retval) break; | |
2242 | +#else | |
2243 | + /* Integer version of -n for tiny systems */ | |
2244 | + case FLAG_n: | |
2245 | + retval=atoi(x)-atoi(y); | |
2246 | + break; | |
2247 | + } | |
2248 | +#endif | |
2249 | } | |
2250 | + /* Perform fallback sort if necessary */ | |
2251 | + if(!retval && !(global_flags&FLAG_s)) | |
2252 | + retval=strcmp(*(char **)xarg, *(char **)yarg); | |
2253 | + return ((flags&FLAG_r)?-1:1)*retval; | |
2254 | +} | |
2255 | ||
2256 | - argv += optind; | |
2257 | - if (!*argv) { | |
2258 | - *--argv = "-"; | |
2259 | - } | |
2260 | +int sort_main(int argc, char **argv) | |
2261 | +{ | |
2262 | + FILE *fp,*outfile=NULL; | |
2263 | + int linecount=0,i,flag; | |
2264 | + char *line,**lines=NULL,c,*optlist="ngMucszbrdfimS:T:o:k:t:"; | |
2265 | ||
2266 | - do { | |
2267 | - fp = xgetoptfile_sort_uniq(argv, "r"); | |
2268 | - while ((line = bb_get_chomped_line_from_file(fp)) != NULL) { | |
2269 | - lines = xrealloc(lines, sizeof(char *) * (nlines + 1)); | |
2270 | - lines[nlines++] = line; | |
2271 | + bb_default_error_retval = 2; | |
2272 | + /* Parse command line options */ | |
2273 | + while((c=getopt(argc,argv,optlist))>0) { | |
2274 | + line=index(optlist,c); | |
2275 | + if(!line) bb_show_usage(); | |
2276 | + switch(*line) { | |
2277 | +#ifdef CONFIG_SORT_BIG | |
2278 | + case 'o': | |
2279 | + if(outfile) bb_error_msg_and_die("Too many -o."); | |
2280 | + outfile=bb_xfopen(optarg,"w"); | |
2281 | + break; | |
2282 | + case 't': | |
2283 | + if(key_separator || optarg[1]) | |
2284 | + bb_error_msg_and_die("Too many -t."); | |
2285 | + key_separator=*optarg; | |
2286 | + break; | |
2287 | + /* parse sort key */ | |
2288 | + case 'k': | |
2289 | + { | |
2290 | + struct sort_key *key=add_key(); | |
2291 | + char *temp, *temp2; | |
2292 | + | |
2293 | + temp=optarg; | |
2294 | + for(i=0;*temp;) { | |
2295 | + /* Start of range */ | |
2296 | + key->range[2*i]=(unsigned short)strtol(temp,&temp,10); | |
2297 | + if(*temp=='.') | |
2298 | + key->range[(2*i)+1]=(unsigned short)strtol(temp+1,&temp,10); | |
2299 | + for(;*temp;temp++) { | |
2300 | + if(*temp==',' && !i++) { | |
2301 | + temp++; | |
2302 | + break; | |
2303 | + } /* no else needed: fall through to syntax error | |
2304 | + because comma isn't in optlist */ | |
2305 | + temp2=index(optlist,*temp); | |
2306 | + flag=(1<<(temp2-optlist)); | |
2307 | + if(!temp2 || (flag>FLAG_M && flag<FLAG_b)) | |
2308 | + bb_error_msg_and_die("Unknown key option."); | |
2309 | + /* b after , means strip _trailing_ space */ | |
2310 | + if(i && flag==FLAG_b) flag=FLAG_bb; | |
2311 | + key->flags|=flag; | |
2312 | + } | |
2313 | + } | |
2314 | + break; | |
2315 | + } | |
2316 | +#endif | |
2317 | + default: | |
2318 | + global_flags|=(1<<(line-optlist)); | |
2319 | + /* global b strips leading and trailing spaces */ | |
2320 | + if(global_flags&FLAG_b) global_flags|=FLAG_bb; | |
2321 | + break; | |
2322 | } | |
2323 | - bb_xferror(fp, *argv); | |
2324 | - bb_fclose_nonstdin(fp); | |
2325 | - } while (*++argv); | |
2326 | - | |
2327 | - /* sort it */ | |
2328 | - qsort(lines, nlines, sizeof(char *), compare); | |
2329 | - | |
2330 | - /* print it */ | |
2331 | - i = 0; | |
2332 | - --nlines; | |
2333 | - if ((inc = 1 - (flags & 2)) < 0) { /* reverse */ | |
2334 | - i = nlines; | |
2335 | } | |
2336 | - flags &= 4; | |
2337 | - | |
2338 | - while (nlines >= 0) { | |
2339 | - if (!flags || !nlines || strcmp(lines[i+inc], lines[i])) { | |
2340 | - puts(lines[i]); | |
2341 | + /* Open input files and read data */ | |
2342 | + for(i=argv[optind] ? optind : optind-1;argv[i];i++) { | |
2343 | + if(i<optind || (*argv[i]=='-' && !argv[i][1])) fp=stdin; | |
2344 | + else fp=bb_xfopen(argv[i],"r"); | |
2345 | + for(;;) { | |
2346 | + line=GET_LINE(fp); | |
2347 | + if(!line) break; | |
2348 | + if(!(linecount&63)) | |
2349 | + lines=xrealloc(lines, sizeof(char *)*(linecount+64)); | |
2350 | + lines[linecount++]=line; | |
2351 | } | |
2352 | - i += inc; | |
2353 | - --nlines; | |
2354 | + fclose(fp); | |
2355 | } | |
2356 | - | |
2357 | +#ifdef CONFIG_SORT_BIG | |
2358 | + /* if no key, perform alphabetic sort */ | |
2359 | + if(!key_list) add_key()->range[0]=1; | |
2360 | + /* handle -c */ | |
2361 | + if(global_flags&FLAG_c) { | |
2362 | + int j=(global_flags&FLAG_u) ? -1 : 0; | |
2363 | + for(i=1;i<linecount;i++) | |
2364 | + if(compare_keys(&lines[i-1],&lines[i])>j) { | |
2365 | + fprintf(stderr,"Check line %d\n",i); | |
2366 | + return 1; | |
2367 | + } | |
2368 | + return 0; | |
2369 | + } | |
2370 | +#endif | |
2371 | + /* Perform the actual sort */ | |
2372 | + qsort(lines,linecount,sizeof(char *),compare_keys); | |
2373 | + /* handle -u */ | |
2374 | + if(global_flags&FLAG_u) { | |
2375 | + for(flag=0,i=1;i<linecount;i++) { | |
2376 | + if(!compare_keys(&lines[flag],&lines[i])) free(lines[i]); | |
2377 | + else lines[++flag]=lines[i]; | |
2378 | + } | |
2379 | + if(linecount) linecount=flag+1; | |
2380 | + } | |
2381 | + /* Print it */ | |
2382 | + if(!outfile) outfile=stdout; | |
2383 | + for(i=0;i<linecount;i++) fprintf(outfile,"%s\n",lines[i]); | |
2384 | bb_fflush_stdout_and_exit(EXIT_SUCCESS); | |
2385 | } | |
2386 | diff -Nur busybox-1.00/coreutils/stat.c busybox/coreutils/stat.c | |
2387 | --- busybox-1.00/coreutils/stat.c 1970-01-01 01:00:00.000000000 +0100 | |
2388 | +++ busybox/coreutils/stat.c 2005-06-04 08:20:13.000000000 +0200 | |
2389 | @@ -0,0 +1,564 @@ | |
2390 | +/* | |
2391 | + * stat -- display file or file system status | |
2392 | + * | |
2393 | + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation. | |
2394 | + * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org> | |
2395 | + * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org> | |
2396 | + * | |
2397 | + * Written by Michael Meskes | |
2398 | + * Taken from coreutils and turned into a busybox applet by Mike Frysinger | |
2399 | + * | |
2400 | + * This program is free software; you can redistribute it and/or modify | |
2401 | + * it under the terms of the GNU General Public License as published by | |
2402 | + * the Free Software Foundation; either version 2 of the License, or | |
2403 | + * (at your option) any later version. | |
2404 | + * | |
2405 | + * This program is distributed in the hope that it will be useful, | |
2406 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2407 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
2408 | + * General Public License for more details. | |
2409 | + * | |
2410 | + * You should have received a copy of the GNU General Public License | |
2411 | + * along with this program; if not, write to the Free Software | |
2412 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
2413 | + * | |
2414 | + */ | |
2415 | + | |
2416 | +#include <stdio.h> | |
2417 | +#include <sys/types.h> | |
2418 | +#include <pwd.h> | |
2419 | +#include <grp.h> | |
2420 | +#include <sys/vfs.h> | |
2421 | +#include <time.h> | |
2422 | +#include <getopt.h> | |
2423 | +#include <sys/stat.h> | |
2424 | +#include <string.h> | |
2425 | +#include "busybox.h" | |
2426 | + | |
2427 | +/* vars to control behavior */ | |
2428 | +#define OPT_TERSE 2 | |
2429 | +#define OPT_DEREFERNCE 4 | |
2430 | +static long flags; | |
2431 | + | |
2432 | +static char const *file_type(struct stat const *st) | |
2433 | +{ | |
2434 | + /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107 | |
2435 | + * for some of these formats. | |
2436 | + * To keep diagnostics grammatical in English, the | |
2437 | + * returned string must start with a consonant. | |
2438 | + */ | |
2439 | + if (S_ISREG(st->st_mode)) return st->st_size == 0 ? "regular empty file" : "regular file"; | |
2440 | + if (S_ISDIR(st->st_mode)) return "directory"; | |
2441 | + if (S_ISBLK(st->st_mode)) return "block special file"; | |
2442 | + if (S_ISCHR(st->st_mode)) return "character special file"; | |
2443 | + if (S_ISFIFO(st->st_mode)) return "fifo"; | |
2444 | + if (S_ISLNK(st->st_mode)) return "symbolic link"; | |
2445 | + if (S_ISSOCK(st->st_mode)) return "socket"; | |
2446 | + if (S_TYPEISMQ(st)) return "message queue"; | |
2447 | + if (S_TYPEISSEM(st)) return "semaphore"; | |
2448 | + if (S_TYPEISSHM(st)) return "shared memory object"; | |
2449 | +#ifdef S_TYPEISTMO | |
2450 | + if (S_TYPEISTMO(st)) return "typed memory object"; | |
2451 | +#endif | |
2452 | + return "weird file"; | |
2453 | +} | |
2454 | + | |
2455 | +static char const *human_time(time_t t) | |
2456 | +{ | |
2457 | + static char *str; | |
2458 | + str = ctime(&t); | |
2459 | + str[strlen(str)-1] = '\0'; | |
2460 | + return str; | |
2461 | +} | |
2462 | + | |
2463 | +/* Return the type of the specified file system. | |
2464 | + * Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris) | |
2465 | + * Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2) | |
2466 | + * Still others have neither and have to get by with f_type (Linux). | |
2467 | + */ | |
2468 | +static char const *human_fstype(long f_type) | |
2469 | +{ | |
2470 | + int i; | |
2471 | + static struct types { | |
2472 | + long type; | |
2473 | + char *fs; | |
2474 | + } humantypes[] = { | |
2475 | + { 0xADFF, "affs" }, | |
2476 | + { 0x1Cd1, "devpts" }, | |
2477 | + { 0x137D, "ext" }, | |
2478 | + { 0xEF51, "ext2" }, | |
2479 | + { 0xEF53, "ext2/ext3" }, | |
2480 | + { 0x3153464a, "jfs" }, | |
2481 | + { 0x58465342, "xfs" }, | |
2482 | + { 0xF995E849, "hpfs" }, | |
2483 | + { 0x9660, "isofs" }, | |
2484 | + { 0x4000, "isofs" }, | |
2485 | + { 0x4004, "isofs" }, | |
2486 | + { 0x137F, "minix" }, | |
2487 | + { 0x138F, "minix (30 char.)" }, | |
2488 | + { 0x2468, "minix v2" }, | |
2489 | + { 0x2478, "minix v2 (30 char.)" }, | |
2490 | + { 0x4d44, "msdos" }, | |
2491 | + { 0x4006, "fat" }, | |
2492 | + { 0x564c, "novell" }, | |
2493 | + { 0x6969, "nfs" }, | |
2494 | + { 0x9fa0, "proc" }, | |
2495 | + { 0x517B, "smb" }, | |
2496 | + { 0x012FF7B4, "xenix" }, | |
2497 | + { 0x012FF7B5, "sysv4" }, | |
2498 | + { 0x012FF7B6, "sysv2" }, | |
2499 | + { 0x012FF7B7, "coh" }, | |
2500 | + { 0x00011954, "ufs" }, | |
2501 | + { 0x012FD16D, "xia" }, | |
2502 | + { 0x5346544e, "ntfs" }, | |
2503 | + { 0x1021994, "tmpfs" }, | |
2504 | + { 0x52654973, "reiserfs" }, | |
2505 | + { 0x28cd3d45, "cramfs" }, | |
2506 | + { 0x7275, "romfs" }, | |
2507 | + { 0x858458f6, "romfs" }, | |
2508 | + { 0x73717368, "squashfs" }, | |
2509 | + { 0x62656572, "sysfs" }, | |
2510 | + { 0, "UNKNOWN" }, | |
2511 | + { 0, NULL } | |
2512 | + }; | |
2513 | + for (i=0; humantypes[i].type; ++i) | |
2514 | + if (humantypes[i].type == f_type) | |
2515 | + return humantypes[i].fs; | |
2516 | + return humantypes[i].fs; | |
2517 | +} | |
2518 | + | |
2519 | +#ifdef CONFIG_FEATURE_STAT_FORMAT | |
2520 | +/* print statfs info */ | |
2521 | +static void print_statfs(char *pformat, size_t buf_len, char m, | |
2522 | + char const *filename, void const *data) | |
2523 | +{ | |
2524 | + struct statfs const *statfsbuf = data; | |
2525 | + | |
2526 | + switch (m) { | |
2527 | + case 'n': | |
2528 | + strncat(pformat, "s", buf_len); | |
2529 | + printf(pformat, filename); | |
2530 | + break; | |
2531 | + case 'i': | |
2532 | + strncat(pformat, "Lx", buf_len); | |
2533 | + printf(pformat, statfsbuf->f_fsid); | |
2534 | + break; | |
2535 | + case 'l': | |
2536 | + strncat(pformat, "lu", buf_len); | |
2537 | + printf(pformat, statfsbuf->f_namelen); | |
2538 | + break; | |
2539 | + case 't': | |
2540 | + strncat(pformat, "lx", buf_len); | |
2541 | + printf(pformat, (unsigned long int) (statfsbuf->f_type)); /* no equiv. */ | |
2542 | + break; | |
2543 | + case 'T': | |
2544 | + strncat(pformat, "s", buf_len); | |
2545 | + printf(pformat, human_fstype(statfsbuf->f_type)); | |
2546 | + break; | |
2547 | + case 'b': | |
2548 | + strncat(pformat, "ld", buf_len); | |
2549 | + printf(pformat, (intmax_t) (statfsbuf->f_blocks)); | |
2550 | + break; | |
2551 | + case 'f': | |
2552 | + strncat(pformat, "ld", buf_len); | |
2553 | + printf(pformat, (intmax_t) (statfsbuf->f_bfree)); | |
2554 | + break; | |
2555 | + case 'a': | |
2556 | + strncat(pformat, "ld", buf_len); | |
2557 | + printf(pformat, (intmax_t) (statfsbuf->f_bavail)); | |
2558 | + break; | |
2559 | + case 's': | |
2560 | + strncat(pformat, "lu", buf_len); | |
2561 | + printf(pformat, (unsigned long int) (statfsbuf->f_bsize)); | |
2562 | + break; | |
2563 | + case 'S': { | |
2564 | + unsigned long int frsize = statfsbuf->f_frsize; | |
2565 | + if (!frsize) | |
2566 | + frsize = statfsbuf->f_bsize; | |
2567 | + strncat(pformat, "lu", buf_len); | |
2568 | + printf(pformat, frsize); | |
2569 | + break; | |
2570 | + } | |
2571 | + case 'c': | |
2572 | + strncat(pformat, "ld", buf_len); | |
2573 | + printf(pformat, (intmax_t) (statfsbuf->f_files)); | |
2574 | + break; | |
2575 | + case 'd': | |
2576 | + strncat(pformat, "ld", buf_len); | |
2577 | + printf(pformat, (intmax_t) (statfsbuf->f_ffree)); | |
2578 | + break; | |
2579 | + default: | |
2580 | + strncat(pformat, "c", buf_len); | |
2581 | + printf(pformat, m); | |
2582 | + break; | |
2583 | + } | |
2584 | +} | |
2585 | + | |
2586 | +/* print stat info */ | |
2587 | +static void print_stat(char *pformat, size_t buf_len, char m, | |
2588 | + char const *filename, void const *data) | |
2589 | +{ | |
2590 | +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) | |
2591 | + struct stat *statbuf = (struct stat *) data; | |
2592 | + struct passwd *pw_ent; | |
2593 | + struct group *gw_ent; | |
2594 | + | |
2595 | + switch (m) { | |
2596 | + case 'n': | |
2597 | + strncat(pformat, "s", buf_len); | |
2598 | + printf(pformat, filename); | |
2599 | + break; | |
2600 | + case 'N': | |
2601 | + strncat(pformat, "s", buf_len); | |
2602 | + if (S_ISLNK(statbuf->st_mode)) { | |
2603 | + char *linkname = xreadlink(filename); | |
2604 | + if (linkname == NULL) { | |
2605 | + bb_perror_msg("cannot read symbolic link '%s'", filename); | |
2606 | + return; | |
2607 | + } | |
2608 | + /*printf("\"%s\" -> \"%s\"", filename, linkname); */ | |
2609 | + printf(pformat, filename); | |
2610 | + printf(" -> "); | |
2611 | + printf(pformat, linkname); | |
2612 | + } else { | |
2613 | + printf(pformat, filename); | |
2614 | + } | |
2615 | + break; | |
2616 | + case 'd': | |
2617 | + strncat(pformat, "lu", buf_len); | |
2618 | + printf(pformat, (uintmax_t) statbuf->st_dev); | |
2619 | + break; | |
2620 | + case 'D': | |
2621 | + strncat(pformat, "lx", buf_len); | |
2622 | + printf(pformat, (uintmax_t) statbuf->st_dev); | |
2623 | + break; | |
2624 | + case 'i': | |
2625 | + strncat(pformat, "lu", buf_len); | |
2626 | + printf(pformat, (uintmax_t) statbuf->st_ino); | |
2627 | + break; | |
2628 | + case 'a': | |
2629 | + strncat(pformat, "lo", buf_len); | |
2630 | + printf(pformat, (unsigned long int) (statbuf->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO))); | |
2631 | + break; | |
2632 | + case 'A': | |
2633 | + strncat(pformat, "s", buf_len); | |
2634 | + printf(pformat, bb_mode_string(statbuf->st_mode)); | |
2635 | + break; | |
2636 | + case 'f': | |
2637 | + strncat(pformat, "lx", buf_len); | |
2638 | + printf(pformat, (unsigned long int) statbuf->st_mode); | |
2639 | + break; | |
2640 | + case 'F': | |
2641 | + strncat(pformat, "s", buf_len); | |
2642 | + printf(pformat, file_type(statbuf)); | |
2643 | + break; | |
2644 | + case 'h': | |
2645 | + strncat(pformat, "lu", buf_len); | |
2646 | + printf(pformat, (unsigned long int) statbuf->st_nlink); | |
2647 | + break; | |
2648 | + case 'u': | |
2649 | + strncat(pformat, "lu", buf_len); | |
2650 | + printf(pformat, (unsigned long int) statbuf->st_uid); | |
2651 | + break; | |
2652 | + case 'U': | |
2653 | + strncat(pformat, "s", buf_len); | |
2654 | + setpwent(); | |
2655 | + pw_ent = getpwuid(statbuf->st_uid); | |
2656 | + printf(pformat, (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN"); | |
2657 | + break; | |
2658 | + case 'g': | |
2659 | + strncat(pformat, "lu", buf_len); | |
2660 | + printf(pformat, (unsigned long int) statbuf->st_gid); | |
2661 | + break; | |
2662 | + case 'G': | |
2663 | + strncat(pformat, "s", buf_len); | |
2664 | + setgrent(); | |
2665 | + gw_ent = getgrgid(statbuf->st_gid); | |
2666 | + printf(pformat, (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN"); | |
2667 | + break; | |
2668 | + case 't': | |
2669 | + strncat(pformat, "lx", buf_len); | |
2670 | + printf(pformat, (unsigned long int) major(statbuf->st_rdev)); | |
2671 | + break; | |
2672 | + case 'T': | |
2673 | + strncat(pformat, "lx", buf_len); | |
2674 | + printf(pformat, (unsigned long int) minor(statbuf->st_rdev)); | |
2675 | + break; | |
2676 | + case 's': | |
2677 | + strncat(pformat, "lu", buf_len); | |
2678 | + printf(pformat, (uintmax_t) (statbuf->st_size)); | |
2679 | + break; | |
2680 | + case 'B': | |
2681 | + strncat(pformat, "lu", buf_len); | |
2682 | + printf(pformat, (unsigned long int) 512); //ST_NBLOCKSIZE | |
2683 | + break; | |
2684 | + case 'b': | |
2685 | + strncat(pformat, "lu", buf_len); | |
2686 | + printf(pformat, (uintmax_t) statbuf->st_blocks); | |
2687 | + break; | |
2688 | + case 'o': | |
2689 | + strncat(pformat, "lu", buf_len); | |
2690 | + printf(pformat, (unsigned long int) statbuf->st_blksize); | |
2691 | + break; | |
2692 | + case 'x': | |
2693 | + strncat(pformat, "s", buf_len); | |
2694 | + printf(pformat, human_time(statbuf->st_atime)); | |
2695 | + break; | |
2696 | + case 'X': | |
2697 | + strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len); | |
2698 | + printf(pformat, (unsigned long int) statbuf->st_atime); | |
2699 | + break; | |
2700 | + case 'y': | |
2701 | + strncat(pformat, "s", buf_len); | |
2702 | + printf(pformat, human_time(statbuf->st_mtime)); | |
2703 | + break; | |
2704 | + case 'Y': | |
2705 | + strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len); | |
2706 | + printf(pformat, (unsigned long int) statbuf->st_mtime); | |
2707 | + break; | |
2708 | + case 'z': | |
2709 | + strncat(pformat, "s", buf_len); | |
2710 | + printf(pformat, human_time(statbuf->st_ctime)); | |
2711 | + break; | |
2712 | + case 'Z': | |
2713 | + strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len); | |
2714 | + printf(pformat, (unsigned long int) statbuf->st_ctime); | |
2715 | + break; | |
2716 | + default: | |
2717 | + strncat(pformat, "c", buf_len); | |
2718 | + printf(pformat, m); | |
2719 | + break; | |
2720 | + } | |
2721 | +} | |
2722 | + | |
2723 | +static void print_it(char const *masterformat, char const *filename, | |
2724 | + void (*print_func) (char *, size_t, char, char const *, void const *), | |
2725 | + void const *data) | |
2726 | +{ | |
2727 | + char *b; | |
2728 | + | |
2729 | + /* create a working copy of the format string */ | |
2730 | + char *format = bb_xstrdup(masterformat); | |
2731 | + | |
2732 | + /* Add 2 to accommodate our conversion of the stat `%s' format string | |
2733 | + * to the printf `%llu' one. */ | |
2734 | + size_t n_alloc = strlen(format) + 2 + 1; | |
2735 | + char *dest = xmalloc(n_alloc); | |
2736 | + | |
2737 | + b = format; | |
2738 | + while (b) { | |
2739 | + char *p = strchr(b, '%'); | |
2740 | + if (p != NULL) { | |
2741 | + size_t len; | |
2742 | + *p++ = '\0'; | |
2743 | + fputs(b, stdout); | |
2744 | + | |
2745 | + len = strspn(p, "#-+.I 0123456789"); | |
2746 | + dest[0] = '%'; | |
2747 | + memcpy(dest + 1, p, len); | |
2748 | + dest[1 + len] = 0; | |
2749 | + p += len; | |
2750 | + | |
2751 | + b = p + 1; | |
2752 | + switch (*p) { | |
2753 | + case '\0': | |
2754 | + b = NULL; | |
2755 | + /* fall through */ | |
2756 | + case '%': | |
2757 | + putchar('%'); | |
2758 | + break; | |
2759 | + default: | |
2760 | + print_func(dest, n_alloc, *p, filename, data); | |
2761 | + break; | |
2762 | + } | |
2763 | + | |
2764 | + } else { | |
2765 | + fputs(b, stdout); | |
2766 | + b = NULL; | |
2767 | + } | |
2768 | + } | |
2769 | + | |
2770 | + free(format); | |
2771 | + free(dest); | |
2772 | +} | |
2773 | +#endif | |
2774 | + | |
2775 | +/* Stat the file system and print what we find. */ | |
2776 | +static int do_statfs(char const *filename, char const *format) | |
2777 | +{ | |
2778 | + struct statfs statfsbuf; | |
2779 | + | |
2780 | + if (statfs(filename, &statfsbuf) != 0) { | |
2781 | + bb_perror_msg("cannot read file system information for '%s'", filename); | |
2782 | + return 0; | |
2783 | + } | |
2784 | + | |
2785 | +#ifdef CONFIG_FEATURE_STAT_FORMAT | |
2786 | + if (format == NULL) | |
2787 | + format = (flags & OPT_TERSE | |
2788 | + ? "%n %i %l %t %s %S %b %f %a %c %d\n" | |
2789 | + : " File: \"%n\"\n" | |
2790 | + " ID: %-8i Namelen: %-7l Type: %T\n" | |
2791 | + "Block size: %-10s Fundamental block size: %S\n" | |
2792 | + "Blocks: Total: %-10b Free: %-10f Available: %a\n" | |
2793 | + "Inodes: Total: %-10c Free: %d\n"); | |
2794 | + print_it(format, filename, print_statfs, &statfsbuf); | |
2795 | +#else | |
2796 | + | |
2797 | + format = (flags & OPT_TERSE | |
2798 | + ? "%s %Lx %lu " | |
2799 | + : " File: \"%s\"\n" | |
2800 | + " ID: %-8Lx Namelen: %-7lu "); | |
2801 | + printf(format, | |
2802 | + filename, | |
2803 | + statfsbuf.f_fsid, | |
2804 | + statfsbuf.f_namelen); | |
2805 | + | |
2806 | + if (flags & OPT_TERSE) | |
2807 | + printf("%lx ", (unsigned long int) (statfsbuf.f_type)); | |
2808 | + else | |
2809 | + printf("Type: %s\n", human_fstype(statfsbuf.f_type)); | |
2810 | + | |
2811 | + format = (flags & OPT_TERSE | |
2812 | + ? "%lu %lu %ld %ld %ld %ld %ld\n" | |
2813 | + : "Block size: %-10lu Fundamental block size: %lu\n" | |
2814 | + "Blocks: Total: %-10ld Free: %-10ld Available: %ld\n" | |
2815 | + "Inodes: Total: %-10ld Free: %ld\n"); | |
2816 | + printf(format, | |
2817 | + (unsigned long int) (statfsbuf.f_bsize), | |
2818 | + statfsbuf.f_frsize ? statfsbuf.f_frsize : statfsbuf.f_bsize, | |
2819 | + (intmax_t) (statfsbuf.f_blocks), | |
2820 | + (intmax_t) (statfsbuf.f_bfree), | |
2821 | + (intmax_t) (statfsbuf.f_bavail), | |
2822 | + (intmax_t) (statfsbuf.f_files), | |
2823 | + (intmax_t) (statfsbuf.f_ffree)); | |
2824 | +#endif | |
2825 | + | |
2826 | + return 1; | |
2827 | +} | |
2828 | + | |
2829 | +/* stat the file and print what we find */ | |
2830 | +static int do_stat(char const *filename, char const *format) | |
2831 | +{ | |
2832 | + struct stat statbuf; | |
2833 | + | |
2834 | + if ((flags & OPT_DEREFERNCE ? stat : lstat) (filename, &statbuf) != 0) { | |
2835 | + bb_perror_msg("cannot stat '%s'", filename); | |
2836 | + return 0; | |
2837 | + } | |
2838 | + | |
2839 | +#ifdef CONFIG_FEATURE_STAT_FORMAT | |
2840 | + if (format == NULL) { | |
2841 | + if (flags & OPT_TERSE) { | |
2842 | + format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n"; | |
2843 | + } else { | |
2844 | + if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) { | |
2845 | + format = | |
2846 | + " File: \"%N\"\n" | |
2847 | + " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n" | |
2848 | + "Device: %Dh/%dd\tInode: %-10i Links: %-5h" | |
2849 | + " Device type: %t,%T\n" | |
2850 | + "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" | |
2851 | + "Access: %x\n" "Modify: %y\n" "Change: %z\n"; | |
2852 | + } else { | |
2853 | + format = | |
2854 | + " File: \"%N\"\n" | |
2855 | + " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n" | |
2856 | + "Device: %Dh/%dd\tInode: %-10i Links: %h\n" | |
2857 | + "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" | |
2858 | + "Access: %x\n" "Modify: %y\n" "Change: %z\n"; | |
2859 | + } | |
2860 | + } | |
2861 | + } | |
2862 | + print_it(format, filename, print_stat, &statbuf); | |
2863 | +#else | |
2864 | + if (flags & OPT_TERSE) { | |
2865 | + printf("%s %lu %lu %lx %lu %lu %lx %lu %lu %lx %lx %lu %lu %lu %lu\n", | |
2866 | + filename, | |
2867 | + (uintmax_t) (statbuf.st_size), | |
2868 | + (uintmax_t) statbuf.st_blocks, | |
2869 | + (unsigned long int) statbuf.st_mode, | |
2870 | + (unsigned long int) statbuf.st_uid, | |
2871 | + (unsigned long int) statbuf.st_gid, | |
2872 | + (uintmax_t) statbuf.st_dev, | |
2873 | + (uintmax_t) statbuf.st_ino, | |
2874 | + (unsigned long int) statbuf.st_nlink, | |
2875 | + (unsigned long int) major(statbuf.st_rdev), | |
2876 | + (unsigned long int) minor(statbuf.st_rdev), | |
2877 | + (unsigned long int) statbuf.st_atime, | |
2878 | + (unsigned long int) statbuf.st_mtime, | |
2879 | + (unsigned long int) statbuf.st_ctime, | |
2880 | + (unsigned long int) statbuf.st_blksize | |
2881 | + ); | |
2882 | + } else { | |
2883 | + char *linkname = NULL; | |
2884 | + | |
2885 | + struct passwd *pw_ent; | |
2886 | + struct group *gw_ent; | |
2887 | + setgrent(); | |
2888 | + gw_ent = getgrgid(statbuf.st_gid); | |
2889 | + setpwent(); | |
2890 | + pw_ent = getpwuid(statbuf.st_uid); | |
2891 | + | |
2892 | + if (S_ISLNK(statbuf.st_mode)) | |
2893 | + linkname = xreadlink(filename); | |
2894 | + if (linkname) | |
2895 | + printf(" File: \"%s\" -> \"%s\"\n", filename, linkname); | |
2896 | + else | |
2897 | + printf(" File: \"%s\"\n", filename); | |
2898 | + | |
2899 | + printf(" Size: %-10lu\tBlocks: %-10lu IO Block: %-6lu %s\n" | |
2900 | + "Device: %lxh/%lud\tInode: %-10lu Links: %-5lu", | |
2901 | + (uintmax_t) (statbuf.st_size), | |
2902 | + (uintmax_t) statbuf.st_blocks, | |
2903 | + (unsigned long int) statbuf.st_blksize, | |
2904 | + file_type(&statbuf), | |
2905 | + (uintmax_t) statbuf.st_dev, | |
2906 | + (uintmax_t) statbuf.st_dev, | |
2907 | + (uintmax_t) statbuf.st_ino, | |
2908 | + (unsigned long int) statbuf.st_nlink); | |
2909 | + if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) | |
2910 | + printf(" Device type: %lx,%lx\n", | |
2911 | + (unsigned long int) major(statbuf.st_rdev), | |
2912 | + (unsigned long int) minor(statbuf.st_rdev)); | |
2913 | + else | |
2914 | + putchar('\n'); | |
2915 | + printf("Access: (%04lo/%10.10s) Uid: (%5lu/%8s) Gid: (%5lu/%8s)\n" | |
2916 | + "Access: %s\n" "Modify: %s\n" "Change: %s\n", | |
2917 | + (unsigned long int) (statbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), | |
2918 | + bb_mode_string(statbuf.st_mode), | |
2919 | + (unsigned long int) statbuf.st_uid, | |
2920 | + (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN", | |
2921 | + (unsigned long int) statbuf.st_gid, | |
2922 | + (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN", | |
2923 | + human_time(statbuf.st_atime), | |
2924 | + human_time(statbuf.st_mtime), | |
2925 | + human_time(statbuf.st_ctime)); | |
2926 | + } | |
2927 | +#endif | |
2928 | + return 1; | |
2929 | +} | |
2930 | + | |
2931 | +int stat_main(int argc, char **argv) | |
2932 | +{ | |
2933 | + int i; | |
2934 | + char *format = NULL; | |
2935 | + int ok = 1; | |
2936 | + int (*statfunc)(char const *, char const *) = do_stat; | |
2937 | + | |
2938 | + flags = bb_getopt_ulflags(argc, argv, "ftL" | |
2939 | +#ifdef CONFIG_FEATURE_STAT_FORMAT | |
2940 | + "c:", &format | |
2941 | +#endif | |
2942 | + ); | |
2943 | + | |
2944 | + if (flags & 1) /* -f */ | |
2945 | + statfunc = do_statfs; | |
2946 | + if (argc == optind) /* files */ | |
2947 | + bb_show_usage(); | |
2948 | + | |
2949 | + for (i = optind; i < argc; ++i) | |
2950 | + ok &= statfunc(argv[i], format); | |
2951 | + | |
2952 | + return (ok ? EXIT_SUCCESS : EXIT_FAILURE); | |
2953 | +} | |
2954 | diff -Nur busybox-1.00/coreutils/sum.c busybox/coreutils/sum.c | |
2955 | --- busybox-1.00/coreutils/sum.c 1970-01-01 01:00:00.000000000 +0100 | |
2956 | +++ busybox/coreutils/sum.c 2005-06-04 08:20:13.000000000 +0200 | |
2957 | @@ -0,0 +1,181 @@ | |
2958 | +/* | |
2959 | + * sum -- checksum and count the blocks in a file | |
2960 | + * Like BSD sum or SysV sum -r, except like SysV sum if -s option is given. | |
2961 | + * | |
2962 | + * Copyright (C) 86, 89, 91, 1995-2002, 2004 Free Software Foundation, Inc. | |
2963 | + * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org> | |
2964 | + * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org> | |
2965 | + * | |
2966 | + * Written by Kayvan Aghaiepour and David MacKenzie | |
2967 | + * Taken from coreutils and turned into a busybox applet by Mike Frysinger | |
2968 | + * | |
2969 | + * This program is free software; you can redistribute it and/or modify | |
2970 | + * it under the terms of the GNU General Public License as published by | |
2971 | + * the Free Software Foundation; either version 2 of the License, or | |
2972 | + * (at your option) any later version. | |
2973 | + * | |
2974 | + * This program is distributed in the hope that it will be useful, | |
2975 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2976 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
2977 | + * General Public License for more details. | |
2978 | + * | |
2979 | + * You should have received a copy of the GNU General Public License | |
2980 | + * along with this program; if not, write to the Free Software | |
2981 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
2982 | + * | |
2983 | + */ | |
2984 | + | |
2985 | +#include <stdio.h> | |
2986 | +#include <sys/types.h> | |
2987 | +#include <sys/stat.h> | |
2988 | +#include <fcntl.h> | |
2989 | +#include <unistd.h> | |
2990 | +#include <getopt.h> | |
2991 | + | |
2992 | +#include "libbb.h" | |
2993 | + | |
2994 | +/* 1 if any of the files read were the standard input */ | |
2995 | +static int have_read_stdin; | |
2996 | + | |
2997 | +/* make a little more readable and avoid using strcmp for just 2 bytes */ | |
2998 | +#define IS_STDIN(s) (s[0] == '-' && s[1] == '\0') | |
2999 | + | |
3000 | +/* Calculate and print the rotated checksum and the size in 1K blocks | |
3001 | + of file FILE, or of the standard input if FILE is "-". | |
3002 | + If PRINT_NAME is >1, print FILE next to the checksum and size. | |
3003 | + The checksum varies depending on sizeof (int). | |
3004 | + Return 1 if successful. */ | |
3005 | +static int bsd_sum_file(const char *file, int print_name) | |
3006 | +{ | |
3007 | + register FILE *fp; | |
3008 | + register int checksum = 0; /* The checksum mod 2^16. */ | |
3009 | + register uintmax_t total_bytes = 0; /* The number of bytes. */ | |
3010 | + register int ch; /* Each character read. */ | |
3011 | + | |
3012 | + if (IS_STDIN(file)) { | |
3013 | + fp = stdin; | |
3014 | + have_read_stdin = 1; | |
3015 | + } else { | |
3016 | + fp = bb_wfopen(file, "r"); | |
3017 | + if (fp == NULL) | |
3018 | + return 0; | |
3019 | + } | |
3020 | + | |
3021 | + while ((ch = getc(fp)) != EOF) { | |
3022 | + ++total_bytes; | |
3023 | + checksum = (checksum >> 1) + ((checksum & 1) << 15); | |
3024 | + checksum += ch; | |
3025 | + checksum &= 0xffff; /* Keep it within bounds. */ | |
3026 | + } | |
3027 | + | |
3028 | + if (ferror(fp)) { | |
3029 | + bb_perror_msg(file); | |
3030 | + bb_fclose_nonstdin(fp); | |
3031 | + return 0; | |
3032 | + } | |
3033 | + | |
3034 | + if (bb_fclose_nonstdin(fp) == EOF) { | |
3035 | + bb_perror_msg(file); | |
3036 | + return 0; | |
3037 | + } | |
3038 | + | |
3039 | + printf("%05d %5s ", checksum, | |
3040 | + make_human_readable_str(total_bytes, 1, 1024)); | |
3041 | + if (print_name > 1) | |
3042 | + puts(file); | |
3043 | + else | |
3044 | + printf("\n"); | |
3045 | + | |
3046 | + return 1; | |
3047 | +} | |
3048 | + | |
3049 | +/* Calculate and print the checksum and the size in 512-byte blocks | |
3050 | + of file FILE, or of the standard input if FILE is "-". | |
3051 | + If PRINT_NAME is >0, print FILE next to the checksum and size. | |
3052 | + Return 1 if successful. */ | |
3053 | +static int sysv_sum_file(const char *file, int print_name) | |
3054 | +{ | |
3055 | + int fd; | |
3056 | + unsigned char buf[8192]; | |
3057 | + uintmax_t total_bytes = 0; | |
3058 | + int r; | |
3059 | + int checksum; | |
3060 | + | |
3061 | + /* The sum of all the input bytes, modulo (UINT_MAX + 1). */ | |
3062 | + unsigned int s = 0; | |
3063 | + | |
3064 | + if (IS_STDIN(file)) { | |
3065 | + fd = 0; | |
3066 | + have_read_stdin = 1; | |
3067 | + } else { | |
3068 | + fd = open(file, O_RDONLY); | |
3069 | + if (fd == -1) { | |
3070 | + bb_perror_msg(file); | |
3071 | + return 0; | |
3072 | + } | |
3073 | + } | |
3074 | + | |
3075 | + while (1) { | |
3076 | + size_t i; | |
3077 | + size_t bytes_read = safe_read(fd, buf, sizeof(buf)); | |
3078 | + | |
3079 | + if (bytes_read == 0) | |
3080 | + break; | |
3081 | + | |
3082 | + if (bytes_read == -1) { | |
3083 | + bb_perror_msg(file); | |
3084 | + if (!IS_STDIN(file)) | |
3085 | + close(fd); | |
3086 | + return 0; | |
3087 | + } | |
3088 | + | |
3089 | + for (i = 0; i < bytes_read; i++) | |
3090 | + s += buf[i]; | |
3091 | + total_bytes += bytes_read; | |
3092 | + } | |
3093 | + | |
3094 | + if (!IS_STDIN(file) && close(fd) == -1) { | |
3095 | + bb_perror_msg(file); | |
3096 | + return 0; | |
3097 | + } | |
3098 | + | |
3099 | + r = (s & 0xffff) + ((s & 0xffffffff) >> 16); | |
3100 | + checksum = (r & 0xffff) + (r >> 16); | |
3101 | + | |
3102 | + printf("%d %s ", checksum, | |
3103 | + make_human_readable_str(total_bytes, 1, 512)); | |
3104 | + if (print_name) | |
3105 | + puts(file); | |
3106 | + else | |
3107 | + printf("\n"); | |
3108 | + | |
3109 | + return 1; | |
3110 | +} | |
3111 | + | |
3112 | +int sum_main(int argc, char **argv) | |
3113 | +{ | |
3114 | + int flags; | |
3115 | + int ok; | |
3116 | + int files_given; | |
3117 | + int (*sum_func)(const char *, int) = bsd_sum_file; | |
3118 | + | |
3119 | + /* give the bsd func priority over sysv func */ | |
3120 | + flags = bb_getopt_ulflags(argc, argv, "sr"); | |
3121 | + if (flags & 1) | |
3122 | + sum_func = sysv_sum_file; | |
3123 | + if (flags & 2) | |
3124 | + sum_func = bsd_sum_file; | |
3125 | + | |
3126 | + have_read_stdin = 0; | |
3127 | + files_given = argc - optind; | |
3128 | + if (files_given <= 0) | |
3129 | + ok = sum_func("-", files_given); | |
3130 | + else | |
3131 | + for (ok = 1; optind < argc; optind++) | |
3132 | + ok &= sum_func(argv[optind], files_given); | |
3133 | + | |
3134 | + if (have_read_stdin && fclose(stdin) == EOF) | |
3135 | + bb_perror_msg_and_die("-"); | |
3136 | + | |
3137 | + exit(ok ? EXIT_SUCCESS : EXIT_FAILURE); | |
3138 | +} | |
3139 | diff -Nur busybox-1.00/coreutils/test.c busybox/coreutils/test.c | |
3140 | --- busybox-1.00/coreutils/test.c 2004-08-11 04:45:47.000000000 +0200 | |
3141 | +++ busybox/coreutils/test.c 2005-06-04 08:20:13.000000000 +0200 | |
3142 | @@ -51,7 +51,7 @@ | |
3143 | unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| | |
3144 | "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; | |
3145 | ||
3146 | - binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| | |
3147 | + binary-operator ::= "="|"=="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| | |
3148 | "-nt"|"-ot"|"-ef"; | |
3149 | operand ::= <any legal UNIX file name> | |
3150 | */ | |
3151 | @@ -135,6 +135,7 @@ | |
3152 | "-L", FILSYM, UNOP}, { | |
3153 | "-S", FILSOCK, UNOP}, { | |
3154 | "=", STREQ, BINOP}, { | |
3155 | + "==", STREQ, BINOP}, { | |
3156 | "!=", STRNE, BINOP}, { | |
3157 | "<", STRLT, BINOP}, { | |
3158 | ">", STRGT, BINOP}, { | |
3159 | @@ -191,6 +192,11 @@ | |
3160 | bb_error_msg_and_die("missing ]"); | |
3161 | argv[argc] = NULL; | |
3162 | } | |
3163 | + if (strcmp(bb_applet_name, "[[") == 0) { | |
3164 | + if (strcmp(argv[--argc], "]]")) | |
3165 | + bb_error_msg_and_die("missing ]]"); | |
3166 | + argv[argc] = NULL; | |
3167 | + } | |
3168 | /* Implement special cases from POSIX.2, section 4.62.4 */ | |
3169 | switch (argc) { | |
3170 | case 1: | |
3171 | @@ -304,7 +310,7 @@ | |
3172 | return strlen(*t_wp) > 0; | |
3173 | } | |
3174 | ||
3175 | -static int binop() | |
3176 | +static int binop(void) | |
3177 | { | |
3178 | const char *opnd1, *opnd2; | |
3179 | struct t_op const *op; | |
3180 | @@ -531,7 +537,7 @@ | |
3181 | return (-1); | |
3182 | } | |
3183 | ||
3184 | -static void initialize_group_array() | |
3185 | +static void initialize_group_array(void) | |
3186 | { | |
3187 | ngroups = getgroups(0, NULL); | |
3188 | group_array = xrealloc(group_array, ngroups * sizeof(gid_t)); | |
3189 | diff -Nur busybox-1.00/coreutils/watch.c busybox/coreutils/watch.c | |
3190 | --- busybox-1.00/coreutils/watch.c 2003-03-19 10:11:34.000000000 +0100 | |
3191 | +++ busybox/coreutils/watch.c 2005-06-04 08:20:13.000000000 +0200 | |
3192 | @@ -100,11 +100,10 @@ | |
3193 | //child | |
3194 | close(1); | |
3195 | dup(old_stdout); | |
3196 | - if (execvp(*watched_argv, watched_argv)) { | |
3197 | - bb_error_msg_and_die("Couldn't run command\n"); | |
3198 | - } | |
3199 | + execvp(*watched_argv, watched_argv); | |
3200 | + bb_perror_msg_and_die(*watched_argv); | |
3201 | } else { | |
3202 | - bb_error_msg_and_die("Couldn't vfork\n"); | |
3203 | + bb_perror_msg_and_die("vfork"); | |
3204 | } | |
3205 | } | |
3206 | } | |
3207 | diff -Nur busybox-1.00/coreutils/who.c busybox/coreutils/who.c | |
3208 | --- busybox-1.00/coreutils/who.c 2004-03-15 09:28:22.000000000 +0100 | |
3209 | +++ busybox/coreutils/who.c 2005-06-04 08:20:13.000000000 +0200 | |
3210 | @@ -74,7 +74,7 @@ | |
3211 | } else | |
3212 | printf("%-8s ", "?"); | |
3213 | ||
3214 | - printf("%-12.12s %s\n", ctime(&(ut->ut_tv.tv_sec)) + 4, ut->ut_host); | |
3215 | + printf("%-12.12s %s\n", ctime((time_t*)&(ut->ut_tv.tv_sec)) + 4, ut->ut_host); | |
3216 | } | |
3217 | } | |
3218 | endutent(); | |
3219 | diff -Nur busybox-1.00/debianutils/Config.in busybox/debianutils/Config.in | |
3220 | --- busybox-1.00/debianutils/Config.in 2004-03-15 09:28:24.000000000 +0100 | |
3221 | +++ busybox/debianutils/Config.in 2005-06-04 08:20:10.000000000 +0200 | |
3222 | @@ -24,6 +24,13 @@ | |
3223 | This program reads a symbolic link and returns the name | |
3224 | of the file it points to | |
3225 | ||
3226 | +config CONFIG_FEATURE_READLINK_FOLLOW | |
3227 | + bool " Enable canonicalization by following all symlinks (-f)" | |
3228 | + default n | |
3229 | + depends on CONFIG_READLINK | |
3230 | + help | |
3231 | + Enable the readlink option (-f). | |
3232 | + | |
3233 | config CONFIG_RUN_PARTS | |
3234 | bool "run-parts" | |
3235 | default n | |
3236 | diff -Nur busybox-1.00/debianutils/readlink.c busybox/debianutils/readlink.c | |
3237 | --- busybox-1.00/debianutils/readlink.c 2003-03-19 10:11:41.000000000 +0100 | |
3238 | +++ busybox/debianutils/readlink.c 2005-06-04 08:20:10.000000000 +0200 | |
3239 | @@ -23,18 +23,38 @@ | |
3240 | #include <errno.h> | |
3241 | #include <unistd.h> | |
3242 | #include <stdlib.h> | |
3243 | +#include <getopt.h> | |
3244 | #include "busybox.h" | |
3245 | ||
3246 | +#ifdef CONFIG_FEATURE_READLINK_FOLLOW | |
3247 | +# define READLINK_FOLLOW "f" | |
3248 | +# define READLINK_FLAG_f (1 << 0) | |
3249 | +#else | |
3250 | +# define READLINK_FOLLOW "" | |
3251 | +#endif | |
3252 | + | |
3253 | +static const char readlink_options[] = READLINK_FOLLOW; | |
3254 | + | |
3255 | int readlink_main(int argc, char **argv) | |
3256 | { | |
3257 | char *buf = NULL; | |
3258 | + unsigned long opt = bb_getopt_ulflags(argc, argv, readlink_options); | |
3259 | +#ifdef CONFIG_FEATURE_READLINK_FOLLOW | |
3260 | + RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX); | |
3261 | +#endif | |
3262 | ||
3263 | /* no options, no getopt */ | |
3264 | ||
3265 | - if (argc != 2) | |
3266 | + if (optind + 1 != argc) | |
3267 | bb_show_usage(); | |
3268 | ||
3269 | - buf = xreadlink(argv[1]); | |
3270 | +#ifdef CONFIG_FEATURE_READLINK_FOLLOW | |
3271 | + if (opt & READLINK_FLAG_f) { | |
3272 | + buf = realpath(argv[optind], resolved_path); | |
3273 | + } else | |
3274 | +#endif | |
3275 | + buf = xreadlink(argv[optind]); | |
3276 | + | |
3277 | if (!buf) | |
3278 | return EXIT_FAILURE; | |
3279 | puts(buf); | |
3280 | diff -Nur busybox-1.00/debianutils/start_stop_daemon.c busybox/debianutils/start_stop_daemon.c | |
3281 | --- busybox-1.00/debianutils/start_stop_daemon.c 2004-04-13 20:28:46.000000000 +0200 | |
3282 | +++ busybox/debianutils/start_stop_daemon.c 2005-06-04 08:20:10.000000000 +0200 | |
3283 | @@ -238,7 +238,7 @@ | |
3284 | &startas, &cmdname, &signame, &userspec, &execname, &pidfile); | |
3285 | ||
3286 | /* Check one and only one context option was given */ | |
3287 | - if ((opt & 0x80000000UL) || (opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) { | |
3288 | + if ((opt & BB_GETOPT_ERROR) || (opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) { | |
3289 | bb_show_usage(); | |
3290 | } | |
3291 | ||
3292 | diff -Nur busybox-1.00/docs/autodocifier.pl busybox/docs/autodocifier.pl | |
3293 | --- busybox-1.00/docs/autodocifier.pl 2004-04-06 17:26:25.000000000 +0200 | |
3294 | +++ busybox/docs/autodocifier.pl 2005-06-04 08:20:06.000000000 +0200 | |
3295 | @@ -271,4 +271,4 @@ | |
3296 | ||
3297 | =cut | |
3298 | ||
3299 | -# $Id$ | |
3300 | +# $Id$ | |
3301 | diff -Nur busybox-1.00/docs/busybox.net/FAQ.html busybox/docs/busybox.net/FAQ.html | |
3302 | --- busybox-1.00/docs/busybox.net/FAQ.html 2004-10-13 11:42:10.000000000 +0200 | |
3303 | +++ busybox/docs/busybox.net/FAQ.html 2005-06-04 08:20:06.000000000 +0200 | |
3304 | @@ -15,14 +15,15 @@ | |
3305 | <li><a href="#bugs">I think I found a bug in BusyBox! What should I do?!</a> | |
3306 | <li><a href="#job_control">Why do I keep getting "sh: can't access tty; job control | |
3307 | turned off" errors? Why doesn't Control-C work within my shell?</a> | |
3308 | +<li><a href="#getting_started">How can I get started using BusyBox?</a> | |
3309 | <li><a href="#demanding">I demand that you to add <favorite feature> right now! How come | |
3310 | you don't answer all my questions on the mailing list instantly? I demand | |
3311 | that you help me with all of my problems <em>Right Now</em>!</a> | |
3312 | -<li><a href="#getting_started">How can I get started using BusyBox?</a> | |
3313 | <li><a href="#helpme">I need help with BusyBox! What should I do?</a> | |
3314 | <li><a href="#contracts">I need you to add <favorite feature>! Are the BusyBox developers willing to | |
3315 | be paid in order to fix bugs or add in <favorite feature>? Are you willing to provide | |
3316 | support contracts?</a> | |
3317 | +<li><a href="#external">Where can I find other small utilities since busybox does not include the features I want?</a></li> | |
3318 | <li><a href="#support">I think you guys are great and I want to help support your work!</a> | |
3319 | ||
3320 | ||
3321 | @@ -76,6 +77,7 @@ | |
3322 | with the generous terms of the GPL BusyBox license</a> you can ship BusyBox | |
3323 | as part of the software on your device. | |
3324 | ||
3325 | + <br> | |
3326 | <a href="#support">Please consider sharing some of the money you make.</a> | |
3327 | ||
3328 | ||
3329 | @@ -84,49 +86,33 @@ | |
3330 | <h2><a name="bugs">I think I found a bug in BusyBox! What should I do?</h2> | |
3331 | <p> | |
3332 | ||
3333 | - If you find a problem with BusyBox, please submit a detailed bug report to | |
3334 | - the BusyBox mailing list at <a href="mailto:busybox@mail.busybox.net"> | |
3335 | - busybox@mail.busybox.net</a>. Please do not send private email to Erik | |
3336 | - (the maintainer of BusyBox) asking for private help unless you are planning | |
3337 | - on paying for consulting services. When we answer questions on the BusyBox | |
3338 | - mailing list, it helps everyone, while private answers help only you... | |
3339 | - | |
3340 | - <p> | |
3341 | - | |
3342 | - If you find bugs, please submit a detailed bug report to the BusyBox mailing | |
3343 | - list at busybox@mail.busybox.net. A well-written bug report should include a | |
3344 | - transcript of a shell session that demonstrates the bad behavior and enables | |
3345 | - anyone else to duplicate the bug on their own machine. The following is such | |
3346 | - an example: | |
3347 | - | |
3348 | -<pre> | |
3349 | - To: busybox@mail.busybox.net | |
3350 | - From: diligent@testing.linux.org | |
3351 | - Subject: /bin/date doesn't work | |
3352 | ||
3353 | - Package: BusyBox | |
3354 | - Version: 1.00 | |
3355 | - | |
3356 | - When I execute BusyBox 'date' it produces unexpected results. | |
3357 | - With GNU date I get the following output: | |
3358 | +<p> | |
3359 | ||
3360 | - $ date | |
3361 | - Fri Oct 8 14:19:41 MDT 2004 | |
3362 | + If you simply need help with using or configuring BusyBox, please submit a | |
3363 | + detailed description of your problem to the BusyBox mailing list at <a | |
3364 | + href="mailto:busybox@mail.busybox.net"> busybox@mail.busybox.net</a>. | |
3365 | + Please do not send private email to Erik (the maintainer of BusyBox) asking | |
3366 | + for private help unless you are planning on paying for consulting services. | |
3367 | + When we answer questions on the BusyBox mailing list, it helps everyone, | |
3368 | + while private answers help only you... | |
3369 | ||
3370 | - But when I use BusyBox date I get this instead: | |
3371 | + <p> | |
3372 | ||
3373 | - $ date | |
3374 | - illegal instruction | |
3375 | + The developers of BusyBox are busy people, and have only so much they can | |
3376 | + keep in their brains at a time. As a result, bug reports sometimes get | |
3377 | + lost when posted to the mailing list. To prevent your bug report from | |
3378 | + getting lost, if you find a bug in BusyBox, please use the <a | |
3379 | + href="http://bugs.busybox.net/">BusyBox Bug and Patch Tracking System</a> | |
3380 | + to submit a detailed bug report. | |
3381 | ||
3382 | - I am using Debian unstable, kernel version 2.4.27 on a x86 system, | |
3383 | - and the latest uClibc from CVS. Thanks for the wonderful program! | |
3384 | + <p> | |
3385 | ||
3386 | - -Diligent | |
3387 | -</pre> | |
3388 | + The same also applies to patches... Regardless of whether your patch is a | |
3389 | + bug fix or adds shiney new features, please post your patch to the <a | |
3390 | + href="http://bugs.busybox.net/">BusyBox Bug and Patch Tracking System</a> | |
3391 | + to make certain it is properly considered. | |
3392 | ||
3393 | - Note the careful description and use of examples showing not only what BusyBox | |
3394 | - does, but also a counter example showing what an equivalent GNU app does. Bug | |
3395 | - reports lacking proper detail may never be fixed... Thanks for understanding. | |
3396 | ||
3397 | <hr /> | |
3398 | <p> | |
3399 | @@ -153,8 +139,8 @@ | |
3400 | An easy method to build your own basic BusyBox based system, is to | |
3401 | follow these simple steps: | |
3402 | <ul> | |
3403 | - <li> Point your web browser <a href="/cgi-bin/cvsweb/buildroot/">here</a> | |
3404 | - <li> Click on "Download tarball" | |
3405 | + <li> Point your web browser <a href="http://buildroot.uclibc.org/">here</a> | |
3406 | + <li> Download a copy of buildroot | |
3407 | <li> Unpack the tarball on your Linux system somewhere | |
3408 | <li> run 'make' and configure things to taste. | |
3409 | <li> run 'unset CC'. Some Linux systems (i.e. Gentoo) set 'CC' | |
3410 | @@ -220,19 +206,25 @@ | |
3411 | href="http://codepoet-consulting.com/">CodePoet Consulting</a> to bid | |
3412 | on your project. If Erik is too busy to personally add your feature, there | |
3413 | are many other active BusyBox contributors who will almost certainly be able | |
3414 | - to help you out. Erik can contact them privatly, and may even let you to | |
3415 | + to help you out. Erik can contact them privately, and may even let you to | |
3416 | post your request for services on the mailing list. | |
3417 | ||
3418 | ||
3419 | <hr /> | |
3420 | <p> | |
3421 | +<h2><a name="external">Where can I find other small utilities since busybox | |
3422 | + does not include the features I want?</a></h2> | |
3423 | +<p> | |
3424 | + We maintain such a <a href="tinyutils.html">list</a> on this site! | |
3425 | + | |
3426 | + | |
3427 | +<hr /> | |
3428 | +<p> | |
3429 | <h2><a name="support">I think you guys are great and I want to help support your work!</a></h2> | |
3430 | <p> | |
3431 | ||
3432 | - Wow, that would be great! Erik personally pays for all the bandwidth, and | |
3433 | - all servers used for busybox.net out of his own pocket. If you would like | |
3434 | - to make a donation to help support BusyBox, and/or request features, you | |
3435 | - can click here: | |
3436 | + Wow, that would be great! If you would like to make a donation to help | |
3437 | + support BusyBox, and/or request features, you can click here: | |
3438 | ||
3439 | <!-- Begin PayPal Logo --> | |
3440 | <center> | |
3441 | @@ -321,4 +313,3 @@ | |
3442 | <br> | |
3443 | ||
3444 | <!--#include file="footer.html" --> | |
3445 | - | |
3446 | diff -Nur busybox-1.00/docs/busybox.net/cvs_anon.html busybox/docs/busybox.net/cvs_anon.html | |
3447 | --- busybox-1.00/docs/busybox.net/cvs_anon.html 2004-03-15 09:28:29.000000000 +0100 | |
3448 | +++ busybox/docs/busybox.net/cvs_anon.html 1970-01-01 01:00:00.000000000 +0100 | |
3449 | @@ -1,57 +0,0 @@ | |
3450 | -<!--#include file="header.html" --> | |
3451 | - | |
3452 | - | |
3453 | -<h3>Anonymous CVS</h3> | |
3454 | - | |
3455 | -We allow anonymous (read-only) CVS access to everyone. The first command you | |
3456 | -need to run for anonymous CVS access is: | |
3457 | -<pre> | |
3458 | -cvs -d:pserver:anonymous@busybox.net:/var/cvs login</pre> | |
3459 | -<p> | |
3460 | -CVS will prompt you for a password. Just press the Enter key (there is no | |
3461 | -password for anonymous access). This step only needs to be done once, the first | |
3462 | -time you attempt to access CVS. | |
3463 | -<p> | |
3464 | -Once the login is complete, you can then check the list of available | |
3465 | -CVS modules by running the following command (all on one line): | |
3466 | -<pre> | |
3467 | -cvs -z3 -d:pserver:anonymous@busybox.net:/var/cvs co -c </pre> | |
3468 | - | |
3469 | -<p> | |
3470 | -If you wish, you can then check out a local copy of any of the | |
3471 | -available modules. The following is an example of how to grab | |
3472 | -a copy of busybox and tinylogin: | |
3473 | -<pre> | |
3474 | - cvs -z3 -d:pserver:anonymous@busybox.net:/var/cvs co -P busybox tinylogin</pre> | |
3475 | -This will create a directory called <b>busybox</b> and a directory called | |
3476 | -<b>tinylogin</b> in the current directory. These directories contain the | |
3477 | -latest and greatest source code for busybox and tinylogin. | |
3478 | - | |
3479 | -<p> | |
3480 | -If you are not already familiar with using CVS, I recommend you visit | |
3481 | -this quick <a href="/cvs_howto.html">Introduction to CVS</a>. | |
3482 | - | |
3483 | -<p> | |
3484 | -I usually create a ~/.cvsrc file with the following things in it, and I | |
3485 | -recommend you should use the same: | |
3486 | -<pre> | |
3487 | - -z3 | |
3488 | - update -dP | |
3489 | - rdiff -u | |
3490 | - diff -ubBwpN | |
3491 | - checkout -P</pre> | |
3492 | - | |
3493 | -<p> | |
3494 | -Once you've checked out a copy of the source tree, you can update your | |
3495 | -source tree at any time so it is in sync with the latest and greatest by | |
3496 | -running the command: | |
3497 | -<pre> | |
3498 | -cvs update</pre> | |
3499 | - | |
3500 | -Because you've only been granted anonymous access to the tree, you won't be | |
3501 | -able to commit any changes. Changes can be submitted for inclusion by posting | |
3502 | -them to the appropriate mailing list. For those that are actively contributing | |
3503 | -<a href="cvs_write.html">CVS write access</a> can be made available. | |
3504 | - | |
3505 | -<!--#include file="footer.html" --> | |
3506 | - | |
3507 | diff -Nur busybox-1.00/docs/busybox.net/cvs_howto.html busybox/docs/busybox.net/cvs_howto.html | |
3508 | --- busybox-1.00/docs/busybox.net/cvs_howto.html 2004-03-15 09:28:29.000000000 +0100 | |
3509 | +++ busybox/docs/busybox.net/cvs_howto.html 1970-01-01 01:00:00.000000000 +0100 | |
3510 | @@ -1,44 +0,0 @@ | |
3511 | -<!--#include file="header.html" --> | |
3512 | - | |
3513 | - | |
3514 | -<h3>How to use CVS</h3> | |
3515 | - | |
3516 | - | |
3517 | -If you want to know all the gory details, you will want to visit | |
3518 | -<a href="http://www.cvshome.org/">the CVS main web page</a>.<p> | |
3519 | -For the impatient, the following is probably about all you need to know: | |
3520 | -<p> | |
3521 | - | |
3522 | -<dl> | |
3523 | - <dt><pre>cvs checkout -c</pre> | |
3524 | - <dd>Will list the modules available for checkout | |
3525 | - <dt><pre>cvs checkout < module name ></pre> | |
3526 | - <dd>Will checkout the named module | |
3527 | - <dt><pre>cvs co < module name ></pre> | |
3528 | - <dd>Same thing | |
3529 | - <dt><pre>cvs update</pre> | |
3530 | - | |
3531 | - <dd>Updates your local archive so it is in sync with the repository | |
3532 | - -- your local updates are left intact. Tries to merge upstream updates | |
3533 | - into your local updates. You will see the following tags when it is | |
3534 | - updating your local repository: C means conflict, U means update, | |
3535 | - P means patched, and M means modified. | |
3536 | - <dt><pre>cvs up</pre> | |
3537 | - <dd>Same thing | |
3538 | - <dt><pre>cvs update < file name ></pre> | |
3539 | - <dd>Same thing but for just the named file(s)/directory(s). | |
3540 | - <dt><pre>cvs commit</pre> | |
3541 | - <dd>Will check in all your work. | |
3542 | - <dt><pre>cvs add < file name ></pre> | |
3543 | - | |
3544 | - <dd>Adds the named file/directory into CVS | |
3545 | - <dt><pre>cvs remove < file name ></pre> | |
3546 | - <dd>Removes the named file/directory from the upstream repository. | |
3547 | - <dt><pre>cvs rm < file name ></pre> | |
3548 | - <dd>Same thing | |
3549 | - <dt><pre>cvs log < file name ></pre> | |
3550 | -</dl> | |
3551 | - | |
3552 | - | |
3553 | -<!--#include file="footer.html" --> | |
3554 | - | |
3555 | diff -Nur busybox-1.00/docs/busybox.net/cvs_write.html busybox/docs/busybox.net/cvs_write.html | |
3556 | --- busybox-1.00/docs/busybox.net/cvs_write.html 2004-09-08 22:13:05.000000000 +0200 | |
3557 | +++ busybox/docs/busybox.net/cvs_write.html 1970-01-01 01:00:00.000000000 +0100 | |
3558 | @@ -1,32 +0,0 @@ | |
3559 | -<!--#include file="header.html" --> | |
3560 | - | |
3561 | - | |
3562 | -<h3>CVS Read/Write Access</h3> | |
3563 | - | |
3564 | -If you want to be able to commit things to CVS, first contribute some | |
3565 | -stuff to show you are serious. Then, very nicely ask | |
3566 | -<a href="mailto:andersen@codepoet.org">Erik Andersen</a> if he will set you up with | |
3567 | -an account. To access CVS, you will want to add the following to set up your environment: | |
3568 | -<pre> | |
3569 | -$ export CVS_RSH=/usr/bin/ssh | |
3570 | -$ export CVSROOT='username@cvs.busybox.net:/var/cvs'</pre> | |
3571 | -<br> | |
3572 | -It goes without saying you must change <em>username</em> to your own | |
3573 | -username... | |
3574 | -<p> | |
3575 | - | |
3576 | -To obtain commit access, you will need to demonstrate you are | |
3577 | -serious by submitting a few good patches first. Then, you will need to | |
3578 | -select a user-name to use when committing stuff, and finally, you will | |
3579 | -need to send me the username you have selected, an ssh key, and the email | |
3580 | -address where you prefer email to be sent (I will forward any email sent | |
3581 | -to you, but not store it). | |
3582 | - | |
3583 | -<p> | |
3584 | -Note that if you would prefer to keep your communications with me | |
3585 | -private, you can encrypt your email using my | |
3586 | -<a href="http://www.codepoet.org/andersen/erik/gpg.asc">public key</a>. | |
3587 | - | |
3588 | -<!--#include file="footer.html" --> | |
3589 | - | |
3590 | - | |
3591 | diff -Nur busybox-1.00/docs/busybox.net/developer.html busybox/docs/busybox.net/developer.html | |
3592 | --- busybox-1.00/docs/busybox.net/developer.html 1970-01-01 01:00:00.000000000 +0100 | |
3593 | +++ busybox/docs/busybox.net/developer.html 2005-06-04 08:20:06.000000000 +0200 | |
3594 | @@ -0,0 +1,58 @@ | |
3595 | +<!--#include file="header.html" --> | |
3596 | + | |
3597 | + | |
3598 | +<h3>Subversion Read/Write Access</h3> | |
3599 | + | |
3600 | +If you want to be able to commit things to Subversion, first contribute some | |
3601 | +stuff to show you are serious. Then, very nicely ask <a | |
3602 | +href="mailto:andersen@codepoet.org">Erik Andersen</a> if he will set you up | |
3603 | +with an commit access to the Subversion repository. To access Subversion, you | |
3604 | +will want to add the following to set up your environment: | |
3605 | + | |
3606 | +<p> | |
3607 | + | |
3608 | +To obtain commit access, you will need to demonstrate you are serious by | |
3609 | +submitting a few good patches first. Then, you will need to select a username | |
3610 | +to use when committing stuff, and finally, you will need to send me the | |
3611 | +username you have selected, an ssh key, and the email address where you prefer | |
3612 | +email to be sent (I will forward any email sent to you, but not store it). | |
3613 | + | |
3614 | +<p> | |
3615 | + | |
3616 | +Note that if you would prefer to keep your communications with me | |
3617 | +private, you can encrypt your email using my | |
3618 | +<a href="http://www.codepoet.org/andersen/erik/gpg.asc">public key</a>. | |
3619 | + | |
3620 | +<p> | |
3621 | + | |
3622 | +Once you are setup with an account, you will need to use your account to | |
3623 | +checkout a copy of BusyBox from Subversion: | |
3624 | + | |
3625 | +<pre> | |
3626 | +svn list svn+ssh://username@svn.uclibc.org/svn/trunk/busybox</pre> | |
3627 | +<br> | |
3628 | +It goes without saying you must change <em>username</em> to your own | |
3629 | +username... | |
3630 | +<p> | |
3631 | + | |
3632 | +You can then enter the newly checked out BusyBox directory, make changes, check | |
3633 | +your changes, diff your changes, revert your changes, and and commit your | |
3634 | +changes usine commands such as: | |
3635 | + | |
3636 | +<pre> | |
3637 | +svn diff | |
3638 | +svn status | |
3639 | +svn revert | |
3640 | +svn commit</pre> | |
3641 | + | |
3642 | +<p> | |
3643 | + | |
3644 | +For additional detail on how to use Subversion, please visit the | |
3645 | +<a href="http://subversion.tigris.org/">the Subversion website</a>. | |
3646 | +You might also want to read online or buy a copy of <a | |
3647 | +href="http://svnbook.red-bean.com/">the Subversion Book</a>... | |
3648 | + | |
3649 | + | |
3650 | +<!--#include file="footer.html" --> | |
3651 | + | |
3652 | + | |
3653 | diff -Nur busybox-1.00/docs/busybox.net/download.html busybox/docs/busybox.net/download.html | |
3654 | --- busybox-1.00/docs/busybox.net/download.html 2004-03-15 09:28:29.000000000 +0100 | |
3655 | +++ busybox/docs/busybox.net/download.html 2005-06-04 08:20:06.000000000 +0200 | |
3656 | @@ -9,27 +9,18 @@ | |
3657 | ||
3658 | <p> | |
3659 | You can also obtain <a href= "downloads/snapshots/">Daily Snapshots</a> of | |
3660 | -the latest stable, and the latest development CVS source trees. | |
3661 | - | |
3662 | -<p> | |
3663 | -BusyBox now has <b>two</b> CVS trees. The "busybox-stable" tree | |
3664 | -contains the older 0.60.x stable series. The "busybox" tree contains | |
3665 | -the latest 1.0.0-preX development version of busybox.<br> | |
3666 | +the latest development source tree for those wishing to follow BusyBox development, | |
3667 | +but cannot or do not wish to use Subversion (svn). | |
3668 | ||
3669 | <ul> | |
3670 | - <li> Click here to browse the <a href="/cgi-bin/cvsweb/busybox/"> | |
3671 | - CVS tree for the 1.0.0-preX development version of BusyBox</a> | |
3672 | - </li> | |
3673 | - | |
3674 | - <li>Click here to browse the <a href="/cgi-bin/cvsweb/busybox.stable/"> | |
3675 | - CVS tree for the stable 0.60.x version of BusyBox</a>. | |
3676 | + <li> Click here to <a href="/cgi-bin/viewcvs.cgi/trunk/busybox/">browse the source tree</a>. | |
3677 | </li> | |
3678 | ||
3679 | - <li>Anonymous <a href="cvs_anon.html">CVS access</a> is available. | |
3680 | + <li>Anonymous <a href="subversion.html">Subversion access</a> is available. | |
3681 | </li> | |
3682 | ||
3683 | - <li>For those that are actively contributing there is | |
3684 | - even <a href="cvs_write.html">CVS write access</a>. | |
3685 | + <li>For those that are actively contributing obtaining | |
3686 | + <a href="developer.html">Subversion read/write access</a> is also possible. | |
3687 | </li> | |
3688 | ||
3689 | </ul> | |
3690 | diff -Nur busybox-1.00/docs/busybox.net/footer.html busybox/docs/busybox.net/footer.html | |
3691 | --- busybox-1.00/docs/busybox.net/footer.html 2004-03-15 09:28:29.000000000 +0100 | |
3692 | +++ busybox/docs/busybox.net/footer.html 2005-06-04 08:20:06.000000000 +0200 | |
3693 | @@ -7,14 +7,34 @@ | |
3694 | ||
3695 | <hr /> | |
3696 | ||
3697 | - <p> | |
3698 | - <font face="arial, helvetica, sans-serif" size="-1"> | |
3699 | - <a HREF="/copyright.txt">Copyright © 1999-2003 Erik Andersen</a> | |
3700 | - <br> | |
3701 | - Mail all comments, insults, suggestions and bribes to | |
3702 | - <br> | |
3703 | - Erik Andersen <A HREF="mailto:andersen@codepoet.org">andersen@codepoet.org</A><BR> | |
3704 | - </font> | |
3705 | + | |
3706 | + <table width="100%"> | |
3707 | + <tr> | |
3708 | + <td width="60%"> | |
3709 | + <font face="arial, helvetica, sans-serif" size="-1"> | |
3710 | + <a href="/copyright.txt">Copyright © 1999-2005 Erik Andersen</a> | |
3711 | + <br> | |
3712 | + Mail all comments, insults, suggestions and bribes to | |
3713 | + <br> | |
3714 | + Erik Andersen <a href="mailto:andersen@codepoet.org">andersen@codepoet.org</a><br> | |
3715 | + </font> | |
3716 | + </td> | |
3717 | + | |
3718 | + <td> | |
3719 | + <a href="http://www.vim.org/"><img border=0 width=88 height=31 | |
3720 | + src="images/written.in.vi.png" | |
3721 | + alt="This site created with the vi editor"></a> | |
3722 | + </td> | |
3723 | + | |
3724 | + <td> | |
3725 | + <a href="http://osuosl.org/"><img border=0 width=114 height=63 | |
3726 | + src="images/osuosl.png" | |
3727 | + alt="This site is kindly hosted by OSL"></a> | |
3728 | + </td> | |
3729 | + | |
3730 | + </TR> | |
3731 | + </table> | |
3732 | ||
3733 | </body> | |
3734 | </html> | |
3735 | + | |
3736 | diff -Nur busybox-1.00/docs/busybox.net/header.html busybox/docs/busybox.net/header.html | |
3737 | --- busybox-1.00/docs/busybox.net/header.html 2004-10-08 12:50:08.000000000 +0200 | |
3738 | +++ busybox/docs/busybox.net/header.html 2005-06-04 08:20:06.000000000 +0200 | |
3739 | @@ -48,9 +48,10 @@ | |
3740 | <br><a href="/lists.html">Mailing Lists</a> | |
3741 | <br><a href="/news.html">Latest News</a> | |
3742 | <br><a href="/download.html">Download</a> | |
3743 | + <br><a href="/cgi-bin/viewcvs.cgi/trunk/busybox/">Browse Source</a> | |
3744 | + <br><a href="/subversion.html">Accessing Source</a> | |
3745 | + <br><a href="http://bugs.busybox.net/">Bug Tracking</a> | |
3746 | <br><a href="/FAQ.html">FAQ</a> | |
3747 | - <br><a href="/cvs_anon.html">Accessing CVS</a> | |
3748 | - <br><a href="/cgi-bin/cvsweb/busybox/">Browse CVS</a> | |
3749 | <br><a href="/docs.html">Documentation</a> | |
3750 | <br><a href="/products.html">Products</a> | |
3751 | <br><a href="/shame.html">Hall of Shame</a> | |
3752 | @@ -58,8 +59,11 @@ | |
3753 | ||
3754 | <p><b>Related Sites</b> | |
3755 | <br><a href="http://uclibc.org/">uClibc.org</a> | |
3756 | + <br><a href="http://cxx.uclibc.org/">uClibc++</a> | |
3757 | <br><a href="http://udhcp.busybox.net/">udhcp</a> | |
3758 | - <br><a href="http://tinylogin.busybox.net/">tinylogin</a> | |
3759 | + <br><a href="http://buildroot.uclibc.org/">buildroot</a> | |
3760 | + <br><a href="http://www.scratchbox.org/">Scratchbox</a> | |
3761 | + <br><a href="http://openembedded.org/">OpenEmbedded</a> | |
3762 | <br><a href="http://www.ucdot.org/">uCdot</a> | |
3763 | <br><a href="http://www.linuxdevices.com">LinuxDevices</a> | |
3764 | <br><a href="http://slashdot.org/">Slashdot</a> | |
3765 | Files busybox-1.00/docs/busybox.net/images/osuosl.png and busybox/docs/busybox.net/images/osuosl.png differ | |
3766 | diff -Nur busybox-1.00/docs/busybox.net/lists.html busybox/docs/busybox.net/lists.html | |
3767 | --- busybox-1.00/docs/busybox.net/lists.html 2004-06-19 08:26:30.000000000 +0200 | |
3768 | +++ busybox/docs/busybox.net/lists.html 2005-06-04 08:20:06.000000000 +0200 | |
3769 | @@ -15,7 +15,8 @@ | |
3770 | wishing to read the complete diff of each and every change to busybox -- not for the | |
3771 | faint of heart. Active developers can subscribe by visiting | |
3772 | <a href="http://codepoet.org/mailman/listinfo/busybox-cvs">this page</a>. | |
3773 | -The CVS server is the only one permtted to post to this list. | |
3774 | +The Subversion server is the only one permtted to post to this list. And yes, | |
3775 | +this list name uses the word 'cvs' even though we don't use that anymore... | |
3776 | ||
3777 | <p> | |
3778 | ||
3779 | diff -Nur busybox-1.00/docs/busybox.net/news.html busybox/docs/busybox.net/news.html | |
3780 | --- busybox-1.00/docs/busybox.net/news.html 2004-10-13 11:42:10.000000000 +0200 | |
3781 | +++ busybox/docs/busybox.net/news.html 2005-06-04 08:20:06.000000000 +0200 | |
3782 | @@ -3,6 +3,25 @@ | |
3783 | ||
3784 | <ul> | |
3785 | ||
3786 | + <li><b>13 January 2005 -- Bug and Patch Tracking</b><p> | |
3787 | + | |
3788 | + Bug reports sometimes get lost when posted to the mailing list. The | |
3789 | + developers of BusyBox are busy people, and have only so much they can keep | |
3790 | + in their brains at a time. In my case, I'm lucky if I can remember my own | |
3791 | + name, much less a bug report posted last week... To prevent your bug report | |
3792 | + from getting lost, if you find a bug in BusyBox, please use the | |
3793 | + <a href="http://bugs.busybox.net/">shiny new Bug and Patch Tracking System</a> | |
3794 | + to post all the gory details. | |
3795 | + | |
3796 | + <p> | |
3797 | + | |
3798 | + The same applies to patches... Regardless of whether your patch | |
3799 | + is a bug fix or adds spiffy new features, please post your patch | |
3800 | + to the Bug and Patch Tracking System to make certain it is | |
3801 | + properly considered. | |
3802 | + | |
3803 | + | |
3804 | + <p> | |
3805 | <li><b>13 October 2004 -- BusyBox 1.00 released</b><p> | |
3806 | ||
3807 | When you take a careful look at nearly every embedded Linux device or | |
3808 | diff -Nur busybox-1.00/docs/busybox.net/oldnews.html busybox/docs/busybox.net/oldnews.html | |
3809 | --- busybox-1.00/docs/busybox.net/oldnews.html 2004-10-13 11:42:10.000000000 +0200 | |
3810 | +++ busybox/docs/busybox.net/oldnews.html 2005-06-04 08:20:06.000000000 +0200 | |
3811 | @@ -888,7 +888,7 @@ | |
3812 | Also, some exciting infrastructure news! Busybox now has its own | |
3813 | <a href="lists/busybox/">mailing list</a>, | |
3814 | publically browsable | |
3815 | - <a href="/cgi-bin/cvsweb/busybox/">CVS tree</a>, | |
3816 | + <a href="/cgi-bin/viewcvs.cgi/trunk/busybox/">CVS tree</a>, | |
3817 | anonymous | |
3818 | <a href="cvs_anon.html">CVS access</a>, and | |
3819 | for those that are actively contributing there is even | |
3820 | diff -Nur busybox-1.00/docs/busybox.net/products.html busybox/docs/busybox.net/products.html | |
3821 | --- busybox-1.00/docs/busybox.net/products.html 2004-10-13 11:42:10.000000000 +0200 | |
3822 | +++ busybox/docs/busybox.net/products.html 2005-06-04 08:20:06.000000000 +0200 | |
3823 | @@ -13,7 +13,7 @@ | |
3824 | <ul> | |
3825 | ||
3826 | ||
3827 | -<li><a href="/cgi-bin/cvsweb/buildroot/">buildroot</a><br>A configurable | |
3828 | +<li><a href="http://buildroot.uclibc.org/">buildroot</a><br>A configurable | |
3829 | means for building your own busybox/uClibc based system systems. | |
3830 | ||
3831 | <li><a href="http://www.pengutronix.de/software/ptxdist_en.html">PTXdist</a><br>another | |
3832 | diff -Nur busybox-1.00/docs/busybox.net/subversion.html busybox/docs/busybox.net/subversion.html | |
3833 | --- busybox-1.00/docs/busybox.net/subversion.html 1970-01-01 01:00:00.000000000 +0100 | |
3834 | +++ busybox/docs/busybox.net/subversion.html 2005-06-04 08:20:06.000000000 +0200 | |
3835 | @@ -0,0 +1,38 @@ | |
3836 | +<!--#include file="header.html" --> | |
3837 | + | |
3838 | + | |
3839 | +<h3>Anonymous Subversion Access</h3> | |
3840 | + | |
3841 | +We allow anonymous (read-only) Subversion (svn) access to everyone. To | |
3842 | +grab a copy of the latest version of BusyBox using anonymous svn access is: | |
3843 | + | |
3844 | +<pre> | |
3845 | +svn co svn://busybox.net/trunk/busybox</pre> | |
3846 | + | |
3847 | + | |
3848 | +<p> | |
3849 | + | |
3850 | +If you are not already familiar with using Subversion, I recommend you visit <a | |
3851 | +href="http://subversion.tigris.org/">the Subversion website</a>. You might | |
3852 | +also want to read online or buy a copy of <a | |
3853 | +href="http://svnbook.red-bean.com/">the Subversion Book</a>. If you are | |
3854 | +already comfortable with using CVS, you may want to skip ahead to the <a | |
3855 | +href="http://svnbook.red-bean.com/en/1.1/apa.html">Subversion for CVS Users</a> | |
3856 | +part of the Subversion Book. | |
3857 | + | |
3858 | +<p> | |
3859 | + | |
3860 | +Once you've checked out a copy of the source tree, you can update your source | |
3861 | +tree at any time so it is in sync with the latest and greatest by entering your | |
3862 | +BusyBox directory and running the command: | |
3863 | + | |
3864 | +<pre> | |
3865 | +svn update</pre> | |
3866 | + | |
3867 | +Because you've only been granted anonymous access to the tree, you won't be | |
3868 | +able to commit any changes. Changes can be submitted for inclusion by posting | |
3869 | +them to the BusyBox mailing list. For those that are actively contributing | |
3870 | +<a href="developer.html">Subversion commit access</a> can be made available. | |
3871 | + | |
3872 | +<!--#include file="footer.html" --> | |
3873 | + | |
3874 | diff -Nur busybox-1.00/docs/busybox.net/tinyutils.html busybox/docs/busybox.net/tinyutils.html | |
3875 | --- busybox-1.00/docs/busybox.net/tinyutils.html 1970-01-01 01:00:00.000000000 +0100 | |
3876 | +++ busybox/docs/busybox.net/tinyutils.html 2005-06-04 08:20:06.000000000 +0200 | |
3877 | @@ -0,0 +1,35 @@ | |
3878 | +<!--#include file="header.html" --> | |
3879 | + | |
3880 | + | |
3881 | +<h3>External Tiny Utilities</h3> | |
3882 | + | |
3883 | +This is a list of tiny utilities whose functionality is not provided by | |
3884 | +busybox. If you have additional suggestions, please send an e-mail to our | |
3885 | +dev mailing list. | |
3886 | + | |
3887 | +<br><br> | |
3888 | + | |
3889 | +<table> | |
3890 | +<tr> | |
3891 | + <th>Feature</th> | |
3892 | + <th>Utilities</th> | |
3893 | +</tr> | |
3894 | + | |
3895 | +<tr> | |
3896 | + <td>SSH</td> | |
3897 | + <td><a href="http://matt.ucc.asn.au/dropbear/">Dropbear</a> has both a sshd and a ssh client.</td> | |
3898 | +</tr> | |
3899 | + | |
3900 | +<tr> | |
3901 | + <td>SMTP</td> | |
3902 | + <td><a href="ftp://ftp.debian.org/debian/pool/main/s/ssmtp/">ssmtp</a> is an extremely simple MTA.</td> | |
3903 | +</tr> | |
3904 | + | |
3905 | +<tr> | |
3906 | + <td>DNS</td> | |
3907 | + <td><a href="http://www.thekelleys.org.uk/dnsmasq/">dnsmasq</a> is a small forwarding DNS server meant for small environments.</td> | |
3908 | +</tr> | |
3909 | +</table> | |
3910 | + | |
3911 | +<!--#include file="footer.html" --> | |
3912 | + | |
3913 | diff -Nur busybox-1.00/docs/busybox_footer.pod busybox/docs/busybox_footer.pod | |
3914 | --- busybox-1.00/docs/busybox_footer.pod 2004-04-25 08:05:14.000000000 +0200 | |
3915 | +++ busybox/docs/busybox_footer.pod 2005-06-04 08:20:06.000000000 +0200 | |
3916 | @@ -254,5 +254,5 @@ | |
3917 | ||
3918 | =cut | |
3919 | ||
3920 | -# $Id$ | |
3921 | +# $Id$ | |
3922 | ||
3923 | diff -Nur busybox-1.00/docs/new-applet-HOWTO.txt busybox/docs/new-applet-HOWTO.txt | |
3924 | --- busybox-1.00/docs/new-applet-HOWTO.txt 2004-03-15 09:28:26.000000000 +0100 | |
3925 | +++ busybox/docs/new-applet-HOWTO.txt 2005-06-04 08:20:06.000000000 +0200 | |
3926 | @@ -52,10 +52,10 @@ | |
3927 | char mu; | |
3928 | ||
3929 | if ((fd = open("/dev/random", O_RDONLY)) < 0) | |
3930 | - perror_msg_and_die("/dev/random"); | |
3931 | + bb_perror_msg_and_die("/dev/random"); | |
3932 | ||
3933 | if ((n = safe_read(fd, &mu, 1)) < 1) | |
3934 | - perror_msg_and_die("/dev/random"); | |
3935 | + bb_perror_msg_and_die("/dev/random"); | |
3936 | ||
3937 | return mu; | |
3938 | } | |
3939 | @@ -137,11 +137,6 @@ | |
3940 | /* all programs below here are alphabetically "greater than" 'mu' */ | |
3941 | ||
3942 | ||
3943 | -Finally, add a define for your applet to include/config.h | |
3944 | - | |
3945 | - #undef CONFIG_MU | |
3946 | - | |
3947 | - | |
3948 | Documentation | |
3949 | ------------- | |
3950 | ||
3951 | diff -Nur busybox-1.00/e2fsprogs/Config.in busybox/e2fsprogs/Config.in | |
3952 | --- busybox-1.00/e2fsprogs/Config.in 1970-01-01 01:00:00.000000000 +0100 | |
3953 | +++ busybox/e2fsprogs/Config.in 2005-06-04 08:20:16.000000000 +0200 | |
3954 | @@ -0,0 +1,20 @@ | |
3955 | +# | |
3956 | +# For a description of the syntax of this configuration file, | |
3957 | +# see scripts/kbuild/config-language.txt. | |
3958 | +# | |
3959 | + | |
3960 | +menu "Linux Ext2 FS Progs" | |
3961 | + | |
3962 | +config CONFIG_CHATTR | |
3963 | + bool "chattr" | |
3964 | + default n | |
3965 | + help | |
3966 | + chattr changes the file attributes on a second extended file system. | |
3967 | + | |
3968 | +config CONFIG_LSATTR | |
3969 | + bool "lsattr" | |
3970 | + default n | |
3971 | + help | |
3972 | + lsattr lists the file attributes on a second extended file system. | |
3973 | + | |
3974 | +endmenu | |
3975 | diff -Nur busybox-1.00/e2fsprogs/Makefile busybox/e2fsprogs/Makefile | |
3976 | --- busybox-1.00/e2fsprogs/Makefile 1970-01-01 01:00:00.000000000 +0100 | |
3977 | +++ busybox/e2fsprogs/Makefile 2005-06-04 08:20:16.000000000 +0200 | |
3978 | @@ -0,0 +1,31 @@ | |
3979 | +# Makefile for busybox | |
3980 | +# | |
3981 | +# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> | |
3982 | +# | |
3983 | +# This program is free software; you can redistribute it and/or modify | |
3984 | +# it under the terms of the GNU General Public License as published by | |
3985 | +# the Free Software Foundation; either version 2 of the License, or | |
3986 | +# (at your option) any later version. | |
3987 | +# | |
3988 | +# This program is distributed in the hope that it will be useful, | |
3989 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
3990 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
3991 | +# General Public License for more details. | |
3992 | +# | |
3993 | +# You should have received a copy of the GNU General Public License | |
3994 | +# along with this program; if not, write to the Free Software | |
3995 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
3996 | +# | |
3997 | + | |
3998 | +top_srcdir=.. | |
3999 | +top_builddir=.. | |
4000 | +srcdir=$(top_srcdir)/e2fsprogs | |
4001 | +E2FSPROGS_DIR:=./ | |
4002 | +include $(top_builddir)/Rules.mak | |
4003 | +include $(top_builddir)/.config | |
4004 | +include Makefile.in | |
4005 | +all: $(libraries-y) | |
4006 | +-include $(top_builddir)/.depend | |
4007 | + | |
4008 | +clean: | |
4009 | + rm -f *.o *.a $(AR_TARGET) | |
4010 | diff -Nur busybox-1.00/e2fsprogs/Makefile.in busybox/e2fsprogs/Makefile.in | |
4011 | --- busybox-1.00/e2fsprogs/Makefile.in 1970-01-01 01:00:00.000000000 +0100 | |
4012 | +++ busybox/e2fsprogs/Makefile.in 2005-06-04 08:20:16.000000000 +0200 | |
4013 | @@ -0,0 +1,44 @@ | |
4014 | +# Makefile for busybox | |
4015 | +# | |
4016 | +# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> | |
4017 | +# | |
4018 | +# This program is free software; you can redistribute it and/or modify | |
4019 | +# it under the terms of the GNU General Public License as published by | |
4020 | +# the Free Software Foundation; either version 2 of the License, or | |
4021 | +# (at your option) any later version. | |
4022 | +# | |
4023 | +# This program is distributed in the hope that it will be useful, | |
4024 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
4025 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
4026 | +# General Public License for more details. | |
4027 | +# | |
4028 | +# You should have received a copy of the GNU General Public License | |
4029 | +# along with this program; if not, write to the Free Software | |
4030 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
4031 | +# | |
4032 | + | |
4033 | +E2FSPROGS_AR:=e2fsprogs.a | |
4034 | +ifndef $(E2FSPROGS_DIR) | |
4035 | +E2FSPROGS_DIR:=$(top_builddir)/e2fsprogs/ | |
4036 | +endif | |
4037 | +srcdir=$(top_srcdir)/e2fsprogs | |
4038 | + | |
4039 | +CFLAGS += -I$(E2FSPROGS_DIR) | |
4040 | + | |
4041 | +E2P_SRC:=fgetsetflags.c fgetsetversion.c pf.c iod.c | |
4042 | +E2P_SRCS:=$(patsubst %,e2p/%, $(E2P_SRC)) | |
4043 | +E2P_OBJS=$(patsubst %.c,%.o, $(E2P_SRCS)) | |
4044 | + | |
4045 | +E2FSPROGS-:= | |
4046 | +E2FSPROGS-$(CONFIG_CHATTR) += chattr.o $(E2P_OBJS) | |
4047 | +E2FSPROGS-$(CONFIG_LSATTR) += lsattr.o $(E2P_OBJS) | |
4048 | + | |
4049 | +libraries-y+=$(E2FSPROGS_DIR)$(E2FSPROGS_AR) | |
4050 | + | |
4051 | + | |
4052 | +$(E2FSPROGS_DIR)$(E2FSPROGS_AR): $(patsubst %,$(E2FSPROGS_DIR)%, $(E2FSPROGS-y)) | |
4053 | + $(AR) -ro $@ $(patsubst %,$(E2FSPROGS_DIR)%, $(E2FSPROGS-y)) | |
4054 | + | |
4055 | +$(E2FSPROGS_DIR)%.o: $(srcdir)/%.c | |
4056 | + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DHAVE_ERRNO_H=1 -DHAVE_UNISTD_H=1 \ | |
4057 | + -DHAVE_EXT2_IOCTLS=1 -DHAVE_EXT2_IOCTLS=1 -c -o $@ $< | |
4058 | diff -Nur busybox-1.00/e2fsprogs/README busybox/e2fsprogs/README | |
4059 | --- busybox-1.00/e2fsprogs/README 1970-01-01 01:00:00.000000000 +0100 | |
4060 | +++ busybox/e2fsprogs/README 2005-06-04 08:20:16.000000000 +0200 | |
4061 | @@ -0,0 +1,3 @@ | |
4062 | +This is a pretty straight rip from the e2fsprogs pkg. | |
4063 | + | |
4064 | +See README's in subdirs for specific info. | |
4065 | diff -Nur busybox-1.00/e2fsprogs/base_device.c busybox/e2fsprogs/base_device.c | |
4066 | --- busybox-1.00/e2fsprogs/base_device.c 1970-01-01 01:00:00.000000000 +0100 | |
4067 | +++ busybox/e2fsprogs/base_device.c 2005-06-04 08:20:16.000000000 +0200 | |
4068 | @@ -0,0 +1,147 @@ | |
4069 | +/* | |
4070 | + * base_device.c | |
4071 | + * | |
4072 | + * Return the "base device" given a particular device; this is used to | |
4073 | + * assure that we only fsck one partition on a particular drive at any | |
4074 | + * one time. Otherwise, the disk heads will be seeking all over the | |
4075 | + * place. If the base device can not be determined, return NULL. | |
4076 | + * | |
4077 | + * The base_device() function returns an allocated string which must | |
4078 | + * be freed. | |
4079 | + * | |
4080 | + * Written by Theodore Ts'o, <tytso@mit.edu> | |
4081 | + * | |
4082 | + * Copyright (C) 2000 Theodore Ts'o. | |
4083 | + * | |
4084 | + * %Begin-Header% | |
4085 | + * This file may be redistributed under the terms of the GNU Public | |
4086 | + * License. | |
4087 | + * %End-Header% | |
4088 | + */ | |
4089 | +#include <stdio.h> | |
4090 | +#include <unistd.h> | |
4091 | +#include <stdlib.h> | |
4092 | +#include <ctype.h> | |
4093 | +#include <string.h> | |
4094 | + | |
4095 | +#include "busybox.h" | |
4096 | + | |
4097 | +#ifdef CONFIG_FEATURE_DEVFS | |
4098 | +/* | |
4099 | + * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3 | |
4100 | + * pathames. | |
4101 | + */ | |
4102 | +static const char *devfs_hier[] = { | |
4103 | + "host", "bus", "target", "lun", 0 | |
4104 | +}; | |
4105 | +#endif | |
4106 | + | |
4107 | +char *base_device(const char *device) | |
4108 | +{ | |
4109 | + char *str, *cp; | |
4110 | +#ifdef CONFIG_FEATURE_DEVFS | |
4111 | + const char **hier, *disk; | |
4112 | + int len; | |
4113 | +#endif | |
4114 | + | |
4115 | + cp = str = bb_xstrdup(device); | |
4116 | + | |
4117 | + /* Skip over /dev/; if it's not present, give up. */ | |
4118 | + if (strncmp(cp, "/dev/", 5) != 0) | |
4119 | + goto errout; | |
4120 | + cp += 5; | |
4121 | + | |
4122 | +#if 0 /* this is for old stuff no one uses anymore ? */ | |
4123 | + /* Skip over /dev/dsk/... */ | |
4124 | + if (strncmp(cp, "dsk/", 4) == 0) | |
4125 | + cp += 4; | |
4126 | +#endif | |
4127 | + | |
4128 | + /* | |
4129 | + * For md devices, we treat them all as if they were all | |
4130 | + * on one disk, since we don't know how to parallelize them. | |
4131 | + */ | |
4132 | + if (cp[0] == 'm' && cp[1] == 'd') { | |
4133 | + *(cp+2) = 0; | |
4134 | + return str; | |
4135 | + } | |
4136 | + | |
4137 | + /* Handle DAC 960 devices */ | |
4138 | + if (strncmp(cp, "rd/", 3) == 0) { | |
4139 | + cp += 3; | |
4140 | + if (cp[0] != 'c' || cp[2] != 'd' || | |
4141 | + !isdigit(cp[1]) || !isdigit(cp[3])) | |
4142 | + goto errout; | |
4143 | + *(cp+4) = 0; | |
4144 | + return str; | |
4145 | + } | |
4146 | + | |
4147 | + /* Now let's handle /dev/hd* and /dev/sd* devices.... */ | |
4148 | + if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) { | |
4149 | + cp += 2; | |
4150 | + /* If there's a single number after /dev/hd, skip it */ | |
4151 | + if (isdigit(*cp)) | |
4152 | + cp++; | |
4153 | + /* What follows must be an alpha char, or give up */ | |
4154 | + if (!isalpha(*cp)) | |
4155 | + goto errout; | |
4156 | + *(cp + 1) = 0; | |
4157 | + return str; | |
4158 | + } | |
4159 | + | |
4160 | +#ifdef CONFIG_FEATURE_DEVFS | |
4161 | + /* Now let's handle devfs (ugh) names */ | |
4162 | + len = 0; | |
4163 | + if (strncmp(cp, "ide/", 4) == 0) | |
4164 | + len = 4; | |
4165 | + if (strncmp(cp, "scsi/", 5) == 0) | |
4166 | + len = 5; | |
4167 | + if (len) { | |
4168 | + cp += len; | |
4169 | + /* | |
4170 | + * Now we proceed down the expected devfs hierarchy. | |
4171 | + * i.e., .../host1/bus2/target3/lun4/... | |
4172 | + * If we don't find the expected token, followed by | |
4173 | + * some number of digits at each level, abort. | |
4174 | + */ | |
4175 | + for (hier = devfs_hier; *hier; hier++) { | |
4176 | + len = strlen(*hier); | |
4177 | + if (strncmp(cp, *hier, len) != 0) | |
4178 | + goto errout; | |
4179 | + cp += len; | |
4180 | + while (*cp != '/' && *cp != 0) { | |
4181 | + if (!isdigit(*cp)) | |
4182 | + goto errout; | |
4183 | + cp++; | |
4184 | + } | |
4185 | + cp++; | |
4186 | + } | |
4187 | + *(cp - 1) = 0; | |
4188 | + return str; | |
4189 | + } | |
4190 | + | |
4191 | + /* Now handle devfs /dev/disc or /dev/disk names */ | |
4192 | + disk = 0; | |
4193 | + if (strncmp(cp, "discs/", 6) == 0) | |
4194 | + disk = "disc"; | |
4195 | + else if (strncmp(cp, "disks/", 6) == 0) | |
4196 | + disk = "disk"; | |
4197 | + if (disk) { | |
4198 | + cp += 6; | |
4199 | + if (strncmp(cp, disk, 4) != 0) | |
4200 | + goto errout; | |
4201 | + cp += 4; | |
4202 | + while (*cp != '/' && *cp != 0) { | |
4203 | + if (!isdigit(*cp)) | |
4204 | + goto errout; | |
4205 | + cp++; | |
4206 | + } | |
4207 | + *cp = 0; | |
4208 | + return str; | |
4209 | + } | |
4210 | +#endif | |
4211 | + | |
4212 | +errout: | |
4213 | + free(str); | |
4214 | + return NULL; | |
4215 | +} | |
4216 | diff -Nur busybox-1.00/e2fsprogs/blkid/blkid.h busybox/e2fsprogs/blkid/blkid.h | |
4217 | --- busybox-1.00/e2fsprogs/blkid/blkid.h 1970-01-01 01:00:00.000000000 +0100 | |
4218 | +++ busybox/e2fsprogs/blkid/blkid.h 2005-06-04 08:20:15.000000000 +0200 | |
4219 | @@ -0,0 +1,105 @@ | |
4220 | +/* | |
4221 | + * blkid.h - Interface for libblkid, a library to identify block devices | |
4222 | + * | |
4223 | + * Copyright (C) 2001 Andreas Dilger | |
4224 | + * Copyright (C) 2003 Theodore Ts'o | |
4225 | + * | |
4226 | + * %Begin-Header% | |
4227 | + * This file may be redistributed under the terms of the | |
4228 | + * GNU Lesser General Public License. | |
4229 | + * %End-Header% | |
4230 | + */ | |
4231 | + | |
4232 | +#ifndef _BLKID_BLKID_H | |
4233 | +#define _BLKID_BLKID_H | |
4234 | + | |
4235 | +#include <sys/types.h> | |
4236 | +#include <linux/types.h> | |
4237 | + | |
4238 | +#ifdef __cplusplus | |
4239 | +extern "C" { | |
4240 | +#endif | |
4241 | + | |
4242 | +#define BLKID_VERSION "1.0.0" | |
4243 | +#define BLKID_DATE "12-Feb-2003" | |
4244 | + | |
4245 | +typedef struct blkid_struct_dev *blkid_dev; | |
4246 | +typedef struct blkid_struct_cache *blkid_cache; | |
4247 | +typedef __s64 blkid_loff_t; | |
4248 | + | |
4249 | +typedef struct blkid_struct_tag_iterate *blkid_tag_iterate; | |
4250 | +typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; | |
4251 | + | |
4252 | +/* | |
4253 | + * Flags for blkid_get_dev | |
4254 | + * | |
4255 | + * BLKID_DEV_CREATE Create an empty device structure if not found | |
4256 | + * in the cache. | |
4257 | + * BLKID_DEV_VERIFY Make sure the device structure corresponds | |
4258 | + * with reality. | |
4259 | + * BLKID_DEV_FIND Just look up a device entry, and return NULL | |
4260 | + * if it is not found. | |
4261 | + * BLKID_DEV_NORMAL Get a valid device structure, either from the | |
4262 | + * cache or by probing the device. | |
4263 | + */ | |
4264 | +#define BLKID_DEV_FIND 0x0000 | |
4265 | +#define BLKID_DEV_CREATE 0x0001 | |
4266 | +#define BLKID_DEV_VERIFY 0x0002 | |
4267 | +#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY) | |
4268 | + | |
4269 | +/* cache.c */ | |
4270 | +extern void blkid_put_cache(blkid_cache cache); | |
4271 | +extern int blkid_get_cache(blkid_cache *cache, const char *filename); | |
4272 | + | |
4273 | +/* dev.c */ | |
4274 | +extern const char *blkid_dev_devname(blkid_dev dev); | |
4275 | + | |
4276 | +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache); | |
4277 | +extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev); | |
4278 | +extern void blkid_dev_iterate_end(blkid_dev_iterate iterate); | |
4279 | + | |
4280 | +/* devno.c */ | |
4281 | +extern char *blkid_devno_to_devname(dev_t devno); | |
4282 | + | |
4283 | +/* devname.c */ | |
4284 | +extern int blkid_probe_all(blkid_cache cache); | |
4285 | +extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, | |
4286 | + int flags); | |
4287 | + | |
4288 | +/* getsize.c */ | |
4289 | +extern blkid_loff_t blkid_get_dev_size(int fd); | |
4290 | + | |
4291 | +/* probe.c */ | |
4292 | +int blkid_known_fstype(const char *fstype); | |
4293 | +extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev); | |
4294 | + | |
4295 | +/* read.c */ | |
4296 | + | |
4297 | +/* resolve.c */ | |
4298 | +extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname, | |
4299 | + const char *devname); | |
4300 | +extern char *blkid_get_devname(blkid_cache cache, const char *token, | |
4301 | + const char *value); | |
4302 | + | |
4303 | +/* tag.c */ | |
4304 | +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev); | |
4305 | +extern int blkid_tag_next(blkid_tag_iterate iterate, | |
4306 | + const char **type, const char **value); | |
4307 | +extern void blkid_tag_iterate_end(blkid_tag_iterate iterate); | |
4308 | + | |
4309 | +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, | |
4310 | + const char *type, | |
4311 | + const char *value); | |
4312 | +extern int blkid_parse_tag_string(const char *token, char **ret_type, | |
4313 | + char **ret_val); | |
4314 | + | |
4315 | +/* version.c */ | |
4316 | +extern int blkid_parse_version_string(const char *ver_string); | |
4317 | +extern int blkid_get_library_version(const char **ver_string, | |
4318 | + const char **date_string); | |
4319 | + | |
4320 | +#ifdef __cplusplus | |
4321 | +} | |
4322 | +#endif | |
4323 | + | |
4324 | +#endif /* _BLKID_BLKID_H */ | |
4325 | diff -Nur busybox-1.00/e2fsprogs/blkid/blkidP.h busybox/e2fsprogs/blkid/blkidP.h | |
4326 | --- busybox-1.00/e2fsprogs/blkid/blkidP.h 1970-01-01 01:00:00.000000000 +0100 | |
4327 | +++ busybox/e2fsprogs/blkid/blkidP.h 2005-06-04 08:20:15.000000000 +0200 | |
4328 | @@ -0,0 +1,239 @@ | |
4329 | +/* | |
4330 | + * blkidP.h - Internal interfaces for libblkid | |
4331 | + * | |
4332 | + * Copyright (C) 2001 Andreas Dilger | |
4333 | + * Copyright (C) 2003 Theodore Ts'o | |
4334 | + * | |
4335 | + * %Begin-Header% | |
4336 | + * This file may be redistributed under the terms of the | |
4337 | + * GNU Lesser General Public License. | |
4338 | + * %End-Header% | |
4339 | + */ | |
4340 | + | |
4341 | +#ifndef _BLKID_BLKIDP_H | |
4342 | +#define _BLKID_BLKIDP_H | |
4343 | + | |
4344 | +#include <sys/types.h> | |
4345 | +#include <stdio.h> | |
4346 | + | |
4347 | +#include <blkid/blkid.h> | |
4348 | + | |
4349 | +#include <blkid/list.h> | |
4350 | + | |
4351 | +#ifdef __GNUC__ | |
4352 | +#define __BLKID_ATTR(x) __attribute__(x) | |
4353 | +#else | |
4354 | +#define __BLKID_ATTR(x) | |
4355 | +#endif | |
4356 | + | |
4357 | + | |
4358 | +/* | |
4359 | + * This describes the attributes of a specific device. | |
4360 | + * We can traverse all of the tags by bid_tags (linking to the tag bit_names). | |
4361 | + * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag | |
4362 | + * values, if they exist. | |
4363 | + */ | |
4364 | +struct blkid_struct_dev | |
4365 | +{ | |
4366 | + struct list_head bid_devs; /* All devices in the cache */ | |
4367 | + struct list_head bid_tags; /* All tags for this device */ | |
4368 | + blkid_cache bid_cache; /* Dev belongs to this cache */ | |
4369 | + char *bid_name; /* Device inode pathname */ | |
4370 | + char *bid_type; /* Preferred device TYPE */ | |
4371 | + int bid_pri; /* Device priority */ | |
4372 | + dev_t bid_devno; /* Device major/minor number */ | |
4373 | + time_t bid_time; /* Last update time of device */ | |
4374 | + unsigned int bid_flags; /* Device status bitflags */ | |
4375 | + char *bid_label; /* Shortcut to device LABEL */ | |
4376 | + char *bid_uuid; /* Shortcut to binary UUID */ | |
4377 | +}; | |
4378 | + | |
4379 | +#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */ | |
4380 | +#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */ | |
4381 | + | |
4382 | +/* | |
4383 | + * Each tag defines a NAME=value pair for a particular device. The tags | |
4384 | + * are linked via bit_names for a single device, so that traversing the | |
4385 | + * names list will get you a list of all tags associated with a device. | |
4386 | + * They are also linked via bit_values for all devices, so one can easily | |
4387 | + * search all tags with a given NAME for a specific value. | |
4388 | + */ | |
4389 | +struct blkid_struct_tag | |
4390 | +{ | |
4391 | + struct list_head bit_tags; /* All tags for this device */ | |
4392 | + struct list_head bit_names; /* All tags with given NAME */ | |
4393 | + char *bit_name; /* NAME of tag (shared) */ | |
4394 | + char *bit_val; /* value of tag */ | |
4395 | + blkid_dev bit_dev; /* pointer to device */ | |
4396 | +}; | |
4397 | +typedef struct blkid_struct_tag *blkid_tag; | |
4398 | + | |
4399 | +/* | |
4400 | + * Minimum number of seconds between device probes, even when reading | |
4401 | + * from the cache. This is to avoid re-probing all devices which were | |
4402 | + * just probed by another program that does not share the cache. | |
4403 | + */ | |
4404 | +#define BLKID_PROBE_MIN 2 | |
4405 | + | |
4406 | +/* | |
4407 | + * Time in seconds an entry remains verified in the in-memory cache | |
4408 | + * before being reverified (in case of long-running processes that | |
4409 | + * keep a cache in memory and continue to use it for a long time). | |
4410 | + */ | |
4411 | +#define BLKID_PROBE_INTERVAL 200 | |
4412 | + | |
4413 | +/* This describes an entire blkid cache file and probed devices. | |
4414 | + * We can traverse all of the found devices via bic_list. | |
4415 | + * We can traverse all of the tag types by bic_tags, which hold empty tags | |
4416 | + * for each tag type. Those tags can be used as list_heads for iterating | |
4417 | + * through all devices with a specific tag type (e.g. LABEL). | |
4418 | + */ | |
4419 | +struct blkid_struct_cache | |
4420 | +{ | |
4421 | + struct list_head bic_devs; /* List head of all devices */ | |
4422 | + struct list_head bic_tags; /* List head of all tag types */ | |
4423 | + time_t bic_time; /* Last probe time */ | |
4424 | + time_t bic_ftime; /* Mod time of the cachefile */ | |
4425 | + unsigned int bic_flags; /* Status flags of the cache */ | |
4426 | + char *bic_filename; /* filename of cache */ | |
4427 | +}; | |
4428 | + | |
4429 | +#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */ | |
4430 | +#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */ | |
4431 | + | |
4432 | +extern char *blkid_strdup(const char *s); | |
4433 | +extern char *blkid_strndup(const char *s, const int length); | |
4434 | + | |
4435 | +#define BLKID_CACHE_FILE "/etc/blkid.tab" | |
4436 | +extern const char *blkid_devdirs[]; | |
4437 | + | |
4438 | +#define BLKID_ERR_IO 5 | |
4439 | +#define BLKID_ERR_PROC 9 | |
4440 | +#define BLKID_ERR_MEM 12 | |
4441 | +#define BLKID_ERR_CACHE 14 | |
4442 | +#define BLKID_ERR_DEV 19 | |
4443 | +#define BLKID_ERR_PARAM 22 | |
4444 | +#define BLKID_ERR_BIG 27 | |
4445 | + | |
4446 | +/* | |
4447 | + * Priority settings for different types of devices | |
4448 | + */ | |
4449 | +#define BLKID_PRI_EVMS 30 | |
4450 | +#define BLKID_PRI_LVM 20 | |
4451 | +#define BLKID_PRI_MD 10 | |
4452 | + | |
4453 | +#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG) | |
4454 | +#define CONFIG_BLKID_DEBUG | |
4455 | +#endif | |
4456 | + | |
4457 | +#define DEBUG_CACHE 0x0001 | |
4458 | +#define DEBUG_DUMP 0x0002 | |
4459 | +#define DEBUG_DEV 0x0004 | |
4460 | +#define DEBUG_DEVNAME 0x0008 | |
4461 | +#define DEBUG_DEVNO 0x0010 | |
4462 | +#define DEBUG_PROBE 0x0020 | |
4463 | +#define DEBUG_READ 0x0040 | |
4464 | +#define DEBUG_RESOLVE 0x0080 | |
4465 | +#define DEBUG_SAVE 0x0100 | |
4466 | +#define DEBUG_TAG 0x0200 | |
4467 | +#define DEBUG_INIT 0x8000 | |
4468 | +#define DEBUG_ALL 0xFFFF | |
4469 | + | |
4470 | +#ifdef CONFIG_BLKID_DEBUG | |
4471 | +#include <stdio.h> | |
4472 | +extern int blkid_debug_mask; | |
4473 | +#define DBG(m,x) if ((m) & blkid_debug_mask) x; | |
4474 | +#else | |
4475 | +#define DBG(m,x) | |
4476 | +#endif | |
4477 | + | |
4478 | +#ifdef CONFIG_BLKID_DEBUG | |
4479 | +static inline void DEB_DUMP_TAG(int mask, blkid_tag tag) | |
4480 | +{ | |
4481 | + if (!(mask & blkid_debug_mask)) | |
4482 | + return; | |
4483 | + | |
4484 | + if (!tag) { | |
4485 | + printf(" tag: NULL\n"); | |
4486 | + return; | |
4487 | + } | |
4488 | + | |
4489 | + printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val); | |
4490 | +} | |
4491 | + | |
4492 | +static inline void DEB_DUMP_DEV(int mask, blkid_dev dev) | |
4493 | +{ | |
4494 | + struct list_head *p; | |
4495 | + | |
4496 | + if (!(mask & blkid_debug_mask)) | |
4497 | + return; | |
4498 | + | |
4499 | + if (!dev) { | |
4500 | + printf(" dev: NULL\n"); | |
4501 | + return; | |
4502 | + } | |
4503 | + | |
4504 | + printf(" dev: name = %s\n", dev->bid_name); | |
4505 | + printf(" dev: DEVNO=\"0x%0Lx\"\n", dev->bid_devno); | |
4506 | + printf(" dev: TIME=\"%lu\"\n", dev->bid_time); | |
4507 | + printf(" dev: PRI=\"%d\"\n", dev->bid_pri); | |
4508 | + printf(" dev: flags = 0x%08X\n", dev->bid_flags); | |
4509 | + | |
4510 | + list_for_each(p, &dev->bid_tags) { | |
4511 | + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); | |
4512 | + DEB_DUMP_TAG(mask, tag); | |
4513 | + } | |
4514 | + printf("\n"); | |
4515 | +} | |
4516 | + | |
4517 | +static inline void DEB_DUMP_CACHE(int mask, blkid_cache cache) | |
4518 | +{ | |
4519 | + struct list_head *p; | |
4520 | + | |
4521 | + if (!cache || !(mask & blkid_debug_mask)) { | |
4522 | + printf("cache: NULL\n"); | |
4523 | + return; | |
4524 | + } | |
4525 | + | |
4526 | + printf("cache: time = %lu\n", cache->bic_time); | |
4527 | + printf("cache: flags = 0x%08X\n", cache->bic_flags); | |
4528 | + | |
4529 | + list_for_each(p, &cache->bic_devs) { | |
4530 | + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); | |
4531 | + DEB_DUMP_DEV(mask, dev); | |
4532 | + } | |
4533 | +} | |
4534 | +#else | |
4535 | +#define DEB_DUMP_TAG(mask, tag) do {} while (0) | |
4536 | +#define DEB_DUMP_DEV(mask, dev) do {} while (0) | |
4537 | +#define DEB_DUMP_CACHE(mask, cache) do {} while (0) | |
4538 | +#endif | |
4539 | + | |
4540 | +/* lseek.c */ | |
4541 | +extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); | |
4542 | + | |
4543 | +/* read.c */ | |
4544 | +extern void blkid_read_cache(blkid_cache cache); | |
4545 | + | |
4546 | +/* save.c */ | |
4547 | +extern int blkid_flush_cache(blkid_cache cache); | |
4548 | + | |
4549 | +/* | |
4550 | + * Functions to create and find a specific tag type: tag.c | |
4551 | + */ | |
4552 | +extern void blkid_free_tag(blkid_tag tag); | |
4553 | +extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type); | |
4554 | +extern int blkid_set_tag(blkid_dev dev, const char *name, | |
4555 | + const char *value, const int vlength); | |
4556 | + | |
4557 | +/* | |
4558 | + * Functions to create and find a specific tag type: dev.c | |
4559 | + */ | |
4560 | +extern blkid_dev blkid_new_dev(void); | |
4561 | +extern void blkid_free_dev(blkid_dev dev); | |
4562 | + | |
4563 | +#ifdef __cplusplus | |
4564 | +} | |
4565 | +#endif | |
4566 | + | |
4567 | +#endif /* _BLKID_BLKIDP_H */ | |
4568 | diff -Nur busybox-1.00/e2fsprogs/blkid/cache.c busybox/e2fsprogs/blkid/cache.c | |
4569 | --- busybox-1.00/e2fsprogs/blkid/cache.c 1970-01-01 01:00:00.000000000 +0100 | |
4570 | +++ busybox/e2fsprogs/blkid/cache.c 2005-06-04 08:20:15.000000000 +0200 | |
4571 | @@ -0,0 +1,126 @@ | |
4572 | +/* | |
4573 | + * cache.c - allocation/initialization/free routines for cache | |
4574 | + * | |
4575 | + * Copyright (C) 2001 Andreas Dilger | |
4576 | + * Copyright (C) 2003 Theodore Ts'o | |
4577 | + * | |
4578 | + * %Begin-Header% | |
4579 | + * This file may be redistributed under the terms of the | |
4580 | + * GNU Lesser General Public License. | |
4581 | + * %End-Header% | |
4582 | + */ | |
4583 | + | |
4584 | +#include <stdlib.h> | |
4585 | +#include <string.h> | |
4586 | +#include <unistd.h> | |
4587 | +#include "blkidP.h" | |
4588 | + | |
4589 | +int blkid_debug_mask = 0; | |
4590 | + | |
4591 | +int blkid_get_cache(blkid_cache *ret_cache, const char *filename) | |
4592 | +{ | |
4593 | + blkid_cache cache; | |
4594 | + | |
4595 | +#ifdef CONFIG_BLKID_DEBUG | |
4596 | + if (!(blkid_debug_mask & DEBUG_INIT)) { | |
4597 | + char *dstr = getenv("BLKID_DEBUG"); | |
4598 | + | |
4599 | + if (dstr) | |
4600 | + blkid_debug_mask = strtoul(dstr, 0, 0); | |
4601 | + blkid_debug_mask |= DEBUG_INIT; | |
4602 | + } | |
4603 | +#endif | |
4604 | + | |
4605 | + DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n", | |
4606 | + filename ? filename : "default cache")); | |
4607 | + | |
4608 | + if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache)))) | |
4609 | + return -BLKID_ERR_MEM; | |
4610 | + | |
4611 | + INIT_LIST_HEAD(&cache->bic_devs); | |
4612 | + INIT_LIST_HEAD(&cache->bic_tags); | |
4613 | + | |
4614 | + if (filename && !strlen(filename)) | |
4615 | + filename = 0; | |
4616 | + if (!filename && (getuid() == geteuid())) | |
4617 | + filename = getenv("BLKID_FILE"); | |
4618 | + if (!filename) | |
4619 | + filename = BLKID_CACHE_FILE; | |
4620 | + cache->bic_filename = blkid_strdup(filename); | |
4621 | + | |
4622 | + blkid_read_cache(cache); | |
4623 | + | |
4624 | + *ret_cache = cache; | |
4625 | + return 0; | |
4626 | +} | |
4627 | + | |
4628 | +void blkid_put_cache(blkid_cache cache) | |
4629 | +{ | |
4630 | + if (!cache) | |
4631 | + return; | |
4632 | + | |
4633 | + (void) blkid_flush_cache(cache); | |
4634 | + | |
4635 | + DBG(DEBUG_CACHE, printf("freeing cache struct\n")); | |
4636 | + | |
4637 | + /* DEB_DUMP_CACHE(cache); */ | |
4638 | + | |
4639 | + while (!list_empty(&cache->bic_devs)) { | |
4640 | + blkid_dev dev = list_entry(cache->bic_devs.next, | |
4641 | + struct blkid_struct_dev, | |
4642 | + bid_devs); | |
4643 | + blkid_free_dev(dev); | |
4644 | + } | |
4645 | + | |
4646 | + while (!list_empty(&cache->bic_tags)) { | |
4647 | + blkid_tag tag = list_entry(cache->bic_tags.next, | |
4648 | + struct blkid_struct_tag, | |
4649 | + bit_tags); | |
4650 | + | |
4651 | + while (!list_empty(&tag->bit_names)) { | |
4652 | + blkid_tag bad = list_entry(tag->bit_names.next, | |
4653 | + struct blkid_struct_tag, | |
4654 | + bit_names); | |
4655 | + | |
4656 | + DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n", | |
4657 | + bad->bit_name, bad->bit_val)); | |
4658 | + blkid_free_tag(bad); | |
4659 | + } | |
4660 | + blkid_free_tag(tag); | |
4661 | + } | |
4662 | + if (cache->bic_filename) | |
4663 | + free(cache->bic_filename); | |
4664 | + | |
4665 | + free(cache); | |
4666 | +} | |
4667 | + | |
4668 | +#ifdef TEST_PROGRAM | |
4669 | +int main(int argc, char** argv) | |
4670 | +{ | |
4671 | + blkid_cache cache = NULL; | |
4672 | + int ret; | |
4673 | + | |
4674 | + blkid_debug_mask = DEBUG_ALL; | |
4675 | + if ((argc > 2)) { | |
4676 | + fprintf(stderr, "Usage: %s [filename] \n", argv[0]); | |
4677 | + exit(1); | |
4678 | + } | |
4679 | + | |
4680 | + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) { | |
4681 | + fprintf(stderr, "error %d parsing cache file %s\n", ret, | |
4682 | + argv[1] ? argv[1] : BLKID_CACHE_FILE); | |
4683 | + exit(1); | |
4684 | + } | |
4685 | + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { | |
4686 | + fprintf(stderr, "%s: error creating cache (%d)\n", | |
4687 | + argv[0], ret); | |
4688 | + exit(1); | |
4689 | + } | |
4690 | + if ((ret = blkid_probe_all(cache) < 0)) | |
4691 | + fprintf(stderr, "error probing devices\n"); | |
4692 | + | |
4693 | + blkid_put_cache(cache); | |
4694 | + | |
4695 | + return ret; | |
4696 | +} | |
4697 | +#endif | |
4698 | diff -Nur busybox-1.00/e2fsprogs/blkid/dev.c busybox/e2fsprogs/blkid/dev.c | |
4699 | --- busybox-1.00/e2fsprogs/blkid/dev.c 1970-01-01 01:00:00.000000000 +0100 | |
4700 | +++ busybox/e2fsprogs/blkid/dev.c 2005-06-04 08:20:15.000000000 +0200 | |
4701 | @@ -0,0 +1,118 @@ | |
4702 | +/* | |
4703 | + * dev.c - allocation/initialization/free routines for dev | |
4704 | + * | |
4705 | + * Copyright (C) 2001 Andreas Dilger | |
4706 | + * Copyright (C) 2003 Theodore Ts'o | |
4707 | + * | |
4708 | + * %Begin-Header% | |
4709 | + * This file may be redistributed under the terms of the | |
4710 | + * GNU Lesser General Public License. | |
4711 | + * %End-Header% | |
4712 | + */ | |
4713 | + | |
4714 | +#include <stdlib.h> | |
4715 | +#include <string.h> | |
4716 | + | |
4717 | +#include "blkidP.h" | |
4718 | + | |
4719 | +blkid_dev blkid_new_dev(void) | |
4720 | +{ | |
4721 | + blkid_dev dev; | |
4722 | + | |
4723 | + if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev)))) | |
4724 | + return NULL; | |
4725 | + | |
4726 | + INIT_LIST_HEAD(&dev->bid_devs); | |
4727 | + INIT_LIST_HEAD(&dev->bid_tags); | |
4728 | + | |
4729 | + return dev; | |
4730 | +} | |
4731 | + | |
4732 | +void blkid_free_dev(blkid_dev dev) | |
4733 | +{ | |
4734 | + if (!dev) | |
4735 | + return; | |
4736 | + | |
4737 | + DBG(DEBUG_DEV, | |
4738 | + printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type)); | |
4739 | + DEB_DUMP_DEV(DEBUG_DEV, dev); | |
4740 | + | |
4741 | + list_del(&dev->bid_devs); | |
4742 | + while (!list_empty(&dev->bid_tags)) { | |
4743 | + blkid_tag tag = list_entry(dev->bid_tags.next, | |
4744 | + struct blkid_struct_tag, | |
4745 | + bit_tags); | |
4746 | + blkid_free_tag(tag); | |
4747 | + } | |
4748 | + if (dev->bid_name) | |
4749 | + free(dev->bid_name); | |
4750 | + free(dev); | |
4751 | +} | |
4752 | + | |
4753 | +/* | |
4754 | + * Given a blkid device, return its name | |
4755 | + */ | |
4756 | +extern const char *blkid_dev_devname(blkid_dev dev) | |
4757 | +{ | |
4758 | + return dev->bid_name; | |
4759 | +} | |
4760 | + | |
4761 | +/* | |
4762 | + * dev iteration routines for the public libblkid interface. | |
4763 | + * | |
4764 | + * These routines do not expose the list.h implementation, which are a | |
4765 | + * contamination of the namespace, and which force us to reveal far, far | |
4766 | + * too much of our internal implemenation. I'm not convinced I want | |
4767 | + * to keep list.h in the long term, anyway. It's fine for kernel | |
4768 | + * programming, but performance is not the #1 priority for this | |
4769 | + * library, and I really don't like the tradeoff of type-safety for | |
4770 | + * performance for this application. [tytso:20030125.2007EST] | |
4771 | + */ | |
4772 | + | |
4773 | +/* | |
4774 | + * This series of functions iterate over all devices in a blkid cache | |
4775 | + */ | |
4776 | +#define DEV_ITERATE_MAGIC 0x01a5284c | |
4777 | + | |
4778 | +struct blkid_struct_dev_iterate { | |
4779 | + int magic; | |
4780 | + blkid_cache cache; | |
4781 | + struct list_head *p; | |
4782 | +}; | |
4783 | + | |
4784 | +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache) | |
4785 | +{ | |
4786 | + blkid_dev_iterate iter; | |
4787 | + | |
4788 | + iter = malloc(sizeof(struct blkid_struct_dev_iterate)); | |
4789 | + if (iter) { | |
4790 | + iter->magic = DEV_ITERATE_MAGIC; | |
4791 | + iter->cache = cache; | |
4792 | + iter->p = cache->bic_devs.next; | |
4793 | + } | |
4794 | + return (iter); | |
4795 | +} | |
4796 | + | |
4797 | +/* | |
4798 | + * Return 0 on success, -1 on error | |
4799 | + */ | |
4800 | +extern int blkid_dev_next(blkid_dev_iterate iter, | |
4801 | + blkid_dev *dev) | |
4802 | +{ | |
4803 | + *dev = 0; | |
4804 | + if (!iter || iter->magic != DEV_ITERATE_MAGIC || | |
4805 | + iter->p == &iter->cache->bic_devs) | |
4806 | + return -1; | |
4807 | + *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs); | |
4808 | + iter->p = iter->p->next; | |
4809 | + return 0; | |
4810 | +} | |
4811 | + | |
4812 | +extern void blkid_dev_iterate_end(blkid_dev_iterate iter) | |
4813 | +{ | |
4814 | + if (!iter || iter->magic != DEV_ITERATE_MAGIC) | |
4815 | + return; | |
4816 | + iter->magic = 0; | |
4817 | + free(iter); | |
4818 | +} | |
4819 | + | |
4820 | diff -Nur busybox-1.00/e2fsprogs/blkid/devname.c busybox/e2fsprogs/blkid/devname.c | |
4821 | --- busybox-1.00/e2fsprogs/blkid/devname.c 1970-01-01 01:00:00.000000000 +0100 | |
4822 | +++ busybox/e2fsprogs/blkid/devname.c 2005-06-04 08:20:15.000000000 +0200 | |
4823 | @@ -0,0 +1,376 @@ | |
4824 | +/* | |
4825 | + * devname.c - get a dev by its device inode name | |
4826 | + * | |
4827 | + * Copyright (C) Andries Brouwer | |
4828 | + * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o | |
4829 | + * Copyright (C) 2001 Andreas Dilger | |
4830 | + * | |
4831 | + * %Begin-Header% | |
4832 | + * This file may be redistributed under the terms of the | |
4833 | + * GNU Lesser General Public License. | |
4834 | + * %End-Header% | |
4835 | + */ | |
4836 | + | |
4837 | +#include <stdio.h> | |
4838 | +#include <string.h> | |
4839 | +#if HAVE_UNISTD_H | |
4840 | +#include <unistd.h> | |
4841 | +#endif | |
4842 | +#include <stdlib.h> | |
4843 | +#include <string.h> | |
4844 | +#include <ctype.h> | |
4845 | +#if HAVE_SYS_TYPES_H | |
4846 | +#include <sys/types.h> | |
4847 | +#endif | |
4848 | +#if HAVE_SYS_STAT_H | |
4849 | +#include <sys/stat.h> | |
4850 | +#endif | |
4851 | +#if HAVE_ERRNO_H | |
4852 | +#include <errno.h> | |
4853 | +#endif | |
4854 | +#if HAVE_SYS_MKDEV_H | |
4855 | +#include <sys/mkdev.h> | |
4856 | +#endif | |
4857 | +#include <time.h> | |
4858 | + | |
4859 | +#include "blkidP.h" | |
4860 | + | |
4861 | +/* | |
4862 | + * Find a dev struct in the cache by device name, if available. | |
4863 | + * | |
4864 | + * If there is no entry with the specified device name, and the create | |
4865 | + * flag is set, then create an empty device entry. | |
4866 | + */ | |
4867 | +blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) | |
4868 | +{ | |
4869 | + blkid_dev dev = NULL, tmp; | |
4870 | + struct list_head *p; | |
4871 | + | |
4872 | + if (!cache || !devname) | |
4873 | + return NULL; | |
4874 | + | |
4875 | + list_for_each(p, &cache->bic_devs) { | |
4876 | + tmp = list_entry(p, struct blkid_struct_dev, bid_devs); | |
4877 | + if (strcmp(tmp->bid_name, devname)) | |
4878 | + continue; | |
4879 | + | |
4880 | + DBG(DEBUG_DEVNAME, | |
4881 | + printf("found devname %s in cache\n", tmp->bid_name)); | |
4882 | + dev = tmp; | |
4883 | + break; | |
4884 | + } | |
4885 | + | |
4886 | + if (!dev && (flags & BLKID_DEV_CREATE)) { | |
4887 | + dev = blkid_new_dev(); | |
4888 | + if (!dev) | |
4889 | + return NULL; | |
4890 | + dev->bid_name = blkid_strdup(devname); | |
4891 | + dev->bid_cache = cache; | |
4892 | + list_add_tail(&dev->bid_devs, &cache->bic_devs); | |
4893 | + cache->bic_flags |= BLKID_BIC_FL_CHANGED; | |
4894 | + } | |
4895 | + | |
4896 | + if (flags & BLKID_DEV_VERIFY) | |
4897 | + dev = blkid_verify(cache, dev); | |
4898 | + return dev; | |
4899 | +} | |
4900 | + | |
4901 | +/* | |
4902 | + * Probe a single block device to add to the device cache. | |
4903 | + */ | |
4904 | +static void probe_one(blkid_cache cache, const char *ptname, | |
4905 | + dev_t devno, int pri) | |
4906 | +{ | |
4907 | + blkid_dev dev = NULL; | |
4908 | + struct list_head *p; | |
4909 | + const char **dir; | |
4910 | + char *devname = NULL; | |
4911 | + | |
4912 | + /* See if we already have this device number in the cache. */ | |
4913 | + list_for_each(p, &cache->bic_devs) { | |
4914 | + blkid_dev tmp = list_entry(p, struct blkid_struct_dev, | |
4915 | + bid_devs); | |
4916 | + if (tmp->bid_devno == devno) { | |
4917 | + dev = blkid_verify(cache, tmp); | |
4918 | + break; | |
4919 | + } | |
4920 | + } | |
4921 | + if (dev && dev->bid_devno == devno) | |
4922 | + goto set_pri; | |
4923 | + | |
4924 | + /* | |
4925 | + * Take a quick look at /dev/ptname for the device number. We check | |
4926 | + * all of the likely device directories. If we don't find it, or if | |
4927 | + * the stat information doesn't check out, use blkid_devno_to_devname() | |
4928 | + * to find it via an exhaustive search for the device major/minor. | |
4929 | + */ | |
4930 | + for (dir = blkid_devdirs; *dir; dir++) { | |
4931 | + struct stat st; | |
4932 | + char device[256]; | |
4933 | + | |
4934 | + sprintf(device, "%s/%s", *dir, ptname); | |
4935 | + if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) && | |
4936 | + dev->bid_devno == devno) | |
4937 | + goto set_pri; | |
4938 | + | |
4939 | + if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) && | |
4940 | + st.st_rdev == devno) { | |
4941 | + devname = blkid_strdup(device); | |
4942 | + break; | |
4943 | + } | |
4944 | + } | |
4945 | + if (!devname) { | |
4946 | + devname = blkid_devno_to_devname(devno); | |
4947 | + if (!devname) | |
4948 | + return; | |
4949 | + } | |
4950 | + dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); | |
4951 | + free(devname); | |
4952 | + | |
4953 | +set_pri: | |
4954 | + if (!pri && !strncmp(ptname, "md", 2)) | |
4955 | + pri = BLKID_PRI_MD; | |
4956 | + if (dev) | |
4957 | + dev->bid_pri = pri; | |
4958 | + return; | |
4959 | +} | |
4960 | + | |
4961 | +#define PROC_PARTITIONS "/proc/partitions" | |
4962 | +#define VG_DIR "/proc/lvm/VGs" | |
4963 | + | |
4964 | +/* | |
4965 | + * This function initializes the UUID cache with devices from the LVM | |
4966 | + * proc hierarchy. We currently depend on the names of the LVM | |
4967 | + * hierarchy giving us the device structure in /dev. (XXX is this a | |
4968 | + * safe thing to do?) | |
4969 | + */ | |
4970 | +#ifdef VG_DIR | |
4971 | +#include <dirent.h> | |
4972 | +static dev_t lvm_get_devno(const char *lvm_device) | |
4973 | +{ | |
4974 | + FILE *lvf; | |
4975 | + char buf[1024]; | |
4976 | + int ma, mi; | |
4977 | + dev_t ret = 0; | |
4978 | + | |
4979 | + DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device)); | |
4980 | + if ((lvf = fopen(lvm_device, "r")) == NULL) { | |
4981 | + DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno, | |
4982 | + strerror(errno))); | |
4983 | + return 0; | |
4984 | + } | |
4985 | + | |
4986 | + while (fgets(buf, sizeof(buf), lvf)) { | |
4987 | + if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { | |
4988 | + ret = makedev(ma, mi); | |
4989 | + break; | |
4990 | + } | |
4991 | + } | |
4992 | + fclose(lvf); | |
4993 | + | |
4994 | + return ret; | |
4995 | +} | |
4996 | + | |
4997 | +static void lvm_probe_all(blkid_cache cache) | |
4998 | +{ | |
4999 | + DIR *vg_list; | |
5000 | + struct dirent *vg_iter; | |
5001 | + int vg_len = strlen(VG_DIR); | |
5002 | + dev_t dev; | |
5003 | + | |
5004 | + if ((vg_list = opendir(VG_DIR)) == NULL) | |
5005 | + return; | |
5006 | + | |
5007 | + DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR)); | |
5008 | + | |
5009 | + while ((vg_iter = readdir(vg_list)) != NULL) { | |
5010 | + DIR *lv_list; | |
5011 | + char *vdirname; | |
5012 | + char *vg_name; | |
5013 | + struct dirent *lv_iter; | |
5014 | + | |
5015 | + vg_name = vg_iter->d_name; | |
5016 | + if (!strcmp(vg_name, ".") || !strcmp(vg_name, "..")) | |
5017 | + continue; | |
5018 | + vdirname = malloc(vg_len + strlen(vg_name) + 8); | |
5019 | + if (!vdirname) | |
5020 | + goto exit; | |
5021 | + sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name); | |
5022 | + | |
5023 | + lv_list = opendir(vdirname); | |
5024 | + free(vdirname); | |
5025 | + if (lv_list == NULL) | |
5026 | + continue; | |
5027 | + | |
5028 | + while ((lv_iter = readdir(lv_list)) != NULL) { | |
5029 | + char *lv_name, *lvm_device; | |
5030 | + | |
5031 | + lv_name = lv_iter->d_name; | |
5032 | + if (!strcmp(lv_name, ".") || !strcmp(lv_name, "..")) | |
5033 | + continue; | |
5034 | + | |
5035 | + lvm_device = malloc(vg_len + strlen(vg_name) + | |
5036 | + strlen(lv_name) + 8); | |
5037 | + if (!lvm_device) { | |
5038 | + closedir(lv_list); | |
5039 | + goto exit; | |
5040 | + } | |
5041 | + sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, | |
5042 | + lv_name); | |
5043 | + dev = lvm_get_devno(lvm_device); | |
5044 | + sprintf(lvm_device, "%s/%s", vg_name, lv_name); | |
5045 | + DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", | |
5046 | + lvm_device, | |
5047 | + (unsigned int) dev)); | |
5048 | + probe_one(cache, lvm_device, dev, BLKID_PRI_LVM); | |
5049 | + free(lvm_device); | |
5050 | + } | |
5051 | + closedir(lv_list); | |
5052 | + } | |
5053 | +exit: | |
5054 | + closedir(vg_list); | |
5055 | +} | |
5056 | +#endif | |
5057 | + | |
5058 | +#define PROC_EVMS_VOLUMES "/proc/evms/volumes" | |
5059 | + | |
5060 | +static int | |
5061 | +evms_probe_all(blkid_cache cache) | |
5062 | +{ | |
5063 | + char line[100]; | |
5064 | + int ma, mi, sz, num = 0; | |
5065 | + FILE *procpt; | |
5066 | + char device[110]; | |
5067 | + | |
5068 | + procpt = fopen(PROC_EVMS_VOLUMES, "r"); | |
5069 | + if (!procpt) | |
5070 | + return 0; | |
5071 | + while (fgets(line, sizeof(line), procpt)) { | |
5072 | + if (sscanf (line, " %d %d %d %*s %*s %[^\n ]", | |
5073 | + &ma, &mi, &sz, device) != 4) | |
5074 | + continue; | |
5075 | + | |
5076 | + DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", | |
5077 | + device, ma, mi)); | |
5078 | + | |
5079 | + probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS); | |
5080 | + num++; | |
5081 | + } | |
5082 | + fclose(procpt); | |
5083 | + return num; | |
5084 | +} | |
5085 | + | |
5086 | +/* | |
5087 | + * Read the device data for all available block devices in the system. | |
5088 | + */ | |
5089 | +int blkid_probe_all(blkid_cache cache) | |
5090 | +{ | |
5091 | + FILE *proc; | |
5092 | + char line[1024]; | |
5093 | + char ptname0[128], ptname1[128], *ptname = 0; | |
5094 | + char *ptnames[2]; | |
5095 | + dev_t devs[2]; | |
5096 | + int ma, mi; | |
5097 | + unsigned long long sz; | |
5098 | + int lens[2] = { 0, 0 }; | |
5099 | + int which = 0, last = 0; | |
5100 | + | |
5101 | + ptnames[0] = ptname0; | |
5102 | + ptnames[1] = ptname1; | |
5103 | + | |
5104 | + if (!cache) | |
5105 | + return -BLKID_ERR_PARAM; | |
5106 | + | |
5107 | + if (cache->bic_flags & BLKID_BIC_FL_PROBED && | |
5108 | + time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) | |
5109 | + return 0; | |
5110 | + | |
5111 | + blkid_read_cache(cache); | |
5112 | + evms_probe_all(cache); | |
5113 | +#ifdef VG_DIR | |
5114 | + lvm_probe_all(cache); | |
5115 | +#endif | |
5116 | + | |
5117 | + proc = fopen(PROC_PARTITIONS, "r"); | |
5118 | + if (!proc) | |
5119 | + return -BLKID_ERR_PROC; | |
5120 | + | |
5121 | + while (fgets(line, sizeof(line), proc)) { | |
5122 | + last = which; | |
5123 | + which ^= 1; | |
5124 | + ptname = ptnames[which]; | |
5125 | + | |
5126 | + if (sscanf(line, " %d %d %llu %128[^\n ]", | |
5127 | + &ma, &mi, &sz, ptname) != 4) | |
5128 | + continue; | |
5129 | + devs[which] = makedev(ma, mi); | |
5130 | + | |
5131 | + DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname)); | |
5132 | + | |
5133 | + /* Skip whole disk devs unless they have no partitions | |
5134 | + * If we don't have a partition on this dev, also | |
5135 | + * check previous dev to see if it didn't have a partn. | |
5136 | + * heuristic: partition name ends in a digit. | |
5137 | + * | |
5138 | + * Skip extended partitions. | |
5139 | + * heuristic: size is 1 | |
5140 | + * | |
5141 | + * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs | |
5142 | + */ | |
5143 | + | |
5144 | + lens[which] = strlen(ptname); | |
5145 | + if (isdigit(ptname[lens[which] - 1])) { | |
5146 | + DBG(DEBUG_DEVNAME, | |
5147 | + printf("partition dev %s, devno 0x%04X\n", | |
5148 | + ptname, (unsigned int) devs[which])); | |
5149 | + | |
5150 | + if (sz > 1) | |
5151 | + probe_one(cache, ptname, devs[which], 0); | |
5152 | + lens[which] = 0; | |
5153 | + lens[last] = 0; | |
5154 | + } else if (lens[last] && strncmp(ptnames[last], ptname, | |
5155 | + lens[last])) { | |
5156 | + DBG(DEBUG_DEVNAME, | |
5157 | + printf("whole dev %s, devno 0x%04X\n", | |
5158 | + ptnames[last], (unsigned int) devs[last])); | |
5159 | + probe_one(cache, ptnames[last], devs[last], 0); | |
5160 | + lens[last] = 0; | |
5161 | + } | |
5162 | + } | |
5163 | + | |
5164 | + /* Handle the last device if it wasn't partitioned */ | |
5165 | + if (lens[which]) | |
5166 | + probe_one(cache, ptname, devs[which], 0); | |
5167 | + | |
5168 | + fclose(proc); | |
5169 | + | |
5170 | + cache->bic_time = time(0); | |
5171 | + cache->bic_flags |= BLKID_BIC_FL_PROBED; | |
5172 | + blkid_flush_cache(cache); | |
5173 | + return 0; | |
5174 | +} | |
5175 | + | |
5176 | +#ifdef TEST_PROGRAM | |
5177 | +int main(int argc, char **argv) | |
5178 | +{ | |
5179 | + blkid_cache cache = NULL; | |
5180 | + int ret; | |
5181 | + | |
5182 | + blkid_debug_mask = DEBUG_ALL; | |
5183 | + if (argc != 1) { | |
5184 | + fprintf(stderr, "Usage: %s\n" | |
5185 | + "Probe all devices and exit\n", argv[0]); | |
5186 | + exit(1); | |
5187 | + } | |
5188 | + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { | |
5189 | + fprintf(stderr, "%s: error creating cache (%d)\n", | |
5190 | + argv[0], ret); | |
5191 | + exit(1); | |
5192 | + } | |
5193 | + if (blkid_probe_all(cache) < 0) | |
5194 | + printf("%s: error probing devices\n", argv[0]); | |
5195 | + | |
5196 | + blkid_put_cache(cache); | |
5197 | + return (0); | |
5198 | +} | |
5199 | +#endif | |
5200 | diff -Nur busybox-1.00/e2fsprogs/blkid/devno.c busybox/e2fsprogs/blkid/devno.c | |
5201 | --- busybox-1.00/e2fsprogs/blkid/devno.c 1970-01-01 01:00:00.000000000 +0100 | |
5202 | +++ busybox/e2fsprogs/blkid/devno.c 2005-06-04 08:20:15.000000000 +0200 | |
5203 | @@ -0,0 +1,233 @@ | |
5204 | +/* | |
5205 | + * devno.c - find a particular device by its device number (major/minor) | |
5206 | + * | |
5207 | + * Copyright (C) 2000, 2001, 2003 Theodore Ts'o | |
5208 | + * Copyright (C) 2001 Andreas Dilger | |
5209 | + * | |
5210 | + * %Begin-Header% | |
5211 | + * This file may be redistributed under the terms of the | |
5212 | + * GNU Lesser General Public License. | |
5213 | + * %End-Header% | |
5214 | + */ | |
5215 | + | |
5216 | +#include <stdio.h> | |
5217 | +#include <string.h> | |
5218 | +#if HAVE_UNISTD_H | |
5219 | +#include <unistd.h> | |
5220 | +#endif | |
5221 | +#include <stdlib.h> | |
5222 | +#include <string.h> | |
5223 | +#if HAVE_SYS_TYPES_H | |
5224 | +#include <sys/types.h> | |
5225 | +#endif | |
5226 | +#if HAVE_SYS_STAT_H | |
5227 | +#include <sys/stat.h> | |
5228 | +#endif | |
5229 | +#include <dirent.h> | |
5230 | +#if HAVE_ERRNO_H | |
5231 | +#include <errno.h> | |
5232 | +#endif | |
5233 | +#if HAVE_SYS_MKDEV_H | |
5234 | +#include <sys/mkdev.h> | |
5235 | +#endif | |
5236 | + | |
5237 | +#include "blkidP.h" | |
5238 | + | |
5239 | +struct dir_list { | |
5240 | + char *name; | |
5241 | + struct dir_list *next; | |
5242 | +}; | |
5243 | + | |
5244 | +char *blkid_strndup(const char *s, int length) | |
5245 | +{ | |
5246 | + char *ret; | |
5247 | + | |
5248 | + if (!s) | |
5249 | + return NULL; | |
5250 | + | |
5251 | + if (!length) | |
5252 | + length = strlen(s); | |
5253 | + | |
5254 | + ret = malloc(length + 1); | |
5255 | + if (ret) { | |
5256 | + strncpy(ret, s, length); | |
5257 | + ret[length] = '\0'; | |
5258 | + } | |
5259 | + return ret; | |
5260 | +} | |
5261 | + | |
5262 | +char *blkid_strdup(const char *s) | |
5263 | +{ | |
5264 | + return blkid_strndup(s, 0); | |
5265 | +} | |
5266 | + | |
5267 | +/* | |
5268 | + * This function adds an entry to the directory list | |
5269 | + */ | |
5270 | +static void add_to_dirlist(const char *name, struct dir_list **list) | |
5271 | +{ | |
5272 | + struct dir_list *dp; | |
5273 | + | |
5274 | + dp = malloc(sizeof(struct dir_list)); | |
5275 | + if (!dp) | |
5276 | + return; | |
5277 | + dp->name = blkid_strdup(name); | |
5278 | + if (!dp->name) { | |
5279 | + free(dp); | |
5280 | + return; | |
5281 | + } | |
5282 | + dp->next = *list; | |
5283 | + *list = dp; | |
5284 | +} | |
5285 | + | |
5286 | +/* | |
5287 | + * This function frees a directory list | |
5288 | + */ | |
5289 | +static void free_dirlist(struct dir_list **list) | |
5290 | +{ | |
5291 | + struct dir_list *dp, *next; | |
5292 | + | |
5293 | + for (dp = *list; dp; dp = next) { | |
5294 | + next = dp->next; | |
5295 | + free(dp->name); | |
5296 | + free(dp); | |
5297 | + } | |
5298 | + *list = NULL; | |
5299 | +} | |
5300 | + | |
5301 | +static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list, | |
5302 | + char **devname) | |
5303 | +{ | |
5304 | + DIR *dir; | |
5305 | + struct dirent *dp; | |
5306 | + char path[1024]; | |
5307 | + int dirlen; | |
5308 | + struct stat st; | |
5309 | + | |
5310 | + if ((dir = opendir(dir_name)) == NULL) | |
5311 | + return; | |
5312 | + dirlen = strlen(dir_name) + 2; | |
5313 | + while ((dp = readdir(dir)) != 0) { | |
5314 | + if (dirlen + strlen(dp->d_name) >= sizeof(path)) | |
5315 | + continue; | |
5316 | + | |
5317 | + if (dp->d_name[0] == '.' && | |
5318 | + ((dp->d_name[1] == 0) || | |
5319 | + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) | |
5320 | + continue; | |
5321 | + | |
5322 | + sprintf(path, "%s/%s", dir_name, dp->d_name); | |
5323 | + if (stat(path, &st) < 0) | |
5324 | + continue; | |
5325 | + | |
5326 | + if (S_ISDIR(st.st_mode)) | |
5327 | + add_to_dirlist(path, list); | |
5328 | + else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) { | |
5329 | + *devname = blkid_strdup(path); | |
5330 | + DBG(DEBUG_DEVNO, | |
5331 | + printf("found 0x%Lx at %s (%p)\n", devno, | |
5332 | + path, *devname)); | |
5333 | + break; | |
5334 | + } | |
5335 | + } | |
5336 | + closedir(dir); | |
5337 | + return; | |
5338 | +} | |
5339 | + | |
5340 | +/* Directories where we will try to search for device numbers */ | |
5341 | +const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL }; | |
5342 | + | |
5343 | +/* | |
5344 | + * This function finds the pathname to a block device with a given | |
5345 | + * device number. It returns a pointer to allocated memory to the | |
5346 | + * pathname on success, and NULL on failure. | |
5347 | + */ | |
5348 | +char *blkid_devno_to_devname(dev_t devno) | |
5349 | +{ | |
5350 | + struct dir_list *list = NULL, *new_list = NULL; | |
5351 | + char *devname = NULL; | |
5352 | + const char **dir; | |
5353 | + | |
5354 | + /* | |
5355 | + * Add the starting directories to search in reverse order of | |
5356 | + * importance, since we are using a stack... | |
5357 | + */ | |
5358 | + for (dir = blkid_devdirs; *dir; dir++) | |
5359 | + add_to_dirlist(*dir, &list); | |
5360 | + | |
5361 | + while (list) { | |
5362 | + struct dir_list *current = list; | |
5363 | + | |
5364 | + list = list->next; | |
5365 | + DBG(DEBUG_DEVNO, printf("directory %s\n", current->name)); | |
5366 | + scan_dir(current->name, devno, &new_list, &devname); | |
5367 | + free(current->name); | |
5368 | + free(current); | |
5369 | + if (devname) | |
5370 | + break; | |
5371 | + /* | |
5372 | + * If we're done checking at this level, descend to | |
5373 | + * the next level of subdirectories. (breadth-first) | |
5374 | + */ | |
5375 | + if (list == NULL) { | |
5376 | + list = new_list; | |
5377 | + new_list = NULL; | |
5378 | + } | |
5379 | + } | |
5380 | + free_dirlist(&list); | |
5381 | + free_dirlist(&new_list); | |
5382 | + | |
5383 | + if (!devname) { | |
5384 | + DBG(DEBUG_DEVNO, | |
5385 | + printf("blkid: couldn't find devno 0x%04lx\n", | |
5386 | + (unsigned long) devno)); | |
5387 | + } else { | |
5388 | + DBG(DEBUG_DEVNO, | |
5389 | + printf("found devno 0x%04Lx as %s\n", devno, devname)); | |
5390 | + } | |
5391 | + | |
5392 | + | |
5393 | + return devname; | |
5394 | +} | |
5395 | + | |
5396 | +#ifdef TEST_PROGRAM | |
5397 | +int main(int argc, char** argv) | |
5398 | +{ | |
5399 | + char *devname, *tmp; | |
5400 | + int major, minor; | |
5401 | + dev_t devno; | |
5402 | + const char *errmsg = "Couldn't parse %s: %s\n"; | |
5403 | + | |
5404 | + blkid_debug_mask = DEBUG_ALL; | |
5405 | + if ((argc != 2) && (argc != 3)) { | |
5406 | + fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n" | |
5407 | + "Resolve a device number to a device name\n", | |
5408 | + argv[0], argv[0]); | |
5409 | + exit(1); | |
5410 | + } | |
5411 | + if (argc == 2) { | |
5412 | + devno = strtoul(argv[1], &tmp, 0); | |
5413 | + if (*tmp) { | |
5414 | + fprintf(stderr, errmsg, "device number", argv[1]); | |
5415 | + exit(1); | |
5416 | + } | |
5417 | + } else { | |
5418 | + major = strtoul(argv[1], &tmp, 0); | |
5419 | + if (*tmp) { | |
5420 | + fprintf(stderr, errmsg, "major number", argv[1]); | |
5421 | + exit(1); | |
5422 | + } | |
5423 | + minor = strtoul(argv[2], &tmp, 0); | |
5424 | + if (*tmp) { | |
5425 | + fprintf(stderr, errmsg, "minor number", argv[2]); | |
5426 | + exit(1); | |
5427 | + } | |
5428 | + devno = makedev(major, minor); | |
5429 | + } | |
5430 | + printf("Looking for device 0x%04Lx\n", devno); | |
5431 | + devname = blkid_devno_to_devname(devno); | |
5432 | + if (devname) | |
5433 | + free(devname); | |
5434 | + return 0; | |
5435 | +} | |
5436 | +#endif | |
5437 | diff -Nur busybox-1.00/e2fsprogs/blkid/getsize.c busybox/e2fsprogs/blkid/getsize.c | |
5438 | --- busybox-1.00/e2fsprogs/blkid/getsize.c 1970-01-01 01:00:00.000000000 +0100 | |
5439 | +++ busybox/e2fsprogs/blkid/getsize.c 2005-06-04 08:20:15.000000000 +0200 | |
5440 | @@ -0,0 +1,180 @@ | |
5441 | +/* | |
5442 | + * getsize.c --- get the size of a partition. | |
5443 | + * | |
5444 | + * Copyright (C) 1995, 1995 Theodore Ts'o. | |
5445 | + * | |
5446 | + * %Begin-Header% | |
5447 | + * This file may be redistributed under the terms of the | |
5448 | + * GNU Lesser General Public License. | |
5449 | + * %End-Header% | |
5450 | + */ | |
5451 | + | |
5452 | +/* include this before sys/queues.h! */ | |
5453 | +#include "blkidP.h" | |
5454 | + | |
5455 | +#include <stdio.h> | |
5456 | +#if HAVE_UNISTD_H | |
5457 | +#include <unistd.h> | |
5458 | +#endif | |
5459 | +#if HAVE_ERRNO_H | |
5460 | +#include <errno.h> | |
5461 | +#endif | |
5462 | +#include <fcntl.h> | |
5463 | +#ifdef HAVE_SYS_IOCTL_H | |
5464 | +#include <sys/ioctl.h> | |
5465 | +#endif | |
5466 | +#ifdef HAVE_LINUX_FD_H | |
5467 | +#include <linux/fd.h> | |
5468 | +#endif | |
5469 | +#ifdef HAVE_SYS_DISKLABEL_H | |
5470 | +#include <sys/disklabel.h> | |
5471 | +#include <sys/stat.h> | |
5472 | +#endif | |
5473 | +#ifdef HAVE_SYS_DISK_H | |
5474 | +#ifdef HAVE_SYS_QUEUE_H | |
5475 | +#include <sys/queue.h> /* for LIST_HEAD */ | |
5476 | +#endif | |
5477 | +#include <sys/disk.h> | |
5478 | +#endif | |
5479 | +#ifdef __linux__ | |
5480 | +#include <sys/utsname.h> | |
5481 | +#endif | |
5482 | + | |
5483 | +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) | |
5484 | +#define BLKGETSIZE _IO(0x12,96) /* return device size */ | |
5485 | +#endif | |
5486 | + | |
5487 | +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) | |
5488 | +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ | |
5489 | +#endif | |
5490 | + | |
5491 | +#ifdef APPLE_DARWIN | |
5492 | +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 | |
5493 | +#endif /* APPLE_DARWIN */ | |
5494 | + | |
5495 | +static int valid_offset(int fd, blkid_loff_t offset) | |
5496 | +{ | |
5497 | + char ch; | |
5498 | + | |
5499 | + if (blkid_llseek(fd, offset, 0) < 0) | |
5500 | + return 0; | |
5501 | + if (read(fd, &ch, 1) < 1) | |
5502 | + return 0; | |
5503 | + return 1; | |
5504 | +} | |
5505 | + | |
5506 | +/* | |
5507 | + * Returns the number of blocks in a partition | |
5508 | + */ | |
5509 | +blkid_loff_t blkid_get_dev_size(int fd) | |
5510 | +{ | |
5511 | + int valid_blkgetsize64 = 1; | |
5512 | +#ifdef __linux__ | |
5513 | + struct utsname ut; | |
5514 | +#endif | |
5515 | + unsigned long long size64; | |
5516 | + unsigned long size; | |
5517 | + blkid_loff_t high, low; | |
5518 | +#ifdef FDGETPRM | |
5519 | + struct floppy_struct this_floppy; | |
5520 | +#endif | |
5521 | +#ifdef HAVE_SYS_DISKLABEL_H | |
5522 | + int part = -1; | |
5523 | + struct disklabel lab; | |
5524 | + struct partition *pp; | |
5525 | + char ch; | |
5526 | + struct stat st; | |
5527 | +#endif /* HAVE_SYS_DISKLABEL_H */ | |
5528 | + | |
5529 | +#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ | |
5530 | + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { | |
5531 | + if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) | |
5532 | + && (size64 << 9 > 0xFFFFFFFF)) | |
5533 | + return 0; /* EFBIG */ | |
5534 | + return (blkid_loff_t) size64 << 9; | |
5535 | + } | |
5536 | +#endif | |
5537 | + | |
5538 | +#ifdef BLKGETSIZE64 | |
5539 | +#ifdef __linux__ | |
5540 | + if ((uname(&ut) == 0) && | |
5541 | + ((ut.release[0] == '2') && (ut.release[1] == '.') && | |
5542 | + (ut.release[2] < '6') && (ut.release[3] == '.'))) | |
5543 | + valid_blkgetsize64 = 0; | |
5544 | +#endif | |
5545 | + if (valid_blkgetsize64 && | |
5546 | + ioctl(fd, BLKGETSIZE64, &size64) >= 0) { | |
5547 | + if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) | |
5548 | + && ((size64) > 0xFFFFFFFF)) | |
5549 | + return 0; /* EFBIG */ | |
5550 | + return size64; | |
5551 | + } | |
5552 | +#endif | |
5553 | + | |
5554 | +#ifdef BLKGETSIZE | |
5555 | + if (ioctl(fd, BLKGETSIZE, &size) >= 0) | |
5556 | + return (blkid_loff_t)size << 9; | |
5557 | +#endif | |
5558 | + | |
5559 | +#ifdef FDGETPRM | |
5560 | + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) | |
5561 | + return (blkid_loff_t)this_floppy.size << 9; | |
5562 | +#endif | |
5563 | +#ifdef HAVE_SYS_DISKLABEL_H | |
5564 | +#if 0 | |
5565 | + /* | |
5566 | + * This should work in theory but I haven't tested it. Anyone | |
5567 | + * on a BSD system want to test this for me? In the meantime, | |
5568 | + * binary search mechanism should work just fine. | |
5569 | + */ | |
5570 | + if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode)) | |
5571 | + part = st.st_rdev & 7; | |
5572 | + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { | |
5573 | + pp = &lab.d_partitions[part]; | |
5574 | + if (pp->p_size) | |
5575 | + return pp->p_size << 9; | |
5576 | + } | |
5577 | +#endif | |
5578 | +#endif /* HAVE_SYS_DISKLABEL_H */ | |
5579 | + | |
5580 | + /* | |
5581 | + * OK, we couldn't figure it out by using a specialized ioctl, | |
5582 | + * which is generally the best way. So do binary search to | |
5583 | + * find the size of the partition. | |
5584 | + */ | |
5585 | + low = 0; | |
5586 | + for (high = 1024; valid_offset(fd, high); high *= 2) | |
5587 | + low = high; | |
5588 | + while (low < high - 1) | |
5589 | + { | |
5590 | + const blkid_loff_t mid = (low + high) / 2; | |
5591 | + | |
5592 | + if (valid_offset(fd, mid)) | |
5593 | + low = mid; | |
5594 | + else | |
5595 | + high = mid; | |
5596 | + } | |
5597 | + return low + 1; | |
5598 | +} | |
5599 | + | |
5600 | +#ifdef TEST_PROGRAM | |
5601 | +int main(int argc, char **argv) | |
5602 | +{ | |
5603 | + blkid_loff_t bytes; | |
5604 | + int fd; | |
5605 | + | |
5606 | + if (argc < 2) { | |
5607 | + fprintf(stderr, "Usage: %s device\n" | |
5608 | + "Determine the size of a device\n", argv[0]); | |
5609 | + return 1; | |
5610 | + } | |
5611 | + | |
5612 | + if ((fd = open(argv[1], O_RDONLY)) < 0) | |
5613 | + perror(argv[0]); | |
5614 | + | |
5615 | + bytes = blkid_get_dev_size(fd); | |
5616 | + printf("Device %s has %Ld 1k blocks.\n", argv[1], bytes >> 10); | |
5617 | + | |
5618 | + return 0; | |
5619 | +} | |
5620 | +#endif | |
5621 | diff -Nur busybox-1.00/e2fsprogs/blkid/list.h busybox/e2fsprogs/blkid/list.h | |
5622 | --- busybox-1.00/e2fsprogs/blkid/list.h 1970-01-01 01:00:00.000000000 +0100 | |
5623 | +++ busybox/e2fsprogs/blkid/list.h 2005-06-04 08:20:15.000000000 +0200 | |
5624 | @@ -0,0 +1,179 @@ | |
5625 | +#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD) | |
5626 | +#define _BLKID_LIST_H | |
5627 | + | |
5628 | +#ifdef __cplusplus | |
5629 | +extern "C" { | |
5630 | +#endif | |
5631 | + | |
5632 | +#ifdef __GNUC__ | |
5633 | +#define _INLINE_ static __inline__ | |
5634 | +#else /* For Watcom C */ | |
5635 | +#define _INLINE_ static inline | |
5636 | +#endif | |
5637 | + | |
5638 | +/* | |
5639 | + * Simple doubly linked list implementation. | |
5640 | + * | |
5641 | + * Some of the internal functions ("__xxx") are useful when | |
5642 | + * manipulating whole lists rather than single entries, as | |
5643 | + * sometimes we already know the next/prev entries and we can | |
5644 | + * generate better code by using them directly rather than | |
5645 | + * using the generic single-entry routines. | |
5646 | + */ | |
5647 | + | |
5648 | +struct list_head { | |
5649 | + struct list_head *next, *prev; | |
5650 | +}; | |
5651 | + | |
5652 | +#define LIST_HEAD_INIT(name) { &(name), &(name) } | |
5653 | + | |
5654 | +#define LIST_HEAD(name) \ | |
5655 | + struct list_head name = LIST_HEAD_INIT(name) | |
5656 | + | |
5657 | +#define INIT_LIST_HEAD(ptr) do { \ | |
5658 | + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ | |
5659 | +} while (0) | |
5660 | + | |
5661 | +/* | |
5662 | + * Insert a new entry between two known consecutive entries. | |
5663 | + * | |
5664 | + * This is only for internal list manipulation where we know | |
5665 | + * the prev/next entries already! | |
5666 | + */ | |
5667 | +_INLINE_ void __list_add(struct list_head * add, | |
5668 | + struct list_head * prev, | |
5669 | + struct list_head * next) | |
5670 | +{ | |
5671 | + next->prev = add; | |
5672 | + add->next = next; | |
5673 | + add->prev = prev; | |
5674 | + prev->next = add; | |
5675 | +} | |
5676 | + | |
5677 | +/** | |
5678 | + * list_add - add a new entry | |
5679 | + * @add: new entry to be added | |
5680 | + * @head: list head to add it after | |
5681 | + * | |
5682 | + * Insert a new entry after the specified head. | |
5683 | + * This is good for implementing stacks. | |
5684 | + */ | |
5685 | +_INLINE_ void list_add(struct list_head *add, struct list_head *head) | |
5686 | +{ | |
5687 | + __list_add(add, head, head->next); | |
5688 | +} | |
5689 | + | |
5690 | +/** | |
5691 | + * list_add_tail - add a new entry | |
5692 | + * @add: new entry to be added | |
5693 | + * @head: list head to add it before | |
5694 | + * | |
5695 | + * Insert a new entry before the specified head. | |
5696 | + * This is useful for implementing queues. | |
5697 | + */ | |
5698 | +_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head) | |
5699 | +{ | |
5700 | + __list_add(add, head->prev, head); | |
5701 | +} | |
5702 | + | |
5703 | +/* | |
5704 | + * Delete a list entry by making the prev/next entries | |
5705 | + * point to each other. | |
5706 | + * | |
5707 | + * This is only for internal list manipulation where we know | |
5708 | + * the prev/next entries already! | |
5709 | + */ | |
5710 | +_INLINE_ void __list_del(struct list_head * prev, | |
5711 | + struct list_head * next) | |
5712 | +{ | |
5713 | + next->prev = prev; | |
5714 | + prev->next = next; | |
5715 | +} | |
5716 | + | |
5717 | +/** | |
5718 | + * list_del - deletes entry from list. | |
5719 | + * @entry: the element to delete from the list. | |
5720 | + * | |
5721 | + * list_empty() on @entry does not return true after this, @entry is | |
5722 | + * in an undefined state. | |
5723 | + */ | |
5724 | +_INLINE_ void list_del(struct list_head *entry) | |
5725 | +{ | |
5726 | + __list_del(entry->prev, entry->next); | |
5727 | +} | |
5728 | + | |
5729 | +/** | |
5730 | + * list_del_init - deletes entry from list and reinitialize it. | |
5731 | + * @entry: the element to delete from the list. | |
5732 | + */ | |
5733 | +_INLINE_ void list_del_init(struct list_head *entry) | |
5734 | +{ | |
5735 | + __list_del(entry->prev, entry->next); | |
5736 | + INIT_LIST_HEAD(entry); | |
5737 | +} | |
5738 | + | |
5739 | +/** | |
5740 | + * list_empty - tests whether a list is empty | |
5741 | + * @head: the list to test. | |
5742 | + */ | |
5743 | +_INLINE_ int list_empty(struct list_head *head) | |
5744 | +{ | |
5745 | + return head->next == head; | |
5746 | +} | |
5747 | + | |
5748 | +/** | |
5749 | + * list_splice - join two lists | |
5750 | + * @list: the new list to add. | |
5751 | + * @head: the place to add it in the first list. | |
5752 | + */ | |
5753 | +_INLINE_ void list_splice(struct list_head *list, struct list_head *head) | |
5754 | +{ | |
5755 | + struct list_head *first = list->next; | |
5756 | + | |
5757 | + if (first != list) { | |
5758 | + struct list_head *last = list->prev; | |
5759 | + struct list_head *at = head->next; | |
5760 | + | |
5761 | + first->prev = head; | |
5762 | + head->next = first; | |
5763 | + | |
5764 | + last->next = at; | |
5765 | + at->prev = last; | |
5766 | + } | |
5767 | +} | |
5768 | + | |
5769 | +/** | |
5770 | + * list_entry - get the struct for this entry | |
5771 | + * @ptr: the &struct list_head pointer. | |
5772 | + * @type: the type of the struct this is embedded in. | |
5773 | + * @member: the name of the list_struct within the struct. | |
5774 | + */ | |
5775 | +#define list_entry(ptr, type, member) \ | |
5776 | + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) | |
5777 | + | |
5778 | +/** | |
5779 | + * list_for_each - iterate over elements in a list | |
5780 | + * @pos: the &struct list_head to use as a loop counter. | |
5781 | + * @head: the head for your list. | |
5782 | + */ | |
5783 | +#define list_for_each(pos, head) \ | |
5784 | + for (pos = (head)->next; pos != (head); pos = pos->next) | |
5785 | + | |
5786 | +/** | |
5787 | + * list_for_each_safe - iterate over elements in a list, but don't dereference | |
5788 | + * pos after the body is done (in case it is freed) | |
5789 | + * @pos: the &struct list_head to use as a loop counter. | |
5790 | + * @pnext: the &struct list_head to use as a pointer to the next item. | |
5791 | + * @head: the head for your list (not included in iteration). | |
5792 | + */ | |
5793 | +#define list_for_each_safe(pos, pnext, head) \ | |
5794 | + for (pos = (head)->next, pnext = pos->next; pos != (head); \ | |
5795 | + pos = pnext, pnext = pos->next) | |
5796 | + | |
5797 | +#undef _INLINE_ | |
5798 | + | |
5799 | +#ifdef __cplusplus | |
5800 | +} | |
5801 | +#endif | |
5802 | + | |
5803 | +#endif /* _BLKID_LIST_H */ | |
5804 | diff -Nur busybox-1.00/e2fsprogs/blkid/llseek.c busybox/e2fsprogs/blkid/llseek.c | |
5805 | --- busybox-1.00/e2fsprogs/blkid/llseek.c 1970-01-01 01:00:00.000000000 +0100 | |
5806 | +++ busybox/e2fsprogs/blkid/llseek.c 2005-06-04 08:20:15.000000000 +0200 | |
5807 | @@ -0,0 +1,139 @@ | |
5808 | +/* | |
5809 | + * llseek.c -- stub calling the llseek system call | |
5810 | + * | |
5811 | + * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o. | |
5812 | + * | |
5813 | + * %Begin-Header% | |
5814 | + * This file may be redistributed under the terms of the | |
5815 | + * GNU Lesser General Public License. | |
5816 | + * %End-Header% | |
5817 | + */ | |
5818 | + | |
5819 | +#if HAVE_SYS_TYPES_H | |
5820 | +#include <sys/types.h> | |
5821 | +#endif | |
5822 | + | |
5823 | +#if HAVE_ERRNO_H | |
5824 | +#include <errno.h> | |
5825 | +#endif | |
5826 | +#if HAVE_UNISTD_H | |
5827 | +#include <unistd.h> | |
5828 | +#endif | |
5829 | +#ifdef __MSDOS__ | |
5830 | +#include <io.h> | |
5831 | +#endif | |
5832 | + | |
5833 | +#include "blkidP.h" | |
5834 | + | |
5835 | +#ifdef __linux__ | |
5836 | + | |
5837 | +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) | |
5838 | + | |
5839 | +#define my_llseek lseek64 | |
5840 | + | |
5841 | +#elif defined(HAVE_LLSEEK) | |
5842 | +#include <syscall.h> | |
5843 | + | |
5844 | +#ifndef HAVE_LLSEEK_PROTOTYPE | |
5845 | +extern long long llseek(int fd, long long offset, int origin); | |
5846 | +#endif | |
5847 | + | |
5848 | +#define my_llseek llseek | |
5849 | + | |
5850 | +#else /* ! HAVE_LLSEEK */ | |
5851 | + | |
5852 | +#if defined(__alpha__) || defined(__ia64__) | |
5853 | + | |
5854 | +#define llseek lseek | |
5855 | + | |
5856 | +#else /* !__alpha__ && !__ia64__*/ | |
5857 | + | |
5858 | +#include <linux/unistd.h> | |
5859 | + | |
5860 | +#ifndef __NR__llseek | |
5861 | +#define __NR__llseek 140 | |
5862 | +#endif | |
5863 | + | |
5864 | +#ifndef __i386__ | |
5865 | +static int _llseek(unsigned int, unsigned long, unsigned long, | |
5866 | + blkid_loff_t *, unsigned int); | |
5867 | + | |
5868 | +static _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high, | |
5869 | + unsigned long, offset_low, blkid_loff_t *, result, | |
5870 | + unsigned int, origin) | |
5871 | +#endif | |
5872 | + | |
5873 | +static blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin) | |
5874 | +{ | |
5875 | + blkid_loff_t result; | |
5876 | + int retval; | |
5877 | + | |
5878 | +#ifndef __i386__ | |
5879 | + retval = _llseek(fd, ((unsigned long long) offset) >> 32, | |
5880 | + ((unsigned long long)offset) & 0xffffffff, | |
5881 | + &result, origin); | |
5882 | +#else | |
5883 | + retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32, | |
5884 | + ((unsigned long long)offset) & 0xffffffff, | |
5885 | + &result, origin); | |
5886 | +#endif | |
5887 | + return (retval == -1 ? (blkid_loff_t) retval : result); | |
5888 | +} | |
5889 | + | |
5890 | +#endif /* __alpha__ || __ia64__ */ | |
5891 | + | |
5892 | +#endif /* HAVE_LLSEEK */ | |
5893 | + | |
5894 | +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence) | |
5895 | +{ | |
5896 | + blkid_loff_t result; | |
5897 | + static int do_compat = 0; | |
5898 | + | |
5899 | + if ((sizeof(off_t) >= sizeof(blkid_loff_t)) || | |
5900 | + (offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1)))) | |
5901 | + return lseek(fd, (off_t) offset, whence); | |
5902 | + | |
5903 | + if (do_compat) { | |
5904 | + errno = EOVERFLOW; | |
5905 | + return -1; | |
5906 | + } | |
5907 | + | |
5908 | + result = my_llseek(fd, offset, whence); | |
5909 | + if (result == -1 && errno == ENOSYS) { | |
5910 | + /* | |
5911 | + * Just in case this code runs on top of an old kernel | |
5912 | + * which does not support the llseek system call | |
5913 | + */ | |
5914 | + do_compat++; | |
5915 | + errno = EOVERFLOW; | |
5916 | + } | |
5917 | + return result; | |
5918 | +} | |
5919 | + | |
5920 | +#else /* !linux */ | |
5921 | + | |
5922 | +#ifndef EOVERFLOW | |
5923 | +#ifdef EXT2_ET_INVALID_ARGUMENT | |
5924 | +#define EOVERFLOW EXT2_ET_INVALID_ARGUMENT | |
5925 | +#else | |
5926 | +#define EOVERFLOW 112 | |
5927 | +#endif | |
5928 | +#endif | |
5929 | + | |
5930 | +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin) | |
5931 | +{ | |
5932 | +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) | |
5933 | + return lseek64 (fd, offset, origin); | |
5934 | +#else | |
5935 | + if ((sizeof(off_t) < sizeof(blkid_loff_t)) && | |
5936 | + (offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) { | |
5937 | + errno = EOVERFLOW; | |
5938 | + return -1; | |
5939 | + } | |
5940 | + return lseek(fd, (off_t) offset, origin); | |
5941 | +#endif | |
5942 | +} | |
5943 | + | |
5944 | +#endif /* linux */ | |
5945 | + | |
5946 | + | |
5947 | diff -Nur busybox-1.00/e2fsprogs/blkid/probe.c busybox/e2fsprogs/blkid/probe.c | |
5948 | --- busybox-1.00/e2fsprogs/blkid/probe.c 1970-01-01 01:00:00.000000000 +0100 | |
5949 | +++ busybox/e2fsprogs/blkid/probe.c 2005-06-04 08:20:15.000000000 +0200 | |
5950 | @@ -0,0 +1,704 @@ | |
5951 | +/* | |
5952 | + * probe.c - identify a block device by its contents, and return a dev | |
5953 | + * struct with the details | |
5954 | + * | |
5955 | + * Copyright (C) 1999 by Andries Brouwer | |
5956 | + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o | |
5957 | + * Copyright (C) 2001 by Andreas Dilger | |
5958 | + * | |
5959 | + * %Begin-Header% | |
5960 | + * This file may be redistributed under the terms of the | |
5961 | + * GNU Lesser General Public License. | |
5962 | + * %End-Header% | |
5963 | + */ | |
5964 | + | |
5965 | +#include <stdio.h> | |
5966 | +#include <string.h> | |
5967 | +#include <stdlib.h> | |
5968 | +#include <unistd.h> | |
5969 | +#include <fcntl.h> | |
5970 | +#include <sys/types.h> | |
5971 | +#ifdef HAVE_SYS_STAT_H | |
5972 | +#include <sys/stat.h> | |
5973 | +#endif | |
5974 | +#ifdef HAVE_SYS_MKDEV_H | |
5975 | +#include <sys/mkdev.h> | |
5976 | +#endif | |
5977 | +#ifdef HAVE_ERRNO_H | |
5978 | +#include <errno.h> | |
5979 | +#endif | |
5980 | +#include "blkidP.h" | |
5981 | +#include "uuid/uuid.h" | |
5982 | +#include "probe.h" | |
5983 | + | |
5984 | +/* | |
5985 | + * This is a special case code to check for an MDRAID device. We do | |
5986 | + * this special since it requires checking for a superblock at the end | |
5987 | + * of the device. | |
5988 | + */ | |
5989 | +static int check_mdraid(int fd, unsigned char *ret_uuid) | |
5990 | +{ | |
5991 | + struct mdp_superblock_s *md; | |
5992 | + blkid_loff_t offset; | |
5993 | + char buf[4096]; | |
5994 | + | |
5995 | + if (fd < 0) | |
5996 | + return -BLKID_ERR_PARAM; | |
5997 | + | |
5998 | + offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; | |
5999 | + | |
6000 | + if (blkid_llseek(fd, offset, 0) < 0 || | |
6001 | + read(fd, buf, 4096) != 4096) | |
6002 | + return -BLKID_ERR_IO; | |
6003 | + | |
6004 | + /* Check for magic number */ | |
6005 | + if (memcmp("\251+N\374", buf, 4)) | |
6006 | + return -BLKID_ERR_PARAM; | |
6007 | + | |
6008 | + if (!ret_uuid) | |
6009 | + return 0; | |
6010 | + *ret_uuid = 0; | |
6011 | + | |
6012 | + /* The MD UUID is not contiguous in the superblock, make it so */ | |
6013 | + md = (struct mdp_superblock_s *)buf; | |
6014 | + if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { | |
6015 | + memcpy(ret_uuid, &md->set_uuid0, 4); | |
6016 | + memcpy(ret_uuid, &md->set_uuid1, 12); | |
6017 | + } | |
6018 | + return 0; | |
6019 | +} | |
6020 | + | |
6021 | +static void set_uuid(blkid_dev dev, uuid_t uuid) | |
6022 | +{ | |
6023 | + char str[37]; | |
6024 | + | |
6025 | + if (!uuid_is_null(uuid)) { | |
6026 | + uuid_unparse(uuid, str); | |
6027 | + blkid_set_tag(dev, "UUID", str, sizeof(str)); | |
6028 | + } | |
6029 | +} | |
6030 | + | |
6031 | +static void get_ext2_info(blkid_dev dev, unsigned char *buf) | |
6032 | +{ | |
6033 | + struct ext2_super_block *es = (struct ext2_super_block *) buf; | |
6034 | + const char *label = 0; | |
6035 | + | |
6036 | + DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", | |
6037 | + blkid_le32(es->s_feature_compat), | |
6038 | + blkid_le32(es->s_feature_incompat), | |
6039 | + blkid_le32(es->s_feature_ro_compat))); | |
6040 | + | |
6041 | + if (strlen(es->s_volume_name)) | |
6042 | + label = es->s_volume_name; | |
6043 | + blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); | |
6044 | + | |
6045 | + set_uuid(dev, es->s_uuid); | |
6046 | +} | |
6047 | + | |
6048 | +static int probe_ext3(int fd __BLKID_ATTR((unused)), | |
6049 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6050 | + blkid_dev dev, | |
6051 | + struct blkid_magic *id, unsigned char *buf) | |
6052 | +{ | |
6053 | + struct ext2_super_block *es; | |
6054 | + | |
6055 | + es = (struct ext2_super_block *)buf; | |
6056 | + | |
6057 | + /* Distinguish between jbd and ext2/3 fs */ | |
6058 | + if (blkid_le32(es->s_feature_incompat) & | |
6059 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | |
6060 | + return -BLKID_ERR_PARAM; | |
6061 | + | |
6062 | + /* Distinguish between ext3 and ext2 */ | |
6063 | + if (!(blkid_le32(es->s_feature_compat) & | |
6064 | + EXT3_FEATURE_COMPAT_HAS_JOURNAL)) | |
6065 | + return -BLKID_ERR_PARAM; | |
6066 | + | |
6067 | + get_ext2_info(dev, buf); | |
6068 | + | |
6069 | + blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); | |
6070 | + | |
6071 | + return 0; | |
6072 | +} | |
6073 | + | |
6074 | +static int probe_ext2(int fd __BLKID_ATTR((unused)), | |
6075 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6076 | + blkid_dev dev, | |
6077 | + struct blkid_magic *id, unsigned char *buf) | |
6078 | +{ | |
6079 | + struct ext2_super_block *es; | |
6080 | +// const char *sec_type = 0, *label = 0; | |
6081 | + | |
6082 | + es = (struct ext2_super_block *)buf; | |
6083 | + | |
6084 | + /* Distinguish between jbd and ext2/3 fs */ | |
6085 | + if (blkid_le32(es->s_feature_incompat) & | |
6086 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | |
6087 | + return -BLKID_ERR_PARAM; | |
6088 | + | |
6089 | + get_ext2_info(dev, buf); | |
6090 | + | |
6091 | + return 0; | |
6092 | +} | |
6093 | + | |
6094 | +static int probe_jbd(int fd __BLKID_ATTR((unused)), | |
6095 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6096 | + blkid_dev dev, | |
6097 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6098 | + unsigned char *buf) | |
6099 | +{ | |
6100 | + struct ext2_super_block *es = (struct ext2_super_block *) buf; | |
6101 | + | |
6102 | + if (!(blkid_le32(es->s_feature_incompat) & | |
6103 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) | |
6104 | + return -BLKID_ERR_PARAM; | |
6105 | + | |
6106 | + get_ext2_info(dev, buf); | |
6107 | + | |
6108 | + return 0; | |
6109 | +} | |
6110 | + | |
6111 | +static int probe_vfat(int fd __BLKID_ATTR((unused)), | |
6112 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6113 | + blkid_dev dev, | |
6114 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6115 | + unsigned char *buf) | |
6116 | +{ | |
6117 | + struct vfat_super_block *vs; | |
6118 | + char serno[10]; | |
6119 | + const char *label = 0; | |
6120 | + int label_len = 0; | |
6121 | + | |
6122 | + vs = (struct vfat_super_block *)buf; | |
6123 | + | |
6124 | + if (strncmp(vs->vs_label, "NO NAME", 7)) { | |
6125 | + char *end = vs->vs_label + sizeof(vs->vs_label) - 1; | |
6126 | + | |
6127 | + while (*end == ' ' && end >= vs->vs_label) | |
6128 | + --end; | |
6129 | + if (end >= vs->vs_label) { | |
6130 | + label = vs->vs_label; | |
6131 | + label_len = end - vs->vs_label + 1; | |
6132 | + } | |
6133 | + } | |
6134 | + | |
6135 | + /* We can't just print them as %04X, because they are unaligned */ | |
6136 | + sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2], | |
6137 | + vs->vs_serno[1], vs->vs_serno[0]); | |
6138 | + blkid_set_tag(dev, "LABEL", label, label_len); | |
6139 | + blkid_set_tag(dev, "UUID", serno, sizeof(serno)); | |
6140 | + | |
6141 | + return 0; | |
6142 | +} | |
6143 | + | |
6144 | +static int probe_msdos(int fd __BLKID_ATTR((unused)), | |
6145 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6146 | + blkid_dev dev, | |
6147 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6148 | + unsigned char *buf) | |
6149 | +{ | |
6150 | + struct msdos_super_block *ms = (struct msdos_super_block *) buf; | |
6151 | + char serno[10]; | |
6152 | + const char *label = 0; | |
6153 | + int label_len = 0; | |
6154 | + | |
6155 | + if (strncmp(ms->ms_label, "NO NAME", 7)) { | |
6156 | + char *end = ms->ms_label + sizeof(ms->ms_label) - 1; | |
6157 | + | |
6158 | + while (*end == ' ' && end >= ms->ms_label) | |
6159 | + --end; | |
6160 | + if (end >= ms->ms_label) { | |
6161 | + label = ms->ms_label; | |
6162 | + label_len = end - ms->ms_label + 1; | |
6163 | + } | |
6164 | + } | |
6165 | + | |
6166 | + /* We can't just print them as %04X, because they are unaligned */ | |
6167 | + sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2], | |
6168 | + ms->ms_serno[1], ms->ms_serno[0]); | |
6169 | + blkid_set_tag(dev, "UUID", serno, 0); | |
6170 | + blkid_set_tag(dev, "LABEL", label, label_len); | |
6171 | + blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos")); | |
6172 | + | |
6173 | + return 0; | |
6174 | +} | |
6175 | + | |
6176 | +static int probe_xfs(int fd __BLKID_ATTR((unused)), | |
6177 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6178 | + blkid_dev dev, | |
6179 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6180 | + unsigned char *buf) | |
6181 | +{ | |
6182 | + struct xfs_super_block *xs; | |
6183 | + const char *label = 0; | |
6184 | + | |
6185 | + xs = (struct xfs_super_block *)buf; | |
6186 | + | |
6187 | + if (strlen(xs->xs_fname)) | |
6188 | + label = xs->xs_fname; | |
6189 | + blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname)); | |
6190 | + set_uuid(dev, xs->xs_uuid); | |
6191 | + return 0; | |
6192 | +} | |
6193 | + | |
6194 | +static int probe_reiserfs(int fd __BLKID_ATTR((unused)), | |
6195 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6196 | + blkid_dev dev, | |
6197 | + struct blkid_magic *id, unsigned char *buf) | |
6198 | +{ | |
6199 | + struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; | |
6200 | + unsigned int blocksize; | |
6201 | + const char *label = 0; | |
6202 | + | |
6203 | + blocksize = blkid_le16(rs->rs_blocksize); | |
6204 | + | |
6205 | + /* If the superblock is inside the journal, we have the wrong one */ | |
6206 | + if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) | |
6207 | + return -BLKID_ERR_BIG; | |
6208 | + | |
6209 | + /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ | |
6210 | + if (!strcmp(id->bim_magic, "ReIsEr2Fs") || | |
6211 | + !strcmp(id->bim_magic, "ReIsEr3Fs")) { | |
6212 | + if (strlen(rs->rs_label)) | |
6213 | + label = rs->rs_label; | |
6214 | + set_uuid(dev, rs->rs_uuid); | |
6215 | + } | |
6216 | + blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label)); | |
6217 | + | |
6218 | + return 0; | |
6219 | +} | |
6220 | + | |
6221 | +static int probe_jfs(int fd __BLKID_ATTR((unused)), | |
6222 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6223 | + blkid_dev dev, | |
6224 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6225 | + unsigned char *buf) | |
6226 | +{ | |
6227 | + struct jfs_super_block *js; | |
6228 | + const char *label = 0; | |
6229 | + | |
6230 | + js = (struct jfs_super_block *)buf; | |
6231 | + | |
6232 | + if (strlen((char *) js->js_label)) | |
6233 | + label = (char *) js->js_label; | |
6234 | + blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label)); | |
6235 | + set_uuid(dev, js->js_uuid); | |
6236 | + return 0; | |
6237 | +} | |
6238 | + | |
6239 | +static int probe_romfs(int fd __BLKID_ATTR((unused)), | |
6240 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6241 | + blkid_dev dev, | |
6242 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6243 | + unsigned char *buf) | |
6244 | +{ | |
6245 | + struct romfs_super_block *ros; | |
6246 | + const char *label = 0; | |
6247 | + | |
6248 | + ros = (struct romfs_super_block *)buf; | |
6249 | + | |
6250 | + if (strlen((char *) ros->ros_volume)) | |
6251 | + label = (char *) ros->ros_volume; | |
6252 | + blkid_set_tag(dev, "LABEL", label, 0); | |
6253 | + return 0; | |
6254 | +} | |
6255 | + | |
6256 | +static int probe_swap0(int fd __BLKID_ATTR((unused)), | |
6257 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6258 | + blkid_dev dev, | |
6259 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6260 | + unsigned char *buf __BLKID_ATTR((unused))) | |
6261 | +{ | |
6262 | + blkid_set_tag(dev, "UUID", 0, 0); | |
6263 | + blkid_set_tag(dev, "LABEL", 0, 0); | |
6264 | + return 0; | |
6265 | +} | |
6266 | + | |
6267 | +static int probe_swap1(int fd, | |
6268 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6269 | + blkid_dev dev, | |
6270 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6271 | + unsigned char *buf __BLKID_ATTR((unused))) | |
6272 | +{ | |
6273 | + struct swap_id_block *sws; | |
6274 | +// const char *label = 0; | |
6275 | + | |
6276 | + probe_swap0(fd, cache, dev, id, buf); | |
6277 | + /* | |
6278 | + * Version 1 swap headers are always located at offset of 1024 | |
6279 | + * bytes, although the swap signature itself is located at the | |
6280 | + * end of the page (which may vary depending on hardware | |
6281 | + * pagesize). | |
6282 | + */ | |
6283 | + if (lseek(fd, 1024, SEEK_SET) < 0) return 1; | |
6284 | + if (!(sws = (struct swap_id_block *)malloc(1024))) return 1; | |
6285 | + if (read(fd, sws, 1024) != 1024) { | |
6286 | + free(sws); | |
6287 | + return 1; | |
6288 | + } | |
6289 | + | |
6290 | + /* arbitrary sanity check.. is there any garbage down there? */ | |
6291 | + if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { | |
6292 | + if (sws->sws_volume[0]) | |
6293 | + blkid_set_tag(dev, "LABEL", sws->sws_volume, | |
6294 | + sizeof(sws->sws_volume)); | |
6295 | + if (sws->sws_uuid[0]) | |
6296 | + set_uuid(dev, sws->sws_uuid); | |
6297 | + } | |
6298 | + free(sws); | |
6299 | + | |
6300 | + return 0; | |
6301 | +} | |
6302 | + | |
6303 | +static const char | |
6304 | +*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", | |
6305 | + "NSR03", "TEA01", 0 }; | |
6306 | + | |
6307 | +static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)), | |
6308 | + blkid_dev dev __BLKID_ATTR((unused)), | |
6309 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6310 | + unsigned char *buf __BLKID_ATTR((unused))) | |
6311 | +{ | |
6312 | + int j, bs; | |
6313 | + struct iso_volume_descriptor isosb; | |
6314 | + const char ** m; | |
6315 | + | |
6316 | + /* determine the block size by scanning in 2K increments | |
6317 | + (block sizes larger than 2K will be null padded) */ | |
6318 | + for (bs = 1; bs < 16; bs++) { | |
6319 | + lseek(fd, bs*2048+32768, SEEK_SET); | |
6320 | + if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb)) | |
6321 | + return 1; | |
6322 | + if (isosb.id[0]) | |
6323 | + break; | |
6324 | + } | |
6325 | + | |
6326 | + /* Scan up to another 64 blocks looking for additional VSD's */ | |
6327 | + for (j = 1; j < 64; j++) { | |
6328 | + if (j > 1) { | |
6329 | + lseek(fd, j*bs*2048+32768, SEEK_SET); | |
6330 | + if (read(fd, (char *)&isosb, sizeof(isosb)) | |
6331 | + != sizeof(isosb)) | |
6332 | + return 1; | |
6333 | + } | |
6334 | + /* If we find NSR0x then call it udf: | |
6335 | + NSR01 for UDF 1.00 | |
6336 | + NSR02 for UDF 1.50 | |
6337 | + NSR03 for UDF 2.00 */ | |
6338 | + if (!strncmp(isosb.id, "NSR0", 4)) | |
6339 | + return 0; | |
6340 | + for (m = udf_magic; *m; m++) | |
6341 | + if (!strncmp(*m, isosb.id, 5)) | |
6342 | + break; | |
6343 | + if (*m == 0) | |
6344 | + return 1; | |
6345 | + } | |
6346 | + return 1; | |
6347 | +} | |
6348 | + | |
6349 | +static int probe_ocfs(int fd __BLKID_ATTR((unused)), | |
6350 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6351 | + blkid_dev dev, | |
6352 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6353 | + unsigned char *buf) | |
6354 | +{ | |
6355 | + struct ocfs_volume_header ovh; | |
6356 | + struct ocfs_volume_label ovl; | |
6357 | + __u32 major; | |
6358 | + | |
6359 | + memcpy(&ovh, buf, sizeof(ovh)); | |
6360 | + memcpy(&ovl, buf+512, sizeof(ovl)); | |
6361 | + | |
6362 | + major = ocfsmajor(ovh); | |
6363 | + if (major == 1) | |
6364 | + blkid_set_tag(dev,"SEC_TYPE","ocfs1",sizeof("ocfs1")); | |
6365 | + else if (major >= 9) | |
6366 | + blkid_set_tag(dev,"SEC_TYPE","ntocfs",sizeof("ntocfs")); | |
6367 | + | |
6368 | + blkid_set_tag(dev, "LABEL", ovl.label, ocfslabellen(ovl)); | |
6369 | + blkid_set_tag(dev, "MOUNT", ovh.mount, ocfsmountlen(ovh)); | |
6370 | + set_uuid(dev, ovl.vol_id); | |
6371 | + return 0; | |
6372 | +} | |
6373 | + | |
6374 | +static int probe_ocfs2(int fd __BLKID_ATTR((unused)), | |
6375 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6376 | + blkid_dev dev, | |
6377 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6378 | + unsigned char *buf) | |
6379 | +{ | |
6380 | + struct ocfs2_super_block *osb; | |
6381 | + | |
6382 | + osb = (struct ocfs2_super_block *)buf; | |
6383 | + | |
6384 | + blkid_set_tag(dev, "LABEL", osb->s_label, sizeof(osb->s_label)); | |
6385 | + set_uuid(dev, osb->s_uuid); | |
6386 | + return 0; | |
6387 | +} | |
6388 | + | |
6389 | +static int probe_oracleasm(int fd __BLKID_ATTR((unused)), | |
6390 | + blkid_cache cache __BLKID_ATTR((unused)), | |
6391 | + blkid_dev dev, | |
6392 | + struct blkid_magic *id __BLKID_ATTR((unused)), | |
6393 | + unsigned char *buf) | |
6394 | +{ | |
6395 | + struct oracle_asm_disk_label *dl; | |
6396 | + | |
6397 | + dl = (struct oracle_asm_disk_label *)buf; | |
6398 | + | |
6399 | + blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); | |
6400 | + return 0; | |
6401 | +} | |
6402 | + | |
6403 | +/* | |
6404 | + * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined | |
6405 | + * in the type_array table below + bim_kbalign. | |
6406 | + * | |
6407 | + * When probing for a lot of magics, we handle everything in 1kB buffers so | |
6408 | + * that we don't have to worry about reading each combination of block sizes. | |
6409 | + */ | |
6410 | +#define BLKID_BLK_OFFS 64 /* currently reiserfs */ | |
6411 | + | |
6412 | +/* | |
6413 | + * Various filesystem magics that we can check for. Note that kboff and | |
6414 | + * sboff are in kilobytes and bytes respectively. All magics are in | |
6415 | + * byte strings so we don't worry about endian issues. | |
6416 | + */ | |
6417 | +static struct blkid_magic type_array[] = { | |
6418 | +/* type kboff sboff len magic probe */ | |
6419 | + { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, | |
6420 | + { "ntfs", 0, 3, 8, "NTFS ", 0 }, | |
6421 | + { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, | |
6422 | + { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, | |
6423 | + { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, | |
6424 | + { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, | |
6425 | + { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, | |
6426 | + { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, | |
6427 | + { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, | |
6428 | + { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, | |
6429 | + { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat }, | |
6430 | + { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat }, | |
6431 | + { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos }, | |
6432 | + { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos }, | |
6433 | + { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos }, | |
6434 | + { "minix", 1, 0x10, 2, "\177\023", 0 }, | |
6435 | + { "minix", 1, 0x10, 2, "\217\023", 0 }, | |
6436 | + { "minix", 1, 0x10, 2, "\150\044", 0 }, | |
6437 | + { "minix", 1, 0x10, 2, "\170\044", 0 }, | |
6438 | + { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, | |
6439 | + { "xfs", 0, 0, 4, "XFSB", probe_xfs }, | |
6440 | + { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, | |
6441 | + { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, | |
6442 | + { "cramfs", 0, 0, 4, "E=\315\034", 0 }, | |
6443 | + { "qnx4", 0, 4, 6, "QNX4FS", 0 }, | |
6444 | + { "udf", 32, 1, 5, "BEA01", probe_udf }, | |
6445 | + { "udf", 32, 1, 5, "BOOT2", probe_udf }, | |
6446 | + { "udf", 32, 1, 5, "CD001", probe_udf }, | |
6447 | + { "udf", 32, 1, 5, "CDW02", probe_udf }, | |
6448 | + { "udf", 32, 1, 5, "NSR02", probe_udf }, | |
6449 | + { "udf", 32, 1, 5, "NSR03", probe_udf }, | |
6450 | + { "udf", 32, 1, 5, "TEA01", probe_udf }, | |
6451 | + { "iso9660", 32, 1, 5, "CD001", 0 }, | |
6452 | + { "iso9660", 32, 9, 5, "CDROM", 0 }, | |
6453 | + { "jfs", 32, 0, 4, "JFS1", probe_jfs }, | |
6454 | + { "hfs", 1, 0, 2, "BD", 0 }, | |
6455 | + { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, | |
6456 | + { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, | |
6457 | + { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, | |
6458 | + { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, | |
6459 | + { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, | |
6460 | + { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, | |
6461 | + { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, | |
6462 | + { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, | |
6463 | + { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, | |
6464 | + { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, | |
6465 | + { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, | |
6466 | + { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, | |
6467 | + { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, | |
6468 | + { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, | |
6469 | + { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, | |
6470 | + { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, | |
6471 | + { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, | |
6472 | + { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, | |
6473 | + { NULL, 0, 0, 0, NULL, NULL } | |
6474 | +}; | |
6475 | + | |
6476 | +/* | |
6477 | + * Verify that the data in dev is consistent with what is on the actual | |
6478 | + * block device (using the devname field only). Normally this will be | |
6479 | + * called when finding items in the cache, but for long running processes | |
6480 | + * is also desirable to revalidate an item before use. | |
6481 | + * | |
6482 | + * If we are unable to revalidate the data, we return the old data and | |
6483 | + * do not set the BLKID_BID_FL_VERIFIED flag on it. | |
6484 | + */ | |
6485 | +blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) | |
6486 | +{ | |
6487 | + struct blkid_magic *id; | |
6488 | + unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf; | |
6489 | + const char *type; | |
6490 | + struct stat st; | |
6491 | + time_t diff, now; | |
6492 | + int fd, idx; | |
6493 | + | |
6494 | + if (!dev) | |
6495 | + return NULL; | |
6496 | + | |
6497 | + now = time(0); | |
6498 | + diff = now - dev->bid_time; | |
6499 | + | |
6500 | + if ((now < dev->bid_time) || | |
6501 | + (diff < BLKID_PROBE_MIN) || | |
6502 | + (dev->bid_flags & BLKID_BID_FL_VERIFIED && | |
6503 | + diff < BLKID_PROBE_INTERVAL)) | |
6504 | + return dev; | |
6505 | + | |
6506 | + DBG(DEBUG_PROBE, | |
6507 | + printf("need to revalidate %s (time since last check %lu)\n", | |
6508 | + dev->bid_name, diff)); | |
6509 | + | |
6510 | + if (((fd = open(dev->bid_name, O_RDONLY)) < 0) || | |
6511 | + (fstat(fd, &st) < 0)) { | |
6512 | + if (errno == ENXIO || errno == ENODEV || errno == ENOENT) { | |
6513 | + blkid_free_dev(dev); | |
6514 | + return NULL; | |
6515 | + } | |
6516 | + /* We don't have read permission, just return cache data. */ | |
6517 | + DBG(DEBUG_PROBE, | |
6518 | + printf("returning unverified data for %s\n", | |
6519 | + dev->bid_name)); | |
6520 | + return dev; | |
6521 | + } | |
6522 | + | |
6523 | + memset(bufs, 0, sizeof(bufs)); | |
6524 | + | |
6525 | + /* | |
6526 | + * Iterate over the type array. If we already know the type, | |
6527 | + * then try that first. If it doesn't work, then blow away | |
6528 | + * the type information, and try again. | |
6529 | + * | |
6530 | + */ | |
6531 | +try_again: | |
6532 | + type = 0; | |
6533 | + if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { | |
6534 | + uuid_t uuid; | |
6535 | + | |
6536 | + if (check_mdraid(fd, uuid) == 0) { | |
6537 | + set_uuid(dev, uuid); | |
6538 | + type = "mdraid"; | |
6539 | + goto found_type; | |
6540 | + } | |
6541 | + } | |
6542 | + for (id = type_array; id->bim_type; id++) { | |
6543 | + if (dev->bid_type && | |
6544 | + strcmp(id->bim_type, dev->bid_type)) | |
6545 | + continue; | |
6546 | + | |
6547 | + idx = id->bim_kboff + (id->bim_sboff >> 10); | |
6548 | + if (idx > BLKID_BLK_OFFS || idx < 0) | |
6549 | + continue; | |
6550 | + buf = bufs[idx]; | |
6551 | + if (!buf) { | |
6552 | + if (lseek(fd, idx << 10, SEEK_SET) < 0) | |
6553 | + continue; | |
6554 | + | |
6555 | + if (!(buf = (unsigned char *)malloc(1024))) | |
6556 | + continue; | |
6557 | + | |
6558 | + if (read(fd, buf, 1024) != 1024) { | |
6559 | + free(buf); | |
6560 | + continue; | |
6561 | + } | |
6562 | + bufs[idx] = buf; | |
6563 | + } | |
6564 | + | |
6565 | + if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff), | |
6566 | + id->bim_len)) | |
6567 | + continue; | |
6568 | + | |
6569 | + if ((id->bim_probe == NULL) || | |
6570 | + (id->bim_probe(fd, cache, dev, id, buf) == 0)) { | |
6571 | + type = id->bim_type; | |
6572 | + goto found_type; | |
6573 | + } | |
6574 | + } | |
6575 | + | |
6576 | + if (!id->bim_type && dev->bid_type) { | |
6577 | + /* | |
6578 | + * Zap the device filesystem type and try again | |
6579 | + */ | |
6580 | + blkid_set_tag(dev, "TYPE", 0, 0); | |
6581 | + blkid_set_tag(dev, "SEC_TYPE", 0, 0); | |
6582 | + blkid_set_tag(dev, "LABEL", 0, 0); | |
6583 | + blkid_set_tag(dev, "UUID", 0, 0); | |
6584 | + goto try_again; | |
6585 | + } | |
6586 | + | |
6587 | + if (!dev->bid_type) { | |
6588 | + blkid_free_dev(dev); | |
6589 | + return NULL; | |
6590 | + } | |
6591 | + | |
6592 | +found_type: | |
6593 | + if (dev && type) { | |
6594 | + dev->bid_devno = st.st_rdev; | |
6595 | + dev->bid_time = time(0); | |
6596 | + dev->bid_flags |= BLKID_BID_FL_VERIFIED; | |
6597 | + cache->bic_flags |= BLKID_BIC_FL_CHANGED; | |
6598 | + | |
6599 | + blkid_set_tag(dev, "TYPE", type, 0); | |
6600 | + | |
6601 | + DBG(DEBUG_PROBE, printf("%s: devno 0x%04Lx, type %s\n", | |
6602 | + dev->bid_name, st.st_rdev, type)); | |
6603 | + } | |
6604 | + | |
6605 | + close(fd); | |
6606 | + | |
6607 | + return dev; | |
6608 | +} | |
6609 | + | |
6610 | +int blkid_known_fstype(const char *fstype) | |
6611 | +{ | |
6612 | + struct blkid_magic *id; | |
6613 | + | |
6614 | + for (id = type_array; id->bim_type; id++) { | |
6615 | + if (strcmp(fstype, id->bim_type) == 0) | |
6616 | + return 1; | |
6617 | + } | |
6618 | + return 0; | |
6619 | +} | |
6620 | + | |
6621 | +#ifdef TEST_PROGRAM | |
6622 | +int main(int argc, char **argv) | |
6623 | +{ | |
6624 | + blkid_dev dev; | |
6625 | + blkid_cache cache; | |
6626 | + int ret; | |
6627 | + | |
6628 | + blkid_debug_mask = DEBUG_ALL; | |
6629 | + if (argc != 2) { | |
6630 | + fprintf(stderr, "Usage: %s device\n" | |
6631 | + "Probe a single device to determine type\n", argv[0]); | |
6632 | + exit(1); | |
6633 | + } | |
6634 | + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { | |
6635 | + fprintf(stderr, "%s: error creating cache (%d)\n", | |
6636 | + argv[0], ret); | |
6637 | + exit(1); | |
6638 | + } | |
6639 | + dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); | |
6640 | + if (!dev) { | |
6641 | + printf("%s: %s has an unsupported type\n", argv[0], argv[1]); | |
6642 | + return (1); | |
6643 | + } | |
6644 | + printf("%s is type %s\n", argv[1], dev->bid_type ? | |
6645 | + dev->bid_type : "(null)"); | |
6646 | + if (dev->bid_label) | |
6647 | + printf("\tlabel is '%s'\n", dev->bid_label); | |
6648 | + if (dev->bid_uuid) | |
6649 | + printf("\tuuid is %s\n", dev->bid_uuid); | |
6650 | + | |
6651 | + blkid_free_dev(dev); | |
6652 | + return (0); | |
6653 | +} | |
6654 | +#endif | |
6655 | diff -Nur busybox-1.00/e2fsprogs/blkid/probe.h busybox/e2fsprogs/blkid/probe.h | |
6656 | --- busybox-1.00/e2fsprogs/blkid/probe.h 1970-01-01 01:00:00.000000000 +0100 | |
6657 | +++ busybox/e2fsprogs/blkid/probe.h 2005-06-04 08:20:15.000000000 +0200 | |
6658 | @@ -0,0 +1,359 @@ | |
6659 | +/* | |
6660 | + * probe.h - constants and on-disk structures for extracting device data | |
6661 | + * | |
6662 | + * Copyright (C) 1999 by Andries Brouwer | |
6663 | + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o | |
6664 | + * Copyright (C) 2001 by Andreas Dilger | |
6665 | + * | |
6666 | + * %Begin-Header% | |
6667 | + * This file may be redistributed under the terms of the | |
6668 | + * GNU Lesser General Public License. | |
6669 | + * %End-Header% | |
6670 | + */ | |
6671 | + | |
6672 | +#ifndef _BLKID_PROBE_H | |
6673 | +#define _BLKID_PROBE_H | |
6674 | + | |
6675 | +#include <linux/types.h> | |
6676 | + | |
6677 | +struct blkid_magic; | |
6678 | + | |
6679 | +typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev, | |
6680 | + struct blkid_magic *id, unsigned char *buf); | |
6681 | + | |
6682 | +struct blkid_magic { | |
6683 | + const char *bim_type; /* type name for this magic */ | |
6684 | + long bim_kboff; /* kilobyte offset of superblock */ | |
6685 | + unsigned bim_sboff; /* byte offset within superblock */ | |
6686 | + unsigned bim_len; /* length of magic */ | |
6687 | + const char *bim_magic; /* magic string */ | |
6688 | + blkid_probe_t bim_probe; /* probe function */ | |
6689 | +}; | |
6690 | + | |
6691 | +/* | |
6692 | + * Structures for each of the content types we want to extract information | |
6693 | + * from. We do not necessarily need the magic field here, because we have | |
6694 | + * already identified the content type before we get this far. It may still | |
6695 | + * be useful if there are probe functions which handle multiple content types. | |
6696 | + */ | |
6697 | +struct ext2_super_block { | |
6698 | + __u32 s_inodes_count; | |
6699 | + __u32 s_blocks_count; | |
6700 | + __u32 s_r_blocks_count; | |
6701 | + __u32 s_free_blocks_count; | |
6702 | + __u32 s_free_inodes_count; | |
6703 | + __u32 s_first_data_block; | |
6704 | + __u32 s_log_block_size; | |
6705 | + __u32 s_dummy3[7]; | |
6706 | + unsigned char s_magic[2]; | |
6707 | + __u16 s_state; | |
6708 | + __u32 s_dummy5[8]; | |
6709 | + __u32 s_feature_compat; | |
6710 | + __u32 s_feature_incompat; | |
6711 | + __u32 s_feature_ro_compat; | |
6712 | + unsigned char s_uuid[16]; | |
6713 | + char s_volume_name[16]; | |
6714 | +}; | |
6715 | +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004 | |
6716 | +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004 | |
6717 | +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008 | |
6718 | + | |
6719 | +struct xfs_super_block { | |
6720 | + unsigned char xs_magic[4]; | |
6721 | + __u32 xs_blocksize; | |
6722 | + __u64 xs_dblocks; | |
6723 | + __u64 xs_rblocks; | |
6724 | + __u32 xs_dummy1[2]; | |
6725 | + unsigned char xs_uuid[16]; | |
6726 | + __u32 xs_dummy2[15]; | |
6727 | + char xs_fname[12]; | |
6728 | + __u32 xs_dummy3[2]; | |
6729 | + __u64 xs_icount; | |
6730 | + __u64 xs_ifree; | |
6731 | + __u64 xs_fdblocks; | |
6732 | +}; | |
6733 | + | |
6734 | +struct reiserfs_super_block { | |
6735 | + __u32 rs_blocks_count; | |
6736 | + __u32 rs_free_blocks; | |
6737 | + __u32 rs_root_block; | |
6738 | + __u32 rs_journal_block; | |
6739 | + __u32 rs_journal_dev; | |
6740 | + __u32 rs_orig_journal_size; | |
6741 | + __u32 rs_dummy2[5]; | |
6742 | + __u16 rs_blocksize; | |
6743 | + __u16 rs_dummy3[3]; | |
6744 | + unsigned char rs_magic[12]; | |
6745 | + __u32 rs_dummy4[5]; | |
6746 | + unsigned char rs_uuid[16]; | |
6747 | + char rs_label[16]; | |
6748 | +}; | |
6749 | + | |
6750 | +struct jfs_super_block { | |
6751 | + unsigned char js_magic[4]; | |
6752 | + __u32 js_version; | |
6753 | + __u64 js_size; | |
6754 | + __u32 js_bsize; | |
6755 | + __u32 js_dummy1; | |
6756 | + __u32 js_pbsize; | |
6757 | + __u32 js_dummy2[27]; | |
6758 | + unsigned char js_uuid[16]; | |
6759 | + unsigned char js_label[16]; | |
6760 | + unsigned char js_loguuid[16]; | |
6761 | +}; | |
6762 | + | |
6763 | +struct romfs_super_block { | |
6764 | + unsigned char ros_magic[8]; | |
6765 | + __u32 ros_dummy1[2]; | |
6766 | + unsigned char ros_volume[16]; | |
6767 | +}; | |
6768 | + | |
6769 | +struct swap_id_block { | |
6770 | +/* unsigned char sws_boot[1024]; */ | |
6771 | + __u32 sws_version; | |
6772 | + __u32 sws_lastpage; | |
6773 | + __u32 sws_nrbad; | |
6774 | + unsigned char sws_uuid[16]; | |
6775 | + unsigned char sws_volume[16]; | |
6776 | + unsigned char sws_pad[117]; | |
6777 | + __u32 sws_badpg; | |
6778 | +}; | |
6779 | + | |
6780 | +/* Yucky misaligned values */ | |
6781 | +struct vfat_super_block { | |
6782 | +/* 00*/ unsigned char vs_ignored[3]; | |
6783 | +/* 03*/ unsigned char vs_sysid[8]; | |
6784 | +/* 0b*/ unsigned char vs_sector_size[2]; | |
6785 | +/* 0d*/ __u8 vs_cluster_size; | |
6786 | +/* 0e*/ __u16 vs_reserved; | |
6787 | +/* 10*/ __u8 vs_fats; | |
6788 | +/* 11*/ unsigned char vs_dir_entries[2]; | |
6789 | +/* 13*/ unsigned char vs_sectors[2]; | |
6790 | +/* 15*/ unsigned char vs_media; | |
6791 | +/* 16*/ __u16 vs_fat_length; | |
6792 | +/* 18*/ __u16 vs_secs_track; | |
6793 | +/* 1a*/ __u16 vs_heads; | |
6794 | +/* 1c*/ __u32 vs_hidden; | |
6795 | +/* 20*/ __u32 vs_total_sect; | |
6796 | +/* 24*/ __u32 vs_fat32_length; | |
6797 | +/* 28*/ __u16 vs_flags; | |
6798 | +/* 2a*/ __u8 vs_version[2]; | |
6799 | +/* 2c*/ __u32 vs_root_cluster; | |
6800 | +/* 30*/ __u16 vs_insfo_sector; | |
6801 | +/* 32*/ __u16 vs_backup_boot; | |
6802 | +/* 34*/ __u16 vs_reserved2[6]; | |
6803 | +/* 40*/ unsigned char vs_unknown[3]; | |
6804 | +/* 43*/ unsigned char vs_serno[4]; | |
6805 | +/* 47*/ char vs_label[11]; | |
6806 | +/* 52*/ unsigned char vs_magic[8]; | |
6807 | +/* 5a*/ unsigned char vs_dummy2[164]; | |
6808 | +/*1fe*/ unsigned char vs_pmagic[2]; | |
6809 | +}; | |
6810 | + | |
6811 | +/* Yucky misaligned values */ | |
6812 | +struct msdos_super_block { | |
6813 | +/* 00*/ unsigned char ms_ignored[3]; | |
6814 | +/* 03*/ unsigned char ms_sysid[8]; | |
6815 | +/* 0b*/ unsigned char ms_sector_size[2]; | |
6816 | +/* 0d*/ __u8 ms_cluster_size; | |
6817 | +/* 0e*/ __u16 ms_reserved; | |
6818 | +/* 10*/ __u8 ms_fats; | |
6819 | +/* 11*/ unsigned char ms_dir_entries[2]; | |
6820 | +/* 13*/ unsigned char ms_sectors[2]; | |
6821 | +/* 15*/ unsigned char ms_media; | |
6822 | +/* 16*/ __u16 ms_fat_length; | |
6823 | +/* 18*/ __u16 ms_secs_track; | |
6824 | +/* 1a*/ __u16 ms_heads; | |
6825 | +/* 1c*/ __u32 ms_hidden; | |
6826 | +/* 20*/ __u32 ms_total_sect; | |
6827 | +/* 24*/ unsigned char ms_unknown[3]; | |
6828 | +/* 27*/ unsigned char ms_serno[4]; | |
6829 | +/* 2b*/ char ms_label[11]; | |
6830 | +/* 36*/ unsigned char ms_magic[8]; | |
6831 | +/* 3d*/ unsigned char ms_dummy2[192]; | |
6832 | +/*1fe*/ unsigned char ms_pmagic[2]; | |
6833 | +}; | |
6834 | + | |
6835 | +struct minix_super_block { | |
6836 | + __u16 ms_ninodes; | |
6837 | + __u16 ms_nzones; | |
6838 | + __u16 ms_imap_blocks; | |
6839 | + __u16 ms_zmap_blocks; | |
6840 | + __u16 ms_firstdatazone; | |
6841 | + __u16 ms_log_zone_size; | |
6842 | + __u32 ms_max_size; | |
6843 | + unsigned char ms_magic[2]; | |
6844 | + __u16 ms_state; | |
6845 | + __u32 ms_zones; | |
6846 | +}; | |
6847 | + | |
6848 | +struct mdp_superblock_s { | |
6849 | + __u32 md_magic; | |
6850 | + __u32 major_version; | |
6851 | + __u32 minor_version; | |
6852 | + __u32 patch_version; | |
6853 | + __u32 gvalid_words; | |
6854 | + __u32 set_uuid0; | |
6855 | + __u32 ctime; | |
6856 | + __u32 level; | |
6857 | + __u32 size; | |
6858 | + __u32 nr_disks; | |
6859 | + __u32 raid_disks; | |
6860 | + __u32 md_minor; | |
6861 | + __u32 not_persistent; | |
6862 | + __u32 set_uuid1; | |
6863 | + __u32 set_uuid2; | |
6864 | + __u32 set_uuid3; | |
6865 | +}; | |
6866 | + | |
6867 | +struct hfs_super_block { | |
6868 | + char h_magic[2]; | |
6869 | + char h_dummy[18]; | |
6870 | + __u32 h_blksize; | |
6871 | +}; | |
6872 | + | |
6873 | +struct ocfs_volume_header { | |
6874 | + unsigned char minor_version[4]; | |
6875 | + unsigned char major_version[4]; | |
6876 | + unsigned char signature[128]; | |
6877 | + unsigned char mount[128]; | |
6878 | + unsigned char mount_len[2]; | |
6879 | +}; | |
6880 | + | |
6881 | +struct ocfs_volume_label { | |
6882 | + unsigned char disk_lock[48]; | |
6883 | + unsigned char label[64]; | |
6884 | + unsigned char label_len[2]; | |
6885 | + unsigned char vol_id[16]; | |
6886 | + unsigned char vol_id_len[2]; | |
6887 | +}; | |
6888 | + | |
6889 | +#define ocfsmajor(o) ((__u32)o.major_version[0] \ | |
6890 | + + (((__u32) o.major_version[1]) << 8) \ | |
6891 | + + (((__u32) o.major_version[2]) << 16) \ | |
6892 | + + (((__u32) o.major_version[3]) << 24)) | |
6893 | +#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8)) | |
6894 | +#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8)) | |
6895 | + | |
6896 | +#define OCFS_MAGIC "OracleCFS" | |
6897 | + | |
6898 | +struct ocfs2_super_block { | |
6899 | + unsigned char signature[8]; | |
6900 | + unsigned char s_dummy1[184]; | |
6901 | + unsigned char s_dummy2[80]; | |
6902 | + unsigned char s_label[64]; | |
6903 | + unsigned char s_uuid[16]; | |
6904 | +}; | |
6905 | + | |
6906 | +#define OCFS2_MIN_BLOCKSIZE 512 | |
6907 | +#define OCFS2_MAX_BLOCKSIZE 4096 | |
6908 | + | |
6909 | +#define OCFS2_SUPER_BLOCK_BLKNO 2 | |
6910 | + | |
6911 | +#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2" | |
6912 | + | |
6913 | +struct oracle_asm_disk_label { | |
6914 | + char dummy[32]; | |
6915 | + char dl_tag[8]; | |
6916 | + char dl_id[24]; | |
6917 | +}; | |
6918 | + | |
6919 | +#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK" | |
6920 | +#define ORACLE_ASM_DISK_LABEL_OFFSET 32 | |
6921 | + | |
6922 | +#define ISODCL(from, to) (to - from + 1) | |
6923 | +struct iso_volume_descriptor { | |
6924 | + char type[ISODCL(1,1)]; /* 711 */ | |
6925 | + char id[ISODCL(2,6)]; | |
6926 | + char version[ISODCL(7,7)]; | |
6927 | + char data[ISODCL(8,2048)]; | |
6928 | +}; | |
6929 | + | |
6930 | +/* | |
6931 | + * Byte swap functions | |
6932 | + */ | |
6933 | +#ifdef __GNUC__ | |
6934 | +#define _INLINE_ static __inline__ | |
6935 | +#else /* For Watcom C */ | |
6936 | +#define _INLINE_ static inline | |
6937 | +#endif | |
6938 | + | |
6939 | +static __u16 blkid_swab16(__u16 val); | |
6940 | +static __u32 blkid_swab32(__u32 val); | |
6941 | +static __u64 blkid_swab64(__u64 val); | |
6942 | + | |
6943 | +#if ((defined __GNUC__) && \ | |
6944 | + (defined(__i386__) || defined(__i486__) || defined(__i586__))) | |
6945 | + | |
6946 | +#define _BLKID_HAVE_ASM_BITOPS_ | |
6947 | + | |
6948 | +_INLINE_ __u32 blkid_swab32(__u32 val) | |
6949 | +{ | |
6950 | +#ifdef EXT2FS_REQUIRE_486 | |
6951 | + __asm__("bswap %0" : "=r" (val) : "0" (val)); | |
6952 | +#else | |
6953 | + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ | |
6954 | + "rorl $16,%0\n\t" /* swap words */ | |
6955 | + "xchgb %b0,%h0" /* swap higher bytes */ | |
6956 | + :"=q" (val) | |
6957 | + : "0" (val)); | |
6958 | +#endif | |
6959 | + return val; | |
6960 | +} | |
6961 | + | |
6962 | +_INLINE_ __u16 blkid_swab16(__u16 val) | |
6963 | +{ | |
6964 | + __asm__("xchgb %b0,%h0" /* swap bytes */ \ | |
6965 | + : "=q" (val) \ | |
6966 | + : "0" (val)); \ | |
6967 | + return val; | |
6968 | +} | |
6969 | + | |
6970 | +_INLINE_ __u64 blkid_swab64(__u64 val) | |
6971 | +{ | |
6972 | + return (blkid_swab32(val >> 32) | | |
6973 | + (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32)); | |
6974 | +} | |
6975 | +#endif | |
6976 | + | |
6977 | +#if !defined(_BLKID_HAVE_ASM_BITOPS_) | |
6978 | + | |
6979 | +_INLINE_ __u16 blkid_swab16(__u16 val) | |
6980 | +{ | |
6981 | + return (val >> 8) | (val << 8); | |
6982 | +} | |
6983 | + | |
6984 | +_INLINE_ __u32 blkid_swab32(__u32 val) | |
6985 | +{ | |
6986 | + return ((val>>24) | ((val>>8)&0xFF00) | | |
6987 | + ((val<<8)&0xFF0000) | (val<<24)); | |
6988 | +} | |
6989 | + | |
6990 | +_INLINE_ __u64 blkid_swab64(__u64 val) | |
6991 | +{ | |
6992 | + return (blkid_swab32(val >> 32) | | |
6993 | + (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32)); | |
6994 | +} | |
6995 | +#endif | |
6996 | + | |
6997 | + | |
6998 | + | |
6999 | +#if __BYTE_ORDER == __BIG_ENDIAN | |
7000 | +#define blkid_le16(x) blkid_swab16(x) | |
7001 | +#define blkid_le32(x) blkid_swab32(x) | |
7002 | +#define blkid_le64(x) blkid_swab64(x) | |
7003 | +#define blkid_be16(x) (x) | |
7004 | +#define blkid_be32(x) (x) | |
7005 | +#define blkid_be64(x) (x) | |
7006 | +#else | |
7007 | +#define blkid_le16(x) (x) | |
7008 | +#define blkid_le32(x) (x) | |
7009 | +#define blkid_le64(x) (x) | |
7010 | +#define blkid_be16(x) blkid_swab16(x) | |
7011 | +#define blkid_be32(x) blkid_swab32(x) | |
7012 | +#define blkid_be64(x) blkid_swab64(x) | |
7013 | +#endif | |
7014 | + | |
7015 | +#undef _INLINE_ | |
7016 | + | |
7017 | +#endif /* _BLKID_PROBE_H */ | |
7018 | diff -Nur busybox-1.00/e2fsprogs/blkid/read.c busybox/e2fsprogs/blkid/read.c | |
7019 | --- busybox-1.00/e2fsprogs/blkid/read.c 1970-01-01 01:00:00.000000000 +0100 | |
7020 | +++ busybox/e2fsprogs/blkid/read.c 2005-06-04 08:20:15.000000000 +0200 | |
7021 | @@ -0,0 +1,459 @@ | |
7022 | +/* | |
7023 | + * read.c - read the blkid cache from disk, to avoid scanning all devices | |
7024 | + * | |
7025 | + * Copyright (C) 2001, 2003 Theodore Y. Ts'o | |
7026 | + * Copyright (C) 2001 Andreas Dilger | |
7027 | + * | |
7028 | + * %Begin-Header% | |
7029 | + * This file may be redistributed under the terms of the | |
7030 | + * GNU Lesser General Public License. | |
7031 | + * %End-Header% | |
7032 | + */ | |
7033 | + | |
7034 | +#include <stdio.h> | |
7035 | +#include <ctype.h> | |
7036 | +#include <string.h> | |
7037 | +#include <time.h> | |
7038 | +#include <sys/types.h> | |
7039 | +#include <sys/stat.h> | |
7040 | +#include <fcntl.h> | |
7041 | +#include <unistd.h> | |
7042 | +#if HAVE_ERRNO_H | |
7043 | +#include <errno.h> | |
7044 | +#endif | |
7045 | + | |
7046 | +#include "blkidP.h" | |
7047 | +#include "uuid/uuid.h" | |
7048 | + | |
7049 | +#ifdef HAVE_STRTOULL | |
7050 | +#define __USE_ISOC9X | |
7051 | +#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */ | |
7052 | +#else | |
7053 | +/* FIXME: need to support real strtoull here */ | |
7054 | +#define STRTOULL strtoul | |
7055 | +#endif | |
7056 | + | |
7057 | +#if HAVE_STDLIB_H | |
7058 | +#include <stdlib.h> | |
7059 | +#endif | |
7060 | + | |
7061 | +/* | |
7062 | + * File format: | |
7063 | + * | |
7064 | + * <device [<NAME="value"> ...]>device_name</device> | |
7065 | + * | |
7066 | + * The following tags are required for each entry: | |
7067 | + * <ID="id"> unique (within this file) ID number of this device | |
7068 | + * <TIME="time"> (ascii time_t) time this entry was last read from disk | |
7069 | + * <TYPE="type"> (detected) type of filesystem/data for this partition | |
7070 | + * | |
7071 | + * The following tags may be present, depending on the device contents | |
7072 | + * <LABEL="label"> (user supplied) label (volume name, etc) | |
7073 | + * <UUID="uuid"> (generated) universally unique identifier (serial no) | |
7074 | + */ | |
7075 | + | |
7076 | +static char *skip_over_blank(char *cp) | |
7077 | +{ | |
7078 | + while (*cp && isspace(*cp)) | |
7079 | + cp++; | |
7080 | + return cp; | |
7081 | +} | |
7082 | + | |
7083 | +static char *skip_over_word(char *cp) | |
7084 | +{ | |
7085 | + char ch; | |
7086 | + | |
7087 | + while ((ch = *cp)) { | |
7088 | + /* If we see a backslash, skip the next character */ | |
7089 | + if (ch == '\\') { | |
7090 | + cp++; | |
7091 | + if (*cp == '\0') | |
7092 | + break; | |
7093 | + cp++; | |
7094 | + continue; | |
7095 | + } | |
7096 | + if (isspace(ch) || ch == '<' || ch == '>') | |
7097 | + break; | |
7098 | + cp++; | |
7099 | + } | |
7100 | + return cp; | |
7101 | +} | |
7102 | + | |
7103 | +static char *strip_line(char *line) | |
7104 | +{ | |
7105 | + char *p; | |
7106 | + | |
7107 | + line = skip_over_blank(line); | |
7108 | + | |
7109 | + p = line + strlen(line) - 1; | |
7110 | + | |
7111 | + while (*line) { | |
7112 | + if (isspace(*p)) | |
7113 | + *p-- = '\0'; | |
7114 | + else | |
7115 | + break; | |
7116 | + } | |
7117 | + | |
7118 | + return line; | |
7119 | +} | |
7120 | + | |
7121 | +#if 0 | |
7122 | +static char *parse_word(char **buf) | |
7123 | +{ | |
7124 | + char *word, *next; | |
7125 | + | |
7126 | + word = *buf; | |
7127 | + if (*word == '\0') | |
7128 | + return NULL; | |
7129 | + | |
7130 | + word = skip_over_blank(word); | |
7131 | + next = skip_over_word(word); | |
7132 | + if (*next) { | |
7133 | + char *end = next - 1; | |
7134 | + if (*end == '"' || *end == '\'') | |
7135 | + *end = '\0'; | |
7136 | + *next++ = '\0'; | |
7137 | + } | |
7138 | + *buf = next; | |
7139 | + | |
7140 | + if (*word == '"' || *word == '\'') | |
7141 | + word++; | |
7142 | + return word; | |
7143 | +} | |
7144 | +#endif | |
7145 | + | |
7146 | +/* | |
7147 | + * Start parsing a new line from the cache. | |
7148 | + * | |
7149 | + * line starts with "<device" return 1 -> continue parsing line | |
7150 | + * line starts with "<foo", empty, or # return 0 -> skip line | |
7151 | + * line starts with other, return -BLKID_ERR_CACHE -> error | |
7152 | + */ | |
7153 | +static int parse_start(char **cp) | |
7154 | +{ | |
7155 | + char *p; | |
7156 | + | |
7157 | + p = strip_line(*cp); | |
7158 | + | |
7159 | + /* Skip comment or blank lines. We can't just NUL the first '#' char, | |
7160 | + * in case it is inside quotes, or escaped. | |
7161 | + */ | |
7162 | + if (*p == '\0' || *p == '#') | |
7163 | + return 0; | |
7164 | + | |
7165 | + if (!strncmp(p, "<device", 7)) { | |
7166 | + DBG(DEBUG_READ, printf("found device header: %8s\n", p)); | |
7167 | + p += 7; | |
7168 | + | |
7169 | + *cp = p; | |
7170 | + return 1; | |
7171 | + } | |
7172 | + | |
7173 | + if (*p == '<') | |
7174 | + return 0; | |
7175 | + | |
7176 | + return -BLKID_ERR_CACHE; | |
7177 | +} | |
7178 | + | |
7179 | +/* Consume the remaining XML on the line (cosmetic only) */ | |
7180 | +static int parse_end(char **cp) | |
7181 | +{ | |
7182 | + *cp = skip_over_blank(*cp); | |
7183 | + | |
7184 | + if (!strncmp(*cp, "</device>", 9)) { | |
7185 | + DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp)); | |
7186 | + *cp += 9; | |
7187 | + return 0; | |
7188 | + } | |
7189 | + | |
7190 | + return -BLKID_ERR_CACHE; | |
7191 | +} | |
7192 | + | |
7193 | +/* | |
7194 | + * Allocate a new device struct with device name filled in. Will handle | |
7195 | + * finding the device on lines of the form: | |
7196 | + * <device foo=bar>devname</device> | |
7197 | + * <device>devname<foo>bar</foo></device> | |
7198 | + */ | |
7199 | +static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp) | |
7200 | +{ | |
7201 | + char *start, *tmp, *end, *name; | |
7202 | + int ret; | |
7203 | + | |
7204 | + if ((ret = parse_start(cp)) <= 0) | |
7205 | + return ret; | |
7206 | + | |
7207 | + start = tmp = strchr(*cp, '>'); | |
7208 | + if (!start) { | |
7209 | + DBG(DEBUG_READ, | |
7210 | + printf("blkid: short line parsing dev: %s\n", *cp)); | |
7211 | + return -BLKID_ERR_CACHE; | |
7212 | + } | |
7213 | + start = skip_over_blank(start + 1); | |
7214 | + end = skip_over_word(start); | |
7215 | + | |
7216 | + DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start)); | |
7217 | + | |
7218 | + if (**cp == '>') | |
7219 | + *cp = end; | |
7220 | + else | |
7221 | + (*cp)++; | |
7222 | + | |
7223 | + *tmp = '\0'; | |
7224 | + | |
7225 | + if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) { | |
7226 | + DBG(DEBUG_READ, | |
7227 | + printf("blkid: missing </device> ending: %s\n", end)); | |
7228 | + } else if (tmp) | |
7229 | + *tmp = '\0'; | |
7230 | + | |
7231 | + if (end - start <= 1) { | |
7232 | + DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp)); | |
7233 | + return -BLKID_ERR_CACHE; | |
7234 | + } | |
7235 | + | |
7236 | + name = blkid_strndup(start, end-start); | |
7237 | + if (name == NULL) | |
7238 | + return -BLKID_ERR_MEM; | |
7239 | + | |
7240 | + DBG(DEBUG_READ, printf("found dev %s\n", name)); | |
7241 | + | |
7242 | + if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) | |
7243 | + return -BLKID_ERR_MEM; | |
7244 | + | |
7245 | + free(name); | |
7246 | + return 1; | |
7247 | +} | |
7248 | + | |
7249 | +/* | |
7250 | + * Extract a tag of the form NAME="value" from the line. | |
7251 | + */ | |
7252 | +static int parse_token(char **name, char **value, char **cp) | |
7253 | +{ | |
7254 | + char *end; | |
7255 | + | |
7256 | + if (!name || !value || !cp) | |
7257 | + return -BLKID_ERR_PARAM; | |
7258 | + | |
7259 | + if (!(*value = strchr(*cp, '='))) | |
7260 | + return 0; | |
7261 | + | |
7262 | + **value = '\0'; | |
7263 | + *name = strip_line(*cp); | |
7264 | + *value = skip_over_blank(*value + 1); | |
7265 | + | |
7266 | + if (**value == '"') { | |
7267 | + end = strchr(*value + 1, '"'); | |
7268 | + if (!end) { | |
7269 | + DBG(DEBUG_READ, | |
7270 | + printf("unbalanced quotes at: %s\n", *value)); | |
7271 | + *cp = *value; | |
7272 | + return -BLKID_ERR_CACHE; | |
7273 | + } | |
7274 | + (*value)++; | |
7275 | + *end = '\0'; | |
7276 | + end++; | |
7277 | + } else { | |
7278 | + end = skip_over_word(*value); | |
7279 | + if (*end) { | |
7280 | + *end = '\0'; | |
7281 | + end++; | |
7282 | + } | |
7283 | + } | |
7284 | + *cp = end; | |
7285 | + | |
7286 | + return 1; | |
7287 | +} | |
7288 | + | |
7289 | +/* | |
7290 | + * Extract a tag of the form <NAME>value</NAME> from the line. | |
7291 | + */ | |
7292 | +/* | |
7293 | +static int parse_xml(char **name, char **value, char **cp) | |
7294 | +{ | |
7295 | + char *end; | |
7296 | + | |
7297 | + if (!name || !value || !cp) | |
7298 | + return -BLKID_ERR_PARAM; | |
7299 | + | |
7300 | + *name = strip_line(*cp); | |
7301 | + | |
7302 | + if ((*name)[0] != '<' || (*name)[1] == '/') | |
7303 | + return 0; | |
7304 | + | |
7305 | + FIXME: finish this. | |
7306 | +} | |
7307 | +*/ | |
7308 | + | |
7309 | +/* | |
7310 | + * Extract a tag from the line. | |
7311 | + * | |
7312 | + * Return 1 if a valid tag was found. | |
7313 | + * Return 0 if no tag found. | |
7314 | + * Return -ve error code. | |
7315 | + */ | |
7316 | +static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) | |
7317 | +{ | |
7318 | + char *name; | |
7319 | + char *value; | |
7320 | + int ret; | |
7321 | + | |
7322 | + if (!cache || !dev) | |
7323 | + return -BLKID_ERR_PARAM; | |
7324 | + | |
7325 | + if ((ret = parse_token(&name, &value, cp)) <= 0 /* && | |
7326 | + (ret = parse_xml(&name, &value, cp)) <= 0 */) | |
7327 | + return ret; | |
7328 | + | |
7329 | + /* Some tags are stored directly in the device struct */ | |
7330 | + if (!strcmp(name, "DEVNO")) | |
7331 | + dev->bid_devno = STRTOULL(value, 0, 0); | |
7332 | + else if (!strcmp(name, "PRI")) | |
7333 | + dev->bid_pri = strtol(value, 0, 0); | |
7334 | + else if (!strcmp(name, "TIME")) | |
7335 | + /* FIXME: need to parse a long long eventually */ | |
7336 | + dev->bid_time = strtol(value, 0, 0); | |
7337 | + else | |
7338 | + ret = blkid_set_tag(dev, name, value, strlen(value)); | |
7339 | + | |
7340 | + DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value)); | |
7341 | + | |
7342 | + return ret < 0 ? ret : 1; | |
7343 | +} | |
7344 | + | |
7345 | +/* | |
7346 | + * Parse a single line of data, and return a newly allocated dev struct. | |
7347 | + * Add the new device to the cache struct, if one was read. | |
7348 | + * | |
7349 | + * Lines are of the form <device [TAG="value" ...]>/dev/foo</device> | |
7350 | + * | |
7351 | + * Returns -ve value on error. | |
7352 | + * Returns 0 otherwise. | |
7353 | + * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL | |
7354 | + * (e.g. comment lines, unknown XML content, etc). | |
7355 | + */ | |
7356 | +static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) | |
7357 | +{ | |
7358 | + blkid_dev dev; | |
7359 | + int ret; | |
7360 | + | |
7361 | + if (!cache || !dev_p) | |
7362 | + return -BLKID_ERR_PARAM; | |
7363 | + | |
7364 | + *dev_p = NULL; | |
7365 | + | |
7366 | + DBG(DEBUG_READ, printf("line: %s\n", cp)); | |
7367 | + | |
7368 | + if ((ret = parse_dev(cache, dev_p, &cp)) <= 0) | |
7369 | + return ret; | |
7370 | + | |
7371 | + dev = *dev_p; | |
7372 | + | |
7373 | + while ((ret = parse_tag(cache, dev, &cp)) > 0) { | |
7374 | + ; | |
7375 | + } | |
7376 | + | |
7377 | + if (dev->bid_type == NULL) { | |
7378 | + DBG(DEBUG_READ, | |
7379 | + printf("blkid: device %s has no TYPE\n",dev->bid_name)); | |
7380 | + blkid_free_dev(dev); | |
7381 | + } | |
7382 | + | |
7383 | + DEB_DUMP_DEV(DEBUG_READ, dev); | |
7384 | + | |
7385 | + return ret; | |
7386 | +} | |
7387 | + | |
7388 | +/* | |
7389 | + * Parse the specified filename, and return the data in the supplied or | |
7390 | + * a newly allocated cache struct. If the file doesn't exist, return a | |
7391 | + * new empty cache struct. | |
7392 | + */ | |
7393 | +void blkid_read_cache(blkid_cache cache) | |
7394 | +{ | |
7395 | + FILE *file; | |
7396 | + char buf[4096]; | |
7397 | + int fd, lineno = 0; | |
7398 | + struct stat st; | |
7399 | + | |
7400 | + if (!cache) | |
7401 | + return; | |
7402 | + | |
7403 | + /* | |
7404 | + * If the file doesn't exist, then we just return an empty | |
7405 | + * struct so that the cache can be populated. | |
7406 | + */ | |
7407 | + if ((fd = open(cache->bic_filename, O_RDONLY)) < 0) | |
7408 | + return; | |
7409 | + if (fstat(fd, &st) < 0) | |
7410 | + goto errout; | |
7411 | + if ((st.st_mtime == cache->bic_ftime) || | |
7412 | + (cache->bic_flags & BLKID_BIC_FL_CHANGED)) { | |
7413 | + DBG(DEBUG_CACHE, printf("skipping re-read of %s\n", | |
7414 | + cache->bic_filename)); | |
7415 | + goto errout; | |
7416 | + } | |
7417 | + | |
7418 | + DBG(DEBUG_CACHE, printf("reading cache file %s\n", | |
7419 | + cache->bic_filename)); | |
7420 | + | |
7421 | + file = fdopen(fd, "r"); | |
7422 | + if (!file) | |
7423 | + goto errout; | |
7424 | + | |
7425 | + while (fgets(buf, sizeof(buf), file)) { | |
7426 | + blkid_dev dev; | |
7427 | + unsigned int end; | |
7428 | + | |
7429 | + lineno++; | |
7430 | + if (buf[0] == 0) | |
7431 | + continue; | |
7432 | + end = strlen(buf) - 1; | |
7433 | + /* Continue reading next line if it ends with a backslash */ | |
7434 | + while (buf[end] == '\\' && end < sizeof(buf) - 2 && | |
7435 | + fgets(buf + end, sizeof(buf) - end, file)) { | |
7436 | + end = strlen(buf) - 1; | |
7437 | + lineno++; | |
7438 | + } | |
7439 | + | |
7440 | + if (blkid_parse_line(cache, &dev, buf) < 0) { | |
7441 | + DBG(DEBUG_READ, | |
7442 | + printf("blkid: bad format on line %d\n", lineno)); | |
7443 | + continue; | |
7444 | + } | |
7445 | + } | |
7446 | + fclose(file); | |
7447 | + | |
7448 | + /* | |
7449 | + * Initially we do not need to write out the cache file. | |
7450 | + */ | |
7451 | + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; | |
7452 | + cache->bic_ftime = st.st_mtime; | |
7453 | + | |
7454 | + return; | |
7455 | +errout: | |
7456 | + close(fd); | |
7457 | + return; | |
7458 | +} | |
7459 | + | |
7460 | +#ifdef TEST_PROGRAM | |
7461 | +int main(int argc, char**argv) | |
7462 | +{ | |
7463 | + blkid_cache cache = NULL; | |
7464 | + int ret; | |
7465 | + | |
7466 | + blkid_debug_mask = DEBUG_ALL; | |
7467 | + if (argc > 2) { | |
7468 | + fprintf(stderr, "Usage: %s [filename]\n" | |
7469 | + "Test parsing of the cache (filename)\n", argv[0]); | |
7470 | + exit(1); | |
7471 | + } | |
7472 | + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) | |
7473 | + fprintf(stderr, "error %d reading cache file %s\n", ret, | |
7474 | + argv[1] ? argv[1] : BLKID_CACHE_FILE); | |
7475 | + | |
7476 | + blkid_put_cache(cache); | |
7477 | + | |
7478 | + return ret; | |
7479 | +} | |
7480 | +#endif | |
7481 | diff -Nur busybox-1.00/e2fsprogs/blkid/resolve.c busybox/e2fsprogs/blkid/resolve.c | |
7482 | --- busybox-1.00/e2fsprogs/blkid/resolve.c 1970-01-01 01:00:00.000000000 +0100 | |
7483 | +++ busybox/e2fsprogs/blkid/resolve.c 2005-06-04 08:20:15.000000000 +0200 | |
7484 | @@ -0,0 +1,140 @@ | |
7485 | +/* | |
7486 | + * resolve.c - resolve names and tags into specific devices | |
7487 | + * | |
7488 | + * Copyright (C) 2001, 2003 Theodore Ts'o. | |
7489 | + * Copyright (C) 2001 Andreas Dilger | |
7490 | + * | |
7491 | + * %Begin-Header% | |
7492 | + * This file may be redistributed under the terms of the | |
7493 | + * GNU Lesser General Public License. | |
7494 | + * %End-Header% | |
7495 | + */ | |
7496 | + | |
7497 | +#include <stdio.h> | |
7498 | +#if HAVE_UNISTD_H | |
7499 | +#include <unistd.h> | |
7500 | +#endif | |
7501 | +#include <stdlib.h> | |
7502 | +#include <fcntl.h> | |
7503 | +#include <string.h> | |
7504 | +#include <sys/types.h> | |
7505 | +#include <sys/stat.h> | |
7506 | +#include "blkidP.h" | |
7507 | +#include "probe.h" | |
7508 | + | |
7509 | +/* | |
7510 | + * Find a tagname (e.g. LABEL or UUID) on a specific device. | |
7511 | + */ | |
7512 | +char *blkid_get_tag_value(blkid_cache cache, const char *tagname, | |
7513 | + const char *devname) | |
7514 | +{ | |
7515 | + blkid_tag found; | |
7516 | + blkid_dev dev; | |
7517 | + blkid_cache c = cache; | |
7518 | + char *ret = NULL; | |
7519 | + | |
7520 | + DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname)); | |
7521 | + | |
7522 | + if (!devname) | |
7523 | + return NULL; | |
7524 | + | |
7525 | + if (!cache) { | |
7526 | + if (blkid_get_cache(&c, NULL) < 0) | |
7527 | + return NULL; | |
7528 | + } | |
7529 | + | |
7530 | + if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) && | |
7531 | + (found = blkid_find_tag_dev(dev, tagname))) | |
7532 | + ret = blkid_strdup(found->bit_val); | |
7533 | + | |
7534 | + if (!cache) | |
7535 | + blkid_put_cache(c); | |
7536 | + | |
7537 | + return ret; | |
7538 | +} | |
7539 | + | |
7540 | +/* | |
7541 | + * Locate a device name from a token (NAME=value string), or (name, value) | |
7542 | + * pair. In the case of a token, value is ignored. If the "token" is not | |
7543 | + * of the form "NAME=value" and there is no value given, then it is assumed | |
7544 | + * to be the actual devname and a copy is returned. | |
7545 | + */ | |
7546 | +char *blkid_get_devname(blkid_cache cache, const char *token, | |
7547 | + const char *value) | |
7548 | +{ | |
7549 | + blkid_dev dev; | |
7550 | + blkid_cache c = cache; | |
7551 | + char *t = 0, *v = 0; | |
7552 | + char *ret = NULL; | |
7553 | + | |
7554 | + if (!token) | |
7555 | + return NULL; | |
7556 | + | |
7557 | + if (!cache) { | |
7558 | + if (blkid_get_cache(&c, NULL) < 0) | |
7559 | + return NULL; | |
7560 | + } | |
7561 | + | |
7562 | + DBG(DEBUG_RESOLVE, | |
7563 | + printf("looking for %s%s%s %s\n", token, value ? "=" : "", | |
7564 | + value ? value : "", cache ? "in cache" : "from disk")); | |
7565 | + | |
7566 | + if (!value) { | |
7567 | + if (!strchr(token, '=')) | |
7568 | + return blkid_strdup(token); | |
7569 | + blkid_parse_tag_string(token, &t, &v); | |
7570 | + if (!t || !v) | |
7571 | + goto errout; | |
7572 | + token = t; | |
7573 | + value = v; | |
7574 | + } | |
7575 | + | |
7576 | + dev = blkid_find_dev_with_tag(c, token, value); | |
7577 | + if (!dev) | |
7578 | + goto errout; | |
7579 | + | |
7580 | + ret = blkid_strdup(blkid_dev_devname(dev)); | |
7581 | + | |
7582 | +errout: | |
7583 | + if (t) | |
7584 | + free(t); | |
7585 | + if (v) | |
7586 | + free(v); | |
7587 | + if (!cache) { | |
7588 | + blkid_put_cache(c); | |
7589 | + } | |
7590 | + return (ret); | |
7591 | +} | |
7592 | + | |
7593 | +#ifdef TEST_PROGRAM | |
7594 | +int main(int argc, char **argv) | |
7595 | +{ | |
7596 | + char *value; | |
7597 | + blkid_cache cache; | |
7598 | + | |
7599 | + blkid_debug_mask = DEBUG_ALL; | |
7600 | + if (argc != 2 && argc != 3) { | |
7601 | + fprintf(stderr, "Usage:\t%s tagname=value\n" | |
7602 | + "\t%s tagname devname\n" | |
7603 | + "Find which device holds a given token or\n" | |
7604 | + "Find what the value of a tag is in a device\n", | |
7605 | + argv[0], argv[0]); | |
7606 | + exit(1); | |
7607 | + } | |
7608 | + if (blkid_get_cache(&cache, "/dev/null") < 0) { | |
7609 | + fprintf(stderr, "Couldn't get blkid cache\n"); | |
7610 | + exit(1); | |
7611 | + } | |
7612 | + | |
7613 | + if (argv[2]) { | |
7614 | + value = blkid_get_tag_value(cache, argv[1], argv[2]); | |
7615 | + printf("%s has tag %s=%s\n", argv[2], argv[1], | |
7616 | + value ? value : "<missing>"); | |
7617 | + } else { | |
7618 | + value = blkid_get_devname(cache, argv[1], NULL); | |
7619 | + printf("%s has tag %s\n", value ? value : "<none>", argv[1]); | |
7620 | + } | |
7621 | + blkid_put_cache(cache); | |
7622 | + return value ? 0 : 1; | |
7623 | +} | |
7624 | +#endif | |
7625 | diff -Nur busybox-1.00/e2fsprogs/blkid/save.c busybox/e2fsprogs/blkid/save.c | |
7626 | --- busybox-1.00/e2fsprogs/blkid/save.c 1970-01-01 01:00:00.000000000 +0100 | |
7627 | +++ busybox/e2fsprogs/blkid/save.c 2005-06-04 08:20:15.000000000 +0200 | |
7628 | @@ -0,0 +1,193 @@ | |
7629 | +/* | |
7630 | + * save.c - write the cache struct to disk | |
7631 | + * | |
7632 | + * Copyright (C) 2001 by Andreas Dilger | |
7633 | + * Copyright (C) 2003 Theodore Ts'o | |
7634 | + * | |
7635 | + * %Begin-Header% | |
7636 | + * This file may be redistributed under the terms of the | |
7637 | + * GNU Lesser General Public License. | |
7638 | + * %End-Header% | |
7639 | + */ | |
7640 | + | |
7641 | +#include <stdio.h> | |
7642 | +#include <string.h> | |
7643 | +#include <stdlib.h> | |
7644 | +#include <unistd.h> | |
7645 | +#include <sys/types.h> | |
7646 | +#ifdef HAVE_SYS_STAT_H | |
7647 | +#include <sys/stat.h> | |
7648 | +#endif | |
7649 | +#ifdef HAVE_SYS_MKDEV_H | |
7650 | +#include <sys/mkdev.h> | |
7651 | +#endif | |
7652 | +#ifdef HAVE_ERRNO_H | |
7653 | +#include <errno.h> | |
7654 | +#endif | |
7655 | +#include "blkidP.h" | |
7656 | + | |
7657 | +static int save_dev(blkid_dev dev, FILE *file) | |
7658 | +{ | |
7659 | + struct list_head *p; | |
7660 | + | |
7661 | + if (!dev || dev->bid_name[0] != '/') | |
7662 | + return 0; | |
7663 | + | |
7664 | + DBG(DEBUG_SAVE, | |
7665 | + printf("device %s, type %s\n", dev->bid_name, dev->bid_type)); | |
7666 | + | |
7667 | + fprintf(file, | |
7668 | + "<device DEVNO=\"0x%04lx\" TIME=\"%lu\"", | |
7669 | + (unsigned long) dev->bid_devno, dev->bid_time); | |
7670 | + if (dev->bid_pri) | |
7671 | + fprintf(file, " PRI=\"%d\"", dev->bid_pri); | |
7672 | + list_for_each(p, &dev->bid_tags) { | |
7673 | + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); | |
7674 | + fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val); | |
7675 | + } | |
7676 | + fprintf(file, ">%s</device>\n", dev->bid_name); | |
7677 | + | |
7678 | + return 0; | |
7679 | +} | |
7680 | + | |
7681 | +/* | |
7682 | + * Write out the cache struct to the cache file on disk. | |
7683 | + */ | |
7684 | +int blkid_flush_cache(blkid_cache cache) | |
7685 | +{ | |
7686 | + struct list_head *p; | |
7687 | + char *tmp = NULL; | |
7688 | + const char *opened = NULL; | |
7689 | + const char *filename; | |
7690 | + FILE *file = NULL; | |
7691 | + int fd, ret = 0; | |
7692 | + struct stat st; | |
7693 | + | |
7694 | + if (!cache) | |
7695 | + return -BLKID_ERR_PARAM; | |
7696 | + | |
7697 | + if (list_empty(&cache->bic_devs) || | |
7698 | + !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) { | |
7699 | + DBG(DEBUG_SAVE, printf("skipping cache file write\n")); | |
7700 | + return 0; | |
7701 | + } | |
7702 | + | |
7703 | + filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE; | |
7704 | + | |
7705 | + /* If we can't write to the cache file, then don't even try */ | |
7706 | + if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) || | |
7707 | + (ret == 0 && access(filename, W_OK) < 0)) { | |
7708 | + DBG(DEBUG_SAVE, | |
7709 | + printf("can't write to cache file %s\n", filename)); | |
7710 | + return 0; | |
7711 | + } | |
7712 | + | |
7713 | + /* | |
7714 | + * Try and create a temporary file in the same directory so | |
7715 | + * that in case of error we don't overwrite the cache file. | |
7716 | + * If the cache file doesn't yet exist, it isn't a regular | |
7717 | + * file (e.g. /dev/null or a socket), or we couldn't create | |
7718 | + * a temporary file then we open it directly. | |
7719 | + */ | |
7720 | + if (ret == 0 && S_ISREG(st.st_mode)) { | |
7721 | + tmp = malloc(strlen(filename) + 8); | |
7722 | + if (tmp) { | |
7723 | + sprintf(tmp, "%s-XXXXXX", filename); | |
7724 | + fd = mkstemp(tmp); | |
7725 | + if (fd >= 0) { | |
7726 | + file = fdopen(fd, "w"); | |
7727 | + opened = tmp; | |
7728 | + } | |
7729 | + fchmod(fd, 0644); | |
7730 | + } | |
7731 | + } | |
7732 | + | |
7733 | + if (!file) { | |
7734 | + file = fopen(filename, "w"); | |
7735 | + opened = filename; | |
7736 | + } | |
7737 | + | |
7738 | + DBG(DEBUG_SAVE, | |
7739 | + printf("writing cache file %s (really %s)\n", | |
7740 | + filename, opened)); | |
7741 | + | |
7742 | + if (!file) { | |
7743 | + ret = errno; | |
7744 | + goto errout; | |
7745 | + } | |
7746 | + | |
7747 | + list_for_each(p, &cache->bic_devs) { | |
7748 | + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); | |
7749 | + if (!dev->bid_type) | |
7750 | + continue; | |
7751 | + if ((ret = save_dev(dev, file)) < 0) | |
7752 | + break; | |
7753 | + } | |
7754 | + | |
7755 | + if (ret >= 0) { | |
7756 | + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; | |
7757 | + ret = 1; | |
7758 | + } | |
7759 | + | |
7760 | + fclose(file); | |
7761 | + if (opened != filename) { | |
7762 | + if (ret < 0) { | |
7763 | + unlink(opened); | |
7764 | + DBG(DEBUG_SAVE, | |
7765 | + printf("unlinked temp cache %s\n", opened)); | |
7766 | + } else { | |
7767 | + char *backup; | |
7768 | + | |
7769 | + backup = malloc(strlen(filename) + 5); | |
7770 | + if (backup) { | |
7771 | + sprintf(backup, "%s.old", filename); | |
7772 | + unlink(backup); | |
7773 | + link(filename, backup); | |
7774 | + free(backup); | |
7775 | + } | |
7776 | + rename(opened, filename); | |
7777 | + DBG(DEBUG_SAVE, | |
7778 | + printf("moved temp cache %s\n", opened)); | |
7779 | + } | |
7780 | + } | |
7781 | + | |
7782 | +errout: | |
7783 | + if (tmp) | |
7784 | + free(tmp); | |
7785 | + return ret; | |
7786 | +} | |
7787 | + | |
7788 | +#ifdef TEST_PROGRAM | |
7789 | +int main(int argc, char **argv) | |
7790 | +{ | |
7791 | + blkid_cache cache = NULL; | |
7792 | + int ret; | |
7793 | + | |
7794 | + blkid_debug_mask = DEBUG_ALL; | |
7795 | + if (argc > 2) { | |
7796 | + fprintf(stderr, "Usage: %s [filename]\n" | |
7797 | + "Test loading/saving a cache (filename)\n", argv[0]); | |
7798 | + exit(1); | |
7799 | + } | |
7800 | + | |
7801 | + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { | |
7802 | + fprintf(stderr, "%s: error creating cache (%d)\n", | |
7803 | + argv[0], ret); | |
7804 | + exit(1); | |
7805 | + } | |
7806 | + if ((ret = blkid_probe_all(cache)) < 0) { | |
7807 | + fprintf(stderr, "error (%d) probing devices\n", ret); | |
7808 | + exit(1); | |
7809 | + } | |
7810 | + cache->bic_filename = blkid_strdup(argv[1]); | |
7811 | + | |
7812 | + if ((ret = blkid_flush_cache(cache)) < 0) { | |
7813 | + fprintf(stderr, "error (%d) saving cache\n", ret); | |
7814 | + exit(1); | |
7815 | + } | |
7816 | + | |
7817 | + blkid_put_cache(cache); | |
7818 | + | |
7819 | + return ret; | |
7820 | +} | |
7821 | +#endif | |
7822 | diff -Nur busybox-1.00/e2fsprogs/blkid/tag.c busybox/e2fsprogs/blkid/tag.c | |
7823 | --- busybox-1.00/e2fsprogs/blkid/tag.c 1970-01-01 01:00:00.000000000 +0100 | |
7824 | +++ busybox/e2fsprogs/blkid/tag.c 2005-06-04 08:20:15.000000000 +0200 | |
7825 | @@ -0,0 +1,340 @@ | |
7826 | +/* | |
7827 | + * tag.c - allocation/initialization/free routines for tag structs | |
7828 | + * | |
7829 | + * Copyright (C) 2001 Andreas Dilger | |
7830 | + * Copyright (C) 2003 Theodore Ts'o | |
7831 | + * | |
7832 | + * %Begin-Header% | |
7833 | + * This file may be redistributed under the terms of the | |
7834 | + * GNU Lesser General Public License. | |
7835 | + * %End-Header% | |
7836 | + */ | |
7837 | + | |
7838 | +#include <stdlib.h> | |
7839 | +#include <string.h> | |
7840 | +#include <stdio.h> | |
7841 | + | |
7842 | +#include "blkidP.h" | |
7843 | + | |
7844 | +static blkid_tag blkid_new_tag(void) | |
7845 | +{ | |
7846 | + blkid_tag tag; | |
7847 | + | |
7848 | + if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag)))) | |
7849 | + return NULL; | |
7850 | + | |
7851 | + INIT_LIST_HEAD(&tag->bit_tags); | |
7852 | + INIT_LIST_HEAD(&tag->bit_names); | |
7853 | + | |
7854 | + return tag; | |
7855 | +} | |
7856 | + | |
7857 | +void blkid_free_tag(blkid_tag tag) | |
7858 | +{ | |
7859 | + if (!tag) | |
7860 | + return; | |
7861 | + | |
7862 | + DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name, | |
7863 | + tag->bit_val ? tag->bit_val : "(NULL)")); | |
7864 | + DEB_DUMP_TAG(DEBUG_TAG, tag); | |
7865 | + | |
7866 | + list_del(&tag->bit_tags); /* list of tags for this device */ | |
7867 | + list_del(&tag->bit_names); /* list of tags with this type */ | |
7868 | + | |
7869 | + if (tag->bit_name) | |
7870 | + free(tag->bit_name); | |
7871 | + if (tag->bit_val) | |
7872 | + free(tag->bit_val); | |
7873 | + | |
7874 | + free(tag); | |
7875 | +} | |
7876 | + | |
7877 | +/* | |
7878 | + * Find the desired tag on a device. If value is NULL, then the | |
7879 | + * first such tag is returned, otherwise return only exact tag if found. | |
7880 | + */ | |
7881 | +blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type) | |
7882 | +{ | |
7883 | + struct list_head *p; | |
7884 | + | |
7885 | + if (!dev || !type) | |
7886 | + return NULL; | |
7887 | + | |
7888 | + list_for_each(p, &dev->bid_tags) { | |
7889 | + blkid_tag tmp = list_entry(p, struct blkid_struct_tag, | |
7890 | + bit_tags); | |
7891 | + | |
7892 | + if (!strcmp(tmp->bit_name, type)) | |
7893 | + return tmp; | |
7894 | + } | |
7895 | + return NULL; | |
7896 | +} | |
7897 | + | |
7898 | +/* | |
7899 | + * Find the desired tag type in the cache. | |
7900 | + * We return the head tag for this tag type. | |
7901 | + */ | |
7902 | +static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) | |
7903 | +{ | |
7904 | + blkid_tag head = NULL, tmp; | |
7905 | + struct list_head *p; | |
7906 | + | |
7907 | + if (!cache || !type) | |
7908 | + return NULL; | |
7909 | + | |
7910 | + list_for_each(p, &cache->bic_tags) { | |
7911 | + tmp = list_entry(p, struct blkid_struct_tag, bit_tags); | |
7912 | + if (!strcmp(tmp->bit_name, type)) { | |
7913 | + DBG(DEBUG_TAG, | |
7914 | + printf(" found cache tag head %s\n", type)); | |
7915 | + head = tmp; | |
7916 | + break; | |
7917 | + } | |
7918 | + } | |
7919 | + return head; | |
7920 | +} | |
7921 | + | |
7922 | +/* | |
7923 | + * Set a tag on an existing device. | |
7924 | + * | |
7925 | + * If value is NULL, then delete the tagsfrom the device. | |
7926 | + */ | |
7927 | +int blkid_set_tag(blkid_dev dev, const char *name, | |
7928 | + const char *value, const int vlength) | |
7929 | +{ | |
7930 | + blkid_tag t = 0, head = 0; | |
7931 | + char *val = 0; | |
7932 | + | |
7933 | + if (!dev || !name) | |
7934 | + return -BLKID_ERR_PARAM; | |
7935 | + | |
7936 | + if (!(val = blkid_strndup(value, vlength)) && value) | |
7937 | + return -BLKID_ERR_MEM; | |
7938 | + t = blkid_find_tag_dev(dev, name); | |
7939 | + if (!value) { | |
7940 | + if (t) | |
7941 | + blkid_free_tag(t); | |
7942 | + } else if (t) { | |
7943 | + if (!strcmp(t->bit_val, val)) { | |
7944 | + /* Same thing, exit */ | |
7945 | + free(val); | |
7946 | + return 0; | |
7947 | + } | |
7948 | + free(t->bit_val); | |
7949 | + t->bit_val = val; | |
7950 | + } else { | |
7951 | + /* Existing tag not present, add to device */ | |
7952 | + if (!(t = blkid_new_tag())) | |
7953 | + goto errout; | |
7954 | + t->bit_name = blkid_strdup(name); | |
7955 | + t->bit_val = val; | |
7956 | + t->bit_dev = dev; | |
7957 | + | |
7958 | + list_add_tail(&t->bit_tags, &dev->bid_tags); | |
7959 | + | |
7960 | + if (dev->bid_cache) { | |
7961 | + head = blkid_find_head_cache(dev->bid_cache, | |
7962 | + t->bit_name); | |
7963 | + if (!head) { | |
7964 | + head = blkid_new_tag(); | |
7965 | + if (!head) | |
7966 | + goto errout; | |
7967 | + | |
7968 | + DBG(DEBUG_TAG, | |
7969 | + printf(" creating new cache tag head %s\n", name)); | |
7970 | + head->bit_name = blkid_strdup(name); | |
7971 | + if (!head->bit_name) | |
7972 | + goto errout; | |
7973 | + list_add_tail(&head->bit_tags, | |
7974 | + &dev->bid_cache->bic_tags); | |
7975 | + } | |
7976 | + list_add_tail(&t->bit_names, &head->bit_names); | |
7977 | + } | |
7978 | + } | |
7979 | + | |
7980 | + /* Link common tags directly to the device struct */ | |
7981 | + if (!strcmp(name, "TYPE")) | |
7982 | + dev->bid_type = val; | |
7983 | + else if (!strcmp(name, "LABEL")) | |
7984 | + dev->bid_label = val; | |
7985 | + else if (!strcmp(name, "UUID")) | |
7986 | + dev->bid_uuid = val; | |
7987 | + | |
7988 | + if (dev->bid_cache) | |
7989 | + dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED; | |
7990 | + return 0; | |
7991 | + | |
7992 | +errout: | |
7993 | + if (t) | |
7994 | + blkid_free_tag(t); | |
7995 | + else if (val) | |
7996 | + free(val); | |
7997 | + if (head) | |
7998 | + blkid_free_tag(head); | |
7999 | + return -BLKID_ERR_MEM; | |
8000 | +} | |
8001 | + | |
8002 | + | |
8003 | +/* | |
8004 | + * Parse a "NAME=value" string. This is slightly different than | |
8005 | + * parse_token, because that will end an unquoted value at a space, while | |
8006 | + * this will assume that an unquoted value is the rest of the token (e.g. | |
8007 | + * if we are passed an already quoted string from the command-line we don't | |
8008 | + * have to both quote and escape quote so that the quotes make it to | |
8009 | + * us). | |
8010 | + * | |
8011 | + * Returns 0 on success, and -1 on failure. | |
8012 | + */ | |
8013 | +int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) | |
8014 | +{ | |
8015 | + char *name, *value, *cp; | |
8016 | + | |
8017 | + DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token)); | |
8018 | + | |
8019 | + if (!token || !(cp = strchr(token, '='))) | |
8020 | + return -1; | |
8021 | + | |
8022 | + name = blkid_strdup(token); | |
8023 | + if (!name) | |
8024 | + return -1; | |
8025 | + value = name + (cp - token); | |
8026 | + *value++ = '\0'; | |
8027 | + if (*value == '"' || *value == '\'') { | |
8028 | + char c = *value++; | |
8029 | + if (!(cp = strrchr(value, c))) | |
8030 | + goto errout; /* missing closing quote */ | |
8031 | + *cp = '\0'; | |
8032 | + } | |
8033 | + value = blkid_strdup(value); | |
8034 | + if (!value) | |
8035 | + goto errout; | |
8036 | + | |
8037 | + *ret_type = name; | |
8038 | + *ret_val = value; | |
8039 | + | |
8040 | + return 0; | |
8041 | + | |
8042 | +errout: | |
8043 | + free(name); | |
8044 | + return -1; | |
8045 | +} | |
8046 | + | |
8047 | +/* | |
8048 | + * Tag iteration routines for the public libblkid interface. | |
8049 | + * | |
8050 | + * These routines do not expose the list.h implementation, which are a | |
8051 | + * contamination of the namespace, and which force us to reveal far, far | |
8052 | + * too much of our internal implemenation. I'm not convinced I want | |
8053 | + * to keep list.h in the long term, anyway. It's fine for kernel | |
8054 | + * programming, but performance is not the #1 priority for this | |
8055 | + * library, and I really don't like the tradeoff of type-safety for | |
8056 | + * performance for this application. [tytso:20030125.2007EST] | |
8057 | + */ | |
8058 | + | |
8059 | +/* | |
8060 | + * This series of functions iterate over all tags in a device | |
8061 | + */ | |
8062 | +#define TAG_ITERATE_MAGIC 0x01a5284c | |
8063 | + | |
8064 | +struct blkid_struct_tag_iterate { | |
8065 | + int magic; | |
8066 | + blkid_dev dev; | |
8067 | + struct list_head *p; | |
8068 | +}; | |
8069 | + | |
8070 | +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev) | |
8071 | +{ | |
8072 | + blkid_tag_iterate iter; | |
8073 | + | |
8074 | + iter = malloc(sizeof(struct blkid_struct_tag_iterate)); | |
8075 | + if (iter) { | |
8076 | + iter->magic = TAG_ITERATE_MAGIC; | |
8077 | + iter->dev = dev; | |
8078 | + iter->p = dev->bid_tags.next; | |
8079 | + } | |
8080 | + return (iter); | |
8081 | +} | |
8082 | + | |
8083 | +/* | |
8084 | + * Return 0 on success, -1 on error | |
8085 | + */ | |
8086 | +extern int blkid_tag_next(blkid_tag_iterate iter, | |
8087 | + const char **type, const char **value) | |
8088 | +{ | |
8089 | + blkid_tag tag; | |
8090 | + | |
8091 | + *type = 0; | |
8092 | + *value = 0; | |
8093 | + if (!iter || iter->magic != TAG_ITERATE_MAGIC || | |
8094 | + iter->p == &iter->dev->bid_tags) | |
8095 | + return -1; | |
8096 | + tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags); | |
8097 | + *type = tag->bit_name; | |
8098 | + *value = tag->bit_val; | |
8099 | + iter->p = iter->p->next; | |
8100 | + return 0; | |
8101 | +} | |
8102 | + | |
8103 | +extern void blkid_tag_iterate_end(blkid_tag_iterate iter) | |
8104 | +{ | |
8105 | + if (!iter || iter->magic != TAG_ITERATE_MAGIC) | |
8106 | + return; | |
8107 | + iter->magic = 0; | |
8108 | + free(iter); | |
8109 | +} | |
8110 | + | |
8111 | +/* | |
8112 | + * This function returns a device which matches a particular | |
8113 | + * type/value pair. If there is more than one device that matches the | |
8114 | + * search specification, it returns the one with the highest priority | |
8115 | + * value. This allows us to give preference to EVMS or LVM devices. | |
8116 | + * | |
8117 | + * XXX there should also be an interface which uses an iterator so we | |
8118 | + * can get all of the devices which match a type/value search parameter. | |
8119 | + */ | |
8120 | +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, | |
8121 | + const char *type, | |
8122 | + const char *value) | |
8123 | +{ | |
8124 | + blkid_tag head; | |
8125 | + blkid_dev dev; | |
8126 | + int pri; | |
8127 | + struct list_head *p; | |
8128 | + | |
8129 | + if (!cache || !type || !value) | |
8130 | + return NULL; | |
8131 | + | |
8132 | + blkid_read_cache(cache); | |
8133 | + | |
8134 | + DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value)); | |
8135 | + | |
8136 | +try_again: | |
8137 | + pri = -1; | |
8138 | + dev = 0; | |
8139 | + head = blkid_find_head_cache(cache, type); | |
8140 | + | |
8141 | + if (head) { | |
8142 | + list_for_each(p, &head->bit_names) { | |
8143 | + blkid_tag tmp = list_entry(p, struct blkid_struct_tag, | |
8144 | + bit_names); | |
8145 | + | |
8146 | + if (!strcmp(tmp->bit_val, value) && | |
8147 | + tmp->bit_dev->bid_pri > pri) { | |
8148 | + dev = tmp->bit_dev; | |
8149 | + pri = dev->bid_pri; | |
8150 | + } | |
8151 | + } | |
8152 | + } | |
8153 | + if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { | |
8154 | + dev = blkid_verify(cache, dev); | |
8155 | + if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)) | |
8156 | + goto try_again; | |
8157 | + } | |
8158 | + | |
8159 | + if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { | |
8160 | + if (blkid_probe_all(cache) < 0) | |
8161 | + return NULL; | |
8162 | + goto try_again; | |
8163 | + } | |
8164 | + return dev; | |
8165 | +} | |
8166 | diff -Nur busybox-1.00/e2fsprogs/blkid/version.c busybox/e2fsprogs/blkid/version.c | |
8167 | --- busybox-1.00/e2fsprogs/blkid/version.c 1970-01-01 01:00:00.000000000 +0100 | |
8168 | +++ busybox/e2fsprogs/blkid/version.c 2005-06-04 08:20:15.000000000 +0200 | |
8169 | @@ -0,0 +1,49 @@ | |
8170 | +/* | |
8171 | + * version.c --- Return the version of the blkid library | |
8172 | + * | |
8173 | + * Copyright (C) 2004 Theodore Ts'o. | |
8174 | + * | |
8175 | + * %Begin-Header% | |
8176 | + * This file may be redistributed under the terms of the GNU Public | |
8177 | + * License. | |
8178 | + * %End-Header% | |
8179 | + */ | |
8180 | + | |
8181 | +#if HAVE_UNISTD_H | |
8182 | +#include <unistd.h> | |
8183 | +#endif | |
8184 | +#include <string.h> | |
8185 | +#include <stdio.h> | |
8186 | +#include <ctype.h> | |
8187 | + | |
8188 | +#include "blkid.h" | |
8189 | +#include "../../version.h" | |
8190 | + | |
8191 | +static const char *lib_version = E2FSPROGS_VERSION; | |
8192 | +static const char *lib_date = E2FSPROGS_DATE; | |
8193 | + | |
8194 | +int blkid_parse_version_string(const char *ver_string) | |
8195 | +{ | |
8196 | + const char *cp; | |
8197 | + int version = 0; | |
8198 | + | |
8199 | + for (cp = ver_string; *cp; cp++) { | |
8200 | + if (*cp == '.') | |
8201 | + continue; | |
8202 | + if (!isdigit(*cp)) | |
8203 | + break; | |
8204 | + version = (version * 10) + (*cp - '0'); | |
8205 | + } | |
8206 | + return version; | |
8207 | +} | |
8208 | + | |
8209 | +int blkid_get_library_version(const char **ver_string, | |
8210 | + const char **date_string) | |
8211 | +{ | |
8212 | + if (ver_string) | |
8213 | + *ver_string = lib_version; | |
8214 | + if (date_string) | |
8215 | + *date_string = lib_date; | |
8216 | + | |
8217 | + return blkid_parse_version_string(lib_version); | |
8218 | +} | |
8219 | diff -Nur busybox-1.00/e2fsprogs/chattr.c busybox/e2fsprogs/chattr.c | |
8220 | --- busybox-1.00/e2fsprogs/chattr.c 1970-01-01 01:00:00.000000000 +0100 | |
8221 | +++ busybox/e2fsprogs/chattr.c 2005-06-04 08:20:16.000000000 +0200 | |
8222 | @@ -0,0 +1,225 @@ | |
8223 | +/* | |
8224 | + * chattr.c - Change file attributes on an ext2 file system | |
8225 | + * | |
8226 | + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> | |
8227 | + * Laboratoire MASI, Institut Blaise Pascal | |
8228 | + * Universite Pierre et Marie Curie (Paris VI) | |
8229 | + * | |
8230 | + * This file can be redistributed under the terms of the GNU General | |
8231 | + * Public License | |
8232 | + */ | |
8233 | + | |
8234 | +/* | |
8235 | + * History: | |
8236 | + * 93/10/30 - Creation | |
8237 | + * 93/11/13 - Replace stat() calls by lstat() to avoid loops | |
8238 | + * 94/02/27 - Integrated in Ted's distribution | |
8239 | + * 98/12/29 - Ignore symlinks when working recursively (G M Sipe) | |
8240 | + * 98/12/29 - Display version info only when -V specified (G M Sipe) | |
8241 | + */ | |
8242 | + | |
8243 | +#include <sys/types.h> | |
8244 | +#include <dirent.h> | |
8245 | +#include <fcntl.h> | |
8246 | +#include <stdio.h> | |
8247 | +#include <stdlib.h> | |
8248 | +#include <unistd.h> | |
8249 | +#include <string.h> | |
8250 | +#include <errno.h> | |
8251 | +#include <sys/param.h> | |
8252 | +#include <sys/stat.h> | |
8253 | +#include <ext2fs/ext2_fs.h> | |
8254 | + | |
8255 | +#ifdef __GNUC__ | |
8256 | +# define EXT2FS_ATTR(x) __attribute__(x) | |
8257 | +#else | |
8258 | +# define EXT2FS_ATTR(x) | |
8259 | +#endif | |
8260 | + | |
8261 | +#include "e2fsbb.h" | |
8262 | +#include "e2p/e2p.h" | |
8263 | + | |
8264 | +#define OPT_ADD 1 | |
8265 | +#define OPT_REM 2 | |
8266 | +#define OPT_SET 4 | |
8267 | +#define OPT_SET_VER 8 | |
8268 | +static int flags; | |
8269 | +static int recursive; | |
8270 | + | |
8271 | +static unsigned long version; | |
8272 | + | |
8273 | +static unsigned long af; | |
8274 | +static unsigned long rf; | |
8275 | +static unsigned long sf; | |
8276 | + | |
8277 | +#ifdef CONFIG_LFS | |
8278 | +# define LSTAT lstat64 | |
8279 | +# define STRUCT_STAT struct stat64 | |
8280 | +#else | |
8281 | +# define LSTAT lstat | |
8282 | +# define STRUCT_STAT struct stat | |
8283 | +#endif | |
8284 | + | |
8285 | +struct flags_char { | |
8286 | + unsigned long flag; | |
8287 | + char optchar; | |
8288 | +}; | |
8289 | + | |
8290 | +static const struct flags_char flags_array[] = { | |
8291 | + { EXT2_NOATIME_FL, 'A' }, | |
8292 | + { EXT2_SYNC_FL, 'S' }, | |
8293 | + { EXT2_DIRSYNC_FL, 'D' }, | |
8294 | + { EXT2_APPEND_FL, 'a' }, | |
8295 | + { EXT2_COMPR_FL, 'c' }, | |
8296 | + { EXT2_NODUMP_FL, 'd' }, | |
8297 | + { EXT2_IMMUTABLE_FL, 'i' }, | |
8298 | + { EXT3_JOURNAL_DATA_FL, 'j' }, | |
8299 | + { EXT2_SECRM_FL, 's' }, | |
8300 | + { EXT2_UNRM_FL, 'u' }, | |
8301 | + { EXT2_NOTAIL_FL, 't' }, | |
8302 | + { EXT2_TOPDIR_FL, 'T' }, | |
8303 | + { 0, 0 } | |
8304 | +}; | |
8305 | + | |
8306 | +static unsigned long get_flag(char c) | |
8307 | +{ | |
8308 | + const struct flags_char *fp; | |
8309 | + for (fp = flags_array; fp->flag; fp++) | |
8310 | + if (fp->optchar == c) | |
8311 | + return fp->flag; | |
8312 | + bb_show_usage(); | |
8313 | + return 0; | |
8314 | +} | |
8315 | + | |
8316 | +static int decode_arg(char *arg) | |
8317 | +{ | |
8318 | + unsigned long *fl; | |
8319 | + char opt = *arg++; | |
8320 | + | |
8321 | + if (opt == '-') { | |
8322 | + flags |= OPT_REM; | |
8323 | + fl = &rf; | |
8324 | + } else if (opt == '+') { | |
8325 | + flags |= OPT_ADD; | |
8326 | + fl = ⁡ | |
8327 | + } else if (opt == '=') { | |
8328 | + flags |= OPT_SET; | |
8329 | + fl = &sf; | |
8330 | + } else | |
8331 | + return EOF; | |
8332 | + | |
8333 | + for (; *arg ; ++arg) | |
8334 | + (*fl) |= get_flag(*arg); | |
8335 | + | |
8336 | + return 1; | |
8337 | +} | |
8338 | + | |
8339 | +static int chattr_dir_proc(const char *, struct dirent *, void *); | |
8340 | + | |
8341 | +static void change_attributes(const char * name) | |
8342 | +{ | |
8343 | + unsigned long fsflags; | |
8344 | + STRUCT_STAT st; | |
8345 | + | |
8346 | + if (LSTAT(name, &st) == -1) { | |
8347 | + bb_error_msg("stat %s failed", name); | |
8348 | + return; | |
8349 | + } | |
8350 | + if (S_ISLNK(st.st_mode) && recursive) | |
8351 | + return; | |
8352 | + | |
8353 | + /* Don't try to open device files, fifos etc. We probably | |
8354 | + * ought to display an error if the file was explicitly given | |
8355 | + * on the command line (whether or not recursive was | |
8356 | + * requested). */ | |
8357 | + if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) | |
8358 | + return; | |
8359 | + | |
8360 | + if (flags & OPT_SET_VER) | |
8361 | + if (fsetversion(name, version) == -1) | |
8362 | + bb_error_msg("setting version on %s", name); | |
8363 | + | |
8364 | + if (flags & OPT_SET) { | |
8365 | + fsflags = sf; | |
8366 | + } else { | |
8367 | + if (fgetflags(name, &fsflags) == -1) { | |
8368 | + bb_error_msg("reading flags on %s", name); | |
8369 | + goto skip_setflags; | |
8370 | + } | |
8371 | + if (flags & OPT_REM) | |
8372 | + fsflags &= ~rf; | |
8373 | + if (flags & OPT_ADD) | |
8374 | + fsflags |= af; | |
8375 | + if (!S_ISDIR(st.st_mode)) | |
8376 | + fsflags &= ~EXT2_DIRSYNC_FL; | |
8377 | + } | |
8378 | + if (fsetflags(name, fsflags) == -1) | |
8379 | + bb_error_msg("setting flags on %s", name); | |
8380 | + | |
8381 | +skip_setflags: | |
8382 | + if (S_ISDIR(st.st_mode) && recursive) | |
8383 | + iterate_on_dir(name, chattr_dir_proc, NULL); | |
8384 | +} | |
8385 | + | |
8386 | +static int chattr_dir_proc(const char *dir_name, struct dirent *de, | |
8387 | + void *private EXT2FS_ATTR((unused))) | |
8388 | +{ | |
8389 | + /*if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {*/ | |
8390 | + if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || \ | |
8391 | + (de->d_name[1] == '.' && de->d_name[2] == '\0'))) { | |
8392 | + char *path = concat_subpath_file(dir_name, de->d_name); | |
8393 | + if (path) { | |
8394 | + change_attributes(path); | |
8395 | + free(path); | |
8396 | + } | |
8397 | + } | |
8398 | + return 0; | |
8399 | +} | |
8400 | + | |
8401 | +int chattr_main(int argc, char **argv) | |
8402 | +{ | |
8403 | + int i; | |
8404 | + char *arg; | |
8405 | + | |
8406 | + /* parse the args */ | |
8407 | + for (i = 1; i < argc; ++i) { | |
8408 | + arg = argv[i]; | |
8409 | + | |
8410 | + /* take care of -R and -v <version> */ | |
8411 | + if (arg[0] == '-') { | |
8412 | + if (arg[1] == 'R' && arg[2] == '\0') { | |
8413 | + recursive = 1; | |
8414 | + continue; | |
8415 | + } else if (arg[1] == 'v' && arg[2] == '\0') { | |
8416 | + char *tmp; | |
8417 | + ++i; | |
8418 | + if (i >= argc) | |
8419 | + bb_show_usage(); | |
8420 | + version = strtol(argv[i], &tmp, 0); | |
8421 | + if (*tmp) | |
8422 | + bb_error_msg_and_die("bad version '%s'", arg); | |
8423 | + flags |= OPT_SET_VER; | |
8424 | + continue; | |
8425 | + } | |
8426 | + } | |
8427 | + | |
8428 | + if (decode_arg(arg) == EOF) | |
8429 | + break; | |
8430 | + } | |
8431 | + | |
8432 | + /* run sanity checks on all the arguments given us */ | |
8433 | + if (i >= argc) | |
8434 | + bb_show_usage(); | |
8435 | + if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM))) | |
8436 | + bb_error_msg_and_die("= is incompatible with - and +"); | |
8437 | + if ((rf & af) != 0) | |
8438 | + bb_error_msg_and_die("Can't set and unset a flag"); | |
8439 | + if (!flags) | |
8440 | + bb_error_msg_and_die("Must use '-v', =, - or +"); | |
8441 | + | |
8442 | + /* now run chattr on all the files passed to us */ | |
8443 | + while (i < argc) | |
8444 | + change_attributes(argv[i++]); | |
8445 | + | |
8446 | + return EXIT_SUCCESS; | |
8447 | +} | |
8448 | diff -Nur busybox-1.00/e2fsprogs/e2fsbb.h busybox/e2fsprogs/e2fsbb.h | |
8449 | --- busybox-1.00/e2fsprogs/e2fsbb.h 1970-01-01 01:00:00.000000000 +0100 | |
8450 | +++ busybox/e2fsprogs/e2fsbb.h 2005-06-04 08:20:16.000000000 +0200 | |
8451 | @@ -0,0 +1,40 @@ | |
8452 | +/* | |
8453 | + * File: e2fsbb.h | |
8454 | + * | |
8455 | + * Redefine a bunch of e2fsprogs stuff to use busybox routines | |
8456 | + * instead. This makes upgrade between e2fsprogs versions easy. | |
8457 | + */ | |
8458 | + | |
8459 | +#ifndef __E2FSBB_H__ | |
8460 | +#define __E2FSBB_H__ 1 | |
8461 | + | |
8462 | +#include "libbb.h" | |
8463 | + | |
8464 | +/* version we've last synced against */ | |
8465 | +#define E2FSPROGS_VERSION "1.37" | |
8466 | +#define E2FSPROGS_DATE "21-Mar-2005" | |
8467 | + | |
8468 | +/* make sure com_err.h isnt included before us */ | |
8469 | +#ifdef __COM_ERR_H__ | |
8470 | +#error You should not have included com_err.h ! | |
8471 | +#endif | |
8472 | +#define __COM_ERR_H__ | |
8473 | + | |
8474 | +/* com_err crap */ | |
8475 | +#define com_err(w, c, fmt, args...) bb_error_msg(fmt, ## args) | |
8476 | +typedef long errcode_t; | |
8477 | +#define ERRCODE_RANGE 8 | |
8478 | +#define error_message(code) strerror((int) (code & ((1<<ERRCODE_RANGE)-1))) | |
8479 | +#define initialize_ext2_error_table(x) | |
8480 | + | |
8481 | +/* NLS crap */ | |
8482 | +#define _(x) x | |
8483 | +#define N_(x) x | |
8484 | +#define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural)) | |
8485 | + | |
8486 | +/* misc crap */ | |
8487 | +#define fatal_error(msg, err) bb_error_msg_and_die(msg) | |
8488 | +#define usage() bb_show_usage() | |
8489 | +#define perror(msg) bb_perror_msg(msg) | |
8490 | + | |
8491 | +#endif /* __E2FSBB_H__ */ | |
8492 | diff -Nur busybox-1.00/e2fsprogs/e2p/e2p.h busybox/e2fsprogs/e2p/e2p.h | |
8493 | --- busybox-1.00/e2fsprogs/e2p/e2p.h 1970-01-01 01:00:00.000000000 +0100 | |
8494 | +++ busybox/e2fsprogs/e2p/e2p.h 2005-06-04 08:20:15.000000000 +0200 | |
8495 | @@ -0,0 +1,59 @@ | |
8496 | +#include <sys/types.h> /* Needed by dirent.h on netbsd */ | |
8497 | +#include <stdio.h> | |
8498 | +#include <dirent.h> | |
8499 | + | |
8500 | +#include <ext2fs/ext2_fs.h> | |
8501 | + | |
8502 | +#define E2P_FEATURE_COMPAT 0 | |
8503 | +#define E2P_FEATURE_INCOMPAT 1 | |
8504 | +#define E2P_FEATURE_RO_INCOMPAT 2 | |
8505 | + | |
8506 | + | |
8507 | +/* `options' for print_flags() */ | |
8508 | + | |
8509 | +#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */ | |
8510 | + | |
8511 | +/*int fgetversion (const char * name, unsigned long * version);*/ | |
8512 | +/*int fsetversion (const char * name, unsigned long version);*/ | |
8513 | +int fgetsetversion(const char * name, unsigned long * get_version, unsigned long set_version); | |
8514 | +#define fgetversion(name, version) fgetsetversion(name, version, 0) | |
8515 | +#define fsetversion(name, version) fgetsetversion(name, NULL, version) | |
8516 | + | |
8517 | +/*int fgetflags (const char * name, unsigned long * flags);*/ | |
8518 | +/*int fsetflags (const char * name, unsigned long flags);*/ | |
8519 | +int fgetsetflags(const char * name, unsigned long * get_flags, unsigned long set_flags); | |
8520 | +#define fgetflags(name, flags) fgetsetflags(name, flags, 0) | |
8521 | +#define fsetflags(name, flags) fgetsetflags(name, NULL, flags) | |
8522 | + | |
8523 | +int getflags (int fd, unsigned long * flags); | |
8524 | +int getversion (int fd, unsigned long * version); | |
8525 | +int iterate_on_dir (const char * dir_name, | |
8526 | + int (*func) (const char *, struct dirent *, void *), | |
8527 | + void * private); | |
8528 | +void list_super(struct ext2_super_block * s); | |
8529 | +void list_super2(struct ext2_super_block * s, FILE *f); | |
8530 | +void print_fs_errors (FILE * f, unsigned short errors); | |
8531 | +void print_flags (FILE * f, unsigned long flags, unsigned options); | |
8532 | +void print_fs_state (FILE * f, unsigned short state); | |
8533 | +int setflags (int fd, unsigned long flags); | |
8534 | +int setversion (int fd, unsigned long version); | |
8535 | + | |
8536 | +const char *e2p_feature2string(int compat, unsigned int mask); | |
8537 | +int e2p_string2feature(char *string, int *compat, unsigned int *mask); | |
8538 | +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array); | |
8539 | + | |
8540 | +int e2p_is_null_uuid(void *uu); | |
8541 | +void e2p_uuid_to_str(void *uu, char *out); | |
8542 | +const char *e2p_uuid2str(void *uu); | |
8543 | + | |
8544 | +const char *e2p_hash2string(int num); | |
8545 | +int e2p_string2hash(char *string); | |
8546 | + | |
8547 | +const char *e2p_mntopt2string(unsigned int mask); | |
8548 | +int e2p_string2mntopt(char *string, unsigned int *mask); | |
8549 | +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok); | |
8550 | + | |
8551 | +unsigned long parse_num_blocks(const char *arg, int log_block_size); | |
8552 | + | |
8553 | +char *e2p_os2string(int os_type); | |
8554 | +int e2p_string2os(char *str); | |
8555 | diff -Nur busybox-1.00/e2fsprogs/e2p/feature.c busybox/e2fsprogs/e2p/feature.c | |
8556 | --- busybox-1.00/e2fsprogs/e2p/feature.c 1970-01-01 01:00:00.000000000 +0100 | |
8557 | +++ busybox/e2fsprogs/e2p/feature.c 2005-06-04 08:20:15.000000000 +0200 | |
8558 | @@ -0,0 +1,190 @@ | |
8559 | +/* | |
8560 | + * feature.c --- convert between features and strings | |
8561 | + * | |
8562 | + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> | |
8563 | + * | |
8564 | + * This file can be redistributed under the terms of the GNU Library General | |
8565 | + * Public License | |
8566 | + * | |
8567 | + */ | |
8568 | + | |
8569 | +#include <stdio.h> | |
8570 | +#include <stdlib.h> | |
8571 | +#include <string.h> | |
8572 | +#include <ctype.h> | |
8573 | +#include <errno.h> | |
8574 | + | |
8575 | +#include "e2p.h" | |
8576 | + | |
8577 | +struct feature { | |
8578 | + int compat; | |
8579 | + unsigned int mask; | |
8580 | + const char *string; | |
8581 | +}; | |
8582 | + | |
8583 | +static struct feature feature_list[] = { | |
8584 | + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC, | |
8585 | + "dir_prealloc" }, | |
8586 | + { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL, | |
8587 | + "has_journal" }, | |
8588 | + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES, | |
8589 | + "imagic_inodes" }, | |
8590 | + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR, | |
8591 | + "ext_attr" }, | |
8592 | + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX, | |
8593 | + "dir_index" }, | |
8594 | + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE, | |
8595 | + "resize_inode" }, | |
8596 | + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, | |
8597 | + "sparse_super" }, | |
8598 | + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE, | |
8599 | + "large_file" }, | |
8600 | + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, | |
8601 | + "compression" }, | |
8602 | + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE, | |
8603 | + "filetype" }, | |
8604 | + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER, | |
8605 | + "needs_recovery" }, | |
8606 | + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, | |
8607 | + "journal_dev" }, | |
8608 | + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, | |
8609 | + "extents" }, | |
8610 | + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, | |
8611 | + "meta_bg" }, | |
8612 | + { 0, 0, 0 }, | |
8613 | +}; | |
8614 | + | |
8615 | +const char *e2p_feature2string(int compat, unsigned int mask) | |
8616 | +{ | |
8617 | + struct feature *f; | |
8618 | + static char buf[20]; | |
8619 | + char fchar; | |
8620 | + int fnum; | |
8621 | + | |
8622 | + for (f = feature_list; f->string; f++) { | |
8623 | + if ((compat == f->compat) && | |
8624 | + (mask == f->mask)) | |
8625 | + return f->string; | |
8626 | + } | |
8627 | + switch (compat) { | |
8628 | + case E2P_FEATURE_COMPAT: | |
8629 | + fchar = 'C'; | |
8630 | + break; | |
8631 | + case E2P_FEATURE_INCOMPAT: | |
8632 | + fchar = 'I'; | |
8633 | + break; | |
8634 | + case E2P_FEATURE_RO_INCOMPAT: | |
8635 | + fchar = 'R'; | |
8636 | + break; | |
8637 | + default: | |
8638 | + fchar = '?'; | |
8639 | + break; | |
8640 | + } | |
8641 | + for (fnum = 0; mask >>= 1; fnum++); | |
8642 | + sprintf(buf, "FEATURE_%c%d", fchar, fnum); | |
8643 | + return buf; | |
8644 | +} | |
8645 | + | |
8646 | +int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) | |
8647 | +{ | |
8648 | + struct feature *f; | |
8649 | + char *eptr; | |
8650 | + int num; | |
8651 | + | |
8652 | + for (f = feature_list; f->string; f++) { | |
8653 | + if (!strcasecmp(string, f->string)) { | |
8654 | + *compat_type = f->compat; | |
8655 | + *mask = f->mask; | |
8656 | + return 0; | |
8657 | + } | |
8658 | + } | |
8659 | + if (strncasecmp(string, "FEATURE_", 8)) | |
8660 | + return 1; | |
8661 | + | |
8662 | + switch (string[8]) { | |
8663 | + case 'c': | |
8664 | + case 'C': | |
8665 | + *compat_type = E2P_FEATURE_COMPAT; | |
8666 | + break; | |
8667 | + case 'i': | |
8668 | + case 'I': | |
8669 | + *compat_type = E2P_FEATURE_INCOMPAT; | |
8670 | + break; | |
8671 | + case 'r': | |
8672 | + case 'R': | |
8673 | + *compat_type = E2P_FEATURE_RO_INCOMPAT; | |
8674 | + break; | |
8675 | + default: | |
8676 | + return 1; | |
8677 | + } | |
8678 | + if (string[9] == 0) | |
8679 | + return 1; | |
8680 | + num = strtol(string+9, &eptr, 10); | |
8681 | + if (num > 32 || num < 0) | |
8682 | + return 1; | |
8683 | + if (*eptr) | |
8684 | + return 1; | |
8685 | + *mask = 1 << num; | |
8686 | + return 0; | |
8687 | +} | |
8688 | + | |
8689 | +static char *skip_over_blanks(char *cp) | |
8690 | +{ | |
8691 | + while (*cp && isspace(*cp)) | |
8692 | + cp++; | |
8693 | + return cp; | |
8694 | +} | |
8695 | + | |
8696 | +static char *skip_over_word(char *cp) | |
8697 | +{ | |
8698 | + while (*cp && !isspace(*cp) && *cp != ',') | |
8699 | + cp++; | |
8700 | + return cp; | |
8701 | +} | |
8702 | + | |
8703 | +/* | |
8704 | + * Edit a feature set array as requested by the user. The ok_array, | |
8705 | + * if set, allows the application to limit what features the user is | |
8706 | + * allowed to set or clear using this function. | |
8707 | + */ | |
8708 | +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) | |
8709 | +{ | |
8710 | + char *cp, *buf, *next; | |
8711 | + int neg; | |
8712 | + unsigned int mask; | |
8713 | + int compat_type; | |
8714 | + | |
8715 | + buf = malloc(strlen(str)+1); | |
8716 | + if (!buf) | |
8717 | + return 1; | |
8718 | + strcpy(buf, str); | |
8719 | + cp = buf; | |
8720 | + while (cp && *cp) { | |
8721 | + neg = 0; | |
8722 | + cp = skip_over_blanks(cp); | |
8723 | + next = skip_over_word(cp); | |
8724 | + if (*next == 0) | |
8725 | + next = 0; | |
8726 | + else | |
8727 | + *next = 0; | |
8728 | + switch (*cp) { | |
8729 | + case '-': | |
8730 | + case '^': | |
8731 | + neg++; | |
8732 | + case '+': | |
8733 | + cp++; | |
8734 | + break; | |
8735 | + } | |
8736 | + if (e2p_string2feature(cp, &compat_type, &mask)) | |
8737 | + return 1; | |
8738 | + if (ok_array && !(ok_array[compat_type] & mask)) | |
8739 | + return 1; | |
8740 | + if (neg) | |
8741 | + compat_array[compat_type] &= ~mask; | |
8742 | + else | |
8743 | + compat_array[compat_type] |= mask; | |
8744 | + cp = next ? next+1 : 0; | |
8745 | + } | |
8746 | + return 0; | |
8747 | +} | |
8748 | + | |
8749 | diff -Nur busybox-1.00/e2fsprogs/e2p/fgetsetflags.c busybox/e2fsprogs/e2p/fgetsetflags.c | |
8750 | --- busybox-1.00/e2fsprogs/e2p/fgetsetflags.c 1970-01-01 01:00:00.000000000 +0100 | |
8751 | +++ busybox/e2fsprogs/e2p/fgetsetflags.c 2005-06-04 08:20:15.000000000 +0200 | |
8752 | @@ -0,0 +1,69 @@ | |
8753 | +/* | |
8754 | + * fgetflags.c - Get a file flags on an ext2 file system | |
8755 | + * fsetflags.c - Set a file flags on an ext2 file system | |
8756 | + * | |
8757 | + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> | |
8758 | + * Laboratoire MASI, Institut Blaise Pascal | |
8759 | + * Universite Pierre et Marie Curie (Paris VI) | |
8760 | + * | |
8761 | + * This file can be redistributed under the terms of the GNU Library General | |
8762 | + * Public License | |
8763 | + */ | |
8764 | + | |
8765 | +/* | |
8766 | + * History: | |
8767 | + * 93/10/30 - Creation | |
8768 | + */ | |
8769 | + | |
8770 | +#if HAVE_ERRNO_H | |
8771 | +#include <errno.h> | |
8772 | +#endif | |
8773 | +#if HAVE_UNISTD_H | |
8774 | +#include <unistd.h> | |
8775 | +#endif | |
8776 | +#include <sys/types.h> | |
8777 | +#include <sys/stat.h> | |
8778 | +#if HAVE_EXT2_IOCTLS | |
8779 | +#include <fcntl.h> | |
8780 | +#include <sys/ioctl.h> | |
8781 | +#endif | |
8782 | + | |
8783 | +#include "e2p.h" | |
8784 | + | |
8785 | +#ifdef O_LARGEFILE | |
8786 | +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) | |
8787 | +#else | |
8788 | +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) | |
8789 | +#endif | |
8790 | + | |
8791 | +int fgetsetflags (const char * name, unsigned long * get_flags, unsigned long set_flags) | |
8792 | +{ | |
8793 | +#if HAVE_EXT2_IOCTLS | |
8794 | + struct stat buf; | |
8795 | + int fd, r, f, save_errno = 0; | |
8796 | + | |
8797 | + if (!stat(name, &buf) && | |
8798 | + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { | |
8799 | + goto notsupp; | |
8800 | + } | |
8801 | + fd = open (name, OPEN_FLAGS); | |
8802 | + if (fd == -1) | |
8803 | + return -1; | |
8804 | + if (!get_flags) { | |
8805 | + f = (int) set_flags; | |
8806 | + r = ioctl (fd, EXT2_IOC_SETFLAGS, &f); | |
8807 | + } else { | |
8808 | + r = ioctl (fd, EXT2_IOC_GETFLAGS, &f); | |
8809 | + *get_flags = f; | |
8810 | + } | |
8811 | + if (r == -1) | |
8812 | + save_errno = errno; | |
8813 | + close (fd); | |
8814 | + if (save_errno) | |
8815 | + errno = save_errno; | |
8816 | + return r; | |
8817 | +#endif /* HAVE_EXT2_IOCTLS */ | |
8818 | +notsupp: | |
8819 | + errno = EOPNOTSUPP; | |
8820 | + return -1; | |
8821 | +} | |
8822 | diff -Nur busybox-1.00/e2fsprogs/e2p/fgetsetversion.c busybox/e2fsprogs/e2p/fgetsetversion.c | |
8823 | --- busybox-1.00/e2fsprogs/e2p/fgetsetversion.c 1970-01-01 01:00:00.000000000 +0100 | |
8824 | +++ busybox/e2fsprogs/e2p/fgetsetversion.c 2005-06-04 08:20:15.000000000 +0200 | |
8825 | @@ -0,0 +1,69 @@ | |
8826 | +/* | |
8827 | + * fgetversion.c - Get a file version on an ext2 file system | |
8828 | + * fsetversion.c - Set a file version on an ext2 file system | |
8829 | + * | |
8830 | + * | |
8831 | + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> | |
8832 | + * Laboratoire MASI, Institut Blaise Pascal | |
8833 | + * Universite Pierre et Marie Curie (Paris VI) | |
8834 | + * | |
8835 | + * This file can be redistributed under the terms of the GNU Library General | |
8836 | + * Public License | |
8837 | + */ | |
8838 | + | |
8839 | +/* | |
8840 | + * History: | |
8841 | + * 93/10/30 - Creation | |
8842 | + */ | |
8843 | + | |
8844 | +#if HAVE_ERRNO_H | |
8845 | +#include <errno.h> | |
8846 | +#endif | |
8847 | +#if HAVE_UNISTD_H | |
8848 | +#include <unistd.h> | |
8849 | +#endif | |
8850 | +#include <fcntl.h> | |
8851 | +#include <sys/ioctl.h> | |
8852 | + | |
8853 | +#include "e2p.h" | |
8854 | + | |
8855 | +#ifdef O_LARGEFILE | |
8856 | +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) | |
8857 | +#else | |
8858 | +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) | |
8859 | +#endif | |
8860 | + | |
8861 | +/* | |
8862 | + To do fsetversion: unsigned long *ptr_version must be set to NULL. | |
8863 | + and unsigned long version must be set to a value | |
8864 | + To do fgetversion: unsigned long *ptr_version must NOT be set to NULL | |
8865 | + and unsigned long version is ignored. | |
8866 | + TITO. | |
8867 | +*/ | |
8868 | + | |
8869 | +int fgetsetversion (const char * name, unsigned long * get_version, unsigned long set_version) | |
8870 | +{ | |
8871 | +#if HAVE_EXT2_IOCTLS | |
8872 | + int fd, r, ver, save_errno = 0; | |
8873 | + | |
8874 | + fd = open (name, OPEN_FLAGS); | |
8875 | + if (fd == -1) | |
8876 | + return -1; | |
8877 | + if (!get_version) { | |
8878 | + ver = (int) set_version; | |
8879 | + r = ioctl (fd, EXT2_IOC_SETVERSION, &ver); | |
8880 | + } else { | |
8881 | + r = ioctl (fd, EXT2_IOC_GETVERSION, &ver); | |
8882 | + *get_version = ver; | |
8883 | + } | |
8884 | + if (r == -1) | |
8885 | + save_errno = errno; | |
8886 | + close (fd); | |
8887 | + if (save_errno) | |
8888 | + errno = save_errno; | |
8889 | + return r; | |
8890 | +#else /* ! HAVE_EXT2_IOCTLS */ | |
8891 | + errno = EOPNOTSUPP; | |
8892 | + return -1; | |
8893 | +#endif /* ! HAVE_EXT2_IOCTLS */ | |
8894 | +} | |
8895 | diff -Nur busybox-1.00/e2fsprogs/e2p/hashstr.c busybox/e2fsprogs/e2p/hashstr.c | |
8896 | --- busybox-1.00/e2fsprogs/e2p/hashstr.c 1970-01-01 01:00:00.000000000 +0100 | |
8897 | +++ busybox/e2fsprogs/e2p/hashstr.c 2005-06-04 08:20:15.000000000 +0200 | |
8898 | @@ -0,0 +1,70 @@ | |
8899 | +/* | |
8900 | + * feature.c --- convert between features and strings | |
8901 | + * | |
8902 | + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> | |
8903 | + * | |
8904 | + * This file can be redistributed under the terms of the GNU Library General | |
8905 | + * Public License | |
8906 | + * | |
8907 | + */ | |
8908 | + | |
8909 | +#include <stdio.h> | |
8910 | +#include <stdlib.h> | |
8911 | +#include <string.h> | |
8912 | +#include <ctype.h> | |
8913 | +#include <errno.h> | |
8914 | + | |
8915 | +#include "e2p.h" | |
8916 | + | |
8917 | +struct hash { | |
8918 | + int num; | |
8919 | + const char *string; | |
8920 | +}; | |
8921 | + | |
8922 | +static struct hash hash_list[] = { | |
8923 | + { EXT2_HASH_LEGACY, "legacy" }, | |
8924 | + { EXT2_HASH_HALF_MD4, "half_md4" }, | |
8925 | + { EXT2_HASH_TEA, "tea" }, | |
8926 | + { 0, 0 }, | |
8927 | +}; | |
8928 | + | |
8929 | +const char *e2p_hash2string(int num) | |
8930 | +{ | |
8931 | + struct hash *p; | |
8932 | + static char buf[20]; | |
8933 | + | |
8934 | + for (p = hash_list; p->string; p++) { | |
8935 | + if (num == p->num) | |
8936 | + return p->string; | |
8937 | + } | |
8938 | + sprintf(buf, "HASHALG_%d", num); | |
8939 | + return buf; | |
8940 | +} | |
8941 | + | |
8942 | +/* | |
8943 | + * Returns the hash algorithm, or -1 on error | |
8944 | + */ | |
8945 | +int e2p_string2hash(char *string) | |
8946 | +{ | |
8947 | + struct hash *p; | |
8948 | + char *eptr; | |
8949 | + int num; | |
8950 | + | |
8951 | + for (p = hash_list; p->string; p++) { | |
8952 | + if (!strcasecmp(string, p->string)) { | |
8953 | + return p->num; | |
8954 | + } | |
8955 | + } | |
8956 | + if (strncasecmp(string, "HASHALG_", 8)) | |
8957 | + return -1; | |
8958 | + | |
8959 | + if (string[8] == 0) | |
8960 | + return -1; | |
8961 | + num = strtol(string+8, &eptr, 10); | |
8962 | + if (num > 255 || num < 0) | |
8963 | + return -1; | |
8964 | + if (*eptr) | |
8965 | + return -1; | |
8966 | + return num; | |
8967 | +} | |
8968 | + | |
8969 | diff -Nur busybox-1.00/e2fsprogs/e2p/iod.c busybox/e2fsprogs/e2p/iod.c | |
8970 | --- busybox-1.00/e2fsprogs/e2p/iod.c 1970-01-01 01:00:00.000000000 +0100 | |
8971 | +++ busybox/e2fsprogs/e2p/iod.c 2005-06-04 08:20:15.000000000 +0200 | |
8972 | @@ -0,0 +1,51 @@ | |
8973 | +/* | |
8974 | + * iod.c - Iterate a function on each entry of a directory | |
8975 | + * | |
8976 | + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> | |
8977 | + * Laboratoire MASI, Institut Blaise Pascal | |
8978 | + * Universite Pierre et Marie Curie (Paris VI) | |
8979 | + * | |
8980 | + * This file can be redistributed under the terms of the GNU Library General | |
8981 | + * Public License | |
8982 | + */ | |
8983 | + | |
8984 | +/* | |
8985 | + * History: | |
8986 | + * 93/10/30 - Creation | |
8987 | + */ | |
8988 | + | |
8989 | +#include "e2p.h" | |
8990 | +#include <unistd.h> | |
8991 | +#include <stdlib.h> | |
8992 | +#include <string.h> | |
8993 | + | |
8994 | +int iterate_on_dir (const char * dir_name, | |
8995 | + int (*func) (const char *, struct dirent *, void *), | |
8996 | + void * private) | |
8997 | +{ | |
8998 | + DIR * dir; | |
8999 | + struct dirent *de, *dep; | |
9000 | + int max_len, len; | |
9001 | + | |
9002 | + max_len = PATH_MAX + sizeof(struct dirent); | |
9003 | + de = (struct dirent *)xmalloc(max_len+1); | |
9004 | + memset(de, 0, max_len+1); | |
9005 | + | |
9006 | + dir = opendir (dir_name); | |
9007 | + if (dir == NULL) { | |
9008 | + free(de); | |
9009 | + return -1; | |
9010 | + } | |
9011 | + while ((dep = readdir (dir))) { | |
9012 | + len = sizeof(struct dirent); | |
9013 | + if (len < dep->d_reclen) | |
9014 | + len = dep->d_reclen; | |
9015 | + if (len > max_len) | |
9016 | + len = max_len; | |
9017 | + memcpy(de, dep, len); | |
9018 | + (*func) (dir_name, de, private); | |
9019 | + } | |
9020 | + free(de); | |
9021 | + closedir(dir); | |
9022 | + return 0; | |
9023 | +} | |
9024 | diff -Nur busybox-1.00/e2fsprogs/e2p/ls.c busybox/e2fsprogs/e2p/ls.c | |
9025 | --- busybox-1.00/e2fsprogs/e2p/ls.c 1970-01-01 01:00:00.000000000 +0100 | |
9026 | +++ busybox/e2fsprogs/e2p/ls.c 2005-06-04 08:20:15.000000000 +0200 | |
9027 | @@ -0,0 +1,276 @@ | |
9028 | +/* | |
9029 | + * ls.c - List the contents of an ext2fs superblock | |
9030 | + * | |
9031 | + * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> | |
9032 | + * Laboratoire MASI, Institut Blaise Pascal | |
9033 | + * Universite Pierre et Marie Curie (Paris VI) | |
9034 | + * | |
9035 | + * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu> | |
9036 | + * | |
9037 | + * This file can be redistributed under the terms of the GNU Library General | |
9038 | + * Public License | |
9039 | + */ | |
9040 | + | |
9041 | +#include <stdio.h> | |
9042 | +#include <sys/types.h> | |
9043 | +#include <string.h> | |
9044 | +#include <grp.h> | |
9045 | +#include <pwd.h> | |
9046 | +#include <time.h> | |
9047 | + | |
9048 | +#include "e2p.h" | |
9049 | + | |
9050 | +static void print_user (unsigned short uid, FILE *f) | |
9051 | +{ | |
9052 | + struct passwd *pw; | |
9053 | + | |
9054 | + fprintf(f, "%u ", uid); | |
9055 | + pw = getpwuid (uid); | |
9056 | + if (pw == NULL) | |
9057 | + fprintf(f, "(user unknown)\n"); | |
9058 | + else | |
9059 | + fprintf(f, "(user %s)\n", pw->pw_name); | |
9060 | +} | |
9061 | + | |
9062 | +static void print_group (unsigned short gid, FILE *f) | |
9063 | +{ | |
9064 | + struct group *gr; | |
9065 | + | |
9066 | + fprintf(f, "%u ", gid); | |
9067 | + gr = getgrgid (gid); | |
9068 | + if (gr == NULL) | |
9069 | + fprintf(f, "(group unknown)\n"); | |
9070 | + else | |
9071 | + fprintf(f, "(group %s)\n", gr->gr_name); | |
9072 | +} | |
9073 | + | |
9074 | +#define MONTH_INT (86400 * 30) | |
9075 | +#define WEEK_INT (86400 * 7) | |
9076 | +#define DAY_INT (86400) | |
9077 | +#define HOUR_INT (60 * 60) | |
9078 | +#define MINUTE_INT (60) | |
9079 | + | |
9080 | +static const char *interval_string(unsigned int secs) | |
9081 | +{ | |
9082 | + static char buf[256], tmp[80]; | |
9083 | + int hr, min, num; | |
9084 | + | |
9085 | + buf[0] = 0; | |
9086 | + | |
9087 | + if (secs == 0) | |
9088 | + return "<none>"; | |
9089 | + | |
9090 | + if (secs >= MONTH_INT) { | |
9091 | + num = secs / MONTH_INT; | |
9092 | + secs -= num*MONTH_INT; | |
9093 | + sprintf(buf, "%d month%s", num, (num>1) ? "s" : ""); | |
9094 | + } | |
9095 | + if (secs >= WEEK_INT) { | |
9096 | + num = secs / WEEK_INT; | |
9097 | + secs -= num*WEEK_INT; | |
9098 | + sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "", | |
9099 | + num, (num>1) ? "s" : ""); | |
9100 | + strcat(buf, tmp); | |
9101 | + } | |
9102 | + if (secs >= DAY_INT) { | |
9103 | + num = secs / DAY_INT; | |
9104 | + secs -= num*DAY_INT; | |
9105 | + sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "", | |
9106 | + num, (num>1) ? "s" : ""); | |
9107 | + strcat(buf, tmp); | |
9108 | + } | |
9109 | + if (secs > 0) { | |
9110 | + hr = secs / HOUR_INT; | |
9111 | + secs -= hr*HOUR_INT; | |
9112 | + min = secs / MINUTE_INT; | |
9113 | + secs -= min*MINUTE_INT; | |
9114 | + sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "", | |
9115 | + hr, min, secs); | |
9116 | + strcat(buf, tmp); | |
9117 | + } | |
9118 | + return buf; | |
9119 | +} | |
9120 | + | |
9121 | +static void print_features(struct ext2_super_block * s, FILE *f) | |
9122 | +{ | |
9123 | +#ifdef EXT2_DYNAMIC_REV | |
9124 | + int i, j, printed=0; | |
9125 | + __u32 *mask = &s->s_feature_compat, m; | |
9126 | + | |
9127 | + fprintf(f, "Filesystem features: "); | |
9128 | + for (i=0; i <3; i++,mask++) { | |
9129 | + for (j=0,m=1; j < 32; j++, m<<=1) { | |
9130 | + if (*mask & m) { | |
9131 | + fprintf(f, " %s", e2p_feature2string(i, m)); | |
9132 | + printed++; | |
9133 | + } | |
9134 | + } | |
9135 | + } | |
9136 | + if (printed == 0) | |
9137 | + fprintf(f, " (none)"); | |
9138 | + fprintf(f, "\n"); | |
9139 | +#endif | |
9140 | +} | |
9141 | + | |
9142 | +static void print_mntopts(struct ext2_super_block * s, FILE *f) | |
9143 | +{ | |
9144 | +#ifdef EXT2_DYNAMIC_REV | |
9145 | + int i, printed=0; | |
9146 | + __u32 mask = s->s_default_mount_opts, m; | |
9147 | + | |
9148 | + fprintf(f, "Default mount options: "); | |
9149 | + if (mask & EXT3_DEFM_JMODE) { | |
9150 | + fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE)); | |
9151 | + printed++; | |
9152 | + } | |
9153 | + for (i=0,m=1; i < 32; i++, m<<=1) { | |
9154 | + if (m & EXT3_DEFM_JMODE) | |
9155 | + continue; | |
9156 | + if (mask & m) { | |
9157 | + fprintf(f, " %s", e2p_mntopt2string(m)); | |
9158 | + printed++; | |
9159 | + } | |
9160 | + } | |
9161 | + if (printed == 0) | |
9162 | + fprintf(f, " (none)"); | |
9163 | + fprintf(f, "\n"); | |
9164 | +#endif | |
9165 | +} | |
9166 | + | |
9167 | + | |
9168 | +#ifndef EXT2_INODE_SIZE | |
9169 | +#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) | |
9170 | +#endif | |
9171 | + | |
9172 | +#ifndef EXT2_GOOD_OLD_REV | |
9173 | +#define EXT2_GOOD_OLD_REV 0 | |
9174 | +#endif | |
9175 | + | |
9176 | +void list_super2(struct ext2_super_block * sb, FILE *f) | |
9177 | +{ | |
9178 | + int inode_blocks_per_group; | |
9179 | + char buf[80], *str; | |
9180 | + time_t tm; | |
9181 | + | |
9182 | + inode_blocks_per_group = (((sb->s_inodes_per_group * | |
9183 | + EXT2_INODE_SIZE(sb)) + | |
9184 | + EXT2_BLOCK_SIZE(sb) - 1) / | |
9185 | + EXT2_BLOCK_SIZE(sb)); | |
9186 | + if (sb->s_volume_name[0]) { | |
9187 | + memset(buf, 0, sizeof(buf)); | |
9188 | + strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name)); | |
9189 | + } else | |
9190 | + strcpy(buf, "<none>"); | |
9191 | + fprintf(f, "Filesystem volume name: %s\n", buf); | |
9192 | + if (sb->s_last_mounted[0]) { | |
9193 | + memset(buf, 0, sizeof(buf)); | |
9194 | + strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted)); | |
9195 | + } else | |
9196 | + strcpy(buf, "<not available>"); | |
9197 | + fprintf(f, "Last mounted on: %s\n", buf); | |
9198 | + fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid)); | |
9199 | + fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic); | |
9200 | + fprintf(f, "Filesystem revision #: %d", sb->s_rev_level); | |
9201 | + if (sb->s_rev_level == EXT2_GOOD_OLD_REV) { | |
9202 | + fprintf(f, " (original)\n"); | |
9203 | +#ifdef EXT2_DYNAMIC_REV | |
9204 | + } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) { | |
9205 | + fprintf(f, " (dynamic)\n"); | |
9206 | +#endif | |
9207 | + } else | |
9208 | + fprintf(f, " (unknown)\n"); | |
9209 | + print_features(sb, f); | |
9210 | + print_mntopts(sb, f); | |
9211 | + fprintf(f, "Filesystem state: "); | |
9212 | + print_fs_state (f, sb->s_state); | |
9213 | + fprintf(f, "\n"); | |
9214 | + fprintf(f, "Errors behavior: "); | |
9215 | + print_fs_errors(f, sb->s_errors); | |
9216 | + fprintf(f, "\n"); | |
9217 | + str = e2p_os2string(sb->s_creator_os); | |
9218 | + fprintf(f, "Filesystem OS type: %s\n", str); | |
9219 | + free(str); | |
9220 | + fprintf(f, "Inode count: %u\n", sb->s_inodes_count); | |
9221 | + fprintf(f, "Block count: %u\n", sb->s_blocks_count); | |
9222 | + fprintf(f, "Reserved block count: %u\n", sb->s_r_blocks_count); | |
9223 | + fprintf(f, "Free blocks: %u\n", sb->s_free_blocks_count); | |
9224 | + fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count); | |
9225 | + fprintf(f, "First block: %u\n", sb->s_first_data_block); | |
9226 | + fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb)); | |
9227 | + fprintf(f, "Fragment size: %u\n", EXT2_FRAG_SIZE(sb)); | |
9228 | + if (sb->s_reserved_gdt_blocks) | |
9229 | + fprintf(f, "Reserved GDT blocks: %u\n", | |
9230 | + sb->s_reserved_gdt_blocks); | |
9231 | + fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group); | |
9232 | + fprintf(f, "Fragments per group: %u\n", sb->s_frags_per_group); | |
9233 | + fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group); | |
9234 | + fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group); | |
9235 | + if (sb->s_first_meta_bg) | |
9236 | + fprintf(f, "First meta block group: %u\n", | |
9237 | + sb->s_first_meta_bg); | |
9238 | + if (sb->s_mkfs_time) { | |
9239 | + tm = sb->s_mkfs_time; | |
9240 | + fprintf(f, "Filesystem created: %s", ctime(&tm)); | |
9241 | + } | |
9242 | + tm = sb->s_mtime; | |
9243 | + fprintf(f, "Last mount time: %s", | |
9244 | + sb->s_mtime ? ctime(&tm) : "n/a\n"); | |
9245 | + tm = sb->s_wtime; | |
9246 | + fprintf(f, "Last write time: %s", ctime(&tm)); | |
9247 | + fprintf(f, "Mount count: %u\n", sb->s_mnt_count); | |
9248 | + fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count); | |
9249 | + tm = sb->s_lastcheck; | |
9250 | + fprintf(f, "Last checked: %s", ctime(&tm)); | |
9251 | + fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval, | |
9252 | + interval_string(sb->s_checkinterval)); | |
9253 | + if (sb->s_checkinterval) | |
9254 | + { | |
9255 | + time_t next; | |
9256 | + | |
9257 | + next = sb->s_lastcheck + sb->s_checkinterval; | |
9258 | + fprintf(f, "Next check after: %s", ctime(&next)); | |
9259 | + } | |
9260 | + fprintf(f, "Reserved blocks uid: "); | |
9261 | + print_user(sb->s_def_resuid, f); | |
9262 | + fprintf(f, "Reserved blocks gid: "); | |
9263 | + print_group(sb->s_def_resgid, f); | |
9264 | + if (sb->s_rev_level >= EXT2_DYNAMIC_REV) { | |
9265 | + fprintf(f, "First inode: %d\n", sb->s_first_ino); | |
9266 | + fprintf(f, "Inode size: %d\n", sb->s_inode_size); | |
9267 | + } | |
9268 | + if (!e2p_is_null_uuid(sb->s_journal_uuid)) | |
9269 | + fprintf(f, "Journal UUID: %s\n", | |
9270 | + e2p_uuid2str(sb->s_journal_uuid)); | |
9271 | + if (sb->s_journal_inum) | |
9272 | + fprintf(f, "Journal inode: %u\n", | |
9273 | + sb->s_journal_inum); | |
9274 | + if (sb->s_journal_dev) | |
9275 | + fprintf(f, "Journal device: 0x%04x\n", | |
9276 | + sb->s_journal_dev); | |
9277 | + if (sb->s_last_orphan) | |
9278 | + fprintf(f, "First orphan inode: %u\n", | |
9279 | + sb->s_last_orphan); | |
9280 | + if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) || | |
9281 | + sb->s_def_hash_version) | |
9282 | + fprintf(f, "Default directory hash: %s\n", | |
9283 | + e2p_hash2string(sb->s_def_hash_version)); | |
9284 | + if (!e2p_is_null_uuid(sb->s_hash_seed)) | |
9285 | + fprintf(f, "Directory Hash Seed: %s\n", | |
9286 | + e2p_uuid2str(sb->s_hash_seed)); | |
9287 | + if (sb->s_jnl_backup_type) { | |
9288 | + fprintf(f, "Journal backup: "); | |
9289 | + switch (sb->s_jnl_backup_type) { | |
9290 | + case 1: | |
9291 | + fprintf(f, "inode blocks\n"); | |
9292 | + break; | |
9293 | + default: | |
9294 | + fprintf(f, "type %u\n", sb->s_jnl_backup_type); | |
9295 | + } | |
9296 | + } | |
9297 | +} | |
9298 | + | |
9299 | +void list_super (struct ext2_super_block * s) | |
9300 | +{ | |
9301 | + list_super2(s, stdout); | |
9302 | +} | |
9303 | + | |
9304 | diff -Nur busybox-1.00/e2fsprogs/e2p/mntopts.c busybox/e2fsprogs/e2p/mntopts.c | |
9305 | --- busybox-1.00/e2fsprogs/e2p/mntopts.c 1970-01-01 01:00:00.000000000 +0100 | |
9306 | +++ busybox/e2fsprogs/e2p/mntopts.c 2005-06-04 08:20:15.000000000 +0200 | |
9307 | @@ -0,0 +1,136 @@ | |
9308 | +/* | |
9309 | + * mountopts.c --- convert between default mount options and strings | |
9310 | + * | |
9311 | + * Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu> | |
9312 | + * | |
9313 | + * This file can be redistributed under the terms of the GNU Library General | |
9314 | + * Public License | |
9315 | + * | |
9316 | + */ | |
9317 | + | |
9318 | +#include <stdio.h> | |
9319 | +#include <stdlib.h> | |
9320 | +#include <string.h> | |
9321 | +#include <ctype.h> | |
9322 | +#include <errno.h> | |
9323 | + | |
9324 | +#include "e2p.h" | |
9325 | + | |
9326 | +struct mntopt { | |
9327 | + unsigned int mask; | |
9328 | + const char *string; | |
9329 | +}; | |
9330 | + | |
9331 | +static struct mntopt mntopt_list[] = { | |
9332 | + { EXT2_DEFM_DEBUG, "debug" }, | |
9333 | + { EXT2_DEFM_BSDGROUPS, "bsdgroups" }, | |
9334 | + { EXT2_DEFM_XATTR_USER, "user_xattr" }, | |
9335 | + { EXT2_DEFM_ACL, "acl" }, | |
9336 | + { EXT2_DEFM_UID16, "uid16" }, | |
9337 | + { EXT3_DEFM_JMODE_DATA, "journal_data" }, | |
9338 | + { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" }, | |
9339 | + { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" }, | |
9340 | + { 0, 0 }, | |
9341 | +}; | |
9342 | + | |
9343 | +const char *e2p_mntopt2string(unsigned int mask) | |
9344 | +{ | |
9345 | + struct mntopt *f; | |
9346 | + static char buf[20]; | |
9347 | + int fnum; | |
9348 | + | |
9349 | + for (f = mntopt_list; f->string; f++) { | |
9350 | + if (mask == f->mask) | |
9351 | + return f->string; | |
9352 | + } | |
9353 | + for (fnum = 0; mask >>= 1; fnum++); | |
9354 | + sprintf(buf, "MNTOPT_%d", fnum); | |
9355 | + return buf; | |
9356 | +} | |
9357 | + | |
9358 | +int e2p_string2mntopt(char *string, unsigned int *mask) | |
9359 | +{ | |
9360 | + struct mntopt *f; | |
9361 | + char *eptr; | |
9362 | + int num; | |
9363 | + | |
9364 | + for (f = mntopt_list; f->string; f++) { | |
9365 | + if (!strcasecmp(string, f->string)) { | |
9366 | + *mask = f->mask; | |
9367 | + return 0; | |
9368 | + } | |
9369 | + } | |
9370 | + if (strncasecmp(string, "MNTOPT_", 8)) | |
9371 | + return 1; | |
9372 | + | |
9373 | + if (string[8] == 0) | |
9374 | + return 1; | |
9375 | + num = strtol(string+8, &eptr, 10); | |
9376 | + if (num > 32 || num < 0) | |
9377 | + return 1; | |
9378 | + if (*eptr) | |
9379 | + return 1; | |
9380 | + *mask = 1 << num; | |
9381 | + return 0; | |
9382 | +} | |
9383 | + | |
9384 | +static char *skip_over_blanks(char *cp) | |
9385 | +{ | |
9386 | + while (*cp && isspace(*cp)) | |
9387 | + cp++; | |
9388 | + return cp; | |
9389 | +} | |
9390 | + | |
9391 | +static char *skip_over_word(char *cp) | |
9392 | +{ | |
9393 | + while (*cp && !isspace(*cp) && *cp != ',') | |
9394 | + cp++; | |
9395 | + return cp; | |
9396 | +} | |
9397 | + | |
9398 | +/* | |
9399 | + * Edit a mntopt set array as requested by the user. The ok | |
9400 | + * parameter, if non-zero, allows the application to limit what | |
9401 | + * mntopts the user is allowed to set or clear using this function. | |
9402 | + */ | |
9403 | +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok) | |
9404 | +{ | |
9405 | + char *cp, *buf, *next; | |
9406 | + int neg; | |
9407 | + unsigned int mask; | |
9408 | + | |
9409 | + buf = malloc(strlen(str)+1); | |
9410 | + if (!buf) | |
9411 | + return 1; | |
9412 | + strcpy(buf, str); | |
9413 | + cp = buf; | |
9414 | + while (cp && *cp) { | |
9415 | + neg = 0; | |
9416 | + cp = skip_over_blanks(cp); | |
9417 | + next = skip_over_word(cp); | |
9418 | + if (*next == 0) | |
9419 | + next = 0; | |
9420 | + else | |
9421 | + *next = 0; | |
9422 | + switch (*cp) { | |
9423 | + case '-': | |
9424 | + case '^': | |
9425 | + neg++; | |
9426 | + case '+': | |
9427 | + cp++; | |
9428 | + break; | |
9429 | + } | |
9430 | + if (e2p_string2mntopt(cp, &mask)) | |
9431 | + return 1; | |
9432 | + if (ok && !(ok & mask)) | |
9433 | + return 1; | |
9434 | + if (mask & EXT3_DEFM_JMODE) | |
9435 | + *mntopts &= ~EXT3_DEFM_JMODE; | |
9436 | + if (neg) | |
9437 | + *mntopts &= ~mask; | |
9438 | + else | |
9439 | + *mntopts |= mask; | |
9440 | + cp = next ? next+1 : 0; | |
9441 | + } | |
9442 | + return 0; | |
9443 | +} | |
9444 | diff -Nur busybox-1.00/e2fsprogs/e2p/ostype.c busybox/e2fsprogs/e2p/ostype.c | |
9445 | --- busybox-1.00/e2fsprogs/e2p/ostype.c 1970-01-01 01:00:00.000000000 +0100 | |
9446 | +++ busybox/e2fsprogs/e2p/ostype.c 2005-06-04 08:20:15.000000000 +0200 | |
9447 | @@ -0,0 +1,73 @@ | |
9448 | +/* | |
9449 | + * getostype.c - Get the Filesystem OS type | |
9450 | + * | |
9451 | + * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu> | |
9452 | + * | |
9453 | + * This file can be redistributed under the terms of the GNU Library General | |
9454 | + * Public License | |
9455 | + */ | |
9456 | + | |
9457 | +#include "e2p.h" | |
9458 | +#include <string.h> | |
9459 | + | |
9460 | +const char *os_tab[] = | |
9461 | + { "Linux", | |
9462 | + "Hurd", | |
9463 | + "Masix", | |
9464 | + "FreeBSD", | |
9465 | + "Lites", | |
9466 | + 0 }; | |
9467 | + | |
9468 | +/* | |
9469 | + * Convert an os_type to a string | |
9470 | + */ | |
9471 | +char *e2p_os2string(int os_type) | |
9472 | +{ | |
9473 | + const char *os; | |
9474 | + char *ret; | |
9475 | + | |
9476 | + if (os_type <= EXT2_OS_LITES) | |
9477 | + os = os_tab[os_type]; | |
9478 | + else | |
9479 | + os = "(unknown os)"; | |
9480 | + | |
9481 | + ret = malloc(strlen(os)+1); | |
9482 | + strcpy(ret, os); | |
9483 | + return ret; | |
9484 | +} | |
9485 | + | |
9486 | +/* | |
9487 | + * Convert an os_type to a string | |
9488 | + */ | |
9489 | +int e2p_string2os(char *str) | |
9490 | +{ | |
9491 | + const char **cpp; | |
9492 | + int i = 0; | |
9493 | + | |
9494 | + for (cpp = os_tab; *cpp; cpp++, i++) { | |
9495 | + if (!strcasecmp(str, *cpp)) | |
9496 | + return i; | |
9497 | + } | |
9498 | + return -1; | |
9499 | +} | |
9500 | + | |
9501 | +#ifdef TEST_PROGRAM | |
9502 | +int main(int argc, char **argv) | |
9503 | +{ | |
9504 | + char *s; | |
9505 | + int i, os; | |
9506 | + | |
9507 | + for (i=0; i <= EXT2_OS_LITES; i++) { | |
9508 | + s = e2p_os2string(i); | |
9509 | + os = e2p_string2os(s); | |
9510 | + printf("%d: %s (%d)\n", i, s, os); | |
9511 | + if (i != os) { | |
9512 | + fprintf(stderr, "Failure!\n"); | |
9513 | + exit(1); | |
9514 | + } | |
9515 | + } | |
9516 | + exit(0); | |
9517 | +} | |
9518 | +#endif | |
9519 | + | |
9520 | + | |
9521 | diff -Nur busybox-1.00/e2fsprogs/e2p/parse_num.c busybox/e2fsprogs/e2p/parse_num.c | |
9522 | --- busybox-1.00/e2fsprogs/e2p/parse_num.c 1970-01-01 01:00:00.000000000 +0100 | |
9523 | +++ busybox/e2fsprogs/e2p/parse_num.c 2005-06-04 08:20:15.000000000 +0200 | |
9524 | @@ -0,0 +1,64 @@ | |
9525 | +/* | |
9526 | + * parse_num.c - Parse the number of blocks | |
9527 | + * | |
9528 | + * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu> | |
9529 | + * | |
9530 | + * This file can be redistributed under the terms of the GNU Library General | |
9531 | + * Public License | |
9532 | + */ | |
9533 | + | |
9534 | +#include "e2p.h" | |
9535 | + | |
9536 | +#include <stdlib.h> | |
9537 | + | |
9538 | +unsigned long parse_num_blocks(const char *arg, int log_block_size) | |
9539 | +{ | |
9540 | + char *p; | |
9541 | + unsigned long long num; | |
9542 | + | |
9543 | + num = strtoull(arg, &p, 0); | |
9544 | + | |
9545 | + if (p[0] && p[1]) | |
9546 | + return 0; | |
9547 | + | |
9548 | + switch (*p) { /* Using fall-through logic */ | |
9549 | + case 'T': case 't': | |
9550 | + num <<= 10; | |
9551 | + case 'G': case 'g': | |
9552 | + num <<= 10; | |
9553 | + case 'M': case 'm': | |
9554 | + num <<= 10; | |
9555 | + case 'K': case 'k': | |
9556 | + num >>= log_block_size; | |
9557 | + break; | |
9558 | + case 's': | |
9559 | + num >>= 1; | |
9560 | + break; | |
9561 | + case '\0': | |
9562 | + break; | |
9563 | + default: | |
9564 | + return 0; | |
9565 | + } | |
9566 | + return num; | |
9567 | +} | |
9568 | + | |
9569 | +#ifdef DEBUG | |
9570 | +#include <unistd.h> | |
9571 | +#include <stdio.h> | |
9572 | + | |
9573 | +main(int argc, char **argv) | |
9574 | +{ | |
9575 | + unsigned long num; | |
9576 | + int log_block_size = 0; | |
9577 | + | |
9578 | + if (argc != 2) { | |
9579 | + fprintf(stderr, "Usage: %s arg\n", argv[0]); | |
9580 | + exit(1); | |
9581 | + } | |
9582 | + | |
9583 | + num = parse_num_blocks(argv[1], log_block_size); | |
9584 | + | |
9585 | + printf("Parsed number: %lu\n", num); | |
9586 | + exit(0); | |
9587 | +} | |
9588 | +#endif | |
9589 | diff -Nur busybox-1.00/e2fsprogs/e2p/pe.c busybox/e2fsprogs/e2p/pe.c | |
9590 | --- busybox-1.00/e2fsprogs/e2p/pe.c 1970-01-01 01:00:00.000000000 +0100 | |
9591 | +++ busybox/e2fsprogs/e2p/pe.c 2005-06-04 08:20:15.000000000 +0200 | |
9592 | @@ -0,0 +1,37 @@ | |
9593 | +/* | |
9594 | + * pe.c - Print a second extended filesystem errors behavior | |
9595 | + * | |
9596 | + * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> | |
9597 | + * Laboratoire MASI, Institut Blaise Pascal | |
9598 | + * Universite Pierre et Marie Curie (Paris VI) | |
9599 | + * | |
9600 | + * This file can be redistributed under the terms of the GNU Library General | |
9601 | + * Public License | |
9602 | + */ | |
9603 | + | |
9604 | +/* | |
9605 | + * History: | |
9606 | + * 94/01/09 - Creation | |
9607 | + */ | |
9608 | + | |
9609 | +#include <stdio.h> | |
9610 | + | |
9611 | +#include "e2p.h" | |
9612 | + | |
9613 | +void print_fs_errors (FILE * f, unsigned short errors) | |
9614 | +{ | |
9615 | + switch (errors) | |
9616 | + { | |
9617 | + case EXT2_ERRORS_CONTINUE: | |
9618 | + fprintf (f, "Continue"); | |
9619 | + break; | |
9620 | + case EXT2_ERRORS_RO: | |
9621 | + fprintf (f, "Remount read-only"); | |
9622 | + break; | |
9623 | + case EXT2_ERRORS_PANIC: | |
9624 | + fprintf (f, "Panic"); | |
9625 | + break; | |
9626 | + default: | |
9627 | + fprintf (f, "Unknown (continue)"); | |
9628 | + } | |
9629 | +} | |
9630 | diff -Nur busybox-1.00/e2fsprogs/e2p/pf.c busybox/e2fsprogs/e2p/pf.c | |
9631 | --- busybox-1.00/e2fsprogs/e2p/pf.c 1970-01-01 01:00:00.000000000 +0100 | |
9632 | +++ busybox/e2fsprogs/e2p/pf.c 2005-06-04 08:20:15.000000000 +0200 | |
9633 | @@ -0,0 +1,74 @@ | |
9634 | +/* | |
9635 | + * pf.c - Print file attributes on an ext2 file system | |
9636 | + * | |
9637 | + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> | |
9638 | + * Laboratoire MASI, Institut Blaise Pascal | |
9639 | + * Universite Pierre et Marie Curie (Paris VI) | |
9640 | + * | |
9641 | + * This file can be redistributed under the terms of the GNU Library General | |
9642 | + * Public License | |
9643 | + */ | |
9644 | + | |
9645 | +/* | |
9646 | + * History: | |
9647 | + * 93/10/30 - Creation | |
9648 | + */ | |
9649 | + | |
9650 | +#include <stdio.h> | |
9651 | + | |
9652 | +#include "e2p.h" | |
9653 | + | |
9654 | +struct flags_name { | |
9655 | + unsigned long flag; | |
9656 | + const char *short_name; | |
9657 | + const char *long_name; | |
9658 | +}; | |
9659 | + | |
9660 | +static struct flags_name flags_array[] = { | |
9661 | + { EXT2_SECRM_FL, "s", "Secure_Deletion" }, | |
9662 | + { EXT2_UNRM_FL, "u" , "Undelete" }, | |
9663 | + { EXT2_SYNC_FL, "S", "Synchronous_Updates" }, | |
9664 | + { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" }, | |
9665 | + { EXT2_IMMUTABLE_FL, "i", "Immutable" }, | |
9666 | + { EXT2_APPEND_FL, "a", "Append_Only" }, | |
9667 | + { EXT2_NODUMP_FL, "d", "No_Dump" }, | |
9668 | + { EXT2_NOATIME_FL, "A", "No_Atime" }, | |
9669 | + { EXT2_COMPR_FL, "c", "Compression_Requested" }, | |
9670 | +#ifdef ENABLE_COMPRESSION | |
9671 | + { EXT2_COMPRBLK_FL, "B", "Compressed_File" }, | |
9672 | + { EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" }, | |
9673 | + { EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" }, | |
9674 | + { EXT2_ECOMPR_FL, "E", "Compression_Error" }, | |
9675 | +#endif | |
9676 | + { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" }, | |
9677 | + { EXT2_INDEX_FL, "I", "Indexed_direcctory" }, | |
9678 | + { EXT2_NOTAIL_FL, "t", "No_Tailmerging" }, | |
9679 | + { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" }, | |
9680 | + { 0, NULL, NULL } | |
9681 | +}; | |
9682 | + | |
9683 | +void print_flags (FILE * f, unsigned long flags, unsigned options) | |
9684 | +{ | |
9685 | + int long_opt = (options & PFOPT_LONG); | |
9686 | + struct flags_name *fp; | |
9687 | + int first = 1; | |
9688 | + | |
9689 | + for (fp = flags_array; fp->flag != 0; fp++) { | |
9690 | + if (flags & fp->flag) { | |
9691 | + if (long_opt) { | |
9692 | + if (first) | |
9693 | + first = 0; | |
9694 | + else | |
9695 | + fputs(", ", f); | |
9696 | + fputs(fp->long_name, f); | |
9697 | + } else | |
9698 | + fputs(fp->short_name, f); | |
9699 | + } else { | |
9700 | + if (!long_opt) | |
9701 | + fputs("-", f); | |
9702 | + } | |
9703 | + } | |
9704 | + if (long_opt && first) | |
9705 | + fputs("---", f); | |
9706 | +} | |
9707 | + | |
9708 | diff -Nur busybox-1.00/e2fsprogs/e2p/ps.c busybox/e2fsprogs/e2p/ps.c | |
9709 | --- busybox-1.00/e2fsprogs/e2p/ps.c 1970-01-01 01:00:00.000000000 +0100 | |
9710 | +++ busybox/e2fsprogs/e2p/ps.c 2005-06-04 08:20:15.000000000 +0200 | |
9711 | @@ -0,0 +1,29 @@ | |
9712 | +/* | |
9713 | + * ps.c - Print filesystem state | |
9714 | + * | |
9715 | + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> | |
9716 | + * Laboratoire MASI, Institut Blaise Pascal | |
9717 | + * Universite Pierre et Marie Curie (Paris VI) | |
9718 | + * | |
9719 | + * This file can be redistributed under the terms of the GNU Library General | |
9720 | + * Public License | |
9721 | + */ | |
9722 | + | |
9723 | +/* | |
9724 | + * History: | |
9725 | + * 93/12/22 - Creation | |
9726 | + */ | |
9727 | + | |
9728 | +#include <stdio.h> | |
9729 | + | |
9730 | +#include "e2p.h" | |
9731 | + | |
9732 | +void print_fs_state (FILE * f, unsigned short state) | |
9733 | +{ | |
9734 | + if (state & EXT2_VALID_FS) | |
9735 | + fprintf (f, " clean"); | |
9736 | + else | |
9737 | + fprintf (f, " not clean"); | |
9738 | + if (state & EXT2_ERROR_FS) | |
9739 | + fprintf (f, " with errors"); | |
9740 | +} | |
9741 | diff -Nur busybox-1.00/e2fsprogs/e2p/uuid.c busybox/e2fsprogs/e2p/uuid.c | |
9742 | --- busybox-1.00/e2fsprogs/e2p/uuid.c 1970-01-01 01:00:00.000000000 +0100 | |
9743 | +++ busybox/e2fsprogs/e2p/uuid.c 2005-06-04 08:20:15.000000000 +0200 | |
9744 | @@ -0,0 +1,79 @@ | |
9745 | +/* | |
9746 | + * uuid.c -- utility routines for manipulating UUID's. | |
9747 | + */ | |
9748 | + | |
9749 | +#include <stdio.h> | |
9750 | +#include <string.h> | |
9751 | +#include <ext2fs/ext2_types.h> | |
9752 | + | |
9753 | +#include "e2p.h" | |
9754 | + | |
9755 | +struct uuid { | |
9756 | + __u32 time_low; | |
9757 | + __u16 time_mid; | |
9758 | + __u16 time_hi_and_version; | |
9759 | + __u16 clock_seq; | |
9760 | + __u8 node[6]; | |
9761 | +}; | |
9762 | + | |
9763 | +/* Returns 1 if the uuid is the NULL uuid */ | |
9764 | +int e2p_is_null_uuid(void *uu) | |
9765 | +{ | |
9766 | + __u8 *cp; | |
9767 | + int i; | |
9768 | + | |
9769 | + for (i=0, cp = uu; i < 16; i++) | |
9770 | + if (*cp) | |
9771 | + return 0; | |
9772 | + return 1; | |
9773 | +} | |
9774 | + | |
9775 | +static void e2p_unpack_uuid(void *in, struct uuid *uu) | |
9776 | +{ | |
9777 | + __u8 *ptr = in; | |
9778 | + __u32 tmp; | |
9779 | + | |
9780 | + tmp = *ptr++; | |
9781 | + tmp = (tmp << 8) | *ptr++; | |
9782 | + tmp = (tmp << 8) | *ptr++; | |
9783 | + tmp = (tmp << 8) | *ptr++; | |
9784 | + uu->time_low = tmp; | |
9785 | + | |
9786 | + tmp = *ptr++; | |
9787 | + tmp = (tmp << 8) | *ptr++; | |
9788 | + uu->time_mid = tmp; | |
9789 | + | |
9790 | + tmp = *ptr++; | |
9791 | + tmp = (tmp << 8) | *ptr++; | |
9792 | + uu->time_hi_and_version = tmp; | |
9793 | + | |
9794 | + tmp = *ptr++; | |
9795 | + tmp = (tmp << 8) | *ptr++; | |
9796 | + uu->clock_seq = tmp; | |
9797 | + | |
9798 | + memcpy(uu->node, ptr, 6); | |
9799 | +} | |
9800 | + | |
9801 | +void e2p_uuid_to_str(void *uu, char *out) | |
9802 | +{ | |
9803 | + struct uuid uuid; | |
9804 | + | |
9805 | + e2p_unpack_uuid(uu, &uuid); | |
9806 | + sprintf(out, | |
9807 | + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", | |
9808 | + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, | |
9809 | + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, | |
9810 | + uuid.node[0], uuid.node[1], uuid.node[2], | |
9811 | + uuid.node[3], uuid.node[4], uuid.node[5]); | |
9812 | +} | |
9813 | + | |
9814 | +const char *e2p_uuid2str(void *uu) | |
9815 | +{ | |
9816 | + static char buf[80]; | |
9817 | + | |
9818 | + if (e2p_is_null_uuid(uu)) | |
9819 | + return "<none>"; | |
9820 | + e2p_uuid_to_str(uu, buf); | |
9821 | + return buf; | |
9822 | +} | |
9823 | + | |
9824 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/alloc.c busybox/e2fsprogs/ext2fs/alloc.c | |
9825 | --- busybox-1.00/e2fsprogs/ext2fs/alloc.c 1970-01-01 01:00:00.000000000 +0100 | |
9826 | +++ busybox/e2fsprogs/ext2fs/alloc.c 2005-06-04 08:20:16.000000000 +0200 | |
9827 | @@ -0,0 +1,173 @@ | |
9828 | +/* | |
9829 | + * alloc.c --- allocate new inodes, blocks for ext2fs | |
9830 | + * | |
9831 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
9832 | + * | |
9833 | + * %Begin-Header% | |
9834 | + * This file may be redistributed under the terms of the GNU Public | |
9835 | + * License. | |
9836 | + * %End-Header% | |
9837 | + * | |
9838 | + */ | |
9839 | + | |
9840 | +#include <stdio.h> | |
9841 | +#if HAVE_UNISTD_H | |
9842 | +#include <unistd.h> | |
9843 | +#endif | |
9844 | +#include <time.h> | |
9845 | +#include <string.h> | |
9846 | +#if HAVE_SYS_STAT_H | |
9847 | +#include <sys/stat.h> | |
9848 | +#endif | |
9849 | +#if HAVE_SYS_TYPES_H | |
9850 | +#include <sys/types.h> | |
9851 | +#endif | |
9852 | + | |
9853 | +#include "ext2_fs.h" | |
9854 | +#include "ext2fs.h" | |
9855 | + | |
9856 | +/* | |
9857 | + * Right now, just search forward from the parent directory's block | |
9858 | + * group to find the next free inode. | |
9859 | + * | |
9860 | + * Should have a special policy for directories. | |
9861 | + */ | |
9862 | +errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, | |
9863 | + int mode EXT2FS_ATTR((unused)), | |
9864 | + ext2fs_inode_bitmap map, ext2_ino_t *ret) | |
9865 | +{ | |
9866 | + ext2_ino_t dir_group = 0; | |
9867 | + ext2_ino_t i; | |
9868 | + ext2_ino_t start_inode; | |
9869 | + | |
9870 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
9871 | + | |
9872 | + if (!map) | |
9873 | + map = fs->inode_map; | |
9874 | + if (!map) | |
9875 | + return EXT2_ET_NO_INODE_BITMAP; | |
9876 | + | |
9877 | + if (dir > 0) | |
9878 | + dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super); | |
9879 | + | |
9880 | + start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1; | |
9881 | + if (start_inode < EXT2_FIRST_INODE(fs->super)) | |
9882 | + start_inode = EXT2_FIRST_INODE(fs->super); | |
9883 | + i = start_inode; | |
9884 | + | |
9885 | + do { | |
9886 | + if (!ext2fs_fast_test_inode_bitmap(map, i)) | |
9887 | + break; | |
9888 | + i++; | |
9889 | + if (i > fs->super->s_inodes_count) | |
9890 | + i = EXT2_FIRST_INODE(fs->super); | |
9891 | + } while (i != start_inode); | |
9892 | + | |
9893 | + if (ext2fs_test_inode_bitmap(map, i)) | |
9894 | + return EXT2_ET_INODE_ALLOC_FAIL; | |
9895 | + *ret = i; | |
9896 | + return 0; | |
9897 | +} | |
9898 | + | |
9899 | +/* | |
9900 | + * Stupid algorithm --- we now just search forward starting from the | |
9901 | + * goal. Should put in a smarter one someday.... | |
9902 | + */ | |
9903 | +errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, | |
9904 | + ext2fs_block_bitmap map, blk_t *ret) | |
9905 | +{ | |
9906 | + blk_t i; | |
9907 | + | |
9908 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
9909 | + | |
9910 | + if (!map) | |
9911 | + map = fs->block_map; | |
9912 | + if (!map) | |
9913 | + return EXT2_ET_NO_BLOCK_BITMAP; | |
9914 | + if (!goal || (goal >= fs->super->s_blocks_count)) | |
9915 | + goal = fs->super->s_first_data_block; | |
9916 | + i = goal; | |
9917 | + do { | |
9918 | + if (!ext2fs_fast_test_block_bitmap(map, i)) { | |
9919 | + *ret = i; | |
9920 | + return 0; | |
9921 | + } | |
9922 | + i++; | |
9923 | + if (i >= fs->super->s_blocks_count) | |
9924 | + i = fs->super->s_first_data_block; | |
9925 | + } while (i != goal); | |
9926 | + return EXT2_ET_BLOCK_ALLOC_FAIL; | |
9927 | +} | |
9928 | + | |
9929 | +/* | |
9930 | + * This function zeros out the allocated block, and updates all of the | |
9931 | + * appropriate filesystem records. | |
9932 | + */ | |
9933 | +errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, | |
9934 | + char *block_buf, blk_t *ret) | |
9935 | +{ | |
9936 | + errcode_t retval; | |
9937 | + blk_t block; | |
9938 | + char *buf = 0; | |
9939 | + | |
9940 | + if (!block_buf) { | |
9941 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
9942 | + if (retval) | |
9943 | + return retval; | |
9944 | + block_buf = buf; | |
9945 | + } | |
9946 | + memset(block_buf, 0, fs->blocksize); | |
9947 | + | |
9948 | + if (!fs->block_map) { | |
9949 | + retval = ext2fs_read_block_bitmap(fs); | |
9950 | + if (retval) | |
9951 | + goto fail; | |
9952 | + } | |
9953 | + | |
9954 | + retval = ext2fs_new_block(fs, goal, 0, &block); | |
9955 | + if (retval) | |
9956 | + goto fail; | |
9957 | + | |
9958 | + retval = io_channel_write_blk(fs->io, block, 1, block_buf); | |
9959 | + if (retval) | |
9960 | + goto fail; | |
9961 | + | |
9962 | + ext2fs_block_alloc_stats(fs, block, +1); | |
9963 | + *ret = block; | |
9964 | + return 0; | |
9965 | + | |
9966 | +fail: | |
9967 | + if (buf) | |
9968 | + ext2fs_free_mem(&buf); | |
9969 | + return retval; | |
9970 | +} | |
9971 | + | |
9972 | +errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish, | |
9973 | + int num, ext2fs_block_bitmap map, blk_t *ret) | |
9974 | +{ | |
9975 | + blk_t b = start; | |
9976 | + | |
9977 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
9978 | + | |
9979 | + if (!map) | |
9980 | + map = fs->block_map; | |
9981 | + if (!map) | |
9982 | + return EXT2_ET_NO_BLOCK_BITMAP; | |
9983 | + if (!b) | |
9984 | + b = fs->super->s_first_data_block; | |
9985 | + if (!finish) | |
9986 | + finish = start; | |
9987 | + if (!num) | |
9988 | + num = 1; | |
9989 | + do { | |
9990 | + if (b+num-1 > fs->super->s_blocks_count) | |
9991 | + b = fs->super->s_first_data_block; | |
9992 | + if (ext2fs_fast_test_block_bitmap_range(map, b, num)) { | |
9993 | + *ret = b; | |
9994 | + return 0; | |
9995 | + } | |
9996 | + b++; | |
9997 | + } while (b != finish); | |
9998 | + return EXT2_ET_BLOCK_ALLOC_FAIL; | |
9999 | +} | |
10000 | + | |
10001 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/alloc_sb.c busybox/e2fsprogs/ext2fs/alloc_sb.c | |
10002 | --- busybox-1.00/e2fsprogs/ext2fs/alloc_sb.c 1970-01-01 01:00:00.000000000 +0100 | |
10003 | +++ busybox/e2fsprogs/ext2fs/alloc_sb.c 2005-06-04 08:20:16.000000000 +0200 | |
10004 | @@ -0,0 +1,57 @@ | |
10005 | +/* | |
10006 | + * alloc_sb.c --- Allocate the superblock and block group descriptors for a | |
10007 | + * newly initialized filesystem. Used by mke2fs when initializing a filesystem | |
10008 | + * | |
10009 | + * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o. | |
10010 | + * | |
10011 | + * %Begin-Header% | |
10012 | + * This file may be redistributed under the terms of the GNU Public | |
10013 | + * License. | |
10014 | + * %End-Header% | |
10015 | + */ | |
10016 | + | |
10017 | +#include <stdio.h> | |
10018 | +#include <string.h> | |
10019 | +#if HAVE_UNISTD_H | |
10020 | +#include <unistd.h> | |
10021 | +#endif | |
10022 | +#include <fcntl.h> | |
10023 | +#include <time.h> | |
10024 | +#if HAVE_SYS_STAT_H | |
10025 | +#include <sys/stat.h> | |
10026 | +#endif | |
10027 | +#if HAVE_SYS_TYPES_H | |
10028 | +#include <sys/types.h> | |
10029 | +#endif | |
10030 | + | |
10031 | +#include "ext2_fs.h" | |
10032 | +#include "ext2fs.h" | |
10033 | + | |
10034 | +int ext2fs_reserve_super_and_bgd(ext2_filsys fs, | |
10035 | + dgrp_t group, | |
10036 | + ext2fs_block_bitmap bmap) | |
10037 | +{ | |
10038 | + blk_t super_blk, old_desc_blk, new_desc_blk; | |
10039 | + int j, old_desc_blocks, num_blocks; | |
10040 | + | |
10041 | + num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk, | |
10042 | + &old_desc_blk, &new_desc_blk, 0); | |
10043 | + | |
10044 | + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) | |
10045 | + old_desc_blocks = fs->super->s_first_meta_bg; | |
10046 | + else | |
10047 | + old_desc_blocks = | |
10048 | + fs->desc_blocks + fs->super->s_reserved_gdt_blocks; | |
10049 | + | |
10050 | + if (super_blk || (group == 0)) | |
10051 | + ext2fs_mark_block_bitmap(bmap, super_blk); | |
10052 | + | |
10053 | + if (old_desc_blk) { | |
10054 | + for (j=0; j < old_desc_blocks; j++) | |
10055 | + ext2fs_mark_block_bitmap(bmap, old_desc_blk + j); | |
10056 | + } | |
10057 | + if (new_desc_blk) | |
10058 | + ext2fs_mark_block_bitmap(bmap, new_desc_blk); | |
10059 | + | |
10060 | + return num_blocks; | |
10061 | +} | |
10062 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/alloc_stats.c busybox/e2fsprogs/ext2fs/alloc_stats.c | |
10063 | --- busybox-1.00/e2fsprogs/ext2fs/alloc_stats.c 1970-01-01 01:00:00.000000000 +0100 | |
10064 | +++ busybox/e2fsprogs/ext2fs/alloc_stats.c 2005-06-04 08:20:16.000000000 +0200 | |
10065 | @@ -0,0 +1,52 @@ | |
10066 | +/* | |
10067 | + * alloc_stats.c --- Update allocation statistics for ext2fs | |
10068 | + * | |
10069 | + * Copyright (C) 2001 Theodore Ts'o. | |
10070 | + * | |
10071 | + * %Begin-Header% | |
10072 | + * This file may be redistributed under the terms of the GNU Public | |
10073 | + * License. | |
10074 | + * %End-Header% | |
10075 | + * | |
10076 | + */ | |
10077 | + | |
10078 | +#include <stdio.h> | |
10079 | + | |
10080 | +#include "ext2_fs.h" | |
10081 | +#include "ext2fs.h" | |
10082 | + | |
10083 | +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, | |
10084 | + int inuse, int isdir) | |
10085 | +{ | |
10086 | + int group = ext2fs_group_of_ino(fs, ino); | |
10087 | + | |
10088 | + if (inuse > 0) | |
10089 | + ext2fs_mark_inode_bitmap(fs->inode_map, ino); | |
10090 | + else | |
10091 | + ext2fs_unmark_inode_bitmap(fs->inode_map, ino); | |
10092 | + fs->group_desc[group].bg_free_inodes_count -= inuse; | |
10093 | + if (isdir) | |
10094 | + fs->group_desc[group].bg_used_dirs_count += inuse; | |
10095 | + fs->super->s_free_inodes_count -= inuse; | |
10096 | + ext2fs_mark_super_dirty(fs); | |
10097 | + ext2fs_mark_ib_dirty(fs); | |
10098 | +} | |
10099 | + | |
10100 | +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse) | |
10101 | +{ | |
10102 | + ext2fs_inode_alloc_stats2(fs, ino, inuse, 0); | |
10103 | +} | |
10104 | + | |
10105 | +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse) | |
10106 | +{ | |
10107 | + int group = ext2fs_group_of_blk(fs, blk); | |
10108 | + | |
10109 | + if (inuse > 0) | |
10110 | + ext2fs_mark_block_bitmap(fs->block_map, blk); | |
10111 | + else | |
10112 | + ext2fs_unmark_block_bitmap(fs->block_map, blk); | |
10113 | + fs->group_desc[group].bg_free_blocks_count -= inuse; | |
10114 | + fs->super->s_free_blocks_count -= inuse; | |
10115 | + ext2fs_mark_super_dirty(fs); | |
10116 | + ext2fs_mark_bb_dirty(fs); | |
10117 | +} | |
10118 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/alloc_tables.c busybox/e2fsprogs/ext2fs/alloc_tables.c | |
10119 | --- busybox-1.00/e2fsprogs/ext2fs/alloc_tables.c 1970-01-01 01:00:00.000000000 +0100 | |
10120 | +++ busybox/e2fsprogs/ext2fs/alloc_tables.c 2005-06-04 08:20:16.000000000 +0200 | |
10121 | @@ -0,0 +1,117 @@ | |
10122 | +/* | |
10123 | + * alloc_tables.c --- Allocate tables for a newly initialized | |
10124 | + * filesystem. Used by mke2fs when initializing a filesystem | |
10125 | + * | |
10126 | + * Copyright (C) 1996 Theodore Ts'o. | |
10127 | + * | |
10128 | + * %Begin-Header% | |
10129 | + * This file may be redistributed under the terms of the GNU Public | |
10130 | + * License. | |
10131 | + * %End-Header% | |
10132 | + */ | |
10133 | + | |
10134 | +#include <stdio.h> | |
10135 | +#include <string.h> | |
10136 | +#if HAVE_UNISTD_H | |
10137 | +#include <unistd.h> | |
10138 | +#endif | |
10139 | +#include <fcntl.h> | |
10140 | +#include <time.h> | |
10141 | +#if HAVE_SYS_STAT_H | |
10142 | +#include <sys/stat.h> | |
10143 | +#endif | |
10144 | +#if HAVE_SYS_TYPES_H | |
10145 | +#include <sys/types.h> | |
10146 | +#endif | |
10147 | + | |
10148 | +#include "ext2_fs.h" | |
10149 | +#include "ext2fs.h" | |
10150 | + | |
10151 | +errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, | |
10152 | + ext2fs_block_bitmap bmap) | |
10153 | +{ | |
10154 | + errcode_t retval; | |
10155 | + blk_t group_blk, start_blk, last_blk, new_blk, blk; | |
10156 | + int j; | |
10157 | + | |
10158 | + group_blk = fs->super->s_first_data_block + | |
10159 | + (group * fs->super->s_blocks_per_group); | |
10160 | + | |
10161 | + last_blk = group_blk + fs->super->s_blocks_per_group; | |
10162 | + if (last_blk >= fs->super->s_blocks_count) | |
10163 | + last_blk = fs->super->s_blocks_count - 1; | |
10164 | + | |
10165 | + if (!bmap) | |
10166 | + bmap = fs->block_map; | |
10167 | + | |
10168 | + /* | |
10169 | + * Allocate the block and inode bitmaps, if necessary | |
10170 | + */ | |
10171 | + if (fs->stride) { | |
10172 | + start_blk = group_blk + fs->inode_blocks_per_group; | |
10173 | + start_blk += ((fs->stride * group) % | |
10174 | + (last_blk - start_blk)); | |
10175 | + if (start_blk > last_blk) | |
10176 | + start_blk = group_blk; | |
10177 | + } else | |
10178 | + start_blk = group_blk; | |
10179 | + | |
10180 | + if (!fs->group_desc[group].bg_block_bitmap) { | |
10181 | + retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, | |
10182 | + 1, bmap, &new_blk); | |
10183 | + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) | |
10184 | + retval = ext2fs_get_free_blocks(fs, group_blk, | |
10185 | + last_blk, 1, bmap, &new_blk); | |
10186 | + if (retval) | |
10187 | + return retval; | |
10188 | + ext2fs_mark_block_bitmap(bmap, new_blk); | |
10189 | + fs->group_desc[group].bg_block_bitmap = new_blk; | |
10190 | + } | |
10191 | + | |
10192 | + if (!fs->group_desc[group].bg_inode_bitmap) { | |
10193 | + retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, | |
10194 | + 1, bmap, &new_blk); | |
10195 | + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) | |
10196 | + retval = ext2fs_get_free_blocks(fs, group_blk, | |
10197 | + last_blk, 1, bmap, &new_blk); | |
10198 | + if (retval) | |
10199 | + return retval; | |
10200 | + ext2fs_mark_block_bitmap(bmap, new_blk); | |
10201 | + fs->group_desc[group].bg_inode_bitmap = new_blk; | |
10202 | + } | |
10203 | + | |
10204 | + /* | |
10205 | + * Allocate the inode table | |
10206 | + */ | |
10207 | + if (!fs->group_desc[group].bg_inode_table) { | |
10208 | + retval = ext2fs_get_free_blocks(fs, group_blk, last_blk, | |
10209 | + fs->inode_blocks_per_group, | |
10210 | + bmap, &new_blk); | |
10211 | + if (retval) | |
10212 | + return retval; | |
10213 | + for (j=0, blk = new_blk; | |
10214 | + j < fs->inode_blocks_per_group; | |
10215 | + j++, blk++) | |
10216 | + ext2fs_mark_block_bitmap(bmap, blk); | |
10217 | + fs->group_desc[group].bg_inode_table = new_blk; | |
10218 | + } | |
10219 | + | |
10220 | + | |
10221 | + return 0; | |
10222 | +} | |
10223 | + | |
10224 | + | |
10225 | + | |
10226 | +errcode_t ext2fs_allocate_tables(ext2_filsys fs) | |
10227 | +{ | |
10228 | + errcode_t retval; | |
10229 | + dgrp_t i; | |
10230 | + | |
10231 | + for (i = 0; i < fs->group_desc_count; i++) { | |
10232 | + retval = ext2fs_allocate_group_table(fs, i, fs->block_map); | |
10233 | + if (retval) | |
10234 | + return retval; | |
10235 | + } | |
10236 | + return 0; | |
10237 | +} | |
10238 | + | |
10239 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/badblocks.c busybox/e2fsprogs/ext2fs/badblocks.c | |
10240 | --- busybox-1.00/e2fsprogs/ext2fs/badblocks.c 1970-01-01 01:00:00.000000000 +0100 | |
10241 | +++ busybox/e2fsprogs/ext2fs/badblocks.c 2005-06-04 08:20:16.000000000 +0200 | |
10242 | @@ -0,0 +1,327 @@ | |
10243 | +/* | |
10244 | + * badblocks.c --- routines to manipulate the bad block structure | |
10245 | + * | |
10246 | + * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. | |
10247 | + * | |
10248 | + * %Begin-Header% | |
10249 | + * This file may be redistributed under the terms of the GNU Public | |
10250 | + * License. | |
10251 | + * %End-Header% | |
10252 | + */ | |
10253 | + | |
10254 | +#include <stdio.h> | |
10255 | +#include <string.h> | |
10256 | +#if HAVE_UNISTD_H | |
10257 | +#include <unistd.h> | |
10258 | +#endif | |
10259 | +#include <fcntl.h> | |
10260 | +#include <time.h> | |
10261 | +#if HAVE_SYS_STAT_H | |
10262 | +#include <sys/stat.h> | |
10263 | +#endif | |
10264 | +#if HAVE_SYS_TYPES_H | |
10265 | +#include <sys/types.h> | |
10266 | +#endif | |
10267 | + | |
10268 | +#include "ext2_fs.h" | |
10269 | +#include "ext2fsP.h" | |
10270 | + | |
10271 | +/* | |
10272 | + * Helper function for making a badblocks list | |
10273 | + */ | |
10274 | +static errcode_t make_u32_list(int size, int num, __u32 *list, | |
10275 | + ext2_u32_list *ret) | |
10276 | +{ | |
10277 | + ext2_u32_list bb; | |
10278 | + errcode_t retval; | |
10279 | + | |
10280 | + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb); | |
10281 | + if (retval) | |
10282 | + return retval; | |
10283 | + memset(bb, 0, sizeof(struct ext2_struct_u32_list)); | |
10284 | + bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; | |
10285 | + bb->size = size ? size : 10; | |
10286 | + bb->num = num; | |
10287 | + retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list); | |
10288 | + if (!bb->list) { | |
10289 | + ext2fs_free_mem(&bb); | |
10290 | + return retval; | |
10291 | + } | |
10292 | + if (list) | |
10293 | + memcpy(bb->list, list, bb->size * sizeof(blk_t)); | |
10294 | + else | |
10295 | + memset(bb->list, 0, bb->size * sizeof(blk_t)); | |
10296 | + *ret = bb; | |
10297 | + return 0; | |
10298 | +} | |
10299 | + | |
10300 | + | |
10301 | +/* | |
10302 | + * This procedure creates an empty u32 list. | |
10303 | + */ | |
10304 | +errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size) | |
10305 | +{ | |
10306 | + return make_u32_list(size, 0, 0, ret); | |
10307 | +} | |
10308 | + | |
10309 | +/* | |
10310 | + * This procedure creates an empty badblocks list. | |
10311 | + */ | |
10312 | +errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) | |
10313 | +{ | |
10314 | + return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret); | |
10315 | +} | |
10316 | + | |
10317 | + | |
10318 | +/* | |
10319 | + * This procedure copies a badblocks list | |
10320 | + */ | |
10321 | +errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest) | |
10322 | +{ | |
10323 | + errcode_t retval; | |
10324 | + | |
10325 | + retval = make_u32_list(src->size, src->num, src->list, dest); | |
10326 | + if (retval) | |
10327 | + return retval; | |
10328 | + (*dest)->badblocks_flags = src->badblocks_flags; | |
10329 | + return 0; | |
10330 | +} | |
10331 | + | |
10332 | +errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, | |
10333 | + ext2_badblocks_list *dest) | |
10334 | +{ | |
10335 | + return ext2fs_u32_copy((ext2_u32_list) src, | |
10336 | + (ext2_u32_list *) dest); | |
10337 | +} | |
10338 | + | |
10339 | +/* | |
10340 | + * This procedure frees a badblocks list. | |
10341 | + * | |
10342 | + * (note: moved to closefs.c) | |
10343 | + */ | |
10344 | + | |
10345 | + | |
10346 | +/* | |
10347 | + * This procedure adds a block to a badblocks list. | |
10348 | + */ | |
10349 | +errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk) | |
10350 | +{ | |
10351 | + errcode_t retval; | |
10352 | + int i, j; | |
10353 | + unsigned long old_size; | |
10354 | + | |
10355 | + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); | |
10356 | + | |
10357 | + if (bb->num >= bb->size) { | |
10358 | + old_size = bb->size * sizeof(__u32); | |
10359 | + bb->size += 100; | |
10360 | + retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32), | |
10361 | + &bb->list); | |
10362 | + if (retval) { | |
10363 | + bb->size -= 100; | |
10364 | + return retval; | |
10365 | + } | |
10366 | + } | |
10367 | + | |
10368 | + /* | |
10369 | + * Add special case code for appending to the end of the list | |
10370 | + */ | |
10371 | + i = bb->num-1; | |
10372 | + if ((bb->num != 0) && (bb->list[i] == blk)) | |
10373 | + return 0; | |
10374 | + if ((bb->num == 0) || (bb->list[i] < blk)) { | |
10375 | + bb->list[bb->num++] = blk; | |
10376 | + return 0; | |
10377 | + } | |
10378 | + | |
10379 | + j = bb->num; | |
10380 | + for (i=0; i < bb->num; i++) { | |
10381 | + if (bb->list[i] == blk) | |
10382 | + return 0; | |
10383 | + if (bb->list[i] > blk) { | |
10384 | + j = i; | |
10385 | + break; | |
10386 | + } | |
10387 | + } | |
10388 | + for (i=bb->num; i > j; i--) | |
10389 | + bb->list[i] = bb->list[i-1]; | |
10390 | + bb->list[j] = blk; | |
10391 | + bb->num++; | |
10392 | + return 0; | |
10393 | +} | |
10394 | + | |
10395 | +errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) | |
10396 | +{ | |
10397 | + return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk); | |
10398 | +} | |
10399 | + | |
10400 | +/* | |
10401 | + * This procedure finds a particular block is on a badblocks | |
10402 | + * list. | |
10403 | + */ | |
10404 | +int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk) | |
10405 | +{ | |
10406 | + int low, high, mid; | |
10407 | + | |
10408 | + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) | |
10409 | + return -1; | |
10410 | + | |
10411 | + if (bb->num == 0) | |
10412 | + return -1; | |
10413 | + | |
10414 | + low = 0; | |
10415 | + high = bb->num-1; | |
10416 | + if (blk == bb->list[low]) | |
10417 | + return low; | |
10418 | + if (blk == bb->list[high]) | |
10419 | + return high; | |
10420 | + | |
10421 | + while (low < high) { | |
10422 | + mid = (low+high)/2; | |
10423 | + if (mid == low || mid == high) | |
10424 | + break; | |
10425 | + if (blk == bb->list[mid]) | |
10426 | + return mid; | |
10427 | + if (blk < bb->list[mid]) | |
10428 | + high = mid; | |
10429 | + else | |
10430 | + low = mid; | |
10431 | + } | |
10432 | + return -1; | |
10433 | +} | |
10434 | + | |
10435 | +/* | |
10436 | + * This procedure tests to see if a particular block is on a badblocks | |
10437 | + * list. | |
10438 | + */ | |
10439 | +int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk) | |
10440 | +{ | |
10441 | + if (ext2fs_u32_list_find(bb, blk) < 0) | |
10442 | + return 0; | |
10443 | + else | |
10444 | + return 1; | |
10445 | +} | |
10446 | + | |
10447 | +int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) | |
10448 | +{ | |
10449 | + return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk); | |
10450 | +} | |
10451 | + | |
10452 | + | |
10453 | +/* | |
10454 | + * Remove a block from the badblock list | |
10455 | + */ | |
10456 | +int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk) | |
10457 | +{ | |
10458 | + int remloc, i; | |
10459 | + | |
10460 | + if (bb->num == 0) | |
10461 | + return -1; | |
10462 | + | |
10463 | + remloc = ext2fs_u32_list_find(bb, blk); | |
10464 | + if (remloc < 0) | |
10465 | + return -1; | |
10466 | + | |
10467 | + for (i = remloc ; i < bb->num-1; i++) | |
10468 | + bb->list[i] = bb->list[i+1]; | |
10469 | + bb->num--; | |
10470 | + return 0; | |
10471 | +} | |
10472 | + | |
10473 | +void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk) | |
10474 | +{ | |
10475 | + ext2fs_u32_list_del(bb, blk); | |
10476 | +} | |
10477 | + | |
10478 | +errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, | |
10479 | + ext2_u32_iterate *ret) | |
10480 | +{ | |
10481 | + ext2_u32_iterate iter; | |
10482 | + errcode_t retval; | |
10483 | + | |
10484 | + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); | |
10485 | + | |
10486 | + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter); | |
10487 | + if (retval) | |
10488 | + return retval; | |
10489 | + | |
10490 | + iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; | |
10491 | + iter->bb = bb; | |
10492 | + iter->ptr = 0; | |
10493 | + *ret = iter; | |
10494 | + return 0; | |
10495 | +} | |
10496 | + | |
10497 | +errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, | |
10498 | + ext2_badblocks_iterate *ret) | |
10499 | +{ | |
10500 | + return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb, | |
10501 | + (ext2_u32_iterate *) ret); | |
10502 | +} | |
10503 | + | |
10504 | + | |
10505 | +int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk) | |
10506 | +{ | |
10507 | + ext2_u32_list bb; | |
10508 | + | |
10509 | + if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) | |
10510 | + return 0; | |
10511 | + | |
10512 | + bb = iter->bb; | |
10513 | + | |
10514 | + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) | |
10515 | + return 0; | |
10516 | + | |
10517 | + if (iter->ptr < bb->num) { | |
10518 | + *blk = bb->list[iter->ptr++]; | |
10519 | + return 1; | |
10520 | + } | |
10521 | + *blk = 0; | |
10522 | + return 0; | |
10523 | +} | |
10524 | + | |
10525 | +int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) | |
10526 | +{ | |
10527 | + return ext2fs_u32_list_iterate((ext2_u32_iterate) iter, | |
10528 | + (__u32 *) blk); | |
10529 | +} | |
10530 | + | |
10531 | + | |
10532 | +void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter) | |
10533 | +{ | |
10534 | + if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) | |
10535 | + return; | |
10536 | + | |
10537 | + iter->bb = 0; | |
10538 | + ext2fs_free_mem(&iter); | |
10539 | +} | |
10540 | + | |
10541 | +void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) | |
10542 | +{ | |
10543 | + ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter); | |
10544 | +} | |
10545 | + | |
10546 | + | |
10547 | +int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2) | |
10548 | +{ | |
10549 | + EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST); | |
10550 | + EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST); | |
10551 | + | |
10552 | + if (bb1->num != bb2->num) | |
10553 | + return 0; | |
10554 | + | |
10555 | + if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0) | |
10556 | + return 0; | |
10557 | + return 1; | |
10558 | +} | |
10559 | + | |
10560 | +int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2) | |
10561 | +{ | |
10562 | + return ext2fs_u32_list_equal((ext2_u32_list) bb1, | |
10563 | + (ext2_u32_list) bb2); | |
10564 | +} | |
10565 | + | |
10566 | +int ext2fs_u32_list_count(ext2_u32_list bb) | |
10567 | +{ | |
10568 | + return bb->num; | |
10569 | +} | |
10570 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/bb_compat.c busybox/e2fsprogs/ext2fs/bb_compat.c | |
10571 | --- busybox-1.00/e2fsprogs/ext2fs/bb_compat.c 1970-01-01 01:00:00.000000000 +0100 | |
10572 | +++ busybox/e2fsprogs/ext2fs/bb_compat.c 2005-06-04 08:20:16.000000000 +0200 | |
10573 | @@ -0,0 +1,63 @@ | |
10574 | +/* | |
10575 | + * bb_compat.c --- compatibility badblocks routines | |
10576 | + * | |
10577 | + * Copyright (C) 1997 Theodore Ts'o. | |
10578 | + * | |
10579 | + * %Begin-Header% | |
10580 | + * This file may be redistributed under the terms of the GNU Public | |
10581 | + * License. | |
10582 | + * %End-Header% | |
10583 | + */ | |
10584 | + | |
10585 | +#include <stdio.h> | |
10586 | +#include <string.h> | |
10587 | +#if HAVE_UNISTD_H | |
10588 | +#include <unistd.h> | |
10589 | +#endif | |
10590 | +#include <fcntl.h> | |
10591 | +#include <time.h> | |
10592 | +#if HAVE_SYS_STAT_H | |
10593 | +#include <sys/stat.h> | |
10594 | +#endif | |
10595 | +#if HAVE_SYS_TYPES_H | |
10596 | +#include <sys/types.h> | |
10597 | +#endif | |
10598 | + | |
10599 | +#include "ext2_fs.h" | |
10600 | +#include "ext2fsP.h" | |
10601 | + | |
10602 | +errcode_t badblocks_list_create(badblocks_list *ret, int size) | |
10603 | +{ | |
10604 | + return ext2fs_badblocks_list_create(ret, size); | |
10605 | +} | |
10606 | + | |
10607 | +void badblocks_list_free(badblocks_list bb) | |
10608 | +{ | |
10609 | + ext2fs_badblocks_list_free(bb); | |
10610 | +} | |
10611 | + | |
10612 | +errcode_t badblocks_list_add(badblocks_list bb, blk_t blk) | |
10613 | +{ | |
10614 | + return ext2fs_badblocks_list_add(bb, blk); | |
10615 | +} | |
10616 | + | |
10617 | +int badblocks_list_test(badblocks_list bb, blk_t blk) | |
10618 | +{ | |
10619 | + return ext2fs_badblocks_list_test(bb, blk); | |
10620 | +} | |
10621 | + | |
10622 | +errcode_t badblocks_list_iterate_begin(badblocks_list bb, | |
10623 | + badblocks_iterate *ret) | |
10624 | +{ | |
10625 | + return ext2fs_badblocks_list_iterate_begin(bb, ret); | |
10626 | +} | |
10627 | + | |
10628 | +int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk) | |
10629 | +{ | |
10630 | + return ext2fs_badblocks_list_iterate(iter, blk); | |
10631 | +} | |
10632 | + | |
10633 | +void badblocks_list_iterate_end(badblocks_iterate iter) | |
10634 | +{ | |
10635 | + ext2fs_badblocks_list_iterate_end(iter); | |
10636 | +} | |
10637 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/bb_inode.c busybox/e2fsprogs/ext2fs/bb_inode.c | |
10638 | --- busybox-1.00/e2fsprogs/ext2fs/bb_inode.c 1970-01-01 01:00:00.000000000 +0100 | |
10639 | +++ busybox/e2fsprogs/ext2fs/bb_inode.c 2005-06-04 08:20:16.000000000 +0200 | |
10640 | @@ -0,0 +1,267 @@ | |
10641 | +/* | |
10642 | + * bb_inode.c --- routines to update the bad block inode. | |
10643 | + * | |
10644 | + * WARNING: This routine modifies a lot of state in the filesystem; if | |
10645 | + * this routine returns an error, the bad block inode may be in an | |
10646 | + * inconsistent state. | |
10647 | + * | |
10648 | + * Copyright (C) 1994, 1995 Theodore Ts'o. | |
10649 | + * | |
10650 | + * %Begin-Header% | |
10651 | + * This file may be redistributed under the terms of the GNU Public | |
10652 | + * License. | |
10653 | + * %End-Header% | |
10654 | + */ | |
10655 | + | |
10656 | +#include <stdio.h> | |
10657 | +#include <string.h> | |
10658 | +#if HAVE_UNISTD_H | |
10659 | +#include <unistd.h> | |
10660 | +#endif | |
10661 | +#include <fcntl.h> | |
10662 | +#include <time.h> | |
10663 | +#if HAVE_SYS_STAT_H | |
10664 | +#include <sys/stat.h> | |
10665 | +#endif | |
10666 | +#if HAVE_SYS_TYPES_H | |
10667 | +#include <sys/types.h> | |
10668 | +#endif | |
10669 | + | |
10670 | +#include "ext2_fs.h" | |
10671 | +#include "ext2fs.h" | |
10672 | + | |
10673 | +struct set_badblock_record { | |
10674 | + ext2_badblocks_iterate bb_iter; | |
10675 | + int bad_block_count; | |
10676 | + blk_t *ind_blocks; | |
10677 | + int max_ind_blocks; | |
10678 | + int ind_blocks_size; | |
10679 | + int ind_blocks_ptr; | |
10680 | + char *block_buf; | |
10681 | + errcode_t err; | |
10682 | +}; | |
10683 | + | |
10684 | +static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, | |
10685 | + e2_blkcnt_t blockcnt, | |
10686 | + blk_t ref_block, int ref_offset, | |
10687 | + void *priv_data); | |
10688 | +static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, | |
10689 | + e2_blkcnt_t blockcnt, | |
10690 | + blk_t ref_block, int ref_offset, | |
10691 | + void *priv_data); | |
10692 | + | |
10693 | +/* | |
10694 | + * Given a bad blocks bitmap, update the bad blocks inode to reflect | |
10695 | + * the map. | |
10696 | + */ | |
10697 | +errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) | |
10698 | +{ | |
10699 | + errcode_t retval; | |
10700 | + struct set_badblock_record rec; | |
10701 | + struct ext2_inode inode; | |
10702 | + | |
10703 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
10704 | + | |
10705 | + if (!fs->block_map) | |
10706 | + return EXT2_ET_NO_BLOCK_BITMAP; | |
10707 | + | |
10708 | + rec.bad_block_count = 0; | |
10709 | + rec.ind_blocks_size = rec.ind_blocks_ptr = 0; | |
10710 | + rec.max_ind_blocks = 10; | |
10711 | + retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t), | |
10712 | + &rec.ind_blocks); | |
10713 | + if (retval) | |
10714 | + return retval; | |
10715 | + memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t)); | |
10716 | + retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf); | |
10717 | + if (retval) | |
10718 | + goto cleanup; | |
10719 | + memset(rec.block_buf, 0, fs->blocksize); | |
10720 | + rec.err = 0; | |
10721 | + | |
10722 | + /* | |
10723 | + * First clear the old bad blocks (while saving the indirect blocks) | |
10724 | + */ | |
10725 | + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, | |
10726 | + BLOCK_FLAG_DEPTH_TRAVERSE, 0, | |
10727 | + clear_bad_block_proc, &rec); | |
10728 | + if (retval) | |
10729 | + goto cleanup; | |
10730 | + if (rec.err) { | |
10731 | + retval = rec.err; | |
10732 | + goto cleanup; | |
10733 | + } | |
10734 | + | |
10735 | + /* | |
10736 | + * Now set the bad blocks! | |
10737 | + * | |
10738 | + * First, mark the bad blocks as used. This prevents a bad | |
10739 | + * block from being used as an indirecto block for the bad | |
10740 | + * block inode (!). | |
10741 | + */ | |
10742 | + if (bb_list) { | |
10743 | + retval = ext2fs_badblocks_list_iterate_begin(bb_list, | |
10744 | + &rec.bb_iter); | |
10745 | + if (retval) | |
10746 | + goto cleanup; | |
10747 | + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, | |
10748 | + BLOCK_FLAG_APPEND, 0, | |
10749 | + set_bad_block_proc, &rec); | |
10750 | + ext2fs_badblocks_list_iterate_end(rec.bb_iter); | |
10751 | + if (retval) | |
10752 | + goto cleanup; | |
10753 | + if (rec.err) { | |
10754 | + retval = rec.err; | |
10755 | + goto cleanup; | |
10756 | + } | |
10757 | + } | |
10758 | + | |
10759 | + /* | |
10760 | + * Update the bad block inode's mod time and block count | |
10761 | + * field. | |
10762 | + */ | |
10763 | + retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); | |
10764 | + if (retval) | |
10765 | + goto cleanup; | |
10766 | + | |
10767 | + inode.i_atime = inode.i_mtime = time(0); | |
10768 | + if (!inode.i_ctime) | |
10769 | + inode.i_ctime = time(0); | |
10770 | + inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512); | |
10771 | + inode.i_size = rec.bad_block_count * fs->blocksize; | |
10772 | + | |
10773 | + retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode); | |
10774 | + if (retval) | |
10775 | + goto cleanup; | |
10776 | + | |
10777 | +cleanup: | |
10778 | + ext2fs_free_mem(&rec.ind_blocks); | |
10779 | + ext2fs_free_mem(&rec.block_buf); | |
10780 | + return retval; | |
10781 | +} | |
10782 | + | |
10783 | +/* | |
10784 | + * Helper function for update_bb_inode() | |
10785 | + * | |
10786 | + * Clear the bad blocks in the bad block inode, while saving the | |
10787 | + * indirect blocks. | |
10788 | + */ | |
10789 | +#ifdef __TURBOC__ | |
10790 | + #pragma argsused | |
10791 | +#endif | |
10792 | +static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, | |
10793 | + e2_blkcnt_t blockcnt, | |
10794 | + blk_t ref_block EXT2FS_ATTR((unused)), | |
10795 | + int ref_offset EXT2FS_ATTR((unused)), | |
10796 | + void *priv_data) | |
10797 | +{ | |
10798 | + struct set_badblock_record *rec = (struct set_badblock_record *) | |
10799 | + priv_data; | |
10800 | + errcode_t retval; | |
10801 | + unsigned long old_size; | |
10802 | + | |
10803 | + if (!*block_nr) | |
10804 | + return 0; | |
10805 | + | |
10806 | + /* | |
10807 | + * If the block number is outrageous, clear it and ignore it. | |
10808 | + */ | |
10809 | + if (*block_nr >= fs->super->s_blocks_count || | |
10810 | + *block_nr < fs->super->s_first_data_block) { | |
10811 | + *block_nr = 0; | |
10812 | + return BLOCK_CHANGED; | |
10813 | + } | |
10814 | + | |
10815 | + if (blockcnt < 0) { | |
10816 | + if (rec->ind_blocks_size >= rec->max_ind_blocks) { | |
10817 | + old_size = rec->max_ind_blocks * sizeof(blk_t); | |
10818 | + rec->max_ind_blocks += 10; | |
10819 | + retval = ext2fs_resize_mem(old_size, | |
10820 | + rec->max_ind_blocks * sizeof(blk_t), | |
10821 | + &rec->ind_blocks); | |
10822 | + if (retval) { | |
10823 | + rec->max_ind_blocks -= 10; | |
10824 | + rec->err = retval; | |
10825 | + return BLOCK_ABORT; | |
10826 | + } | |
10827 | + } | |
10828 | + rec->ind_blocks[rec->ind_blocks_size++] = *block_nr; | |
10829 | + } | |
10830 | + | |
10831 | + /* | |
10832 | + * Mark the block as unused, and update accounting information | |
10833 | + */ | |
10834 | + ext2fs_block_alloc_stats(fs, *block_nr, -1); | |
10835 | + | |
10836 | + *block_nr = 0; | |
10837 | + return BLOCK_CHANGED; | |
10838 | +} | |
10839 | + | |
10840 | + | |
10841 | +/* | |
10842 | + * Helper function for update_bb_inode() | |
10843 | + * | |
10844 | + * Set the block list in the bad block inode, using the supplied bitmap. | |
10845 | + */ | |
10846 | +#ifdef __TURBOC__ | |
10847 | + #pragma argsused | |
10848 | +#endif | |
10849 | +static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, | |
10850 | + e2_blkcnt_t blockcnt, | |
10851 | + blk_t ref_block EXT2FS_ATTR((unused)), | |
10852 | + int ref_offset EXT2FS_ATTR((unused)), | |
10853 | + void *priv_data) | |
10854 | +{ | |
10855 | + struct set_badblock_record *rec = (struct set_badblock_record *) | |
10856 | + priv_data; | |
10857 | + errcode_t retval; | |
10858 | + blk_t blk; | |
10859 | + | |
10860 | + if (blockcnt >= 0) { | |
10861 | + /* | |
10862 | + * Get the next bad block. | |
10863 | + */ | |
10864 | + if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk)) | |
10865 | + return BLOCK_ABORT; | |
10866 | + rec->bad_block_count++; | |
10867 | + } else { | |
10868 | + /* | |
10869 | + * An indirect block; fetch a block from the | |
10870 | + * previously used indirect block list. The block | |
10871 | + * most be not marked as used; if so, get another one. | |
10872 | + * If we run out of reserved indirect blocks, allocate | |
10873 | + * a new one. | |
10874 | + */ | |
10875 | + retry: | |
10876 | + if (rec->ind_blocks_ptr < rec->ind_blocks_size) { | |
10877 | + blk = rec->ind_blocks[rec->ind_blocks_ptr++]; | |
10878 | + if (ext2fs_test_block_bitmap(fs->block_map, blk)) | |
10879 | + goto retry; | |
10880 | + } else { | |
10881 | + retval = ext2fs_new_block(fs, 0, 0, &blk); | |
10882 | + if (retval) { | |
10883 | + rec->err = retval; | |
10884 | + return BLOCK_ABORT; | |
10885 | + } | |
10886 | + } | |
10887 | + retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf); | |
10888 | + if (retval) { | |
10889 | + rec->err = retval; | |
10890 | + return BLOCK_ABORT; | |
10891 | + } | |
10892 | + } | |
10893 | + | |
10894 | + /* | |
10895 | + * Update block counts | |
10896 | + */ | |
10897 | + ext2fs_block_alloc_stats(fs, blk, +1); | |
10898 | + | |
10899 | + *block_nr = blk; | |
10900 | + return BLOCK_CHANGED; | |
10901 | +} | |
10902 | + | |
10903 | + | |
10904 | + | |
10905 | + | |
10906 | + | |
10907 | + | |
10908 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/bitmaps.c busybox/e2fsprogs/ext2fs/bitmaps.c | |
10909 | --- busybox-1.00/e2fsprogs/ext2fs/bitmaps.c 1970-01-01 01:00:00.000000000 +0100 | |
10910 | +++ busybox/e2fsprogs/ext2fs/bitmaps.c 2005-06-04 08:20:16.000000000 +0200 | |
10911 | @@ -0,0 +1,212 @@ | |
10912 | +/* | |
10913 | + * bitmaps.c --- routines to read, write, and manipulate the inode and | |
10914 | + * block bitmaps. | |
10915 | + * | |
10916 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
10917 | + * | |
10918 | + * %Begin-Header% | |
10919 | + * This file may be redistributed under the terms of the GNU Public | |
10920 | + * License. | |
10921 | + * %End-Header% | |
10922 | + */ | |
10923 | + | |
10924 | +#include <stdio.h> | |
10925 | +#include <string.h> | |
10926 | +#if HAVE_UNISTD_H | |
10927 | +#include <unistd.h> | |
10928 | +#endif | |
10929 | +#include <fcntl.h> | |
10930 | +#include <time.h> | |
10931 | +#if HAVE_SYS_STAT_H | |
10932 | +#include <sys/stat.h> | |
10933 | +#endif | |
10934 | +#if HAVE_SYS_TYPES_H | |
10935 | +#include <sys/types.h> | |
10936 | +#endif | |
10937 | + | |
10938 | +#include "ext2_fs.h" | |
10939 | +#include "ext2fs.h" | |
10940 | + | |
10941 | +static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end, | |
10942 | + const char *descr, char *init_map, | |
10943 | + ext2fs_generic_bitmap *ret) | |
10944 | +{ | |
10945 | + ext2fs_generic_bitmap bitmap; | |
10946 | + errcode_t retval; | |
10947 | + size_t size; | |
10948 | + | |
10949 | + retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap), | |
10950 | + &bitmap); | |
10951 | + if (retval) | |
10952 | + return retval; | |
10953 | + | |
10954 | + bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; | |
10955 | + bitmap->fs = NULL; | |
10956 | + bitmap->start = start; | |
10957 | + bitmap->end = end; | |
10958 | + bitmap->real_end = real_end; | |
10959 | + bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK; | |
10960 | + if (descr) { | |
10961 | + retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description); | |
10962 | + if (retval) { | |
10963 | + ext2fs_free_mem(&bitmap); | |
10964 | + return retval; | |
10965 | + } | |
10966 | + strcpy(bitmap->description, descr); | |
10967 | + } else | |
10968 | + bitmap->description = 0; | |
10969 | + | |
10970 | + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); | |
10971 | + retval = ext2fs_get_mem(size, &bitmap->bitmap); | |
10972 | + if (retval) { | |
10973 | + ext2fs_free_mem(&bitmap->description); | |
10974 | + ext2fs_free_mem(&bitmap); | |
10975 | + return retval; | |
10976 | + } | |
10977 | + | |
10978 | + if (init_map) | |
10979 | + memcpy(bitmap->bitmap, init_map, size); | |
10980 | + else | |
10981 | + memset(bitmap->bitmap, 0, size); | |
10982 | + *ret = bitmap; | |
10983 | + return 0; | |
10984 | +} | |
10985 | + | |
10986 | +errcode_t ext2fs_allocate_generic_bitmap(__u32 start, | |
10987 | + __u32 end, | |
10988 | + __u32 real_end, | |
10989 | + const char *descr, | |
10990 | + ext2fs_generic_bitmap *ret) | |
10991 | +{ | |
10992 | + return make_bitmap(start, end, real_end, descr, 0, ret); | |
10993 | +} | |
10994 | + | |
10995 | +errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, | |
10996 | + ext2fs_generic_bitmap *dest) | |
10997 | +{ | |
10998 | + errcode_t retval; | |
10999 | + ext2fs_generic_bitmap new_map; | |
11000 | + | |
11001 | + retval = make_bitmap(src->start, src->end, src->real_end, | |
11002 | + src->description, src->bitmap, &new_map); | |
11003 | + if (retval) | |
11004 | + return retval; | |
11005 | + new_map->magic = src->magic; | |
11006 | + new_map->fs = src->fs; | |
11007 | + new_map->base_error_code = src->base_error_code; | |
11008 | + *dest = new_map; | |
11009 | + return 0; | |
11010 | +} | |
11011 | + | |
11012 | +void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map) | |
11013 | +{ | |
11014 | + __u32 i, j; | |
11015 | + | |
11016 | + for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++) | |
11017 | + ext2fs_set_bit(j, map->bitmap); | |
11018 | + | |
11019 | + return; | |
11020 | +} | |
11021 | + | |
11022 | +errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, | |
11023 | + const char *descr, | |
11024 | + ext2fs_inode_bitmap *ret) | |
11025 | +{ | |
11026 | + ext2fs_inode_bitmap bitmap; | |
11027 | + errcode_t retval; | |
11028 | + __u32 start, end, real_end; | |
11029 | + | |
11030 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
11031 | + | |
11032 | + fs->write_bitmaps = ext2fs_write_bitmaps; | |
11033 | + | |
11034 | + start = 1; | |
11035 | + end = fs->super->s_inodes_count; | |
11036 | + real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count); | |
11037 | + | |
11038 | + retval = ext2fs_allocate_generic_bitmap(start, end, real_end, | |
11039 | + descr, &bitmap); | |
11040 | + if (retval) | |
11041 | + return retval; | |
11042 | + | |
11043 | + bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP; | |
11044 | + bitmap->fs = fs; | |
11045 | + bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK; | |
11046 | + | |
11047 | + *ret = bitmap; | |
11048 | + return 0; | |
11049 | +} | |
11050 | + | |
11051 | +errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, | |
11052 | + const char *descr, | |
11053 | + ext2fs_block_bitmap *ret) | |
11054 | +{ | |
11055 | + ext2fs_block_bitmap bitmap; | |
11056 | + errcode_t retval; | |
11057 | + __u32 start, end, real_end; | |
11058 | + | |
11059 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
11060 | + | |
11061 | + fs->write_bitmaps = ext2fs_write_bitmaps; | |
11062 | + | |
11063 | + start = fs->super->s_first_data_block; | |
11064 | + end = fs->super->s_blocks_count-1; | |
11065 | + real_end = (EXT2_BLOCKS_PER_GROUP(fs->super) | |
11066 | + * fs->group_desc_count)-1 + start; | |
11067 | + | |
11068 | + retval = ext2fs_allocate_generic_bitmap(start, end, real_end, | |
11069 | + descr, &bitmap); | |
11070 | + if (retval) | |
11071 | + return retval; | |
11072 | + | |
11073 | + bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP; | |
11074 | + bitmap->fs = fs; | |
11075 | + bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK; | |
11076 | + | |
11077 | + *ret = bitmap; | |
11078 | + return 0; | |
11079 | +} | |
11080 | + | |
11081 | +errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, | |
11082 | + ext2_ino_t end, ext2_ino_t *oend) | |
11083 | +{ | |
11084 | + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP); | |
11085 | + | |
11086 | + if (end > bitmap->real_end) | |
11087 | + return EXT2_ET_FUDGE_INODE_BITMAP_END; | |
11088 | + if (oend) | |
11089 | + *oend = bitmap->end; | |
11090 | + bitmap->end = end; | |
11091 | + return 0; | |
11092 | +} | |
11093 | + | |
11094 | +errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, | |
11095 | + blk_t end, blk_t *oend) | |
11096 | +{ | |
11097 | + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP); | |
11098 | + | |
11099 | + if (end > bitmap->real_end) | |
11100 | + return EXT2_ET_FUDGE_BLOCK_BITMAP_END; | |
11101 | + if (oend) | |
11102 | + *oend = bitmap->end; | |
11103 | + bitmap->end = end; | |
11104 | + return 0; | |
11105 | +} | |
11106 | + | |
11107 | +void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap) | |
11108 | +{ | |
11109 | + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP)) | |
11110 | + return; | |
11111 | + | |
11112 | + memset(bitmap->bitmap, 0, | |
11113 | + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); | |
11114 | +} | |
11115 | + | |
11116 | +void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap) | |
11117 | +{ | |
11118 | + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP)) | |
11119 | + return; | |
11120 | + | |
11121 | + memset(bitmap->bitmap, 0, | |
11122 | + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); | |
11123 | +} | |
11124 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/bitops.c busybox/e2fsprogs/ext2fs/bitops.c | |
11125 | --- busybox-1.00/e2fsprogs/ext2fs/bitops.c 1970-01-01 01:00:00.000000000 +0100 | |
11126 | +++ busybox/e2fsprogs/ext2fs/bitops.c 2005-06-04 08:20:16.000000000 +0200 | |
11127 | @@ -0,0 +1,91 @@ | |
11128 | +/* | |
11129 | + * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined | |
11130 | + * routines. | |
11131 | + * | |
11132 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
11133 | + * | |
11134 | + * %Begin-Header% | |
11135 | + * This file may be redistributed under the terms of the GNU Public | |
11136 | + * License. | |
11137 | + * %End-Header% | |
11138 | + */ | |
11139 | + | |
11140 | +#include <stdio.h> | |
11141 | +#if HAVE_SYS_TYPES_H | |
11142 | +#include <sys/types.h> | |
11143 | +#endif | |
11144 | + | |
11145 | +#include "ext2_fs.h" | |
11146 | +#include "ext2fs.h" | |
11147 | + | |
11148 | +#ifndef _EXT2_HAVE_ASM_BITOPS_ | |
11149 | + | |
11150 | +/* | |
11151 | + * For the benefit of those who are trying to port Linux to another | |
11152 | + * architecture, here are some C-language equivalents. You should | |
11153 | + * recode these in the native assmebly language, if at all possible. | |
11154 | + * | |
11155 | + * C language equivalents written by Theodore Ts'o, 9/26/92. | |
11156 | + * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian | |
11157 | + * systems, as well as non-32 bit systems. | |
11158 | + */ | |
11159 | + | |
11160 | +int ext2fs_set_bit(int nr,void * addr) | |
11161 | +{ | |
11162 | + int mask, retval; | |
11163 | + unsigned char *ADDR = (unsigned char *) addr; | |
11164 | + | |
11165 | + ADDR += nr >> 3; | |
11166 | + mask = 1 << (nr & 0x07); | |
11167 | + retval = mask & *ADDR; | |
11168 | + *ADDR |= mask; | |
11169 | + return retval; | |
11170 | +} | |
11171 | + | |
11172 | +int ext2fs_clear_bit(int nr, void * addr) | |
11173 | +{ | |
11174 | + int mask, retval; | |
11175 | + unsigned char *ADDR = (unsigned char *) addr; | |
11176 | + | |
11177 | + ADDR += nr >> 3; | |
11178 | + mask = 1 << (nr & 0x07); | |
11179 | + retval = mask & *ADDR; | |
11180 | + *ADDR &= ~mask; | |
11181 | + return retval; | |
11182 | +} | |
11183 | + | |
11184 | +int ext2fs_test_bit(int nr, const void * addr) | |
11185 | +{ | |
11186 | + int mask; | |
11187 | + const unsigned char *ADDR = (const unsigned char *) addr; | |
11188 | + | |
11189 | + ADDR += nr >> 3; | |
11190 | + mask = 1 << (nr & 0x07); | |
11191 | + return (mask & *ADDR); | |
11192 | +} | |
11193 | + | |
11194 | +#endif /* !_EXT2_HAVE_ASM_BITOPS_ */ | |
11195 | + | |
11196 | +void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, | |
11197 | + const char *description) | |
11198 | +{ | |
11199 | +#ifndef OMIT_COM_ERR | |
11200 | + if (description) | |
11201 | + com_err(0, errcode, "#%lu for %s", arg, description); | |
11202 | + else | |
11203 | + com_err(0, errcode, "#%lu", arg); | |
11204 | +#endif | |
11205 | +} | |
11206 | + | |
11207 | +void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, | |
11208 | + int code, unsigned long arg) | |
11209 | +{ | |
11210 | +#ifndef OMIT_COM_ERR | |
11211 | + if (bitmap->description) | |
11212 | + com_err(0, bitmap->base_error_code+code, | |
11213 | + "#%lu for %s", arg, bitmap->description); | |
11214 | + else | |
11215 | + com_err(0, bitmap->base_error_code + code, "#%lu", arg); | |
11216 | +#endif | |
11217 | +} | |
11218 | + | |
11219 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/bitops.h busybox/e2fsprogs/ext2fs/bitops.h | |
11220 | --- busybox-1.00/e2fsprogs/ext2fs/bitops.h 1970-01-01 01:00:00.000000000 +0100 | |
11221 | +++ busybox/e2fsprogs/ext2fs/bitops.h 2005-06-04 08:20:16.000000000 +0200 | |
11222 | @@ -0,0 +1,617 @@ | |
11223 | +/* | |
11224 | + * bitops.h --- Bitmap frobbing code. The byte swapping routines are | |
11225 | + * also included here. | |
11226 | + * | |
11227 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
11228 | + * | |
11229 | + * %Begin-Header% | |
11230 | + * This file may be redistributed under the terms of the GNU Public | |
11231 | + * License. | |
11232 | + * %End-Header% | |
11233 | + * | |
11234 | + * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992, | |
11235 | + * Linus Torvalds. | |
11236 | + */ | |
11237 | + | |
11238 | + | |
11239 | +extern int ext2fs_set_bit(int nr,void * addr); | |
11240 | +extern int ext2fs_clear_bit(int nr, void * addr); | |
11241 | +extern int ext2fs_test_bit(int nr, const void * addr); | |
11242 | +extern __u16 ext2fs_swab16(__u16 val); | |
11243 | +extern __u32 ext2fs_swab32(__u32 val); | |
11244 | + | |
11245 | +#ifdef WORDS_BIGENDIAN | |
11246 | +#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x)) | |
11247 | +#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x)) | |
11248 | +#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x)) | |
11249 | +#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x)) | |
11250 | +#define ext2fs_cpu_to_be32(x) ((__u32)(x)) | |
11251 | +#define ext2fs_be32_to_cpu(x) ((__u32)(x)) | |
11252 | +#define ext2fs_cpu_to_be16(x) ((__u16)(x)) | |
11253 | +#define ext2fs_be16_to_cpu(x) ((__u16)(x)) | |
11254 | +#else | |
11255 | +#define ext2fs_cpu_to_le32(x) ((__u32)(x)) | |
11256 | +#define ext2fs_le32_to_cpu(x) ((__u32)(x)) | |
11257 | +#define ext2fs_cpu_to_le16(x) ((__u16)(x)) | |
11258 | +#define ext2fs_le16_to_cpu(x) ((__u16)(x)) | |
11259 | +#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x)) | |
11260 | +#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x)) | |
11261 | +#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x)) | |
11262 | +#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x)) | |
11263 | +#endif | |
11264 | + | |
11265 | +/* | |
11266 | + * EXT2FS bitmap manipulation routines. | |
11267 | + */ | |
11268 | + | |
11269 | +/* Support for sending warning messages from the inline subroutines */ | |
11270 | +extern const char *ext2fs_block_string; | |
11271 | +extern const char *ext2fs_inode_string; | |
11272 | +extern const char *ext2fs_mark_string; | |
11273 | +extern const char *ext2fs_unmark_string; | |
11274 | +extern const char *ext2fs_test_string; | |
11275 | +extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, | |
11276 | + const char *description); | |
11277 | +extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, | |
11278 | + int code, unsigned long arg); | |
11279 | + | |
11280 | +extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); | |
11281 | +extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, | |
11282 | + blk_t block); | |
11283 | +extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); | |
11284 | + | |
11285 | +extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); | |
11286 | +extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11287 | + ext2_ino_t inode); | |
11288 | +extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); | |
11289 | + | |
11290 | +extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, | |
11291 | + blk_t block); | |
11292 | +extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, | |
11293 | + blk_t block); | |
11294 | +extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, | |
11295 | + blk_t block); | |
11296 | + | |
11297 | +extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11298 | + ext2_ino_t inode); | |
11299 | +extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11300 | + ext2_ino_t inode); | |
11301 | +extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11302 | + ext2_ino_t inode); | |
11303 | +extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap); | |
11304 | +extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap); | |
11305 | +extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap); | |
11306 | +extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap); | |
11307 | + | |
11308 | +extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11309 | + blk_t block, int num); | |
11310 | +extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11311 | + blk_t block, int num); | |
11312 | +extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11313 | + blk_t block, int num); | |
11314 | +extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11315 | + blk_t block, int num); | |
11316 | +extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11317 | + blk_t block, int num); | |
11318 | +extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11319 | + blk_t block, int num); | |
11320 | +extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map); | |
11321 | + | |
11322 | +/* These two routines moved to gen_bitmap.c */ | |
11323 | +extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, | |
11324 | + __u32 bitno); | |
11325 | +extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, | |
11326 | + blk_t bitno); | |
11327 | +/* | |
11328 | + * The inline routines themselves... | |
11329 | + * | |
11330 | + * If NO_INLINE_FUNCS is defined, then we won't try to do inline | |
11331 | + * functions at all; they will be included as normal functions in | |
11332 | + * inline.c | |
11333 | + */ | |
11334 | +#ifdef NO_INLINE_FUNCS | |
11335 | +#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \ | |
11336 | + defined(__i586__) || defined(__mc68000__) || \ | |
11337 | + defined(__sparc__))) | |
11338 | + /* This prevents bitops.c from trying to include the C */ | |
11339 | + /* function version of these functions */ | |
11340 | +#define _EXT2_HAVE_ASM_BITOPS_ | |
11341 | +#endif | |
11342 | +#endif /* NO_INLINE_FUNCS */ | |
11343 | + | |
11344 | +#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) | |
11345 | +#ifdef INCLUDE_INLINE_FUNCS | |
11346 | +#define _INLINE_ extern | |
11347 | +#else | |
11348 | +#ifdef __GNUC__ | |
11349 | +#define _INLINE_ extern __inline__ | |
11350 | +#else /* For Watcom C */ | |
11351 | +#define _INLINE_ extern inline | |
11352 | +#endif | |
11353 | +#endif | |
11354 | + | |
11355 | +#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \ | |
11356 | + (defined(__i386__) || defined(__i486__) || defined(__i586__))) | |
11357 | + | |
11358 | +#define _EXT2_HAVE_ASM_BITOPS_ | |
11359 | +#define _EXT2_HAVE_ASM_SWAB_ | |
11360 | +#define _EXT2_HAVE_ASM_FINDBIT_ | |
11361 | + | |
11362 | +/* | |
11363 | + * These are done by inline assembly for speed reasons..... | |
11364 | + * | |
11365 | + * All bitoperations return 0 if the bit was cleared before the | |
11366 | + * operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32 | |
11367 | + * is the LSB of (addr+1). | |
11368 | + */ | |
11369 | + | |
11370 | +/* | |
11371 | + * Some hacks to defeat gcc over-optimizations.. | |
11372 | + */ | |
11373 | +struct __dummy_h { unsigned long a[100]; }; | |
11374 | +#define EXT2FS_ADDR (*(struct __dummy_h *) addr) | |
11375 | +#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr) | |
11376 | + | |
11377 | +_INLINE_ int ext2fs_set_bit(int nr, void * addr) | |
11378 | +{ | |
11379 | + int oldbit; | |
11380 | + | |
11381 | + __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0" | |
11382 | + :"=r" (oldbit),"=m" (EXT2FS_ADDR) | |
11383 | + :"r" (nr)); | |
11384 | + return oldbit; | |
11385 | +} | |
11386 | + | |
11387 | +_INLINE_ int ext2fs_clear_bit(int nr, void * addr) | |
11388 | +{ | |
11389 | + int oldbit; | |
11390 | + | |
11391 | + __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0" | |
11392 | + :"=r" (oldbit),"=m" (EXT2FS_ADDR) | |
11393 | + :"r" (nr)); | |
11394 | + return oldbit; | |
11395 | +} | |
11396 | + | |
11397 | +_INLINE_ int ext2fs_test_bit(int nr, const void * addr) | |
11398 | +{ | |
11399 | + int oldbit; | |
11400 | + | |
11401 | + __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" | |
11402 | + :"=r" (oldbit) | |
11403 | + :"m" (EXT2FS_CONST_ADDR),"r" (nr)); | |
11404 | + return oldbit; | |
11405 | +} | |
11406 | + | |
11407 | +#if 0 | |
11408 | +_INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size) | |
11409 | +{ | |
11410 | + int d0, d1, d2; | |
11411 | + int res; | |
11412 | + | |
11413 | + if (!size) | |
11414 | + return 0; | |
11415 | + /* This looks at memory. Mark it volatile to tell gcc not to move it around */ | |
11416 | + __asm__ __volatile__( | |
11417 | + "cld\n\t" | |
11418 | + "xorl %%eax,%%eax\n\t" | |
11419 | + "xorl %%edx,%%edx\n\t" | |
11420 | + "repe; scasl\n\t" | |
11421 | + "je 1f\n\t" | |
11422 | + "movl -4(%%edi),%%eax\n\t" | |
11423 | + "subl $4,%%edi\n\t" | |
11424 | + "bsfl %%eax,%%edx\n" | |
11425 | + "1:\tsubl %%esi,%%edi\n\t" | |
11426 | + "shll $3,%%edi\n\t" | |
11427 | + "addl %%edi,%%edx" | |
11428 | + :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) | |
11429 | + :"1" ((size + 31) >> 5), "2" (addr), "S" (addr)); | |
11430 | + return res; | |
11431 | +} | |
11432 | + | |
11433 | +_INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset) | |
11434 | +{ | |
11435 | + unsigned long * p = ((unsigned long *) addr) + (offset >> 5); | |
11436 | + int set = 0, bit = offset & 31, res; | |
11437 | + | |
11438 | + if (bit) { | |
11439 | + /* | |
11440 | + * Look for zero in first byte | |
11441 | + */ | |
11442 | + __asm__("bsfl %1,%0\n\t" | |
11443 | + "jne 1f\n\t" | |
11444 | + "movl $32, %0\n" | |
11445 | + "1:" | |
11446 | + : "=r" (set) | |
11447 | + : "r" (*p >> bit)); | |
11448 | + if (set < (32 - bit)) | |
11449 | + return set + offset; | |
11450 | + set = 32 - bit; | |
11451 | + p++; | |
11452 | + } | |
11453 | + /* | |
11454 | + * No bit found yet, search remaining full bytes for a bit | |
11455 | + */ | |
11456 | + res = ext2fs_find_first_bit_set(p, size - 32 * (p - (unsigned long *) addr)); | |
11457 | + return (offset + set + res); | |
11458 | +} | |
11459 | +#endif | |
11460 | + | |
11461 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
11462 | +_INLINE_ __u32 ext2fs_swab32(__u32 val) | |
11463 | +{ | |
11464 | +#ifdef EXT2FS_REQUIRE_486 | |
11465 | + __asm__("bswap %0" : "=r" (val) : "0" (val)); | |
11466 | +#else | |
11467 | + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ | |
11468 | + "rorl $16,%0\n\t" /* swap words */ | |
11469 | + "xchgb %b0,%h0" /* swap higher bytes */ | |
11470 | + :"=q" (val) | |
11471 | + : "0" (val)); | |
11472 | +#endif | |
11473 | + return val; | |
11474 | +} | |
11475 | + | |
11476 | +_INLINE_ __u16 ext2fs_swab16(__u16 val) | |
11477 | +{ | |
11478 | + __asm__("xchgb %b0,%h0" /* swap bytes */ \ | |
11479 | + : "=q" (val) \ | |
11480 | + : "0" (val)); \ | |
11481 | + return val; | |
11482 | +} | |
11483 | +#endif | |
11484 | + | |
11485 | +#undef EXT2FS_ADDR | |
11486 | + | |
11487 | +#endif /* i386 */ | |
11488 | + | |
11489 | +#ifdef __mc68000__ | |
11490 | + | |
11491 | +#define _EXT2_HAVE_ASM_BITOPS_ | |
11492 | + | |
11493 | +_INLINE_ int ext2fs_set_bit(int nr,void * addr) | |
11494 | +{ | |
11495 | + char retval; | |
11496 | + | |
11497 | + __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" | |
11498 | + : "=d" (retval) : "d" (nr^7), "a" (addr)); | |
11499 | + | |
11500 | + return retval; | |
11501 | +} | |
11502 | + | |
11503 | +_INLINE_ int ext2fs_clear_bit(int nr, void * addr) | |
11504 | +{ | |
11505 | + char retval; | |
11506 | + | |
11507 | + __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" | |
11508 | + : "=d" (retval) : "d" (nr^7), "a" (addr)); | |
11509 | + | |
11510 | + return retval; | |
11511 | +} | |
11512 | + | |
11513 | +_INLINE_ int ext2fs_test_bit(int nr, const void * addr) | |
11514 | +{ | |
11515 | + char retval; | |
11516 | + | |
11517 | + __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0" | |
11518 | + : "=d" (retval) : "d" (nr^7), "a" (addr)); | |
11519 | + | |
11520 | + return retval; | |
11521 | +} | |
11522 | + | |
11523 | +#endif /* __mc68000__ */ | |
11524 | + | |
11525 | + | |
11526 | +#if !defined(_EXT2_HAVE_ASM_SWAB_) && defined(EXT2FS_ENABLE_SWAPFS) | |
11527 | + | |
11528 | +_INLINE_ __u16 ext2fs_swab16(__u16 val) | |
11529 | +{ | |
11530 | + return (val >> 8) | (val << 8); | |
11531 | +} | |
11532 | + | |
11533 | +_INLINE_ __u32 ext2fs_swab32(__u32 val) | |
11534 | +{ | |
11535 | + return ((val>>24) | ((val>>8)&0xFF00) | | |
11536 | + ((val<<8)&0xFF0000) | (val<<24)); | |
11537 | +} | |
11538 | + | |
11539 | +#endif /* !_EXT2_HAVE_ASM_SWAB */ | |
11540 | + | |
11541 | +#if !defined(_EXT2_HAVE_ASM_FINDBIT_) | |
11542 | +_INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size) | |
11543 | +{ | |
11544 | + char *cp = (unsigned char *) addr; | |
11545 | + int res = 0, d0; | |
11546 | + | |
11547 | + if (!size) | |
11548 | + return 0; | |
11549 | + | |
11550 | + while ((size > res) && (*cp == 0)) { | |
11551 | + cp++; | |
11552 | + res += 8; | |
11553 | + } | |
11554 | + d0 = ffs(*cp); | |
11555 | + if (d0 == 0) | |
11556 | + return size; | |
11557 | + | |
11558 | + return res + d0 - 1; | |
11559 | +} | |
11560 | + | |
11561 | +_INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset) | |
11562 | +{ | |
11563 | + unsigned char * p; | |
11564 | + int set = 0, bit = offset & 7, res = 0, d0; | |
11565 | + | |
11566 | + res = offset >> 3; | |
11567 | + p = ((unsigned char *) addr) + res; | |
11568 | + | |
11569 | + if (bit) { | |
11570 | + set = ffs(*p & ~((1 << bit) - 1)); | |
11571 | + if (set) | |
11572 | + return (offset & ~7) + set - 1; | |
11573 | + p++; | |
11574 | + res += 8; | |
11575 | + } | |
11576 | + while ((size > res) && (*p == 0)) { | |
11577 | + p++; | |
11578 | + res += 8; | |
11579 | + } | |
11580 | + d0 = ffs(*p); | |
11581 | + if (d0 == 0) | |
11582 | + return size; | |
11583 | + | |
11584 | + return (res + d0 - 1); | |
11585 | +} | |
11586 | +#endif | |
11587 | + | |
11588 | +_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, | |
11589 | + blk_t bitno); | |
11590 | + | |
11591 | +_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, | |
11592 | + blk_t bitno) | |
11593 | +{ | |
11594 | + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { | |
11595 | + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno); | |
11596 | + return 0; | |
11597 | + } | |
11598 | + return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap); | |
11599 | +} | |
11600 | + | |
11601 | +_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, | |
11602 | + blk_t block) | |
11603 | +{ | |
11604 | + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) | |
11605 | + bitmap, | |
11606 | + block); | |
11607 | +} | |
11608 | + | |
11609 | +_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, | |
11610 | + blk_t block) | |
11611 | +{ | |
11612 | + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, | |
11613 | + block); | |
11614 | +} | |
11615 | + | |
11616 | +_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, | |
11617 | + blk_t block) | |
11618 | +{ | |
11619 | + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, | |
11620 | + block); | |
11621 | +} | |
11622 | + | |
11623 | +_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11624 | + ext2_ino_t inode) | |
11625 | +{ | |
11626 | + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, | |
11627 | + inode); | |
11628 | +} | |
11629 | + | |
11630 | +_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11631 | + ext2_ino_t inode) | |
11632 | +{ | |
11633 | + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, | |
11634 | + inode); | |
11635 | +} | |
11636 | + | |
11637 | +_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11638 | + ext2_ino_t inode) | |
11639 | +{ | |
11640 | + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, | |
11641 | + inode); | |
11642 | +} | |
11643 | + | |
11644 | +_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, | |
11645 | + blk_t block) | |
11646 | +{ | |
11647 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11648 | + if ((block < bitmap->start) || (block > bitmap->end)) { | |
11649 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, | |
11650 | + bitmap->description); | |
11651 | + return; | |
11652 | + } | |
11653 | +#endif | |
11654 | + ext2fs_set_bit(block - bitmap->start, bitmap->bitmap); | |
11655 | +} | |
11656 | + | |
11657 | +_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, | |
11658 | + blk_t block) | |
11659 | +{ | |
11660 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11661 | + if ((block < bitmap->start) || (block > bitmap->end)) { | |
11662 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, | |
11663 | + block, bitmap->description); | |
11664 | + return; | |
11665 | + } | |
11666 | +#endif | |
11667 | + ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap); | |
11668 | +} | |
11669 | + | |
11670 | +_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, | |
11671 | + blk_t block) | |
11672 | +{ | |
11673 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11674 | + if ((block < bitmap->start) || (block > bitmap->end)) { | |
11675 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, | |
11676 | + block, bitmap->description); | |
11677 | + return 0; | |
11678 | + } | |
11679 | +#endif | |
11680 | + return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap); | |
11681 | +} | |
11682 | + | |
11683 | +_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11684 | + ext2_ino_t inode) | |
11685 | +{ | |
11686 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11687 | + if ((inode < bitmap->start) || (inode > bitmap->end)) { | |
11688 | + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK, | |
11689 | + inode, bitmap->description); | |
11690 | + return; | |
11691 | + } | |
11692 | +#endif | |
11693 | + ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap); | |
11694 | +} | |
11695 | + | |
11696 | +_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11697 | + ext2_ino_t inode) | |
11698 | +{ | |
11699 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11700 | + if ((inode < bitmap->start) || (inode > bitmap->end)) { | |
11701 | + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK, | |
11702 | + inode, bitmap->description); | |
11703 | + return; | |
11704 | + } | |
11705 | +#endif | |
11706 | + ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap); | |
11707 | +} | |
11708 | + | |
11709 | +_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, | |
11710 | + ext2_ino_t inode) | |
11711 | +{ | |
11712 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11713 | + if ((inode < bitmap->start) || (inode > bitmap->end)) { | |
11714 | + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST, | |
11715 | + inode, bitmap->description); | |
11716 | + return 0; | |
11717 | + } | |
11718 | +#endif | |
11719 | + return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap); | |
11720 | +} | |
11721 | + | |
11722 | +_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap) | |
11723 | +{ | |
11724 | + return bitmap->start; | |
11725 | +} | |
11726 | + | |
11727 | +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap) | |
11728 | +{ | |
11729 | + return bitmap->start; | |
11730 | +} | |
11731 | + | |
11732 | +_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap) | |
11733 | +{ | |
11734 | + return bitmap->end; | |
11735 | +} | |
11736 | + | |
11737 | +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap) | |
11738 | +{ | |
11739 | + return bitmap->end; | |
11740 | +} | |
11741 | + | |
11742 | +_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11743 | + blk_t block, int num) | |
11744 | +{ | |
11745 | + int i; | |
11746 | + | |
11747 | + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { | |
11748 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, | |
11749 | + block, bitmap->description); | |
11750 | + return 0; | |
11751 | + } | |
11752 | + for (i=0; i < num; i++) { | |
11753 | + if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) | |
11754 | + return 0; | |
11755 | + } | |
11756 | + return 1; | |
11757 | +} | |
11758 | + | |
11759 | +_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11760 | + blk_t block, int num) | |
11761 | +{ | |
11762 | + int i; | |
11763 | + | |
11764 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11765 | + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { | |
11766 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, | |
11767 | + block, bitmap->description); | |
11768 | + return 0; | |
11769 | + } | |
11770 | +#endif | |
11771 | + for (i=0; i < num; i++) { | |
11772 | + if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) | |
11773 | + return 0; | |
11774 | + } | |
11775 | + return 1; | |
11776 | +} | |
11777 | + | |
11778 | +_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11779 | + blk_t block, int num) | |
11780 | +{ | |
11781 | + int i; | |
11782 | + | |
11783 | + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { | |
11784 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, | |
11785 | + bitmap->description); | |
11786 | + return; | |
11787 | + } | |
11788 | + for (i=0; i < num; i++) | |
11789 | + ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); | |
11790 | +} | |
11791 | + | |
11792 | +_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11793 | + blk_t block, int num) | |
11794 | +{ | |
11795 | + int i; | |
11796 | + | |
11797 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11798 | + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { | |
11799 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, | |
11800 | + bitmap->description); | |
11801 | + return; | |
11802 | + } | |
11803 | +#endif | |
11804 | + for (i=0; i < num; i++) | |
11805 | + ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); | |
11806 | +} | |
11807 | + | |
11808 | +_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11809 | + blk_t block, int num) | |
11810 | +{ | |
11811 | + int i; | |
11812 | + | |
11813 | + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { | |
11814 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, | |
11815 | + bitmap->description); | |
11816 | + return; | |
11817 | + } | |
11818 | + for (i=0; i < num; i++) | |
11819 | + ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); | |
11820 | +} | |
11821 | + | |
11822 | +_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, | |
11823 | + blk_t block, int num) | |
11824 | +{ | |
11825 | + int i; | |
11826 | + | |
11827 | +#ifdef EXT2FS_DEBUG_FAST_OPS | |
11828 | + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { | |
11829 | + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, | |
11830 | + bitmap->description); | |
11831 | + return; | |
11832 | + } | |
11833 | +#endif | |
11834 | + for (i=0; i < num; i++) | |
11835 | + ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); | |
11836 | +} | |
11837 | +#undef _INLINE_ | |
11838 | +#endif | |
11839 | + | |
11840 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/block.c busybox/e2fsprogs/ext2fs/block.c | |
11841 | --- busybox-1.00/e2fsprogs/ext2fs/block.c 1970-01-01 01:00:00.000000000 +0100 | |
11842 | +++ busybox/e2fsprogs/ext2fs/block.c 2005-06-04 08:20:16.000000000 +0200 | |
11843 | @@ -0,0 +1,437 @@ | |
11844 | +/* | |
11845 | + * block.c --- iterate over all blocks in an inode | |
11846 | + * | |
11847 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
11848 | + * | |
11849 | + * %Begin-Header% | |
11850 | + * This file may be redistributed under the terms of the GNU Public | |
11851 | + * License. | |
11852 | + * %End-Header% | |
11853 | + */ | |
11854 | + | |
11855 | +#include <stdio.h> | |
11856 | +#include <string.h> | |
11857 | +#if HAVE_UNISTD_H | |
11858 | +#include <unistd.h> | |
11859 | +#endif | |
11860 | + | |
11861 | +#include "ext2_fs.h" | |
11862 | +#include "ext2fs.h" | |
11863 | + | |
11864 | +struct block_context { | |
11865 | + ext2_filsys fs; | |
11866 | + int (*func)(ext2_filsys fs, | |
11867 | + blk_t *blocknr, | |
11868 | + e2_blkcnt_t bcount, | |
11869 | + blk_t ref_blk, | |
11870 | + int ref_offset, | |
11871 | + void *priv_data); | |
11872 | + e2_blkcnt_t bcount; | |
11873 | + int bsize; | |
11874 | + int flags; | |
11875 | + errcode_t errcode; | |
11876 | + char *ind_buf; | |
11877 | + char *dind_buf; | |
11878 | + char *tind_buf; | |
11879 | + void *priv_data; | |
11880 | +}; | |
11881 | + | |
11882 | +static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, | |
11883 | + int ref_offset, struct block_context *ctx) | |
11884 | +{ | |
11885 | + int ret = 0, changed = 0; | |
11886 | + int i, flags, limit, offset; | |
11887 | + blk_t *block_nr; | |
11888 | + | |
11889 | + limit = ctx->fs->blocksize >> 2; | |
11890 | + if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | |
11891 | + !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) | |
11892 | + ret = (*ctx->func)(ctx->fs, ind_block, | |
11893 | + BLOCK_COUNT_IND, ref_block, | |
11894 | + ref_offset, ctx->priv_data); | |
11895 | + if (!*ind_block || (ret & BLOCK_ABORT)) { | |
11896 | + ctx->bcount += limit; | |
11897 | + return ret; | |
11898 | + } | |
11899 | + if (*ind_block >= ctx->fs->super->s_blocks_count || | |
11900 | + *ind_block < ctx->fs->super->s_first_data_block) { | |
11901 | + ctx->errcode = EXT2_ET_BAD_IND_BLOCK; | |
11902 | + ret |= BLOCK_ERROR; | |
11903 | + return ret; | |
11904 | + } | |
11905 | + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block, | |
11906 | + ctx->ind_buf); | |
11907 | + if (ctx->errcode) { | |
11908 | + ret |= BLOCK_ERROR; | |
11909 | + return ret; | |
11910 | + } | |
11911 | + | |
11912 | + block_nr = (blk_t *) ctx->ind_buf; | |
11913 | + offset = 0; | |
11914 | + if (ctx->flags & BLOCK_FLAG_APPEND) { | |
11915 | + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { | |
11916 | + flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, | |
11917 | + *ind_block, offset, | |
11918 | + ctx->priv_data); | |
11919 | + changed |= flags; | |
11920 | + if (flags & BLOCK_ABORT) { | |
11921 | + ret |= BLOCK_ABORT; | |
11922 | + break; | |
11923 | + } | |
11924 | + offset += sizeof(blk_t); | |
11925 | + } | |
11926 | + } else { | |
11927 | + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { | |
11928 | + if (*block_nr == 0) | |
11929 | + continue; | |
11930 | + flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, | |
11931 | + *ind_block, offset, | |
11932 | + ctx->priv_data); | |
11933 | + changed |= flags; | |
11934 | + if (flags & BLOCK_ABORT) { | |
11935 | + ret |= BLOCK_ABORT; | |
11936 | + break; | |
11937 | + } | |
11938 | + offset += sizeof(blk_t); | |
11939 | + } | |
11940 | + } | |
11941 | + if (changed & BLOCK_CHANGED) { | |
11942 | + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, | |
11943 | + ctx->ind_buf); | |
11944 | + if (ctx->errcode) | |
11945 | + ret |= BLOCK_ERROR | BLOCK_ABORT; | |
11946 | + } | |
11947 | + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | |
11948 | + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && | |
11949 | + !(ret & BLOCK_ABORT)) | |
11950 | + ret |= (*ctx->func)(ctx->fs, ind_block, | |
11951 | + BLOCK_COUNT_IND, ref_block, | |
11952 | + ref_offset, ctx->priv_data); | |
11953 | + return ret; | |
11954 | +} | |
11955 | + | |
11956 | +static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, | |
11957 | + int ref_offset, struct block_context *ctx) | |
11958 | +{ | |
11959 | + int ret = 0, changed = 0; | |
11960 | + int i, flags, limit, offset; | |
11961 | + blk_t *block_nr; | |
11962 | + | |
11963 | + limit = ctx->fs->blocksize >> 2; | |
11964 | + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | | |
11965 | + BLOCK_FLAG_DATA_ONLY))) | |
11966 | + ret = (*ctx->func)(ctx->fs, dind_block, | |
11967 | + BLOCK_COUNT_DIND, ref_block, | |
11968 | + ref_offset, ctx->priv_data); | |
11969 | + if (!*dind_block || (ret & BLOCK_ABORT)) { | |
11970 | + ctx->bcount += limit*limit; | |
11971 | + return ret; | |
11972 | + } | |
11973 | + if (*dind_block >= ctx->fs->super->s_blocks_count || | |
11974 | + *dind_block < ctx->fs->super->s_first_data_block) { | |
11975 | + ctx->errcode = EXT2_ET_BAD_DIND_BLOCK; | |
11976 | + ret |= BLOCK_ERROR; | |
11977 | + return ret; | |
11978 | + } | |
11979 | + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block, | |
11980 | + ctx->dind_buf); | |
11981 | + if (ctx->errcode) { | |
11982 | + ret |= BLOCK_ERROR; | |
11983 | + return ret; | |
11984 | + } | |
11985 | + | |
11986 | + block_nr = (blk_t *) ctx->dind_buf; | |
11987 | + offset = 0; | |
11988 | + if (ctx->flags & BLOCK_FLAG_APPEND) { | |
11989 | + for (i = 0; i < limit; i++, block_nr++) { | |
11990 | + flags = block_iterate_ind(block_nr, | |
11991 | + *dind_block, offset, | |
11992 | + ctx); | |
11993 | + changed |= flags; | |
11994 | + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | |
11995 | + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | |
11996 | + break; | |
11997 | + } | |
11998 | + offset += sizeof(blk_t); | |
11999 | + } | |
12000 | + } else { | |
12001 | + for (i = 0; i < limit; i++, block_nr++) { | |
12002 | + if (*block_nr == 0) { | |
12003 | + ctx->bcount += limit; | |
12004 | + continue; | |
12005 | + } | |
12006 | + flags = block_iterate_ind(block_nr, | |
12007 | + *dind_block, offset, | |
12008 | + ctx); | |
12009 | + changed |= flags; | |
12010 | + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | |
12011 | + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | |
12012 | + break; | |
12013 | + } | |
12014 | + offset += sizeof(blk_t); | |
12015 | + } | |
12016 | + } | |
12017 | + if (changed & BLOCK_CHANGED) { | |
12018 | + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, | |
12019 | + ctx->dind_buf); | |
12020 | + if (ctx->errcode) | |
12021 | + ret |= BLOCK_ERROR | BLOCK_ABORT; | |
12022 | + } | |
12023 | + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | |
12024 | + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && | |
12025 | + !(ret & BLOCK_ABORT)) | |
12026 | + ret |= (*ctx->func)(ctx->fs, dind_block, | |
12027 | + BLOCK_COUNT_DIND, ref_block, | |
12028 | + ref_offset, ctx->priv_data); | |
12029 | + return ret; | |
12030 | +} | |
12031 | + | |
12032 | +static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, | |
12033 | + int ref_offset, struct block_context *ctx) | |
12034 | +{ | |
12035 | + int ret = 0, changed = 0; | |
12036 | + int i, flags, limit, offset; | |
12037 | + blk_t *block_nr; | |
12038 | + | |
12039 | + limit = ctx->fs->blocksize >> 2; | |
12040 | + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | | |
12041 | + BLOCK_FLAG_DATA_ONLY))) | |
12042 | + ret = (*ctx->func)(ctx->fs, tind_block, | |
12043 | + BLOCK_COUNT_TIND, ref_block, | |
12044 | + ref_offset, ctx->priv_data); | |
12045 | + if (!*tind_block || (ret & BLOCK_ABORT)) { | |
12046 | + ctx->bcount += limit*limit*limit; | |
12047 | + return ret; | |
12048 | + } | |
12049 | + if (*tind_block >= ctx->fs->super->s_blocks_count || | |
12050 | + *tind_block < ctx->fs->super->s_first_data_block) { | |
12051 | + ctx->errcode = EXT2_ET_BAD_TIND_BLOCK; | |
12052 | + ret |= BLOCK_ERROR; | |
12053 | + return ret; | |
12054 | + } | |
12055 | + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block, | |
12056 | + ctx->tind_buf); | |
12057 | + if (ctx->errcode) { | |
12058 | + ret |= BLOCK_ERROR; | |
12059 | + return ret; | |
12060 | + } | |
12061 | + | |
12062 | + block_nr = (blk_t *) ctx->tind_buf; | |
12063 | + offset = 0; | |
12064 | + if (ctx->flags & BLOCK_FLAG_APPEND) { | |
12065 | + for (i = 0; i < limit; i++, block_nr++) { | |
12066 | + flags = block_iterate_dind(block_nr, | |
12067 | + *tind_block, | |
12068 | + offset, ctx); | |
12069 | + changed |= flags; | |
12070 | + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | |
12071 | + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | |
12072 | + break; | |
12073 | + } | |
12074 | + offset += sizeof(blk_t); | |
12075 | + } | |
12076 | + } else { | |
12077 | + for (i = 0; i < limit; i++, block_nr++) { | |
12078 | + if (*block_nr == 0) { | |
12079 | + ctx->bcount += limit*limit; | |
12080 | + continue; | |
12081 | + } | |
12082 | + flags = block_iterate_dind(block_nr, | |
12083 | + *tind_block, | |
12084 | + offset, ctx); | |
12085 | + changed |= flags; | |
12086 | + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | |
12087 | + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | |
12088 | + break; | |
12089 | + } | |
12090 | + offset += sizeof(blk_t); | |
12091 | + } | |
12092 | + } | |
12093 | + if (changed & BLOCK_CHANGED) { | |
12094 | + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, | |
12095 | + ctx->tind_buf); | |
12096 | + if (ctx->errcode) | |
12097 | + ret |= BLOCK_ERROR | BLOCK_ABORT; | |
12098 | + } | |
12099 | + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | |
12100 | + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && | |
12101 | + !(ret & BLOCK_ABORT)) | |
12102 | + ret |= (*ctx->func)(ctx->fs, tind_block, | |
12103 | + BLOCK_COUNT_TIND, ref_block, | |
12104 | + ref_offset, ctx->priv_data); | |
12105 | + | |
12106 | + return ret; | |
12107 | +} | |
12108 | + | |
12109 | +errcode_t ext2fs_block_iterate2(ext2_filsys fs, | |
12110 | + ext2_ino_t ino, | |
12111 | + int flags, | |
12112 | + char *block_buf, | |
12113 | + int (*func)(ext2_filsys fs, | |
12114 | + blk_t *blocknr, | |
12115 | + e2_blkcnt_t blockcnt, | |
12116 | + blk_t ref_blk, | |
12117 | + int ref_offset, | |
12118 | + void *priv_data), | |
12119 | + void *priv_data) | |
12120 | +{ | |
12121 | + int i; | |
12122 | + int got_inode = 0; | |
12123 | + int ret = 0; | |
12124 | + blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */ | |
12125 | + struct ext2_inode inode; | |
12126 | + errcode_t retval; | |
12127 | + struct block_context ctx; | |
12128 | + int limit; | |
12129 | + | |
12130 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
12131 | + | |
12132 | + /* | |
12133 | + * Check to see if we need to limit large files | |
12134 | + */ | |
12135 | + if (flags & BLOCK_FLAG_NO_LARGE) { | |
12136 | + ctx.errcode = ext2fs_read_inode(fs, ino, &inode); | |
12137 | + if (ctx.errcode) | |
12138 | + return ctx.errcode; | |
12139 | + got_inode = 1; | |
12140 | + if (!LINUX_S_ISDIR(inode.i_mode) && | |
12141 | + (inode.i_size_high != 0)) | |
12142 | + return EXT2_ET_FILE_TOO_BIG; | |
12143 | + } | |
12144 | + | |
12145 | + retval = ext2fs_get_blocks(fs, ino, blocks); | |
12146 | + if (retval) | |
12147 | + return retval; | |
12148 | + | |
12149 | + limit = fs->blocksize >> 2; | |
12150 | + | |
12151 | + ctx.fs = fs; | |
12152 | + ctx.func = func; | |
12153 | + ctx.priv_data = priv_data; | |
12154 | + ctx.flags = flags; | |
12155 | + ctx.bcount = 0; | |
12156 | + if (block_buf) { | |
12157 | + ctx.ind_buf = block_buf; | |
12158 | + } else { | |
12159 | + retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf); | |
12160 | + if (retval) | |
12161 | + return retval; | |
12162 | + } | |
12163 | + ctx.dind_buf = ctx.ind_buf + fs->blocksize; | |
12164 | + ctx.tind_buf = ctx.dind_buf + fs->blocksize; | |
12165 | + | |
12166 | + /* | |
12167 | + * Iterate over the HURD translator block (if present) | |
12168 | + */ | |
12169 | + if ((fs->super->s_creator_os == EXT2_OS_HURD) && | |
12170 | + !(flags & BLOCK_FLAG_DATA_ONLY)) { | |
12171 | + ctx.errcode = ext2fs_read_inode(fs, ino, &inode); | |
12172 | + if (ctx.errcode) | |
12173 | + goto abort_exit; | |
12174 | + got_inode = 1; | |
12175 | + if (inode.osd1.hurd1.h_i_translator) { | |
12176 | + ret |= (*ctx.func)(fs, | |
12177 | + &inode.osd1.hurd1.h_i_translator, | |
12178 | + BLOCK_COUNT_TRANSLATOR, | |
12179 | + 0, 0, priv_data); | |
12180 | + if (ret & BLOCK_ABORT) | |
12181 | + goto abort_exit; | |
12182 | + } | |
12183 | + } | |
12184 | + | |
12185 | + /* | |
12186 | + * Iterate over normal data blocks | |
12187 | + */ | |
12188 | + for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) { | |
12189 | + if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) { | |
12190 | + ret |= (*ctx.func)(fs, &blocks[i], | |
12191 | + ctx.bcount, 0, i, priv_data); | |
12192 | + if (ret & BLOCK_ABORT) | |
12193 | + goto abort_exit; | |
12194 | + } | |
12195 | + } | |
12196 | + if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { | |
12197 | + ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, | |
12198 | + 0, EXT2_IND_BLOCK, &ctx); | |
12199 | + if (ret & BLOCK_ABORT) | |
12200 | + goto abort_exit; | |
12201 | + } else | |
12202 | + ctx.bcount += limit; | |
12203 | + if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { | |
12204 | + ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, | |
12205 | + 0, EXT2_DIND_BLOCK, &ctx); | |
12206 | + if (ret & BLOCK_ABORT) | |
12207 | + goto abort_exit; | |
12208 | + } else | |
12209 | + ctx.bcount += limit * limit; | |
12210 | + if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { | |
12211 | + ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, | |
12212 | + 0, EXT2_TIND_BLOCK, &ctx); | |
12213 | + if (ret & BLOCK_ABORT) | |
12214 | + goto abort_exit; | |
12215 | + } | |
12216 | + | |
12217 | +abort_exit: | |
12218 | + if (ret & BLOCK_CHANGED) { | |
12219 | + if (!got_inode) { | |
12220 | + retval = ext2fs_read_inode(fs, ino, &inode); | |
12221 | + if (retval) | |
12222 | + return retval; | |
12223 | + } | |
12224 | + for (i=0; i < EXT2_N_BLOCKS; i++) | |
12225 | + inode.i_block[i] = blocks[i]; | |
12226 | + retval = ext2fs_write_inode(fs, ino, &inode); | |
12227 | + if (retval) | |
12228 | + return retval; | |
12229 | + } | |
12230 | + | |
12231 | + if (!block_buf) | |
12232 | + ext2fs_free_mem(&ctx.ind_buf); | |
12233 | + | |
12234 | + return (ret & BLOCK_ERROR) ? ctx.errcode : 0; | |
12235 | +} | |
12236 | + | |
12237 | +/* | |
12238 | + * Emulate the old ext2fs_block_iterate function! | |
12239 | + */ | |
12240 | + | |
12241 | +struct xlate { | |
12242 | + int (*func)(ext2_filsys fs, | |
12243 | + blk_t *blocknr, | |
12244 | + int bcount, | |
12245 | + void *priv_data); | |
12246 | + void *real_private; | |
12247 | +}; | |
12248 | + | |
12249 | +#ifdef __TURBOC__ | |
12250 | + #pragma argsused | |
12251 | +#endif | |
12252 | +static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, | |
12253 | + blk_t ref_block EXT2FS_ATTR((unused)), | |
12254 | + int ref_offset EXT2FS_ATTR((unused)), | |
12255 | + void *priv_data) | |
12256 | +{ | |
12257 | + struct xlate *xl = (struct xlate *) priv_data; | |
12258 | + | |
12259 | + return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private); | |
12260 | +} | |
12261 | + | |
12262 | +errcode_t ext2fs_block_iterate(ext2_filsys fs, | |
12263 | + ext2_ino_t ino, | |
12264 | + int flags, | |
12265 | + char *block_buf, | |
12266 | + int (*func)(ext2_filsys fs, | |
12267 | + blk_t *blocknr, | |
12268 | + int blockcnt, | |
12269 | + void *priv_data), | |
12270 | + void *priv_data) | |
12271 | +{ | |
12272 | + struct xlate xl; | |
12273 | + | |
12274 | + xl.real_private = priv_data; | |
12275 | + xl.func = func; | |
12276 | + | |
12277 | + return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags, | |
12278 | + block_buf, xlate_func, &xl); | |
12279 | +} | |
12280 | + | |
12281 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/bmap.c busybox/e2fsprogs/ext2fs/bmap.c | |
12282 | --- busybox-1.00/e2fsprogs/ext2fs/bmap.c 1970-01-01 01:00:00.000000000 +0100 | |
12283 | +++ busybox/e2fsprogs/ext2fs/bmap.c 2005-06-04 08:20:16.000000000 +0200 | |
12284 | @@ -0,0 +1,270 @@ | |
12285 | +/* | |
12286 | + * bmap.c --- logical to physical block mapping | |
12287 | + * | |
12288 | + * Copyright (C) 1997 Theodore Ts'o. | |
12289 | + * | |
12290 | + * %Begin-Header% | |
12291 | + * This file may be redistributed under the terms of the GNU Public | |
12292 | + * License. | |
12293 | + * %End-Header% | |
12294 | + */ | |
12295 | + | |
12296 | +#include <stdio.h> | |
12297 | +#include <string.h> | |
12298 | +#if HAVE_UNISTD_H | |
12299 | +#include <unistd.h> | |
12300 | +#endif | |
12301 | + | |
12302 | +#include "ext2_fs.h" | |
12303 | +#include "ext2fs.h" | |
12304 | + | |
12305 | +#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS) | |
12306 | +#define _BMAP_INLINE_ __inline__ | |
12307 | +#else | |
12308 | +#define _BMAP_INLINE_ | |
12309 | +#endif | |
12310 | + | |
12311 | +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, | |
12312 | + struct ext2_inode *inode, | |
12313 | + char *block_buf, int bmap_flags, | |
12314 | + blk_t block, blk_t *phys_blk); | |
12315 | + | |
12316 | +#define inode_bmap(inode, nr) ((inode)->i_block[(nr)]) | |
12317 | + | |
12318 | +static _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags, | |
12319 | + blk_t ind, char *block_buf, | |
12320 | + int *blocks_alloc, | |
12321 | + blk_t nr, blk_t *ret_blk) | |
12322 | +{ | |
12323 | + errcode_t retval; | |
12324 | + blk_t b; | |
12325 | + | |
12326 | + if (!ind) { | |
12327 | + if (flags & BMAP_SET) | |
12328 | + return EXT2_ET_SET_BMAP_NO_IND; | |
12329 | + *ret_blk = 0; | |
12330 | + return 0; | |
12331 | + } | |
12332 | + retval = io_channel_read_blk(fs->io, ind, 1, block_buf); | |
12333 | + if (retval) | |
12334 | + return retval; | |
12335 | + | |
12336 | + if (flags & BMAP_SET) { | |
12337 | + b = *ret_blk; | |
12338 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
12339 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
12340 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) | |
12341 | + b = ext2fs_swab32(b); | |
12342 | +#endif | |
12343 | + ((blk_t *) block_buf)[nr] = b; | |
12344 | + return io_channel_write_blk(fs->io, ind, 1, block_buf); | |
12345 | + } | |
12346 | + | |
12347 | + b = ((blk_t *) block_buf)[nr]; | |
12348 | + | |
12349 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
12350 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
12351 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) | |
12352 | + b = ext2fs_swab32(b); | |
12353 | +#endif | |
12354 | + | |
12355 | + if (!b && (flags & BMAP_ALLOC)) { | |
12356 | + b = nr ? ((blk_t *) block_buf)[nr-1] : 0; | |
12357 | + retval = ext2fs_alloc_block(fs, b, | |
12358 | + block_buf + fs->blocksize, &b); | |
12359 | + if (retval) | |
12360 | + return retval; | |
12361 | + | |
12362 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
12363 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
12364 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) | |
12365 | + ((blk_t *) block_buf)[nr] = ext2fs_swab32(b); | |
12366 | + else | |
12367 | +#endif | |
12368 | + ((blk_t *) block_buf)[nr] = b; | |
12369 | + | |
12370 | + retval = io_channel_write_blk(fs->io, ind, 1, block_buf); | |
12371 | + if (retval) | |
12372 | + return retval; | |
12373 | + | |
12374 | + (*blocks_alloc)++; | |
12375 | + } | |
12376 | + | |
12377 | + *ret_blk = b; | |
12378 | + return 0; | |
12379 | +} | |
12380 | + | |
12381 | +static _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags, | |
12382 | + blk_t dind, char *block_buf, | |
12383 | + int *blocks_alloc, | |
12384 | + blk_t nr, blk_t *ret_blk) | |
12385 | +{ | |
12386 | + blk_t b; | |
12387 | + errcode_t retval; | |
12388 | + blk_t addr_per_block; | |
12389 | + | |
12390 | + addr_per_block = (blk_t) fs->blocksize >> 2; | |
12391 | + | |
12392 | + retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf, | |
12393 | + blocks_alloc, nr / addr_per_block, &b); | |
12394 | + if (retval) | |
12395 | + return retval; | |
12396 | + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, | |
12397 | + nr % addr_per_block, ret_blk); | |
12398 | + return retval; | |
12399 | +} | |
12400 | + | |
12401 | +static _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags, | |
12402 | + blk_t tind, char *block_buf, | |
12403 | + int *blocks_alloc, | |
12404 | + blk_t nr, blk_t *ret_blk) | |
12405 | +{ | |
12406 | + blk_t b; | |
12407 | + errcode_t retval; | |
12408 | + blk_t addr_per_block; | |
12409 | + | |
12410 | + addr_per_block = (blk_t) fs->blocksize >> 2; | |
12411 | + | |
12412 | + retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf, | |
12413 | + blocks_alloc, nr / addr_per_block, &b); | |
12414 | + if (retval) | |
12415 | + return retval; | |
12416 | + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, | |
12417 | + nr % addr_per_block, ret_blk); | |
12418 | + return retval; | |
12419 | +} | |
12420 | + | |
12421 | +errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, | |
12422 | + char *block_buf, int bmap_flags, blk_t block, | |
12423 | + blk_t *phys_blk) | |
12424 | +{ | |
12425 | + struct ext2_inode inode_buf; | |
12426 | + blk_t addr_per_block; | |
12427 | + blk_t b; | |
12428 | + char *buf = 0; | |
12429 | + errcode_t retval = 0; | |
12430 | + int blocks_alloc = 0, inode_dirty = 0; | |
12431 | + | |
12432 | + if (!(bmap_flags & BMAP_SET)) | |
12433 | + *phys_blk = 0; | |
12434 | + | |
12435 | + /* Read inode structure if necessary */ | |
12436 | + if (!inode) { | |
12437 | + retval = ext2fs_read_inode(fs, ino, &inode_buf); | |
12438 | + if (retval) | |
12439 | + return retval; | |
12440 | + inode = &inode_buf; | |
12441 | + } | |
12442 | + addr_per_block = (blk_t) fs->blocksize >> 2; | |
12443 | + | |
12444 | + if (!block_buf) { | |
12445 | + retval = ext2fs_get_mem(fs->blocksize * 2, &buf); | |
12446 | + if (retval) | |
12447 | + return retval; | |
12448 | + block_buf = buf; | |
12449 | + } | |
12450 | + | |
12451 | + if (block < EXT2_NDIR_BLOCKS) { | |
12452 | + if (bmap_flags & BMAP_SET) { | |
12453 | + b = *phys_blk; | |
12454 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
12455 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
12456 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) | |
12457 | + b = ext2fs_swab32(b); | |
12458 | +#endif | |
12459 | + inode_bmap(inode, block) = b; | |
12460 | + inode_dirty++; | |
12461 | + goto done; | |
12462 | + } | |
12463 | + | |
12464 | + *phys_blk = inode_bmap(inode, block); | |
12465 | + b = block ? inode_bmap(inode, block-1) : 0; | |
12466 | + | |
12467 | + if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { | |
12468 | + retval = ext2fs_alloc_block(fs, b, block_buf, &b); | |
12469 | + if (retval) | |
12470 | + goto done; | |
12471 | + inode_bmap(inode, block) = b; | |
12472 | + blocks_alloc++; | |
12473 | + *phys_blk = b; | |
12474 | + } | |
12475 | + goto done; | |
12476 | + } | |
12477 | + | |
12478 | + /* Indirect block */ | |
12479 | + block -= EXT2_NDIR_BLOCKS; | |
12480 | + if (block < addr_per_block) { | |
12481 | + b = inode_bmap(inode, EXT2_IND_BLOCK); | |
12482 | + if (!b) { | |
12483 | + if (!(bmap_flags & BMAP_ALLOC)) { | |
12484 | + if (bmap_flags & BMAP_SET) | |
12485 | + retval = EXT2_ET_SET_BMAP_NO_IND; | |
12486 | + goto done; | |
12487 | + } | |
12488 | + | |
12489 | + b = inode_bmap(inode, EXT2_IND_BLOCK-1); | |
12490 | + retval = ext2fs_alloc_block(fs, b, block_buf, &b); | |
12491 | + if (retval) | |
12492 | + goto done; | |
12493 | + inode_bmap(inode, EXT2_IND_BLOCK) = b; | |
12494 | + blocks_alloc++; | |
12495 | + } | |
12496 | + retval = block_ind_bmap(fs, bmap_flags, b, block_buf, | |
12497 | + &blocks_alloc, block, phys_blk); | |
12498 | + goto done; | |
12499 | + } | |
12500 | + | |
12501 | + /* Doubly indirect block */ | |
12502 | + block -= addr_per_block; | |
12503 | + if (block < addr_per_block * addr_per_block) { | |
12504 | + b = inode_bmap(inode, EXT2_DIND_BLOCK); | |
12505 | + if (!b) { | |
12506 | + if (!(bmap_flags & BMAP_ALLOC)) { | |
12507 | + if (bmap_flags & BMAP_SET) | |
12508 | + retval = EXT2_ET_SET_BMAP_NO_IND; | |
12509 | + goto done; | |
12510 | + } | |
12511 | + | |
12512 | + b = inode_bmap(inode, EXT2_IND_BLOCK); | |
12513 | + retval = ext2fs_alloc_block(fs, b, block_buf, &b); | |
12514 | + if (retval) | |
12515 | + goto done; | |
12516 | + inode_bmap(inode, EXT2_DIND_BLOCK) = b; | |
12517 | + blocks_alloc++; | |
12518 | + } | |
12519 | + retval = block_dind_bmap(fs, bmap_flags, b, block_buf, | |
12520 | + &blocks_alloc, block, phys_blk); | |
12521 | + goto done; | |
12522 | + } | |
12523 | + | |
12524 | + /* Triply indirect block */ | |
12525 | + block -= addr_per_block * addr_per_block; | |
12526 | + b = inode_bmap(inode, EXT2_TIND_BLOCK); | |
12527 | + if (!b) { | |
12528 | + if (!(bmap_flags & BMAP_ALLOC)) { | |
12529 | + if (bmap_flags & BMAP_SET) | |
12530 | + retval = EXT2_ET_SET_BMAP_NO_IND; | |
12531 | + goto done; | |
12532 | + } | |
12533 | + | |
12534 | + b = inode_bmap(inode, EXT2_DIND_BLOCK); | |
12535 | + retval = ext2fs_alloc_block(fs, b, block_buf, &b); | |
12536 | + if (retval) | |
12537 | + goto done; | |
12538 | + inode_bmap(inode, EXT2_TIND_BLOCK) = b; | |
12539 | + blocks_alloc++; | |
12540 | + } | |
12541 | + retval = block_tind_bmap(fs, bmap_flags, b, block_buf, | |
12542 | + &blocks_alloc, block, phys_blk); | |
12543 | +done: | |
12544 | + if (buf) | |
12545 | + ext2fs_free_mem(&buf); | |
12546 | + if ((retval == 0) && (blocks_alloc || inode_dirty)) { | |
12547 | + inode->i_blocks += (blocks_alloc * fs->blocksize) / 512; | |
12548 | + retval = ext2fs_write_inode(fs, ino, inode); | |
12549 | + } | |
12550 | + return retval; | |
12551 | +} | |
12552 | + | |
12553 | + | |
12554 | + | |
12555 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/bmove.c busybox/e2fsprogs/ext2fs/bmove.c | |
12556 | --- busybox-1.00/e2fsprogs/ext2fs/bmove.c 1970-01-01 01:00:00.000000000 +0100 | |
12557 | +++ busybox/e2fsprogs/ext2fs/bmove.c 2005-06-04 08:20:16.000000000 +0200 | |
12558 | @@ -0,0 +1,160 @@ | |
12559 | +/* | |
12560 | + * bmove.c --- Move blocks around to make way for a particular | |
12561 | + * filesystem structure. | |
12562 | + * | |
12563 | + * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed | |
12564 | + * under the terms of the GNU Public License. | |
12565 | + */ | |
12566 | + | |
12567 | +#include <stdio.h> | |
12568 | +#include <string.h> | |
12569 | +#if HAVE_UNISTD_H | |
12570 | +#include <unistd.h> | |
12571 | +#endif | |
12572 | +#if HAVE_SYS_TYPES_H | |
12573 | +#include <sys/types.h> | |
12574 | +#endif | |
12575 | +#if HAVE_SYS_TIME_H | |
12576 | +#include <sys/time.h> | |
12577 | +#endif | |
12578 | + | |
12579 | +#include "ext2_fs.h" | |
12580 | +#include "ext2fsP.h" | |
12581 | + | |
12582 | +struct process_block_struct { | |
12583 | + ext2_ino_t ino; | |
12584 | + struct ext2_inode * inode; | |
12585 | + ext2fs_block_bitmap reserve; | |
12586 | + ext2fs_block_bitmap alloc_map; | |
12587 | + errcode_t error; | |
12588 | + char *buf; | |
12589 | + int add_dir; | |
12590 | + int flags; | |
12591 | +}; | |
12592 | + | |
12593 | +static int process_block(ext2_filsys fs, blk_t *block_nr, | |
12594 | + e2_blkcnt_t blockcnt, blk_t ref_block, | |
12595 | + int ref_offset, void *priv_data) | |
12596 | +{ | |
12597 | + struct process_block_struct *pb; | |
12598 | + errcode_t retval; | |
12599 | + int ret; | |
12600 | + blk_t block, orig; | |
12601 | + | |
12602 | + pb = (struct process_block_struct *) priv_data; | |
12603 | + block = orig = *block_nr; | |
12604 | + ret = 0; | |
12605 | + | |
12606 | + /* | |
12607 | + * Let's see if this is one which we need to relocate | |
12608 | + */ | |
12609 | + if (ext2fs_test_block_bitmap(pb->reserve, block)) { | |
12610 | + do { | |
12611 | + if (++block >= fs->super->s_blocks_count) | |
12612 | + block = fs->super->s_first_data_block; | |
12613 | + if (block == orig) { | |
12614 | + pb->error = EXT2_ET_BLOCK_ALLOC_FAIL; | |
12615 | + return BLOCK_ABORT; | |
12616 | + } | |
12617 | + } while (ext2fs_test_block_bitmap(pb->reserve, block) || | |
12618 | + ext2fs_test_block_bitmap(pb->alloc_map, block)); | |
12619 | + | |
12620 | + retval = io_channel_read_blk(fs->io, orig, 1, pb->buf); | |
12621 | + if (retval) { | |
12622 | + pb->error = retval; | |
12623 | + return BLOCK_ABORT; | |
12624 | + } | |
12625 | + retval = io_channel_write_blk(fs->io, block, 1, pb->buf); | |
12626 | + if (retval) { | |
12627 | + pb->error = retval; | |
12628 | + return BLOCK_ABORT; | |
12629 | + } | |
12630 | + *block_nr = block; | |
12631 | + ext2fs_mark_block_bitmap(pb->alloc_map, block); | |
12632 | + ret = BLOCK_CHANGED; | |
12633 | + if (pb->flags & EXT2_BMOVE_DEBUG) | |
12634 | + printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino, | |
12635 | + blockcnt, orig, block); | |
12636 | + } | |
12637 | + if (pb->add_dir) { | |
12638 | + retval = ext2fs_add_dir_block(fs->dblist, pb->ino, | |
12639 | + block, (int) blockcnt); | |
12640 | + if (retval) { | |
12641 | + pb->error = retval; | |
12642 | + ret |= BLOCK_ABORT; | |
12643 | + } | |
12644 | + } | |
12645 | + return ret; | |
12646 | +} | |
12647 | + | |
12648 | +errcode_t ext2fs_move_blocks(ext2_filsys fs, | |
12649 | + ext2fs_block_bitmap reserve, | |
12650 | + ext2fs_block_bitmap alloc_map, | |
12651 | + int flags) | |
12652 | +{ | |
12653 | + ext2_ino_t ino; | |
12654 | + struct ext2_inode inode; | |
12655 | + errcode_t retval; | |
12656 | + struct process_block_struct pb; | |
12657 | + ext2_inode_scan scan; | |
12658 | + char *block_buf; | |
12659 | + | |
12660 | + retval = ext2fs_open_inode_scan(fs, 0, &scan); | |
12661 | + if (retval) | |
12662 | + return retval; | |
12663 | + | |
12664 | + pb.reserve = reserve; | |
12665 | + pb.error = 0; | |
12666 | + pb.alloc_map = alloc_map ? alloc_map : fs->block_map; | |
12667 | + pb.flags = flags; | |
12668 | + | |
12669 | + retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf); | |
12670 | + if (retval) | |
12671 | + return retval; | |
12672 | + pb.buf = block_buf + fs->blocksize * 3; | |
12673 | + | |
12674 | + /* | |
12675 | + * If GET_DBLIST is set in the flags field, then we should | |
12676 | + * gather directory block information while we're doing the | |
12677 | + * block move. | |
12678 | + */ | |
12679 | + if (flags & EXT2_BMOVE_GET_DBLIST) { | |
12680 | + if (fs->dblist) { | |
12681 | + ext2fs_free_dblist(fs->dblist); | |
12682 | + fs->dblist = NULL; | |
12683 | + } | |
12684 | + retval = ext2fs_init_dblist(fs, 0); | |
12685 | + if (retval) | |
12686 | + return retval; | |
12687 | + } | |
12688 | + | |
12689 | + retval = ext2fs_get_next_inode(scan, &ino, &inode); | |
12690 | + if (retval) | |
12691 | + return retval; | |
12692 | + | |
12693 | + while (ino) { | |
12694 | + if ((inode.i_links_count == 0) || | |
12695 | + !ext2fs_inode_has_valid_blocks(&inode)) | |
12696 | + goto next; | |
12697 | + | |
12698 | + pb.ino = ino; | |
12699 | + pb.inode = &inode; | |
12700 | + | |
12701 | + pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && | |
12702 | + flags & EXT2_BMOVE_GET_DBLIST); | |
12703 | + | |
12704 | + retval = ext2fs_block_iterate2(fs, ino, 0, block_buf, | |
12705 | + process_block, &pb); | |
12706 | + if (retval) | |
12707 | + return retval; | |
12708 | + if (pb.error) | |
12709 | + return pb.error; | |
12710 | + | |
12711 | + next: | |
12712 | + retval = ext2fs_get_next_inode(scan, &ino, &inode); | |
12713 | + if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) | |
12714 | + goto next; | |
12715 | + } | |
12716 | + return 0; | |
12717 | +} | |
12718 | + | |
12719 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/brel.h busybox/e2fsprogs/ext2fs/brel.h | |
12720 | --- busybox-1.00/e2fsprogs/ext2fs/brel.h 1970-01-01 01:00:00.000000000 +0100 | |
12721 | +++ busybox/e2fsprogs/ext2fs/brel.h 2005-06-04 08:20:16.000000000 +0200 | |
12722 | @@ -0,0 +1,86 @@ | |
12723 | +/* | |
12724 | + * brel.h | |
12725 | + * | |
12726 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
12727 | + * | |
12728 | + * %Begin-Header% | |
12729 | + * This file may be redistributed under the terms of the GNU Public | |
12730 | + * License. | |
12731 | + * %End-Header% | |
12732 | + */ | |
12733 | + | |
12734 | +struct ext2_block_relocate_entry { | |
12735 | + blk_t new; | |
12736 | + __s16 offset; | |
12737 | + __u16 flags; | |
12738 | + union { | |
12739 | + blk_t block_ref; | |
12740 | + ext2_ino_t inode_ref; | |
12741 | + } owner; | |
12742 | +}; | |
12743 | + | |
12744 | +#define RELOCATE_TYPE_REF 0x0007 | |
12745 | +#define RELOCATE_BLOCK_REF 0x0001 | |
12746 | +#define RELOCATE_INODE_REF 0x0002 | |
12747 | + | |
12748 | +typedef struct ext2_block_relocation_table *ext2_brel; | |
12749 | + | |
12750 | +struct ext2_block_relocation_table { | |
12751 | + __u32 magic; | |
12752 | + char *name; | |
12753 | + blk_t current; | |
12754 | + void *priv_data; | |
12755 | + | |
12756 | + /* | |
12757 | + * Add a block relocation entry. | |
12758 | + */ | |
12759 | + errcode_t (*put)(ext2_brel brel, blk_t old, | |
12760 | + struct ext2_block_relocate_entry *ent); | |
12761 | + | |
12762 | + /* | |
12763 | + * Get a block relocation entry. | |
12764 | + */ | |
12765 | + errcode_t (*get)(ext2_brel brel, blk_t old, | |
12766 | + struct ext2_block_relocate_entry *ent); | |
12767 | + | |
12768 | + /* | |
12769 | + * Initialize for iterating over the block relocation entries. | |
12770 | + */ | |
12771 | + errcode_t (*start_iter)(ext2_brel brel); | |
12772 | + | |
12773 | + /* | |
12774 | + * The iterator function for the inode relocation entries. | |
12775 | + * Returns an inode number of 0 when out of entries. | |
12776 | + */ | |
12777 | + errcode_t (*next)(ext2_brel brel, blk_t *old, | |
12778 | + struct ext2_block_relocate_entry *ent); | |
12779 | + | |
12780 | + /* | |
12781 | + * Move the inode relocation table from one block number to | |
12782 | + * another. | |
12783 | + */ | |
12784 | + errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new); | |
12785 | + | |
12786 | + /* | |
12787 | + * Remove a block relocation entry. | |
12788 | + */ | |
12789 | + errcode_t (*delete)(ext2_brel brel, blk_t old); | |
12790 | + | |
12791 | + | |
12792 | + /* | |
12793 | + * Free the block relocation table. | |
12794 | + */ | |
12795 | + errcode_t (*free)(ext2_brel brel); | |
12796 | +}; | |
12797 | + | |
12798 | +errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, | |
12799 | + ext2_brel *brel); | |
12800 | + | |
12801 | +#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent)) | |
12802 | +#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent)) | |
12803 | +#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel))) | |
12804 | +#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent)) | |
12805 | +#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new)) | |
12806 | +#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old)) | |
12807 | +#define ext2fs_brel_free(brel) ((brel)->free((brel))) | |
12808 | + | |
12809 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/brel_ma.c busybox/e2fsprogs/ext2fs/brel_ma.c | |
12810 | --- busybox-1.00/e2fsprogs/ext2fs/brel_ma.c 1970-01-01 01:00:00.000000000 +0100 | |
12811 | +++ busybox/e2fsprogs/ext2fs/brel_ma.c 2005-06-04 08:20:16.000000000 +0200 | |
12812 | @@ -0,0 +1,197 @@ | |
12813 | +/* | |
12814 | + * brel_ma.c | |
12815 | + * | |
12816 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
12817 | + * | |
12818 | + * TODO: rewrite to not use a direct array!!! (Fortunately this | |
12819 | + * module isn't really used yet.) | |
12820 | + * | |
12821 | + * %Begin-Header% | |
12822 | + * This file may be redistributed under the terms of the GNU Public | |
12823 | + * License. | |
12824 | + * %End-Header% | |
12825 | + */ | |
12826 | + | |
12827 | +#include <fcntl.h> | |
12828 | +#include <stdio.h> | |
12829 | +#include <string.h> | |
12830 | +#if HAVE_UNISTD_H | |
12831 | +#include <unistd.h> | |
12832 | +#endif | |
12833 | +#if HAVE_ERRNO_H | |
12834 | +#include <errno.h> | |
12835 | +#endif | |
12836 | + | |
12837 | +#include "ext2_fs.h" | |
12838 | +#include "ext2fs.h" | |
12839 | +#include "brel.h" | |
12840 | + | |
12841 | +static errcode_t bma_put(ext2_brel brel, blk_t old, | |
12842 | + struct ext2_block_relocate_entry *ent); | |
12843 | +static errcode_t bma_get(ext2_brel brel, blk_t old, | |
12844 | + struct ext2_block_relocate_entry *ent); | |
12845 | +static errcode_t bma_start_iter(ext2_brel brel); | |
12846 | +static errcode_t bma_next(ext2_brel brel, blk_t *old, | |
12847 | + struct ext2_block_relocate_entry *ent); | |
12848 | +static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new); | |
12849 | +static errcode_t bma_delete(ext2_brel brel, blk_t old); | |
12850 | +static errcode_t bma_free(ext2_brel brel); | |
12851 | + | |
12852 | +struct brel_ma { | |
12853 | + __u32 magic; | |
12854 | + blk_t max_block; | |
12855 | + struct ext2_block_relocate_entry *entries; | |
12856 | +}; | |
12857 | + | |
12858 | +errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, | |
12859 | + ext2_brel *new_brel) | |
12860 | +{ | |
12861 | + ext2_brel brel = 0; | |
12862 | + errcode_t retval; | |
12863 | + struct brel_ma *ma = 0; | |
12864 | + size_t size; | |
12865 | + | |
12866 | + *new_brel = 0; | |
12867 | + | |
12868 | + /* | |
12869 | + * Allocate memory structures | |
12870 | + */ | |
12871 | + retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table), | |
12872 | + &brel); | |
12873 | + if (retval) | |
12874 | + goto errout; | |
12875 | + memset(brel, 0, sizeof(struct ext2_block_relocation_table)); | |
12876 | + | |
12877 | + retval = ext2fs_get_mem(strlen(name)+1, &brel->name); | |
12878 | + if (retval) | |
12879 | + goto errout; | |
12880 | + strcpy(brel->name, name); | |
12881 | + | |
12882 | + retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma); | |
12883 | + if (retval) | |
12884 | + goto errout; | |
12885 | + memset(ma, 0, sizeof(struct brel_ma)); | |
12886 | + brel->priv_data = ma; | |
12887 | + | |
12888 | + size = (size_t) (sizeof(struct ext2_block_relocate_entry) * | |
12889 | + (max_block+1)); | |
12890 | + retval = ext2fs_get_mem(size, &ma->entries); | |
12891 | + if (retval) | |
12892 | + goto errout; | |
12893 | + memset(ma->entries, 0, size); | |
12894 | + ma->max_block = max_block; | |
12895 | + | |
12896 | + /* | |
12897 | + * Fill in the brel data structure | |
12898 | + */ | |
12899 | + brel->put = bma_put; | |
12900 | + brel->get = bma_get; | |
12901 | + brel->start_iter = bma_start_iter; | |
12902 | + brel->next = bma_next; | |
12903 | + brel->move = bma_move; | |
12904 | + brel->delete = bma_delete; | |
12905 | + brel->free = bma_free; | |
12906 | + | |
12907 | + *new_brel = brel; | |
12908 | + return 0; | |
12909 | + | |
12910 | +errout: | |
12911 | + bma_free(brel); | |
12912 | + return retval; | |
12913 | +} | |
12914 | + | |
12915 | +static errcode_t bma_put(ext2_brel brel, blk_t old, | |
12916 | + struct ext2_block_relocate_entry *ent) | |
12917 | +{ | |
12918 | + struct brel_ma *ma; | |
12919 | + | |
12920 | + ma = brel->priv_data; | |
12921 | + if (old > ma->max_block) | |
12922 | + return EXT2_ET_INVALID_ARGUMENT; | |
12923 | + ma->entries[(unsigned)old] = *ent; | |
12924 | + return 0; | |
12925 | +} | |
12926 | + | |
12927 | +static errcode_t bma_get(ext2_brel brel, blk_t old, | |
12928 | + struct ext2_block_relocate_entry *ent) | |
12929 | +{ | |
12930 | + struct brel_ma *ma; | |
12931 | + | |
12932 | + ma = brel->priv_data; | |
12933 | + if (old > ma->max_block) | |
12934 | + return EXT2_ET_INVALID_ARGUMENT; | |
12935 | + if (ma->entries[(unsigned)old].new == 0) | |
12936 | + return ENOENT; | |
12937 | + *ent = ma->entries[old]; | |
12938 | + return 0; | |
12939 | +} | |
12940 | + | |
12941 | +static errcode_t bma_start_iter(ext2_brel brel) | |
12942 | +{ | |
12943 | + brel->current = 0; | |
12944 | + return 0; | |
12945 | +} | |
12946 | + | |
12947 | +static errcode_t bma_next(ext2_brel brel, blk_t *old, | |
12948 | + struct ext2_block_relocate_entry *ent) | |
12949 | +{ | |
12950 | + struct brel_ma *ma; | |
12951 | + | |
12952 | + ma = brel->priv_data; | |
12953 | + while (++brel->current < ma->max_block) { | |
12954 | + if (ma->entries[(unsigned)brel->current].new == 0) | |
12955 | + continue; | |
12956 | + *old = brel->current; | |
12957 | + *ent = ma->entries[(unsigned)brel->current]; | |
12958 | + return 0; | |
12959 | + } | |
12960 | + *old = 0; | |
12961 | + return 0; | |
12962 | +} | |
12963 | + | |
12964 | +static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new) | |
12965 | +{ | |
12966 | + struct brel_ma *ma; | |
12967 | + | |
12968 | + ma = brel->priv_data; | |
12969 | + if ((old > ma->max_block) || (new > ma->max_block)) | |
12970 | + return EXT2_ET_INVALID_ARGUMENT; | |
12971 | + if (ma->entries[(unsigned)old].new == 0) | |
12972 | + return ENOENT; | |
12973 | + ma->entries[(unsigned)new] = ma->entries[old]; | |
12974 | + ma->entries[(unsigned)old].new = 0; | |
12975 | + return 0; | |
12976 | +} | |
12977 | + | |
12978 | +static errcode_t bma_delete(ext2_brel brel, blk_t old) | |
12979 | +{ | |
12980 | + struct brel_ma *ma; | |
12981 | + | |
12982 | + ma = brel->priv_data; | |
12983 | + if (old > ma->max_block) | |
12984 | + return EXT2_ET_INVALID_ARGUMENT; | |
12985 | + if (ma->entries[(unsigned)old].new == 0) | |
12986 | + return ENOENT; | |
12987 | + ma->entries[(unsigned)old].new = 0; | |
12988 | + return 0; | |
12989 | +} | |
12990 | + | |
12991 | +static errcode_t bma_free(ext2_brel brel) | |
12992 | +{ | |
12993 | + struct brel_ma *ma; | |
12994 | + | |
12995 | + if (!brel) | |
12996 | + return 0; | |
12997 | + | |
12998 | + ma = brel->priv_data; | |
12999 | + | |
13000 | + if (ma) { | |
13001 | + if (ma->entries) | |
13002 | + ext2fs_free_mem(&ma->entries); | |
13003 | + ext2fs_free_mem(&ma); | |
13004 | + } | |
13005 | + if (brel->name) | |
13006 | + ext2fs_free_mem(&brel->name); | |
13007 | + ext2fs_free_mem(&brel); | |
13008 | + return 0; | |
13009 | +} | |
13010 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/check_desc.c busybox/e2fsprogs/ext2fs/check_desc.c | |
13011 | --- busybox-1.00/e2fsprogs/ext2fs/check_desc.c 1970-01-01 01:00:00.000000000 +0100 | |
13012 | +++ busybox/e2fsprogs/ext2fs/check_desc.c 2005-06-04 08:20:16.000000000 +0200 | |
13013 | @@ -0,0 +1,68 @@ | |
13014 | +/* | |
13015 | + * check_desc.c --- Check the group descriptors of an ext2 filesystem | |
13016 | + * | |
13017 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
13018 | + * | |
13019 | + * %Begin-Header% | |
13020 | + * This file may be redistributed under the terms of the GNU Public | |
13021 | + * License. | |
13022 | + * %End-Header% | |
13023 | + */ | |
13024 | + | |
13025 | +#include <stdio.h> | |
13026 | +#include <string.h> | |
13027 | +#if HAVE_UNISTD_H | |
13028 | +#include <unistd.h> | |
13029 | +#endif | |
13030 | +#include <fcntl.h> | |
13031 | +#include <time.h> | |
13032 | +#if HAVE_SYS_STAT_H | |
13033 | +#include <sys/stat.h> | |
13034 | +#endif | |
13035 | +#if HAVE_SYS_TYPES_H | |
13036 | +#include <sys/types.h> | |
13037 | +#endif | |
13038 | + | |
13039 | +#include "ext2_fs.h" | |
13040 | +#include "ext2fs.h" | |
13041 | + | |
13042 | +/* | |
13043 | + * This routine sanity checks the group descriptors | |
13044 | + */ | |
13045 | +errcode_t ext2fs_check_desc(ext2_filsys fs) | |
13046 | +{ | |
13047 | + dgrp_t i; | |
13048 | + blk_t block = fs->super->s_first_data_block; | |
13049 | + blk_t next; | |
13050 | + | |
13051 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
13052 | + | |
13053 | + for (i = 0; i < fs->group_desc_count; i++) { | |
13054 | + next = block + fs->super->s_blocks_per_group; | |
13055 | + /* | |
13056 | + * Check to make sure block bitmap for group is | |
13057 | + * located within the group. | |
13058 | + */ | |
13059 | + if (fs->group_desc[i].bg_block_bitmap < block || | |
13060 | + fs->group_desc[i].bg_block_bitmap >= next) | |
13061 | + return EXT2_ET_GDESC_BAD_BLOCK_MAP; | |
13062 | + /* | |
13063 | + * Check to make sure inode bitmap for group is | |
13064 | + * located within the group | |
13065 | + */ | |
13066 | + if (fs->group_desc[i].bg_inode_bitmap < block || | |
13067 | + fs->group_desc[i].bg_inode_bitmap >= next) | |
13068 | + return EXT2_ET_GDESC_BAD_INODE_MAP; | |
13069 | + /* | |
13070 | + * Check to make sure inode table for group is located | |
13071 | + * within the group | |
13072 | + */ | |
13073 | + if (fs->group_desc[i].bg_inode_table < block || | |
13074 | + ((fs->group_desc[i].bg_inode_table + | |
13075 | + fs->inode_blocks_per_group) >= next)) | |
13076 | + return EXT2_ET_GDESC_BAD_INODE_TABLE; | |
13077 | + | |
13078 | + block = next; | |
13079 | + } | |
13080 | + return 0; | |
13081 | +} | |
13082 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/closefs.c busybox/e2fsprogs/ext2fs/closefs.c | |
13083 | --- busybox-1.00/e2fsprogs/ext2fs/closefs.c 1970-01-01 01:00:00.000000000 +0100 | |
13084 | +++ busybox/e2fsprogs/ext2fs/closefs.c 2005-06-04 08:20:16.000000000 +0200 | |
13085 | @@ -0,0 +1,381 @@ | |
13086 | +/* | |
13087 | + * closefs.c --- close an ext2 filesystem | |
13088 | + * | |
13089 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
13090 | + * | |
13091 | + * %Begin-Header% | |
13092 | + * This file may be redistributed under the terms of the GNU Public | |
13093 | + * License. | |
13094 | + * %End-Header% | |
13095 | + */ | |
13096 | + | |
13097 | +#include <stdio.h> | |
13098 | +#if HAVE_UNISTD_H | |
13099 | +#include <unistd.h> | |
13100 | +#endif | |
13101 | +#include <time.h> | |
13102 | +#include <string.h> | |
13103 | + | |
13104 | +#include "ext2_fs.h" | |
13105 | +#include "ext2fsP.h" | |
13106 | + | |
13107 | +static int test_root(int a, int b) | |
13108 | +{ | |
13109 | + if (a == 0) | |
13110 | + return 1; | |
13111 | + while (1) { | |
13112 | + if (a == 1) | |
13113 | + return 1; | |
13114 | + if (a % b) | |
13115 | + return 0; | |
13116 | + a = a / b; | |
13117 | + } | |
13118 | +} | |
13119 | + | |
13120 | +int ext2fs_bg_has_super(ext2_filsys fs, int group_block) | |
13121 | +{ | |
13122 | + if (!(fs->super->s_feature_ro_compat & | |
13123 | + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) | |
13124 | + return 1; | |
13125 | + | |
13126 | + if (test_root(group_block, 3) || (test_root(group_block, 5)) || | |
13127 | + test_root(group_block, 7)) | |
13128 | + return 1; | |
13129 | + | |
13130 | + return 0; | |
13131 | +} | |
13132 | + | |
13133 | +int ext2fs_super_and_bgd_loc(ext2_filsys fs, | |
13134 | + dgrp_t group, | |
13135 | + blk_t *ret_super_blk, | |
13136 | + blk_t *ret_old_desc_blk, | |
13137 | + blk_t *ret_new_desc_blk, | |
13138 | + int *ret_meta_bg) | |
13139 | +{ | |
13140 | + blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0; | |
13141 | + unsigned int meta_bg, meta_bg_size; | |
13142 | + int numblocks, has_super; | |
13143 | + int old_desc_blocks; | |
13144 | + | |
13145 | + group_block = fs->super->s_first_data_block + | |
13146 | + (group * fs->super->s_blocks_per_group); | |
13147 | + | |
13148 | + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) | |
13149 | + old_desc_blocks = fs->super->s_first_meta_bg; | |
13150 | + else | |
13151 | + old_desc_blocks = | |
13152 | + fs->desc_blocks + fs->super->s_reserved_gdt_blocks; | |
13153 | + | |
13154 | + if (group == fs->group_desc_count-1) { | |
13155 | + numblocks = (fs->super->s_blocks_count - | |
13156 | + fs->super->s_first_data_block) % | |
13157 | + fs->super->s_blocks_per_group; | |
13158 | + if (!numblocks) | |
13159 | + numblocks = fs->super->s_blocks_per_group; | |
13160 | + } else | |
13161 | + numblocks = fs->super->s_blocks_per_group; | |
13162 | + | |
13163 | + has_super = ext2fs_bg_has_super(fs, group); | |
13164 | + | |
13165 | + if (has_super) { | |
13166 | + super_blk = group_block; | |
13167 | + numblocks--; | |
13168 | + } | |
13169 | + meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); | |
13170 | + meta_bg = group / meta_bg_size; | |
13171 | + | |
13172 | + if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || | |
13173 | + (meta_bg < fs->super->s_first_meta_bg)) { | |
13174 | + if (has_super) { | |
13175 | + old_desc_blk = group_block + 1; | |
13176 | + numblocks -= old_desc_blocks; | |
13177 | + } | |
13178 | + } else { | |
13179 | + if (((group % meta_bg_size) == 0) || | |
13180 | + ((group % meta_bg_size) == 1) || | |
13181 | + ((group % meta_bg_size) == (meta_bg_size-1))) { | |
13182 | + if (has_super) | |
13183 | + has_super = 1; | |
13184 | + new_desc_blk = group_block + has_super; | |
13185 | + numblocks--; | |
13186 | + } | |
13187 | + } | |
13188 | + | |
13189 | + numblocks -= 2 + fs->inode_blocks_per_group; | |
13190 | + | |
13191 | + if (ret_super_blk) | |
13192 | + *ret_super_blk = super_blk; | |
13193 | + if (ret_old_desc_blk) | |
13194 | + *ret_old_desc_blk = old_desc_blk; | |
13195 | + if (ret_new_desc_blk) | |
13196 | + *ret_new_desc_blk = new_desc_blk; | |
13197 | + if (ret_meta_bg) | |
13198 | + *ret_meta_bg = meta_bg; | |
13199 | + return (numblocks); | |
13200 | +} | |
13201 | + | |
13202 | + | |
13203 | +/* | |
13204 | + * This function forces out the primary superblock. We need to only | |
13205 | + * write out those fields which we have changed, since if the | |
13206 | + * filesystem is mounted, it may have changed some of the other | |
13207 | + * fields. | |
13208 | + * | |
13209 | + * It takes as input a superblock which has already been byte swapped | |
13210 | + * (if necessary). | |
13211 | + * | |
13212 | + */ | |
13213 | +static errcode_t write_primary_superblock(ext2_filsys fs, | |
13214 | + struct ext2_super_block *super) | |
13215 | +{ | |
13216 | + __u16 *old_super, *new_super; | |
13217 | + int check_idx, write_idx, size; | |
13218 | + errcode_t retval; | |
13219 | + | |
13220 | + if (!fs->io->manager->write_byte || !fs->orig_super) { | |
13221 | + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); | |
13222 | + retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE, | |
13223 | + super); | |
13224 | + io_channel_set_blksize(fs->io, fs->blocksize); | |
13225 | + return retval; | |
13226 | + } | |
13227 | + | |
13228 | + old_super = (__u16 *) fs->orig_super; | |
13229 | + new_super = (__u16 *) super; | |
13230 | + | |
13231 | + for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) { | |
13232 | + if (old_super[check_idx] == new_super[check_idx]) | |
13233 | + continue; | |
13234 | + write_idx = check_idx; | |
13235 | + for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++) | |
13236 | + if (old_super[check_idx] == new_super[check_idx]) | |
13237 | + break; | |
13238 | + size = 2 * (check_idx - write_idx); | |
13239 | +#if 0 | |
13240 | + printf("Writing %d bytes starting at %d\n", | |
13241 | + size, write_idx*2); | |
13242 | +#endif | |
13243 | + retval = io_channel_write_byte(fs->io, | |
13244 | + SUPERBLOCK_OFFSET + (2 * write_idx), size, | |
13245 | + new_super + write_idx); | |
13246 | + if (retval) | |
13247 | + return retval; | |
13248 | + } | |
13249 | + memcpy(fs->orig_super, super, SUPERBLOCK_SIZE); | |
13250 | + return 0; | |
13251 | +} | |
13252 | + | |
13253 | + | |
13254 | +/* | |
13255 | + * Updates the revision to EXT2_DYNAMIC_REV | |
13256 | + */ | |
13257 | +void ext2fs_update_dynamic_rev(ext2_filsys fs) | |
13258 | +{ | |
13259 | + struct ext2_super_block *sb = fs->super; | |
13260 | + | |
13261 | + if (sb->s_rev_level > EXT2_GOOD_OLD_REV) | |
13262 | + return; | |
13263 | + | |
13264 | + sb->s_rev_level = EXT2_DYNAMIC_REV; | |
13265 | + sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; | |
13266 | + sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; | |
13267 | + /* s_uuid is handled by e2fsck already */ | |
13268 | + /* other fields should be left alone */ | |
13269 | +} | |
13270 | + | |
13271 | +static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, | |
13272 | + blk_t group_block, | |
13273 | + struct ext2_super_block *super_shadow) | |
13274 | +{ | |
13275 | + dgrp_t sgrp = group; | |
13276 | + | |
13277 | + if (sgrp > ((1 << 16) - 1)) | |
13278 | + sgrp = (1 << 16) - 1; | |
13279 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
13280 | + if (fs->flags & EXT2_FLAG_SWAP_BYTES) | |
13281 | + super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); | |
13282 | + else | |
13283 | +#endif | |
13284 | + fs->super->s_block_group_nr = sgrp; | |
13285 | + | |
13286 | + return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE, | |
13287 | + super_shadow); | |
13288 | +} | |
13289 | + | |
13290 | + | |
13291 | +errcode_t ext2fs_flush(ext2_filsys fs) | |
13292 | +{ | |
13293 | + dgrp_t i,j; | |
13294 | + blk_t group_block; | |
13295 | + errcode_t retval; | |
13296 | + unsigned long fs_state; | |
13297 | + struct ext2_super_block *super_shadow = 0; | |
13298 | + struct ext2_group_desc *group_shadow = 0; | |
13299 | + struct ext2_group_desc *s, *t; | |
13300 | + char *group_ptr; | |
13301 | + int old_desc_blocks; | |
13302 | + | |
13303 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
13304 | + | |
13305 | + fs_state = fs->super->s_state; | |
13306 | + | |
13307 | + fs->super->s_wtime = time(NULL); | |
13308 | + fs->super->s_block_group_nr = 0; | |
13309 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
13310 | + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | |
13311 | + retval = EXT2_ET_NO_MEMORY; | |
13312 | + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); | |
13313 | + if (retval) | |
13314 | + goto errout; | |
13315 | + retval = ext2fs_get_mem((size_t)(fs->blocksize * | |
13316 | + fs->desc_blocks), | |
13317 | + &group_shadow); | |
13318 | + if (retval) | |
13319 | + goto errout; | |
13320 | + memset(group_shadow, 0, (size_t) fs->blocksize * | |
13321 | + fs->desc_blocks); | |
13322 | + | |
13323 | + /* swap the group descriptors */ | |
13324 | + for (j=0, s=fs->group_desc, t=group_shadow; | |
13325 | + j < fs->group_desc_count; j++, t++, s++) { | |
13326 | + *t = *s; | |
13327 | + ext2fs_swap_group_desc(t); | |
13328 | + } | |
13329 | + } else { | |
13330 | + super_shadow = fs->super; | |
13331 | + group_shadow = fs->group_desc; | |
13332 | + } | |
13333 | +#else | |
13334 | + super_shadow = fs->super; | |
13335 | + group_shadow = fs->group_desc; | |
13336 | +#endif | |
13337 | + | |
13338 | + /* | |
13339 | + * If this is an external journal device, don't write out the | |
13340 | + * block group descriptors or any of the backup superblocks | |
13341 | + */ | |
13342 | + if (fs->super->s_feature_incompat & | |
13343 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | |
13344 | + goto write_primary_superblock_only; | |
13345 | + | |
13346 | + /* | |
13347 | + * Set the state of the FS to be non-valid. (The state has | |
13348 | + * already been backed up earlier, and will be restored after | |
13349 | + * we write out the backup superblocks.) | |
13350 | + */ | |
13351 | + fs->super->s_state &= ~EXT2_VALID_FS; | |
13352 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
13353 | + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | |
13354 | + *super_shadow = *fs->super; | |
13355 | + ext2fs_swap_super(super_shadow); | |
13356 | + } | |
13357 | +#endif | |
13358 | + | |
13359 | + /* | |
13360 | + * Write out the master group descriptors, and the backup | |
13361 | + * superblocks and group descriptors. | |
13362 | + */ | |
13363 | + group_block = fs->super->s_first_data_block; | |
13364 | + group_ptr = (char *) group_shadow; | |
13365 | + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) | |
13366 | + old_desc_blocks = fs->super->s_first_meta_bg; | |
13367 | + else | |
13368 | + old_desc_blocks = fs->desc_blocks; | |
13369 | + | |
13370 | + for (i = 0; i < fs->group_desc_count; i++) { | |
13371 | + blk_t super_blk, old_desc_blk, new_desc_blk; | |
13372 | + int meta_bg; | |
13373 | + | |
13374 | + ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, | |
13375 | + &new_desc_blk, &meta_bg); | |
13376 | + | |
13377 | + if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { | |
13378 | + retval = write_backup_super(fs, i, super_blk, | |
13379 | + super_shadow); | |
13380 | + if (retval) | |
13381 | + goto errout; | |
13382 | + } | |
13383 | + if (fs->flags & EXT2_FLAG_SUPER_ONLY) | |
13384 | + continue; | |
13385 | + if ((old_desc_blk) && | |
13386 | + (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { | |
13387 | + retval = io_channel_write_blk(fs->io, | |
13388 | + old_desc_blk, old_desc_blocks, group_ptr); | |
13389 | + if (retval) | |
13390 | + goto errout; | |
13391 | + } | |
13392 | + if (new_desc_blk) { | |
13393 | + retval = io_channel_write_blk(fs->io, new_desc_blk, | |
13394 | + 1, group_ptr + (meta_bg*fs->blocksize)); | |
13395 | + if (retval) | |
13396 | + goto errout; | |
13397 | + } | |
13398 | + } | |
13399 | + fs->super->s_block_group_nr = 0; | |
13400 | + fs->super->s_state = fs_state; | |
13401 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
13402 | + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | |
13403 | + *super_shadow = *fs->super; | |
13404 | + ext2fs_swap_super(super_shadow); | |
13405 | + } | |
13406 | +#endif | |
13407 | + | |
13408 | + /* | |
13409 | + * If the write_bitmaps() function is present, call it to | |
13410 | + * flush the bitmaps. This is done this way so that a simple | |
13411 | + * program that doesn't mess with the bitmaps doesn't need to | |
13412 | + * drag in the bitmaps.c code. | |
13413 | + */ | |
13414 | + if (fs->write_bitmaps) { | |
13415 | + retval = fs->write_bitmaps(fs); | |
13416 | + if (retval) | |
13417 | + goto errout; | |
13418 | + } | |
13419 | + | |
13420 | +write_primary_superblock_only: | |
13421 | + /* | |
13422 | + * Write out master superblock. This has to be done | |
13423 | + * separately, since it is located at a fixed location | |
13424 | + * (SUPERBLOCK_OFFSET). We flush all other pending changes | |
13425 | + * out to disk first, just to avoid a race condition with an | |
13426 | + * insy-tinsy window.... | |
13427 | + */ | |
13428 | + retval = io_channel_flush(fs->io); | |
13429 | + retval = write_primary_superblock(fs, super_shadow); | |
13430 | + if (retval) | |
13431 | + goto errout; | |
13432 | + | |
13433 | + fs->flags &= ~EXT2_FLAG_DIRTY; | |
13434 | + | |
13435 | + retval = io_channel_flush(fs->io); | |
13436 | +errout: | |
13437 | + fs->super->s_state = fs_state; | |
13438 | + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | |
13439 | + if (super_shadow) | |
13440 | + ext2fs_free_mem(&super_shadow); | |
13441 | + if (group_shadow) | |
13442 | + ext2fs_free_mem(&group_shadow); | |
13443 | + } | |
13444 | + return retval; | |
13445 | +} | |
13446 | + | |
13447 | +errcode_t ext2fs_close(ext2_filsys fs) | |
13448 | +{ | |
13449 | + errcode_t retval; | |
13450 | + | |
13451 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
13452 | + | |
13453 | + if (fs->flags & EXT2_FLAG_DIRTY) { | |
13454 | + retval = ext2fs_flush(fs); | |
13455 | + if (retval) | |
13456 | + return retval; | |
13457 | + } | |
13458 | + if (fs->write_bitmaps) { | |
13459 | + retval = fs->write_bitmaps(fs); | |
13460 | + if (retval) | |
13461 | + return retval; | |
13462 | + } | |
13463 | + ext2fs_free(fs); | |
13464 | + return 0; | |
13465 | +} | |
13466 | + | |
13467 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/cmp_bitmaps.c busybox/e2fsprogs/ext2fs/cmp_bitmaps.c | |
13468 | --- busybox-1.00/e2fsprogs/ext2fs/cmp_bitmaps.c 1970-01-01 01:00:00.000000000 +0100 | |
13469 | +++ busybox/e2fsprogs/ext2fs/cmp_bitmaps.c 2005-06-04 08:20:16.000000000 +0200 | |
13470 | @@ -0,0 +1,72 @@ | |
13471 | +/* | |
13472 | + * cmp_bitmaps.c --- routines to compare inode and block bitmaps. | |
13473 | + * | |
13474 | + * Copyright (C) 1995 Theodore Ts'o. | |
13475 | + * | |
13476 | + * %Begin-Header% | |
13477 | + * This file may be redistributed under the terms of the GNU Public | |
13478 | + * License. | |
13479 | + * %End-Header% | |
13480 | + */ | |
13481 | + | |
13482 | +#include <stdio.h> | |
13483 | +#include <string.h> | |
13484 | +#if HAVE_UNISTD_H | |
13485 | +#include <unistd.h> | |
13486 | +#endif | |
13487 | +#include <fcntl.h> | |
13488 | +#include <time.h> | |
13489 | +#if HAVE_SYS_STAT_H | |
13490 | +#include <sys/stat.h> | |
13491 | +#endif | |
13492 | +#if HAVE_SYS_TYPES_H | |
13493 | +#include <sys/types.h> | |
13494 | +#endif | |
13495 | + | |
13496 | +#include "ext2_fs.h" | |
13497 | +#include "ext2fs.h" | |
13498 | + | |
13499 | +errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, | |
13500 | + ext2fs_block_bitmap bm2) | |
13501 | +{ | |
13502 | + blk_t i; | |
13503 | + | |
13504 | + EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP); | |
13505 | + EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP); | |
13506 | + | |
13507 | + if ((bm1->start != bm2->start) || | |
13508 | + (bm1->end != bm2->end) || | |
13509 | + (memcmp(bm1->bitmap, bm2->bitmap, | |
13510 | + (size_t) (bm1->end - bm1->start)/8))) | |
13511 | + return EXT2_ET_NEQ_BLOCK_BITMAP; | |
13512 | + | |
13513 | + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) | |
13514 | + if (ext2fs_fast_test_block_bitmap(bm1, i) != | |
13515 | + ext2fs_fast_test_block_bitmap(bm2, i)) | |
13516 | + return EXT2_ET_NEQ_BLOCK_BITMAP; | |
13517 | + | |
13518 | + return 0; | |
13519 | +} | |
13520 | + | |
13521 | +errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, | |
13522 | + ext2fs_inode_bitmap bm2) | |
13523 | +{ | |
13524 | + ext2_ino_t i; | |
13525 | + | |
13526 | + EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP); | |
13527 | + EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP); | |
13528 | + | |
13529 | + if ((bm1->start != bm2->start) || | |
13530 | + (bm1->end != bm2->end) || | |
13531 | + (memcmp(bm1->bitmap, bm2->bitmap, | |
13532 | + (size_t) (bm1->end - bm1->start)/8))) | |
13533 | + return EXT2_ET_NEQ_INODE_BITMAP; | |
13534 | + | |
13535 | + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) | |
13536 | + if (ext2fs_fast_test_inode_bitmap(bm1, i) != | |
13537 | + ext2fs_fast_test_inode_bitmap(bm2, i)) | |
13538 | + return EXT2_ET_NEQ_INODE_BITMAP; | |
13539 | + | |
13540 | + return 0; | |
13541 | +} | |
13542 | + | |
13543 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dblist.c busybox/e2fsprogs/ext2fs/dblist.c | |
13544 | --- busybox-1.00/e2fsprogs/ext2fs/dblist.c 1970-01-01 01:00:00.000000000 +0100 | |
13545 | +++ busybox/e2fsprogs/ext2fs/dblist.c 2005-06-04 08:20:16.000000000 +0200 | |
13546 | @@ -0,0 +1,260 @@ | |
13547 | +/* | |
13548 | + * dblist.c -- directory block list functions | |
13549 | + * | |
13550 | + * Copyright 1997 by Theodore Ts'o | |
13551 | + * | |
13552 | + * %Begin-Header% | |
13553 | + * This file may be redistributed under the terms of the GNU Public | |
13554 | + * License. | |
13555 | + * %End-Header% | |
13556 | + * | |
13557 | + */ | |
13558 | + | |
13559 | +#include <stdio.h> | |
13560 | +#if HAVE_UNISTD_H | |
13561 | +#include <unistd.h> | |
13562 | +#endif | |
13563 | +#include <string.h> | |
13564 | +#include <time.h> | |
13565 | + | |
13566 | +#include "ext2_fs.h" | |
13567 | +#include "ext2fsP.h" | |
13568 | + | |
13569 | +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b); | |
13570 | + | |
13571 | +/* | |
13572 | + * Returns the number of directories in the filesystem as reported by | |
13573 | + * the group descriptors. Of course, the group descriptors could be | |
13574 | + * wrong! | |
13575 | + */ | |
13576 | +errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs) | |
13577 | +{ | |
13578 | + dgrp_t i; | |
13579 | + ext2_ino_t num_dirs, max_dirs; | |
13580 | + | |
13581 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
13582 | + | |
13583 | + num_dirs = 0; | |
13584 | + max_dirs = fs->super->s_inodes_per_group; | |
13585 | + for (i = 0; i < fs->group_desc_count; i++) { | |
13586 | + if (fs->group_desc[i].bg_used_dirs_count > max_dirs) | |
13587 | + num_dirs += max_dirs / 8; | |
13588 | + else | |
13589 | + num_dirs += fs->group_desc[i].bg_used_dirs_count; | |
13590 | + } | |
13591 | + if (num_dirs > fs->super->s_inodes_count) | |
13592 | + num_dirs = fs->super->s_inodes_count; | |
13593 | + | |
13594 | + *ret_num_dirs = num_dirs; | |
13595 | + | |
13596 | + return 0; | |
13597 | +} | |
13598 | + | |
13599 | +/* | |
13600 | + * helper function for making a new directory block list (for | |
13601 | + * initialize and copy). | |
13602 | + */ | |
13603 | +static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count, | |
13604 | + struct ext2_db_entry *list, | |
13605 | + ext2_dblist *ret_dblist) | |
13606 | +{ | |
13607 | + ext2_dblist dblist; | |
13608 | + errcode_t retval; | |
13609 | + size_t len; | |
13610 | + | |
13611 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
13612 | + | |
13613 | + if ((ret_dblist == 0) && fs->dblist && | |
13614 | + (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST)) | |
13615 | + return 0; | |
13616 | + | |
13617 | + retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist); | |
13618 | + if (retval) | |
13619 | + return retval; | |
13620 | + memset(dblist, 0, sizeof(struct ext2_struct_dblist)); | |
13621 | + | |
13622 | + dblist->magic = EXT2_ET_MAGIC_DBLIST; | |
13623 | + dblist->fs = fs; | |
13624 | + if (size) | |
13625 | + dblist->size = size; | |
13626 | + else { | |
13627 | + retval = ext2fs_get_num_dirs(fs, &dblist->size); | |
13628 | + if (retval) | |
13629 | + goto cleanup; | |
13630 | + dblist->size = (dblist->size * 2) + 12; | |
13631 | + } | |
13632 | + len = (size_t) sizeof(struct ext2_db_entry) * dblist->size; | |
13633 | + dblist->count = count; | |
13634 | + retval = ext2fs_get_mem(len, &dblist->list); | |
13635 | + if (retval) | |
13636 | + goto cleanup; | |
13637 | + | |
13638 | + if (list) | |
13639 | + memcpy(dblist->list, list, len); | |
13640 | + else | |
13641 | + memset(dblist->list, 0, len); | |
13642 | + if (ret_dblist) | |
13643 | + *ret_dblist = dblist; | |
13644 | + else | |
13645 | + fs->dblist = dblist; | |
13646 | + return 0; | |
13647 | +cleanup: | |
13648 | + if (dblist) | |
13649 | + ext2fs_free_mem(&dblist); | |
13650 | + return retval; | |
13651 | +} | |
13652 | + | |
13653 | +/* | |
13654 | + * Initialize a directory block list | |
13655 | + */ | |
13656 | +errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist) | |
13657 | +{ | |
13658 | + ext2_dblist dblist; | |
13659 | + errcode_t retval; | |
13660 | + | |
13661 | + retval = make_dblist(fs, 0, 0, 0, &dblist); | |
13662 | + if (retval) | |
13663 | + return retval; | |
13664 | + | |
13665 | + dblist->sorted = 1; | |
13666 | + if (ret_dblist) | |
13667 | + *ret_dblist = dblist; | |
13668 | + else | |
13669 | + fs->dblist = dblist; | |
13670 | + | |
13671 | + return 0; | |
13672 | +} | |
13673 | + | |
13674 | +/* | |
13675 | + * Copy a directory block list | |
13676 | + */ | |
13677 | +errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest) | |
13678 | +{ | |
13679 | + ext2_dblist dblist; | |
13680 | + errcode_t retval; | |
13681 | + | |
13682 | + retval = make_dblist(src->fs, src->size, src->count, src->list, | |
13683 | + &dblist); | |
13684 | + if (retval) | |
13685 | + return retval; | |
13686 | + dblist->sorted = src->sorted; | |
13687 | + *dest = dblist; | |
13688 | + return 0; | |
13689 | +} | |
13690 | + | |
13691 | +/* | |
13692 | + * Close a directory block list | |
13693 | + * | |
13694 | + * (moved to closefs.c) | |
13695 | + */ | |
13696 | + | |
13697 | + | |
13698 | +/* | |
13699 | + * Add a directory block to the directory block list | |
13700 | + */ | |
13701 | +errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, | |
13702 | + int blockcnt) | |
13703 | +{ | |
13704 | + struct ext2_db_entry *new_entry; | |
13705 | + errcode_t retval; | |
13706 | + unsigned long old_size; | |
13707 | + | |
13708 | + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); | |
13709 | + | |
13710 | + if (dblist->count >= dblist->size) { | |
13711 | + old_size = dblist->size * sizeof(struct ext2_db_entry); | |
13712 | + dblist->size += 100; | |
13713 | + retval = ext2fs_resize_mem(old_size, (size_t) dblist->size * | |
13714 | + sizeof(struct ext2_db_entry), | |
13715 | + &dblist->list); | |
13716 | + if (retval) { | |
13717 | + dblist->size -= 100; | |
13718 | + return retval; | |
13719 | + } | |
13720 | + } | |
13721 | + new_entry = dblist->list + ( (int) dblist->count++); | |
13722 | + new_entry->blk = blk; | |
13723 | + new_entry->ino = ino; | |
13724 | + new_entry->blockcnt = blockcnt; | |
13725 | + | |
13726 | + dblist->sorted = 0; | |
13727 | + | |
13728 | + return 0; | |
13729 | +} | |
13730 | + | |
13731 | +/* | |
13732 | + * Change the directory block to the directory block list | |
13733 | + */ | |
13734 | +errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, | |
13735 | + int blockcnt) | |
13736 | +{ | |
13737 | + dgrp_t i; | |
13738 | + | |
13739 | + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); | |
13740 | + | |
13741 | + for (i=0; i < dblist->count; i++) { | |
13742 | + if ((dblist->list[i].ino != ino) || | |
13743 | + (dblist->list[i].blockcnt != blockcnt)) | |
13744 | + continue; | |
13745 | + dblist->list[i].blk = blk; | |
13746 | + dblist->sorted = 0; | |
13747 | + return 0; | |
13748 | + } | |
13749 | + return EXT2_ET_DB_NOT_FOUND; | |
13750 | +} | |
13751 | + | |
13752 | +void ext2fs_dblist_sort(ext2_dblist dblist, | |
13753 | + EXT2_QSORT_TYPE (*sortfunc)(const void *, | |
13754 | + const void *)) | |
13755 | +{ | |
13756 | + if (!sortfunc) | |
13757 | + sortfunc = dir_block_cmp; | |
13758 | + qsort(dblist->list, (size_t) dblist->count, | |
13759 | + sizeof(struct ext2_db_entry), sortfunc); | |
13760 | + dblist->sorted = 1; | |
13761 | +} | |
13762 | + | |
13763 | +/* | |
13764 | + * This function iterates over the directory block list | |
13765 | + */ | |
13766 | +errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, | |
13767 | + int (*func)(ext2_filsys fs, | |
13768 | + struct ext2_db_entry *db_info, | |
13769 | + void *priv_data), | |
13770 | + void *priv_data) | |
13771 | +{ | |
13772 | + ext2_ino_t i; | |
13773 | + int ret; | |
13774 | + | |
13775 | + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); | |
13776 | + | |
13777 | + if (!dblist->sorted) | |
13778 | + ext2fs_dblist_sort(dblist, 0); | |
13779 | + for (i=0; i < dblist->count; i++) { | |
13780 | + ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data); | |
13781 | + if (ret & DBLIST_ABORT) | |
13782 | + return 0; | |
13783 | + } | |
13784 | + return 0; | |
13785 | +} | |
13786 | + | |
13787 | +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b) | |
13788 | +{ | |
13789 | + const struct ext2_db_entry *db_a = | |
13790 | + (const struct ext2_db_entry *) a; | |
13791 | + const struct ext2_db_entry *db_b = | |
13792 | + (const struct ext2_db_entry *) b; | |
13793 | + | |
13794 | + if (db_a->blk != db_b->blk) | |
13795 | + return (int) (db_a->blk - db_b->blk); | |
13796 | + | |
13797 | + if (db_a->ino != db_b->ino) | |
13798 | + return (int) (db_a->ino - db_b->ino); | |
13799 | + | |
13800 | + return (int) (db_a->blockcnt - db_b->blockcnt); | |
13801 | +} | |
13802 | + | |
13803 | +int ext2fs_dblist_count(ext2_dblist dblist) | |
13804 | +{ | |
13805 | + return (int) dblist->count; | |
13806 | +} | |
13807 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dblist_dir.c busybox/e2fsprogs/ext2fs/dblist_dir.c | |
13808 | --- busybox-1.00/e2fsprogs/ext2fs/dblist_dir.c 1970-01-01 01:00:00.000000000 +0100 | |
13809 | +++ busybox/e2fsprogs/ext2fs/dblist_dir.c 2005-06-04 08:20:16.000000000 +0200 | |
13810 | @@ -0,0 +1,75 @@ | |
13811 | +/* | |
13812 | + * dblist_dir.c --- iterate by directory entry | |
13813 | + * | |
13814 | + * Copyright 1997 by Theodore Ts'o | |
13815 | + * | |
13816 | + * %Begin-Header% | |
13817 | + * This file may be redistributed under the terms of the GNU Public | |
13818 | + * License. | |
13819 | + * %End-Header% | |
13820 | + * | |
13821 | + */ | |
13822 | + | |
13823 | +#include <stdio.h> | |
13824 | +#if HAVE_UNISTD_H | |
13825 | +#include <unistd.h> | |
13826 | +#endif | |
13827 | +#include <string.h> | |
13828 | +#include <time.h> | |
13829 | + | |
13830 | +#include "ext2_fs.h" | |
13831 | +#include "ext2fsP.h" | |
13832 | + | |
13833 | +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info, | |
13834 | + void *priv_data); | |
13835 | + | |
13836 | +errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist, | |
13837 | + int flags, | |
13838 | + char *block_buf, | |
13839 | + int (*func)(ext2_ino_t dir, | |
13840 | + int entry, | |
13841 | + struct ext2_dir_entry *dirent, | |
13842 | + int offset, | |
13843 | + int blocksize, | |
13844 | + char *buf, | |
13845 | + void *priv_data), | |
13846 | + void *priv_data) | |
13847 | +{ | |
13848 | + errcode_t retval; | |
13849 | + struct dir_context ctx; | |
13850 | + | |
13851 | + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); | |
13852 | + | |
13853 | + ctx.dir = 0; | |
13854 | + ctx.flags = flags; | |
13855 | + if (block_buf) | |
13856 | + ctx.buf = block_buf; | |
13857 | + else { | |
13858 | + retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf); | |
13859 | + if (retval) | |
13860 | + return retval; | |
13861 | + } | |
13862 | + ctx.func = func; | |
13863 | + ctx.priv_data = priv_data; | |
13864 | + ctx.errcode = 0; | |
13865 | + | |
13866 | + retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx); | |
13867 | + | |
13868 | + if (!block_buf) | |
13869 | + ext2fs_free_mem(&ctx.buf); | |
13870 | + if (retval) | |
13871 | + return retval; | |
13872 | + return ctx.errcode; | |
13873 | +} | |
13874 | + | |
13875 | +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info, | |
13876 | + void *priv_data) | |
13877 | +{ | |
13878 | + struct dir_context *ctx; | |
13879 | + | |
13880 | + ctx = (struct dir_context *) priv_data; | |
13881 | + ctx->dir = db_info->ino; | |
13882 | + | |
13883 | + return ext2fs_process_dir_block(fs, &db_info->blk, | |
13884 | + db_info->blockcnt, 0, 0, priv_data); | |
13885 | +} | |
13886 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dir_iterate.c busybox/e2fsprogs/ext2fs/dir_iterate.c | |
13887 | --- busybox-1.00/e2fsprogs/ext2fs/dir_iterate.c 1970-01-01 01:00:00.000000000 +0100 | |
13888 | +++ busybox/e2fsprogs/ext2fs/dir_iterate.c 2005-06-04 08:20:16.000000000 +0200 | |
13889 | @@ -0,0 +1,219 @@ | |
13890 | +/* | |
13891 | + * dir_iterate.c --- ext2fs directory iteration operations | |
13892 | + * | |
13893 | + * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o. | |
13894 | + * | |
13895 | + * %Begin-Header% | |
13896 | + * This file may be redistributed under the terms of the GNU Public | |
13897 | + * License. | |
13898 | + * %End-Header% | |
13899 | + */ | |
13900 | + | |
13901 | +#include <stdio.h> | |
13902 | +#include <string.h> | |
13903 | +#if HAVE_UNISTD_H | |
13904 | +#include <unistd.h> | |
13905 | +#endif | |
13906 | +#if HAVE_ERRNO_H | |
13907 | +#include <errno.h> | |
13908 | +#endif | |
13909 | + | |
13910 | +#include "ext2_fs.h" | |
13911 | +#include "ext2fsP.h" | |
13912 | + | |
13913 | +/* | |
13914 | + * This function checks to see whether or not a potential deleted | |
13915 | + * directory entry looks valid. What we do is check the deleted entry | |
13916 | + * and each successive entry to make sure that they all look valid and | |
13917 | + * that the last deleted entry ends at the beginning of the next | |
13918 | + * undeleted entry. Returns 1 if the deleted entry looks valid, zero | |
13919 | + * if not valid. | |
13920 | + */ | |
13921 | +static int ext2fs_validate_entry(char *buf, int offset, int final_offset) | |
13922 | +{ | |
13923 | + struct ext2_dir_entry *dirent; | |
13924 | + | |
13925 | + while (offset < final_offset) { | |
13926 | + dirent = (struct ext2_dir_entry *)(buf + offset); | |
13927 | + offset += dirent->rec_len; | |
13928 | + if ((dirent->rec_len < 8) || | |
13929 | + ((dirent->rec_len % 4) != 0) || | |
13930 | + (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) | |
13931 | + return 0; | |
13932 | + } | |
13933 | + return (offset == final_offset); | |
13934 | +} | |
13935 | + | |
13936 | +errcode_t ext2fs_dir_iterate2(ext2_filsys fs, | |
13937 | + ext2_ino_t dir, | |
13938 | + int flags, | |
13939 | + char *block_buf, | |
13940 | + int (*func)(ext2_ino_t dir, | |
13941 | + int entry, | |
13942 | + struct ext2_dir_entry *dirent, | |
13943 | + int offset, | |
13944 | + int blocksize, | |
13945 | + char *buf, | |
13946 | + void *priv_data), | |
13947 | + void *priv_data) | |
13948 | +{ | |
13949 | + struct dir_context ctx; | |
13950 | + errcode_t retval; | |
13951 | + | |
13952 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
13953 | + | |
13954 | + retval = ext2fs_check_directory(fs, dir); | |
13955 | + if (retval) | |
13956 | + return retval; | |
13957 | + | |
13958 | + ctx.dir = dir; | |
13959 | + ctx.flags = flags; | |
13960 | + if (block_buf) | |
13961 | + ctx.buf = block_buf; | |
13962 | + else { | |
13963 | + retval = ext2fs_get_mem(fs->blocksize, &ctx.buf); | |
13964 | + if (retval) | |
13965 | + return retval; | |
13966 | + } | |
13967 | + ctx.func = func; | |
13968 | + ctx.priv_data = priv_data; | |
13969 | + ctx.errcode = 0; | |
13970 | + retval = ext2fs_block_iterate2(fs, dir, 0, 0, | |
13971 | + ext2fs_process_dir_block, &ctx); | |
13972 | + if (!block_buf) | |
13973 | + ext2fs_free_mem(&ctx.buf); | |
13974 | + if (retval) | |
13975 | + return retval; | |
13976 | + return ctx.errcode; | |
13977 | +} | |
13978 | + | |
13979 | +struct xlate { | |
13980 | + int (*func)(struct ext2_dir_entry *dirent, | |
13981 | + int offset, | |
13982 | + int blocksize, | |
13983 | + char *buf, | |
13984 | + void *priv_data); | |
13985 | + void *real_private; | |
13986 | +}; | |
13987 | + | |
13988 | +static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)), | |
13989 | + int entry EXT2FS_ATTR((unused)), | |
13990 | + struct ext2_dir_entry *dirent, int offset, | |
13991 | + int blocksize, char *buf, void *priv_data) | |
13992 | +{ | |
13993 | + struct xlate *xl = (struct xlate *) priv_data; | |
13994 | + | |
13995 | + return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private); | |
13996 | +} | |
13997 | + | |
13998 | +extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, | |
13999 | + ext2_ino_t dir, | |
14000 | + int flags, | |
14001 | + char *block_buf, | |
14002 | + int (*func)(struct ext2_dir_entry *dirent, | |
14003 | + int offset, | |
14004 | + int blocksize, | |
14005 | + char *buf, | |
14006 | + void *priv_data), | |
14007 | + void *priv_data) | |
14008 | +{ | |
14009 | + struct xlate xl; | |
14010 | + | |
14011 | + xl.real_private = priv_data; | |
14012 | + xl.func = func; | |
14013 | + | |
14014 | + return ext2fs_dir_iterate2(fs, dir, flags, block_buf, | |
14015 | + xlate_func, &xl); | |
14016 | +} | |
14017 | + | |
14018 | + | |
14019 | +/* | |
14020 | + * Helper function which is private to this module. Used by | |
14021 | + * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate() | |
14022 | + */ | |
14023 | +int ext2fs_process_dir_block(ext2_filsys fs, | |
14024 | + blk_t *blocknr, | |
14025 | + e2_blkcnt_t blockcnt, | |
14026 | + blk_t ref_block EXT2FS_ATTR((unused)), | |
14027 | + int ref_offset EXT2FS_ATTR((unused)), | |
14028 | + void *priv_data) | |
14029 | +{ | |
14030 | + struct dir_context *ctx = (struct dir_context *) priv_data; | |
14031 | + unsigned int offset = 0; | |
14032 | + unsigned int next_real_entry = 0; | |
14033 | + int ret = 0; | |
14034 | + int changed = 0; | |
14035 | + int do_abort = 0; | |
14036 | + int entry, size; | |
14037 | + struct ext2_dir_entry *dirent; | |
14038 | + | |
14039 | + if (blockcnt < 0) | |
14040 | + return 0; | |
14041 | + | |
14042 | + entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE; | |
14043 | + | |
14044 | + ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf); | |
14045 | + if (ctx->errcode) | |
14046 | + return BLOCK_ABORT; | |
14047 | + | |
14048 | + while (offset < fs->blocksize) { | |
14049 | + dirent = (struct ext2_dir_entry *) (ctx->buf + offset); | |
14050 | + if (((offset + dirent->rec_len) > fs->blocksize) || | |
14051 | + (dirent->rec_len < 8) || | |
14052 | + ((dirent->rec_len % 4) != 0) || | |
14053 | + (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { | |
14054 | + ctx->errcode = EXT2_ET_DIR_CORRUPTED; | |
14055 | + return BLOCK_ABORT; | |
14056 | + } | |
14057 | + if (!dirent->inode && | |
14058 | + !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY)) | |
14059 | + goto next; | |
14060 | + | |
14061 | + ret = (ctx->func)(ctx->dir, | |
14062 | + (next_real_entry > offset) ? | |
14063 | + DIRENT_DELETED_FILE : entry, | |
14064 | + dirent, offset, | |
14065 | + fs->blocksize, ctx->buf, | |
14066 | + ctx->priv_data); | |
14067 | + if (entry < DIRENT_OTHER_FILE) | |
14068 | + entry++; | |
14069 | + | |
14070 | + if (ret & DIRENT_CHANGED) | |
14071 | + changed++; | |
14072 | + if (ret & DIRENT_ABORT) { | |
14073 | + do_abort++; | |
14074 | + break; | |
14075 | + } | |
14076 | +next: | |
14077 | + if (next_real_entry == offset) | |
14078 | + next_real_entry += dirent->rec_len; | |
14079 | + | |
14080 | + if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) { | |
14081 | + size = ((dirent->name_len & 0xFF) + 11) & ~3; | |
14082 | + | |
14083 | + if (dirent->rec_len != size) { | |
14084 | + unsigned int final_offset; | |
14085 | + | |
14086 | + final_offset = offset + dirent->rec_len; | |
14087 | + offset += size; | |
14088 | + while (offset < final_offset && | |
14089 | + !ext2fs_validate_entry(ctx->buf, | |
14090 | + offset, | |
14091 | + final_offset)) | |
14092 | + offset += 4; | |
14093 | + continue; | |
14094 | + } | |
14095 | + } | |
14096 | + offset += dirent->rec_len; | |
14097 | + } | |
14098 | + | |
14099 | + if (changed) { | |
14100 | + ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf); | |
14101 | + if (ctx->errcode) | |
14102 | + return BLOCK_ABORT; | |
14103 | + } | |
14104 | + if (do_abort) | |
14105 | + return BLOCK_ABORT; | |
14106 | + return 0; | |
14107 | +} | |
14108 | + | |
14109 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dirblock.c busybox/e2fsprogs/ext2fs/dirblock.c | |
14110 | --- busybox-1.00/e2fsprogs/ext2fs/dirblock.c 1970-01-01 01:00:00.000000000 +0100 | |
14111 | +++ busybox/e2fsprogs/ext2fs/dirblock.c 2005-06-04 08:20:16.000000000 +0200 | |
14112 | @@ -0,0 +1,130 @@ | |
14113 | +/* | |
14114 | + * dirblock.c --- directory block routines. | |
14115 | + * | |
14116 | + * Copyright (C) 1995, 1996 Theodore Ts'o. | |
14117 | + * | |
14118 | + * %Begin-Header% | |
14119 | + * This file may be redistributed under the terms of the GNU Public | |
14120 | + * License. | |
14121 | + * %End-Header% | |
14122 | + */ | |
14123 | + | |
14124 | +#include <stdio.h> | |
14125 | +#if HAVE_UNISTD_H | |
14126 | +#include <unistd.h> | |
14127 | +#endif | |
14128 | +#include <string.h> | |
14129 | +#include <time.h> | |
14130 | + | |
14131 | +#include "ext2_fs.h" | |
14132 | +#include "ext2fs.h" | |
14133 | + | |
14134 | +errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, | |
14135 | + void *buf, int flags EXT2FS_ATTR((unused))) | |
14136 | +{ | |
14137 | + errcode_t retval; | |
14138 | + char *p, *end; | |
14139 | + struct ext2_dir_entry *dirent; | |
14140 | + unsigned int name_len, rec_len, do_swap; | |
14141 | + | |
14142 | + | |
14143 | + retval = io_channel_read_blk(fs->io, block, 1, buf); | |
14144 | + if (retval) | |
14145 | + return retval; | |
14146 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
14147 | + do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES| | |
14148 | + EXT2_FLAG_SWAP_BYTES_READ)) != 0; | |
14149 | +#endif | |
14150 | + p = (char *) buf; | |
14151 | + end = (char *) buf + fs->blocksize; | |
14152 | + while (p < end-8) { | |
14153 | + dirent = (struct ext2_dir_entry *) p; | |
14154 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
14155 | + if (do_swap) { | |
14156 | + dirent->inode = ext2fs_swab32(dirent->inode); | |
14157 | + dirent->rec_len = ext2fs_swab16(dirent->rec_len); | |
14158 | + dirent->name_len = ext2fs_swab16(dirent->name_len); | |
14159 | + } | |
14160 | +#endif | |
14161 | + name_len = dirent->name_len; | |
14162 | +#ifdef WORDS_BIGENDIAN | |
14163 | + if (flags & EXT2_DIRBLOCK_V2_STRUCT) | |
14164 | + dirent->name_len = ext2fs_swab16(dirent->name_len); | |
14165 | +#endif | |
14166 | + rec_len = dirent->rec_len; | |
14167 | + if ((rec_len < 8) || (rec_len % 4)) { | |
14168 | + rec_len = 8; | |
14169 | + retval = EXT2_ET_DIR_CORRUPTED; | |
14170 | + } | |
14171 | + if (((name_len & 0xFF) + 8) > dirent->rec_len) | |
14172 | + retval = EXT2_ET_DIR_CORRUPTED; | |
14173 | + p += rec_len; | |
14174 | + } | |
14175 | + return retval; | |
14176 | +} | |
14177 | + | |
14178 | +errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, | |
14179 | + void *buf) | |
14180 | +{ | |
14181 | + return ext2fs_read_dir_block2(fs, block, buf, 0); | |
14182 | +} | |
14183 | + | |
14184 | + | |
14185 | +errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, | |
14186 | + void *inbuf, int flags EXT2FS_ATTR((unused))) | |
14187 | +{ | |
14188 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
14189 | + int do_swap = 0; | |
14190 | + errcode_t retval; | |
14191 | + char *p, *end; | |
14192 | + char *buf = 0; | |
14193 | + struct ext2_dir_entry *dirent; | |
14194 | + | |
14195 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
14196 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) | |
14197 | + do_swap = 1; | |
14198 | + | |
14199 | +#ifndef WORDS_BIGENDIAN | |
14200 | + if (!do_swap) | |
14201 | + return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); | |
14202 | +#endif | |
14203 | + | |
14204 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
14205 | + if (retval) | |
14206 | + return retval; | |
14207 | + memcpy(buf, inbuf, fs->blocksize); | |
14208 | + p = buf; | |
14209 | + end = buf + fs->blocksize; | |
14210 | + while (p < end) { | |
14211 | + dirent = (struct ext2_dir_entry *) p; | |
14212 | + if ((dirent->rec_len < 8) || | |
14213 | + (dirent->rec_len % 4)) { | |
14214 | + ext2fs_free_mem(&buf); | |
14215 | + return (EXT2_ET_DIR_CORRUPTED); | |
14216 | + } | |
14217 | + p += dirent->rec_len; | |
14218 | + if (do_swap) { | |
14219 | + dirent->inode = ext2fs_swab32(dirent->inode); | |
14220 | + dirent->rec_len = ext2fs_swab16(dirent->rec_len); | |
14221 | + dirent->name_len = ext2fs_swab16(dirent->name_len); | |
14222 | + } | |
14223 | +#ifdef WORDS_BIGENDIAN | |
14224 | + if (flags & EXT2_DIRBLOCK_V2_STRUCT) | |
14225 | + dirent->name_len = ext2fs_swab16(dirent->name_len); | |
14226 | +#endif | |
14227 | + } | |
14228 | + retval = io_channel_write_blk(fs->io, block, 1, buf); | |
14229 | + ext2fs_free_mem(&buf); | |
14230 | + return retval; | |
14231 | +#else | |
14232 | + return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); | |
14233 | +#endif | |
14234 | +} | |
14235 | + | |
14236 | + | |
14237 | +errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, | |
14238 | + void *inbuf) | |
14239 | +{ | |
14240 | + return ext2fs_write_dir_block2(fs, block, inbuf, 0); | |
14241 | +} | |
14242 | + | |
14243 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dirhash.c busybox/e2fsprogs/ext2fs/dirhash.c | |
14244 | --- busybox-1.00/e2fsprogs/ext2fs/dirhash.c 1970-01-01 01:00:00.000000000 +0100 | |
14245 | +++ busybox/e2fsprogs/ext2fs/dirhash.c 2005-06-04 08:20:16.000000000 +0200 | |
14246 | @@ -0,0 +1,233 @@ | |
14247 | +/* | |
14248 | + * dirhash.c -- Calculate the hash of a directory entry | |
14249 | + * | |
14250 | + * Copyright (c) 2001 Daniel Phillips | |
14251 | + * | |
14252 | + * Copyright (c) 2002 Theodore Ts'o. | |
14253 | + * | |
14254 | + * %Begin-Header% | |
14255 | + * This file may be redistributed under the terms of the GNU Public | |
14256 | + * License. | |
14257 | + * %End-Header% | |
14258 | + */ | |
14259 | + | |
14260 | +#include <stdio.h> | |
14261 | +#include <string.h> | |
14262 | + | |
14263 | +#include "ext2_fs.h" | |
14264 | +#include "ext2fs.h" | |
14265 | + | |
14266 | +/* | |
14267 | + * Keyed 32-bit hash function using TEA in a Davis-Meyer function | |
14268 | + * H0 = Key | |
14269 | + * Hi = E Mi(Hi-1) + Hi-1 | |
14270 | + * | |
14271 | + * (see Applied Cryptography, 2nd edition, p448). | |
14272 | + * | |
14273 | + * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998 | |
14274 | + * | |
14275 | + * This code is made available under the terms of the GPL | |
14276 | + */ | |
14277 | +#define DELTA 0x9E3779B9 | |
14278 | + | |
14279 | +static void TEA_transform(__u32 buf[4], __u32 const in[]) | |
14280 | +{ | |
14281 | + __u32 sum = 0; | |
14282 | + __u32 b0 = buf[0], b1 = buf[1]; | |
14283 | + __u32 a = in[0], b = in[1], c = in[2], d = in[3]; | |
14284 | + int n = 16; | |
14285 | + | |
14286 | + do { | |
14287 | + sum += DELTA; | |
14288 | + b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); | |
14289 | + b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); | |
14290 | + } while(--n); | |
14291 | + | |
14292 | + buf[0] += b0; | |
14293 | + buf[1] += b1; | |
14294 | +} | |
14295 | + | |
14296 | +/* F, G and H are basic MD4 functions: selection, majority, parity */ | |
14297 | +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | |
14298 | +#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) | |
14299 | +#define H(x, y, z) ((x) ^ (y) ^ (z)) | |
14300 | + | |
14301 | +/* | |
14302 | + * The generic round function. The application is so specific that | |
14303 | + * we don't bother protecting all the arguments with parens, as is generally | |
14304 | + * good macro practice, in favor of extra legibility. | |
14305 | + * Rotation is separate from addition to prevent recomputation | |
14306 | + */ | |
14307 | +#define ROUND(f, a, b, c, d, x, s) \ | |
14308 | + (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) | |
14309 | +#define K1 0 | |
14310 | +#define K2 013240474631UL | |
14311 | +#define K3 015666365641UL | |
14312 | + | |
14313 | +/* | |
14314 | + * Basic cut-down MD4 transform. Returns only 32 bits of result. | |
14315 | + */ | |
14316 | +static void halfMD4Transform (__u32 buf[4], __u32 const in[]) | |
14317 | +{ | |
14318 | + __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; | |
14319 | + | |
14320 | + /* Round 1 */ | |
14321 | + ROUND(F, a, b, c, d, in[0] + K1, 3); | |
14322 | + ROUND(F, d, a, b, c, in[1] + K1, 7); | |
14323 | + ROUND(F, c, d, a, b, in[2] + K1, 11); | |
14324 | + ROUND(F, b, c, d, a, in[3] + K1, 19); | |
14325 | + ROUND(F, a, b, c, d, in[4] + K1, 3); | |
14326 | + ROUND(F, d, a, b, c, in[5] + K1, 7); | |
14327 | + ROUND(F, c, d, a, b, in[6] + K1, 11); | |
14328 | + ROUND(F, b, c, d, a, in[7] + K1, 19); | |
14329 | + | |
14330 | + /* Round 2 */ | |
14331 | + ROUND(G, a, b, c, d, in[1] + K2, 3); | |
14332 | + ROUND(G, d, a, b, c, in[3] + K2, 5); | |
14333 | + ROUND(G, c, d, a, b, in[5] + K2, 9); | |
14334 | + ROUND(G, b, c, d, a, in[7] + K2, 13); | |
14335 | + ROUND(G, a, b, c, d, in[0] + K2, 3); | |
14336 | + ROUND(G, d, a, b, c, in[2] + K2, 5); | |
14337 | + ROUND(G, c, d, a, b, in[4] + K2, 9); | |
14338 | + ROUND(G, b, c, d, a, in[6] + K2, 13); | |
14339 | + | |
14340 | + /* Round 3 */ | |
14341 | + ROUND(H, a, b, c, d, in[3] + K3, 3); | |
14342 | + ROUND(H, d, a, b, c, in[7] + K3, 9); | |
14343 | + ROUND(H, c, d, a, b, in[2] + K3, 11); | |
14344 | + ROUND(H, b, c, d, a, in[6] + K3, 15); | |
14345 | + ROUND(H, a, b, c, d, in[1] + K3, 3); | |
14346 | + ROUND(H, d, a, b, c, in[5] + K3, 9); | |
14347 | + ROUND(H, c, d, a, b, in[0] + K3, 11); | |
14348 | + ROUND(H, b, c, d, a, in[4] + K3, 15); | |
14349 | + | |
14350 | + buf[0] += a; | |
14351 | + buf[1] += b; | |
14352 | + buf[2] += c; | |
14353 | + buf[3] += d; | |
14354 | +} | |
14355 | + | |
14356 | +#undef ROUND | |
14357 | +#undef F | |
14358 | +#undef G | |
14359 | +#undef H | |
14360 | +#undef K1 | |
14361 | +#undef K2 | |
14362 | +#undef K3 | |
14363 | + | |
14364 | +/* The old legacy hash */ | |
14365 | +static ext2_dirhash_t dx_hack_hash (const char *name, int len) | |
14366 | +{ | |
14367 | + __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; | |
14368 | + while (len--) { | |
14369 | + __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); | |
14370 | + | |
14371 | + if (hash & 0x80000000) hash -= 0x7fffffff; | |
14372 | + hash1 = hash0; | |
14373 | + hash0 = hash; | |
14374 | + } | |
14375 | + return (hash0 << 1); | |
14376 | +} | |
14377 | + | |
14378 | +static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) | |
14379 | +{ | |
14380 | + __u32 pad, val; | |
14381 | + int i; | |
14382 | + | |
14383 | + pad = (__u32)len | ((__u32)len << 8); | |
14384 | + pad |= pad << 16; | |
14385 | + | |
14386 | + val = pad; | |
14387 | + if (len > num*4) | |
14388 | + len = num * 4; | |
14389 | + for (i=0; i < len; i++) { | |
14390 | + if ((i % 4) == 0) | |
14391 | + val = pad; | |
14392 | + val = msg[i] + (val << 8); | |
14393 | + if ((i % 4) == 3) { | |
14394 | + *buf++ = val; | |
14395 | + val = pad; | |
14396 | + num--; | |
14397 | + } | |
14398 | + } | |
14399 | + if (--num >= 0) | |
14400 | + *buf++ = val; | |
14401 | + while (--num >= 0) | |
14402 | + *buf++ = pad; | |
14403 | +} | |
14404 | + | |
14405 | +/* | |
14406 | + * Returns the hash of a filename. If len is 0 and name is NULL, then | |
14407 | + * this function can be used to test whether or not a hash version is | |
14408 | + * supported. | |
14409 | + * | |
14410 | + * The seed is an 4 longword (32 bits) "secret" which can be used to | |
14411 | + * uniquify a hash. If the seed is all zero's, then some default seed | |
14412 | + * may be used. | |
14413 | + * | |
14414 | + * A particular hash version specifies whether or not the seed is | |
14415 | + * represented, and whether or not the returned hash is 32 bits or 64 | |
14416 | + * bits. 32 bit hashes will return 0 for the minor hash. | |
14417 | + */ | |
14418 | +errcode_t ext2fs_dirhash(int version, const char *name, int len, | |
14419 | + const __u32 *seed, | |
14420 | + ext2_dirhash_t *ret_hash, | |
14421 | + ext2_dirhash_t *ret_minor_hash) | |
14422 | +{ | |
14423 | + __u32 hash; | |
14424 | + __u32 minor_hash = 0; | |
14425 | + const char *p; | |
14426 | + int i; | |
14427 | + __u32 in[8], buf[4]; | |
14428 | + | |
14429 | + /* Initialize the default seed for the hash checksum functions */ | |
14430 | + buf[0] = 0x67452301; | |
14431 | + buf[1] = 0xefcdab89; | |
14432 | + buf[2] = 0x98badcfe; | |
14433 | + buf[3] = 0x10325476; | |
14434 | + | |
14435 | + /* Check to see if the seed is all zero's */ | |
14436 | + if (seed) { | |
14437 | + for (i=0; i < 4; i++) { | |
14438 | + if (seed[i]) | |
14439 | + break; | |
14440 | + } | |
14441 | + if (i < 4) | |
14442 | + memcpy(buf, seed, sizeof(buf)); | |
14443 | + } | |
14444 | + | |
14445 | + switch (version) { | |
14446 | + case EXT2_HASH_LEGACY: | |
14447 | + hash = dx_hack_hash(name, len); | |
14448 | + break; | |
14449 | + case EXT2_HASH_HALF_MD4: | |
14450 | + p = name; | |
14451 | + while (len > 0) { | |
14452 | + str2hashbuf(p, len, in, 8); | |
14453 | + halfMD4Transform(buf, in); | |
14454 | + len -= 32; | |
14455 | + p += 32; | |
14456 | + } | |
14457 | + minor_hash = buf[2]; | |
14458 | + hash = buf[1]; | |
14459 | + break; | |
14460 | + case EXT2_HASH_TEA: | |
14461 | + p = name; | |
14462 | + while (len > 0) { | |
14463 | + str2hashbuf(p, len, in, 4); | |
14464 | + TEA_transform(buf, in); | |
14465 | + len -= 16; | |
14466 | + p += 16; | |
14467 | + } | |
14468 | + hash = buf[0]; | |
14469 | + minor_hash = buf[1]; | |
14470 | + break; | |
14471 | + default: | |
14472 | + *ret_hash = 0; | |
14473 | + return EXT2_ET_DIRHASH_UNSUPP; | |
14474 | + } | |
14475 | + *ret_hash = hash & ~1; | |
14476 | + if (ret_minor_hash) | |
14477 | + *ret_minor_hash = minor_hash; | |
14478 | + return 0; | |
14479 | +} | |
14480 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dosio.c busybox/e2fsprogs/ext2fs/dosio.c | |
14481 | --- busybox-1.00/e2fsprogs/ext2fs/dosio.c 1970-01-01 01:00:00.000000000 +0100 | |
14482 | +++ busybox/e2fsprogs/ext2fs/dosio.c 2005-06-04 08:20:16.000000000 +0200 | |
14483 | @@ -0,0 +1,456 @@ | |
14484 | +/* | |
14485 | + * dosio.c -- Disk I/O module for the ext2fs/DOS library. | |
14486 | + * | |
14487 | + * Copyright (c) 1997 by Theodore Ts'o. | |
14488 | + * | |
14489 | + * Copyright (c) 1997 Mark Habersack | |
14490 | + * This file may be distributed under the terms of the GNU Public License. | |
14491 | + * | |
14492 | + */ | |
14493 | + | |
14494 | +#include <stdio.h> | |
14495 | +#include <bios.h> | |
14496 | +#include <string.h> | |
14497 | +#include <ctype.h> | |
14498 | +#include <io.h> | |
14499 | +#ifdef HAVE_ERRNO_H | |
14500 | +#include <errno.h> | |
14501 | +#endif | |
14502 | + | |
14503 | +#include <ext2fs/ext2_types.h> | |
14504 | +#include "utils.h" | |
14505 | +#include "dosio.h" | |
14506 | +#include "et/com_err.h" | |
14507 | +#include "ext2_err.h" | |
14508 | +#include "ext2fs/io.h" | |
14509 | + | |
14510 | +/* | |
14511 | + * Some helper macros | |
14512 | + */ | |
14513 | +#define LINUX_EXT2FS 0x83 | |
14514 | +#define LINUX_SWAP 0x82 | |
14515 | +#define WRITE_ERR(_msg_) write(2, _msg_, strlen(_msg_)) | |
14516 | +#define WRITE_ERR_S(_msg_) write(2, _msg_, sizeof(_msg_)) | |
14517 | + | |
14518 | +/* | |
14519 | + * Exported variables | |
14520 | + */ | |
14521 | +unsigned long _dio_error; | |
14522 | +unsigned long _dio_hw_error; | |
14523 | + | |
14524 | +/* | |
14525 | + * Array of all opened partitions | |
14526 | + */ | |
14527 | +static PARTITION **partitions = NULL; | |
14528 | +static unsigned short npart = 0; /* Number of mapped partitions */ | |
14529 | +static PARTITION *active = NULL; | |
14530 | + | |
14531 | +/* | |
14532 | + * I/O Manager routine prototypes | |
14533 | + */ | |
14534 | +static errcode_t dos_open(const char *dev, int flags, io_channel *channel); | |
14535 | +static errcode_t dos_close(io_channel channel); | |
14536 | +static errcode_t dos_set_blksize(io_channel channel, int blksize); | |
14537 | +static errcode_t dos_read_blk(io_channel channel, unsigned long block, | |
14538 | + int count, void *buf); | |
14539 | +static errcode_t dos_write_blk(io_channel channel, unsigned long block, | |
14540 | + int count, const void *buf); | |
14541 | +static errcode_t dos_flush(io_channel channel); | |
14542 | + | |
14543 | +static struct struct_io_manager struct_dos_manager = { | |
14544 | + EXT2_ET_MAGIC_IO_MANAGER, | |
14545 | + "DOS I/O Manager", | |
14546 | + dos_open, | |
14547 | + dos_close, | |
14548 | + dos_set_blksize, | |
14549 | + dos_read_blk, | |
14550 | + dos_write_blk, | |
14551 | + dos_flush | |
14552 | +}; | |
14553 | +io_manager dos_io_manager = &struct_dos_manager; | |
14554 | + | |
14555 | +/* | |
14556 | + * Macro taken from unix_io.c | |
14557 | + */ | |
14558 | +/* | |
14559 | + * For checking structure magic numbers... | |
14560 | + */ | |
14561 | + | |
14562 | +#define EXT2_CHECK_MAGIC(struct, code) \ | |
14563 | + if ((struct)->magic != (code)) return (code) | |
14564 | + | |
14565 | +/* | |
14566 | + * Calculates a CHS address of a sector from its LBA | |
14567 | + * offset for the given partition. | |
14568 | + */ | |
14569 | +static void lba2chs(unsigned long lba_addr, CHS *chs, PARTITION *part) | |
14570 | +{ | |
14571 | + unsigned long abss; | |
14572 | + | |
14573 | + chs->offset = lba_addr & 0x000001FF; | |
14574 | + abss = (lba_addr >> 9) + part->start; | |
14575 | + chs->cyl = abss / (part->sects * part->heads); | |
14576 | + chs->head = (abss / part->sects) % part->heads; | |
14577 | + chs->sector = (abss % part->sects) + 1; | |
14578 | +} | |
14579 | + | |
14580 | +#ifdef __TURBOC__ | |
14581 | +#pragma argsused | |
14582 | +#endif | |
14583 | +/* | |
14584 | + * Scans the passed partition table looking for *pno partition | |
14585 | + * that has LINUX_EXT2FS type. | |
14586 | + * | |
14587 | + * TODO: | |
14588 | + * For partition numbers >5 Linux uses DOS extended partitions - | |
14589 | + * dive into them an return an appropriate entry. Also dive into | |
14590 | + * extended partitions when scanning for a first Linux/ext2fs. | |
14591 | + */ | |
14592 | +static PTABLE_ENTRY *scan_partition_table(PTABLE_ENTRY *pentry, | |
14593 | + unsigned short phys, | |
14594 | + unsigned char *pno) | |
14595 | +{ | |
14596 | + unsigned i; | |
14597 | + | |
14598 | + if(*pno != 0xFF && *pno >= 5) | |
14599 | + return NULL; /* We don't support extended partitions for now */ | |
14600 | + | |
14601 | + if(*pno != 0xFF) | |
14602 | + { | |
14603 | + if(pentry[*pno].type == LINUX_EXT2FS) | |
14604 | + return &pentry[*pno]; | |
14605 | + else | |
14606 | + { | |
14607 | + if(!pentry[*pno].type) | |
14608 | + *pno = 0xFE; | |
14609 | + else if(pentry[*pno].type == LINUX_SWAP) | |
14610 | + *pno = 0xFD; | |
14611 | + return NULL; | |
14612 | + } | |
14613 | + } | |
14614 | + | |
14615 | + for(i = 0; i < 4; i++) | |
14616 | + if(pentry[i].type == LINUX_EXT2FS) | |
14617 | + { | |
14618 | + *pno = i; | |
14619 | + return &pentry[i]; | |
14620 | + } | |
14621 | + | |
14622 | + return NULL; | |
14623 | +} | |
14624 | + | |
14625 | +/* | |
14626 | + * Allocate libext2fs structures associated with I/O manager | |
14627 | + */ | |
14628 | +static io_channel alloc_io_channel(PARTITION *part) | |
14629 | +{ | |
14630 | + io_channel ioch; | |
14631 | + | |
14632 | + ioch = (io_channel)malloc(sizeof(struct struct_io_channel)); | |
14633 | + if (!ioch) | |
14634 | + return NULL; | |
14635 | + memset(ioch, 0, sizeof(struct struct_io_channel)); | |
14636 | + ioch->magic = EXT2_ET_MAGIC_IO_CHANNEL; | |
14637 | + ioch->manager = dos_io_manager; | |
14638 | + ioch->name = (char *)malloc(strlen(part->dev)+1); | |
14639 | + if (!ioch->name) { | |
14640 | + free(ioch); | |
14641 | + return NULL; | |
14642 | + } | |
14643 | + strcpy(ioch->name, part->dev); | |
14644 | + ioch->private_data = part; | |
14645 | + ioch->block_size = 1024; /* The smallest ext2fs block size */ | |
14646 | + ioch->read_error = 0; | |
14647 | + ioch->write_error = 0; | |
14648 | + | |
14649 | + return ioch; | |
14650 | +} | |
14651 | + | |
14652 | +#ifdef __TURBOC__ | |
14653 | +#pragma argsused | |
14654 | +#endif | |
14655 | +/* | |
14656 | + * Open the 'name' partition, initialize all information structures | |
14657 | + * we need to keep and create libext2fs I/O manager. | |
14658 | + */ | |
14659 | +static errcode_t dos_open(const char *dev, int flags, io_channel *channel) | |
14660 | +{ | |
14661 | + unsigned char *tmp, sec[512]; | |
14662 | + PARTITION *part; | |
14663 | + PTABLE_ENTRY *pent; | |
14664 | + PARTITION **newparts; | |
14665 | + | |
14666 | + if(!dev) | |
14667 | + { | |
14668 | + _dio_error = ERR_BADDEV; | |
14669 | + return EXT2_ET_BAD_DEVICE_NAME; | |
14670 | + } | |
14671 | + | |
14672 | + /* | |
14673 | + * First check whether the dev name is OK | |
14674 | + */ | |
14675 | + tmp = (unsigned char*)strrchr(dev, '/'); | |
14676 | + if(!tmp) | |
14677 | + { | |
14678 | + _dio_error = ERR_BADDEV; | |
14679 | + return EXT2_ET_BAD_DEVICE_NAME; | |
14680 | + } | |
14681 | + *tmp = 0; | |
14682 | + if(strcmp(dev, "/dev")) | |
14683 | + { | |
14684 | + _dio_error = ERR_BADDEV; | |
14685 | + return EXT2_ET_BAD_DEVICE_NAME; | |
14686 | + } | |
14687 | + *tmp++ = '/'; | |
14688 | + | |
14689 | + /* | |
14690 | + * Check whether the partition data is already in cache | |
14691 | + */ | |
14692 | + | |
14693 | + part = (PARTITION*)malloc(sizeof(PARTITION)); | |
14694 | + if (!part) | |
14695 | + return ENOMEM; | |
14696 | + { | |
14697 | + int i = 0; | |
14698 | + | |
14699 | + for(;i < npart; i++) | |
14700 | + if(!strcmp(partitions[i]->dev, dev)) | |
14701 | + { | |
14702 | + /* Found it! Make it the active one */ | |
14703 | + active = partitions[i]; | |
14704 | + *channel = alloc_io_channel(active); | |
14705 | + if (!*channel) | |
14706 | + return ENOMEM; | |
14707 | + return 0; | |
14708 | + } | |
14709 | + } | |
14710 | + | |
14711 | + /* | |
14712 | + * Drive number & optionally partn number | |
14713 | + */ | |
14714 | + switch(tmp[0]) | |
14715 | + { | |
14716 | + case 'h': | |
14717 | + case 's': | |
14718 | + part->phys = 0x80; | |
14719 | + part->phys += toupper(tmp[2]) - 'A'; | |
14720 | + /* | |
14721 | + * Do we have the partition number? | |
14722 | + */ | |
14723 | + if(tmp[3]) | |
14724 | + part->pno = isdigit((int)tmp[3]) ? tmp[3] - '0' - 1: 0; | |
14725 | + else | |
14726 | + part->pno = 0xFF; | |
14727 | + break; | |
14728 | + | |
14729 | + case 'f': | |
14730 | + if(tmp[2]) | |
14731 | + part->phys = isdigit((int)tmp[2]) ? tmp[2] - '0' : 0; | |
14732 | + else | |
14733 | + part->phys = 0x00; /* We'll assume /dev/fd0 */ | |
14734 | + break; | |
14735 | + | |
14736 | + default: | |
14737 | + _dio_error = ERR_BADDEV; | |
14738 | + return ENODEV; | |
14739 | + } | |
14740 | + | |
14741 | + if(part->phys < 0x80) | |
14742 | + { | |
14743 | + /* We don't support floppies for now */ | |
14744 | + _dio_error = ERR_NOTSUPP; | |
14745 | + return EINVAL; | |
14746 | + } | |
14747 | + | |
14748 | + part->dev = strdup(dev); | |
14749 | + | |
14750 | + /* | |
14751 | + * Get drive's geometry | |
14752 | + */ | |
14753 | + _dio_hw_error = biosdisk(DISK_GET_GEOMETRY, | |
14754 | + part->phys, | |
14755 | + 0, /* head */ | |
14756 | + 0, /* cylinder */ | |
14757 | + 1, /* sector */ | |
14758 | + 1, /* just one sector */ | |
14759 | + sec); | |
14760 | + | |
14761 | + if(!HW_OK()) | |
14762 | + { | |
14763 | + _dio_error = ERR_HARDWARE; | |
14764 | + if (part) | |
14765 | + free(part); | |
14766 | + return EFAULT; | |
14767 | + } | |
14768 | + | |
14769 | + /* | |
14770 | + * Calculate the geometry | |
14771 | + */ | |
14772 | + part->cyls = (unsigned short)(((sec[0] >> 6) << 8) + sec[1] + 1); | |
14773 | + part->heads = sec[3] + 1; | |
14774 | + part->sects = sec[0] & 0x3F; | |
14775 | + | |
14776 | + /* | |
14777 | + * Now that we know all we need, let's look for the partition | |
14778 | + */ | |
14779 | + _dio_hw_error = biosdisk(DISK_READ, part->phys, 0, 0, 1, 1, sec); | |
14780 | + | |
14781 | + if(!HW_OK()) | |
14782 | + { | |
14783 | + _dio_error = ERR_HARDWARE; | |
14784 | + if (part) | |
14785 | + free(part); | |
14786 | + return EFAULT; | |
14787 | + } | |
14788 | + | |
14789 | + pent = (PTABLE_ENTRY*)&sec[0x1BE]; | |
14790 | + pent = scan_partition_table(pent, part->phys, &part->pno); | |
14791 | + | |
14792 | + if(!pent) | |
14793 | + { | |
14794 | + _dio_error = part->pno == 0xFE ? ERR_EMPTYPART : | |
14795 | + part->pno == 0xFD ? ERR_LINUXSWAP : ERR_NOTEXT2FS; | |
14796 | + if (part) | |
14797 | + free(part); | |
14798 | + return ENODEV; | |
14799 | + } | |
14800 | + | |
14801 | + /* | |
14802 | + * Calculate the remaining figures | |
14803 | + */ | |
14804 | + { | |
14805 | + unsigned long fsec, fhead, fcyl; | |
14806 | + | |
14807 | + fsec = (unsigned long)(pent->start_sec & 0x3F); | |
14808 | + fhead = (unsigned long)pent->start_head; | |
14809 | + fcyl = ((pent->start_sec >> 6) << 8) + pent->start_cyl; | |
14810 | + part->start = fsec + fhead * part->sects + fcyl * | |
14811 | + (part->heads * part->sects) - 1; | |
14812 | + part->len = pent->size; | |
14813 | + } | |
14814 | + | |
14815 | + /* | |
14816 | + * Add the partition to the table | |
14817 | + */ | |
14818 | + newparts = (PARTITION**)realloc(partitions, sizeof(PARTITION) * npart); | |
14819 | + if (!newparts) { | |
14820 | + free(part); | |
14821 | + return ENOMEM; | |
14822 | + } | |
14823 | + partitions = newparts; | |
14824 | + partitions[npart++] = active = part; | |
14825 | + | |
14826 | + /* | |
14827 | + * Now alloc all libe2fs structures | |
14828 | + */ | |
14829 | + *channel = alloc_io_channel(active); | |
14830 | + if (!*channel) | |
14831 | + return ENOMEM; | |
14832 | + | |
14833 | + return 0; | |
14834 | +} | |
14835 | + | |
14836 | +static errcode_t dos_close(io_channel channel) | |
14837 | +{ | |
14838 | + if (channel->name) | |
14839 | + free(channel->name); | |
14840 | + if (channel) | |
14841 | + free(channel); | |
14842 | + | |
14843 | + return 0; | |
14844 | +} | |
14845 | + | |
14846 | +static errcode_t dos_set_blksize(io_channel channel, int blksize) | |
14847 | +{ | |
14848 | + channel->block_size = blksize; | |
14849 | + | |
14850 | + return 0; | |
14851 | +} | |
14852 | + | |
14853 | +static errcode_t dos_read_blk(io_channel channel, unsigned long block, | |
14854 | + int count, void *buf) | |
14855 | +{ | |
14856 | + PARTITION *part; | |
14857 | + size_t size; | |
14858 | + ext2_loff_t loc; | |
14859 | + CHS chs; | |
14860 | + | |
14861 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
14862 | + part = (PARTITION*)channel->private_data; | |
14863 | + | |
14864 | + size = (size_t)((count < 0) ? -count : count * channel->block_size); | |
14865 | + loc = (ext2_loff_t) block * channel->block_size; | |
14866 | + | |
14867 | + lba2chs(loc, &chs, part); | |
14868 | + /* | |
14869 | + * Potential bug here: | |
14870 | + * If DJGPP is used then reads of >18 sectors will fail! | |
14871 | + * Have to rewrite biosdisk. | |
14872 | + */ | |
14873 | + _dio_hw_error = biosdisk(DISK_READ, | |
14874 | + part->phys, | |
14875 | + chs.head, | |
14876 | + chs.cyl, | |
14877 | + chs.sector, | |
14878 | + size < 512 ? 1 : size/512, | |
14879 | + buf); | |
14880 | + | |
14881 | + if(!HW_OK()) | |
14882 | + { | |
14883 | + _dio_error = ERR_HARDWARE; | |
14884 | + return EFAULT; | |
14885 | + } | |
14886 | + | |
14887 | + return 0; | |
14888 | +} | |
14889 | + | |
14890 | +static errcode_t dos_write_blk(io_channel channel, unsigned long block, | |
14891 | + int count, const void *buf) | |
14892 | +{ | |
14893 | + PARTITION *part; | |
14894 | + size_t size; | |
14895 | + ext2_loff_t loc; | |
14896 | + CHS chs; | |
14897 | + | |
14898 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
14899 | + part = (PARTITION*)channel->private_data; | |
14900 | + | |
14901 | + if(count == 1) | |
14902 | + size = (size_t)channel->block_size; | |
14903 | + else | |
14904 | + { | |
14905 | + if (count < 0) | |
14906 | + size = (size_t)-count; | |
14907 | + else | |
14908 | + size = (size_t)(count * channel->block_size); | |
14909 | + } | |
14910 | + | |
14911 | + loc = (ext2_loff_t)block * channel->block_size; | |
14912 | + lba2chs(loc, &chs, part); | |
14913 | + _dio_hw_error = biosdisk(DISK_WRITE, | |
14914 | + part->phys, | |
14915 | + chs.head, | |
14916 | + chs.cyl, | |
14917 | + chs.sector, | |
14918 | + size < 512 ? 1 : size/512, | |
14919 | + (void*)buf); | |
14920 | + | |
14921 | + if(!HW_OK()) | |
14922 | + { | |
14923 | + _dio_error = ERR_HARDWARE; | |
14924 | + return EFAULT; | |
14925 | + } | |
14926 | + | |
14927 | + return 0; | |
14928 | +} | |
14929 | + | |
14930 | +#ifdef __TURBOC__ | |
14931 | +#pragma argsused | |
14932 | +#endif | |
14933 | +static errcode_t dos_flush(io_channel channel) | |
14934 | +{ | |
14935 | + /* | |
14936 | + * No buffers, no flush... | |
14937 | + */ | |
14938 | + return 0; | |
14939 | +} | |
14940 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dosio.h busybox/e2fsprogs/ext2fs/dosio.h | |
14941 | --- busybox-1.00/e2fsprogs/ext2fs/dosio.h 1970-01-01 01:00:00.000000000 +0100 | |
14942 | +++ busybox/e2fsprogs/ext2fs/dosio.h 2005-06-04 08:20:16.000000000 +0200 | |
14943 | @@ -0,0 +1,153 @@ | |
14944 | +/* | |
14945 | + * v1.0 | |
14946 | + * | |
14947 | + * Disk I/O include file for the ext2fs/DOS library. | |
14948 | + * | |
14949 | + * Copyright (c) 1997 Mark Habersack | |
14950 | + * This file may be distributed under the terms of the GNU Public License. | |
14951 | + * | |
14952 | + */ | |
14953 | +#ifndef __diskio_h | |
14954 | +#define __diskio_h | |
14955 | +#ifdef __TURBOC__ | |
14956 | +#ifndef __LARGE__ | |
14957 | +# error "ext2fs/DOS library requires LARGE model!" | |
14958 | +#endif | |
14959 | +#endif | |
14960 | + | |
14961 | +#ifdef __TURBOC__ | |
14962 | +#include "msdos.h" | |
14963 | +#endif | |
14964 | + | |
14965 | +/* | |
14966 | + * A helper structure used in LBA => CHS conversion | |
14967 | + */ | |
14968 | +typedef struct | |
14969 | +{ | |
14970 | + unsigned short cyl; /* Cylinder (or track) */ | |
14971 | + unsigned short head; | |
14972 | + unsigned short sector; | |
14973 | + unsigned short offset; /* Offset of byte within the sector */ | |
14974 | +} CHS; | |
14975 | + | |
14976 | +/* | |
14977 | + * All partition data we need is here | |
14978 | + */ | |
14979 | +typedef struct | |
14980 | +{ | |
14981 | + char *dev; /* _Linux_ device name (like "/dev/hda1") */ | |
14982 | + unsigned char phys; /* Physical DOS drive number */ | |
14983 | + unsigned long start; /* LBA address of partition start */ | |
14984 | + unsigned long len; /* length of partition in sectors */ | |
14985 | + unsigned char pno; /* Partition number (read from *dev) */ | |
14986 | + | |
14987 | + /* This partition's drive geometry */ | |
14988 | + unsigned short cyls; | |
14989 | + unsigned short heads; | |
14990 | + unsigned short sects; | |
14991 | +} PARTITION; | |
14992 | + | |
14993 | +/* | |
14994 | + * PC partition table entry format | |
14995 | + */ | |
14996 | +#ifdef __DJGPP__ | |
14997 | +#pragma pack(1) | |
14998 | +#endif | |
14999 | +typedef struct | |
15000 | +{ | |
15001 | + unsigned char active; | |
15002 | + unsigned char start_head; | |
15003 | + unsigned char start_sec; | |
15004 | + unsigned char start_cyl; | |
15005 | + unsigned char type; | |
15006 | + unsigned char end_head; | |
15007 | + unsigned char end_sec; | |
15008 | + unsigned char end_cyl; | |
15009 | + unsigned long first_sec_rel; | |
15010 | + unsigned long size; | |
15011 | +} PTABLE_ENTRY; | |
15012 | +#ifdef __DJGPP__ | |
15013 | +#pragma pack() | |
15014 | +#endif | |
15015 | + | |
15016 | +/* | |
15017 | + * INT 0x13 operation codes | |
15018 | + */ | |
15019 | +#define DISK_READ 0x02 | |
15020 | +#define DISK_WRITE 0x03 | |
15021 | +#define DISK_GET_GEOMETRY 0x08 | |
15022 | +#define DISK_READY 0x10 | |
15023 | + | |
15024 | +/* | |
15025 | + * Errors to put in _dio_error | |
15026 | + */ | |
15027 | +#define ERR_BADDEV 0x00000001L | |
15028 | +#define ERR_HARDWARE 0x00000002L | |
15029 | +#define ERR_NOTSUPP 0x00000003L | |
15030 | +#define ERR_NOTEXT2FS 0x00000004L | |
15031 | +#define ERR_EMPTYPART 0x00000005L | |
15032 | +#define ERR_LINUXSWAP 0x00000006L | |
15033 | + | |
15034 | +/* | |
15035 | + * Functions in diskio.c | |
15036 | + */ | |
15037 | + | |
15038 | +/* | |
15039 | + * Variable contains last module's error | |
15040 | + */ | |
15041 | +extern unsigned long _dio_error; | |
15042 | + | |
15043 | +/* | |
15044 | + * This one contains last hardware error (if _dio_error == ERR_HARDWARE) | |
15045 | + */ | |
15046 | +extern unsigned long _dio_hw_error; | |
15047 | + | |
15048 | +/* | |
15049 | + * Macros to check for disk hardware errors | |
15050 | + */ | |
15051 | +#define HW_OK() ((unsigned char)_dio_hw_error == 0x00) | |
15052 | +#define HW_BAD_CMD() ((unsigned char)_dio_hw_error == 0x01) | |
15053 | +#define HW_NO_ADDR_MARK() ((unsigned char)_dio_hw_error == 0x02) | |
15054 | +#define HW_WRITE_PROT() ((unsigned char)_dio_hw_error == 0x03) | |
15055 | +#define HW_NO_SECTOR() ((unsigned char)_dio_hw_error == 0x04) | |
15056 | +#define HW_RESET_FAIL() ((unsigned char)_dio_hw_error == 0x05) | |
15057 | +#define HW_DISK_CHANGED() ((unsigned char)_dio_hw_error == 0x06) | |
15058 | +#define HW_DRIVE_FAIL() ((unsigned char)_dio_hw_error == 0x07) | |
15059 | +#define HW_DMA_OVERRUN() ((unsigned char)_dio_hw_error == 0x08) | |
15060 | +#define HW_DMA_BOUNDARY() ((unsigned char)_dio_hw_error == 0x09) | |
15061 | +#define HW_BAD_SECTOR() ((unsigned char)_dio_hw_error == 0x0A) | |
15062 | +#define HW_BAD_TRACK() ((unsigned char)_dio_hw_error == 0x0B) | |
15063 | +#define HW_UNSUPP_TRACK() ((unsigned char)_dio_hw_error == 0x0C) | |
15064 | +#define HW_BAD_CRC_ECC() ((unsigned char)_dio_hw_error == 0x10) | |
15065 | +#define HW_CRC_ECC_CORR() ((unsigned char)_dio_hw_error == 0x11) | |
15066 | +#define HW_CONTR_FAIL() ((unsigned char)_dio_hw_error == 0x20) | |
15067 | +#define HW_SEEK_FAIL() ((unsigned char)_dio_hw_error == 0x40) | |
15068 | +#define HW_ATTACH_FAIL() ((unsigned char)_dio_hw_error == 0x80) | |
15069 | +#define HW_DRIVE_NREADY() ((unsigned char)_dio_hw_error == 0xAA) | |
15070 | +#define HW_UNDEF_ERROR() ((unsigned char)_dio_hw_error == 0xBB) | |
15071 | +#define HW_WRITE_FAULT() ((unsigned char)_dio_hw_error == 0xCC) | |
15072 | +#define HW_STATUS_ERROR() ((unsigned char)_dio_hw_error == 0xE0) | |
15073 | +#define HW_SENSE_FAIL() ((unsigned char)_dio_hw_error == 0xFF) | |
15074 | + | |
15075 | + | |
15076 | +/* | |
15077 | + * Open the specified partition. | |
15078 | + * String 'dev' must have a format: | |
15079 | + * | |
15080 | + * /dev/{sd|hd|fd}[X] | |
15081 | + * | |
15082 | + * where, | |
15083 | + * | |
15084 | + * only one of the option in curly braces can be used and X is an optional | |
15085 | + * partition number for the given device. If X is not specified, function | |
15086 | + * scans the drive's partition table in search for the first Linux ext2fs | |
15087 | + * partition (signature 0x83). Along the way it dives into every extended | |
15088 | + * partition encountered. | |
15089 | + * Scan ends if either (a) there are no more used partition entries, or | |
15090 | + * (b) there is no Xth partition. | |
15091 | + * | |
15092 | + * Routine returns 0 on success and !=0 otherwise. | |
15093 | + */ | |
15094 | +int open_partition(char *dev); | |
15095 | + | |
15096 | +#endif /* __diskio_h */ | |
15097 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/dupfs.c busybox/e2fsprogs/ext2fs/dupfs.c | |
15098 | --- busybox-1.00/e2fsprogs/ext2fs/dupfs.c 1970-01-01 01:00:00.000000000 +0100 | |
15099 | +++ busybox/e2fsprogs/ext2fs/dupfs.c 2005-06-04 08:20:16.000000000 +0200 | |
15100 | @@ -0,0 +1,96 @@ | |
15101 | +/* | |
15102 | + * dupfs.c --- duplicate a ext2 filesystem handle | |
15103 | + * | |
15104 | + * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o. | |
15105 | + * | |
15106 | + * %Begin-Header% | |
15107 | + * This file may be redistributed under the terms of the GNU Public | |
15108 | + * License. | |
15109 | + * %End-Header% | |
15110 | + */ | |
15111 | + | |
15112 | +#include <stdio.h> | |
15113 | +#if HAVE_UNISTD_H | |
15114 | +#include <unistd.h> | |
15115 | +#endif | |
15116 | +#include <time.h> | |
15117 | +#include <string.h> | |
15118 | + | |
15119 | +#include "ext2_fs.h" | |
15120 | +#include "ext2fsP.h" | |
15121 | + | |
15122 | +errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest) | |
15123 | +{ | |
15124 | + ext2_filsys fs; | |
15125 | + errcode_t retval; | |
15126 | + | |
15127 | + EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
15128 | + | |
15129 | + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); | |
15130 | + if (retval) | |
15131 | + return retval; | |
15132 | + | |
15133 | + *fs = *src; | |
15134 | + fs->device_name = 0; | |
15135 | + fs->super = 0; | |
15136 | + fs->orig_super = 0; | |
15137 | + fs->group_desc = 0; | |
15138 | + fs->inode_map = 0; | |
15139 | + fs->block_map = 0; | |
15140 | + fs->badblocks = 0; | |
15141 | + fs->dblist = 0; | |
15142 | + | |
15143 | + io_channel_bumpcount(fs->io); | |
15144 | + if (fs->icache) | |
15145 | + fs->icache->refcount++; | |
15146 | + | |
15147 | + retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name); | |
15148 | + if (retval) | |
15149 | + goto errout; | |
15150 | + strcpy(fs->device_name, src->device_name); | |
15151 | + | |
15152 | + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super); | |
15153 | + if (retval) | |
15154 | + goto errout; | |
15155 | + memcpy(fs->super, src->super, SUPERBLOCK_SIZE); | |
15156 | + | |
15157 | + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); | |
15158 | + if (retval) | |
15159 | + goto errout; | |
15160 | + memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE); | |
15161 | + | |
15162 | + retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, | |
15163 | + &fs->group_desc); | |
15164 | + if (retval) | |
15165 | + goto errout; | |
15166 | + memcpy(fs->group_desc, src->group_desc, | |
15167 | + (size_t) fs->desc_blocks * fs->blocksize); | |
15168 | + | |
15169 | + if (src->inode_map) { | |
15170 | + retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map); | |
15171 | + if (retval) | |
15172 | + goto errout; | |
15173 | + } | |
15174 | + if (src->block_map) { | |
15175 | + retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map); | |
15176 | + if (retval) | |
15177 | + goto errout; | |
15178 | + } | |
15179 | + if (src->badblocks) { | |
15180 | + retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks); | |
15181 | + if (retval) | |
15182 | + goto errout; | |
15183 | + } | |
15184 | + if (src->dblist) { | |
15185 | + retval = ext2fs_copy_dblist(src->dblist, &fs->dblist); | |
15186 | + if (retval) | |
15187 | + goto errout; | |
15188 | + } | |
15189 | + *dest = fs; | |
15190 | + return 0; | |
15191 | +errout: | |
15192 | + ext2fs_free(fs); | |
15193 | + return retval; | |
15194 | + | |
15195 | +} | |
15196 | + | |
15197 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/e2image.h busybox/e2fsprogs/ext2fs/e2image.h | |
15198 | --- busybox-1.00/e2fsprogs/ext2fs/e2image.h 1970-01-01 01:00:00.000000000 +0100 | |
15199 | +++ busybox/e2fsprogs/ext2fs/e2image.h 2005-06-04 08:20:16.000000000 +0200 | |
15200 | @@ -0,0 +1,51 @@ | |
15201 | +/* | |
15202 | + * e2image.h --- header file describing the ext2 image format | |
15203 | + * | |
15204 | + * Copyright (C) 2000 Theodore Ts'o. | |
15205 | + * | |
15206 | + * Note: this uses the POSIX IO interfaces, unlike most of the other | |
15207 | + * functions in this library. So sue me. | |
15208 | + * | |
15209 | + * %Begin-Header% | |
15210 | + * This file may be redistributed under the terms of the GNU Public | |
15211 | + * License. | |
15212 | + * %End-Header% | |
15213 | + */ | |
15214 | + | |
15215 | + | |
15216 | +struct ext2_image_hdr { | |
15217 | + __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */ | |
15218 | + char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */ | |
15219 | + char fs_hostname[64];/* Hostname of machine of image */ | |
15220 | + char fs_netaddr[32]; /* Network address */ | |
15221 | + __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */ | |
15222 | + __u32 fs_device; /* Device number of image */ | |
15223 | + char fs_device_name[64]; /* Device name */ | |
15224 | + char fs_uuid[16]; /* UUID of filesystem */ | |
15225 | + __u32 fs_blocksize; /* Block size of the filesystem */ | |
15226 | + __u32 fs_reserved[8]; | |
15227 | + | |
15228 | + __u32 image_device; /* Device number of image file */ | |
15229 | + __u32 image_inode; /* Inode number of image file */ | |
15230 | + __u32 image_time; /* Time of image creation */ | |
15231 | + __u32 image_reserved[8]; | |
15232 | + | |
15233 | + __u32 offset_super; /* Byte offset of the sb and descriptors */ | |
15234 | + __u32 offset_inode; /* Byte offset of the inode table */ | |
15235 | + __u32 offset_inodemap; /* Byte offset of the inode bitmaps */ | |
15236 | + __u32 offset_blockmap; /* Byte offset of the inode bitmaps */ | |
15237 | + __u32 offset_reserved[8]; | |
15238 | +}; | |
15239 | + | |
15240 | + | |
15241 | + | |
15242 | + | |
15243 | + | |
15244 | + | |
15245 | + | |
15246 | + | |
15247 | + | |
15248 | + | |
15249 | + | |
15250 | + | |
15251 | + | |
15252 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/expanddir.c busybox/e2fsprogs/ext2fs/expanddir.c | |
15253 | --- busybox-1.00/e2fsprogs/ext2fs/expanddir.c 1970-01-01 01:00:00.000000000 +0100 | |
15254 | +++ busybox/e2fsprogs/ext2fs/expanddir.c 2005-06-04 08:20:16.000000000 +0200 | |
15255 | @@ -0,0 +1,126 @@ | |
15256 | +/* | |
15257 | + * expand.c --- expand an ext2fs directory | |
15258 | + * | |
15259 | + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. | |
15260 | + * | |
15261 | + * %Begin-Header% | |
15262 | + * This file may be redistributed under the terms of the GNU Public | |
15263 | + * License. | |
15264 | + * %End-Header% | |
15265 | + */ | |
15266 | + | |
15267 | +#include <stdio.h> | |
15268 | +#include <string.h> | |
15269 | +#if HAVE_UNISTD_H | |
15270 | +#include <unistd.h> | |
15271 | +#endif | |
15272 | + | |
15273 | +#include "ext2_fs.h" | |
15274 | +#include "ext2fs.h" | |
15275 | + | |
15276 | +struct expand_dir_struct { | |
15277 | + int done; | |
15278 | + int newblocks; | |
15279 | + errcode_t err; | |
15280 | +}; | |
15281 | + | |
15282 | +static int expand_dir_proc(ext2_filsys fs, | |
15283 | + blk_t *blocknr, | |
15284 | + e2_blkcnt_t blockcnt, | |
15285 | + blk_t ref_block EXT2FS_ATTR((unused)), | |
15286 | + int ref_offset EXT2FS_ATTR((unused)), | |
15287 | + void *priv_data) | |
15288 | +{ | |
15289 | + struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; | |
15290 | + blk_t new_blk; | |
15291 | + static blk_t last_blk = 0; | |
15292 | + char *block; | |
15293 | + errcode_t retval; | |
15294 | + | |
15295 | + if (*blocknr) { | |
15296 | + last_blk = *blocknr; | |
15297 | + return 0; | |
15298 | + } | |
15299 | + retval = ext2fs_new_block(fs, last_blk, 0, &new_blk); | |
15300 | + if (retval) { | |
15301 | + es->err = retval; | |
15302 | + return BLOCK_ABORT; | |
15303 | + } | |
15304 | + if (blockcnt > 0) { | |
15305 | + retval = ext2fs_new_dir_block(fs, 0, 0, &block); | |
15306 | + if (retval) { | |
15307 | + es->err = retval; | |
15308 | + return BLOCK_ABORT; | |
15309 | + } | |
15310 | + es->done = 1; | |
15311 | + retval = ext2fs_write_dir_block(fs, new_blk, block); | |
15312 | + } else { | |
15313 | + retval = ext2fs_get_mem(fs->blocksize, &block); | |
15314 | + if (retval) { | |
15315 | + es->err = retval; | |
15316 | + return BLOCK_ABORT; | |
15317 | + } | |
15318 | + memset(block, 0, fs->blocksize); | |
15319 | + retval = io_channel_write_blk(fs->io, new_blk, 1, block); | |
15320 | + } | |
15321 | + if (retval) { | |
15322 | + es->err = retval; | |
15323 | + return BLOCK_ABORT; | |
15324 | + } | |
15325 | + ext2fs_free_mem(&block); | |
15326 | + *blocknr = new_blk; | |
15327 | + ext2fs_block_alloc_stats(fs, new_blk, +1); | |
15328 | + es->newblocks++; | |
15329 | + | |
15330 | + if (es->done) | |
15331 | + return (BLOCK_CHANGED | BLOCK_ABORT); | |
15332 | + else | |
15333 | + return BLOCK_CHANGED; | |
15334 | +} | |
15335 | + | |
15336 | +errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir) | |
15337 | +{ | |
15338 | + errcode_t retval; | |
15339 | + struct expand_dir_struct es; | |
15340 | + struct ext2_inode inode; | |
15341 | + | |
15342 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
15343 | + | |
15344 | + if (!(fs->flags & EXT2_FLAG_RW)) | |
15345 | + return EXT2_ET_RO_FILSYS; | |
15346 | + | |
15347 | + if (!fs->block_map) | |
15348 | + return EXT2_ET_NO_BLOCK_BITMAP; | |
15349 | + | |
15350 | + retval = ext2fs_check_directory(fs, dir); | |
15351 | + if (retval) | |
15352 | + return retval; | |
15353 | + | |
15354 | + es.done = 0; | |
15355 | + es.err = 0; | |
15356 | + es.newblocks = 0; | |
15357 | + | |
15358 | + retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND, | |
15359 | + 0, expand_dir_proc, &es); | |
15360 | + | |
15361 | + if (es.err) | |
15362 | + return es.err; | |
15363 | + if (!es.done) | |
15364 | + return EXT2_ET_EXPAND_DIR_ERR; | |
15365 | + | |
15366 | + /* | |
15367 | + * Update the size and block count fields in the inode. | |
15368 | + */ | |
15369 | + retval = ext2fs_read_inode(fs, dir, &inode); | |
15370 | + if (retval) | |
15371 | + return retval; | |
15372 | + | |
15373 | + inode.i_size += fs->blocksize; | |
15374 | + inode.i_blocks += (fs->blocksize / 512) * es.newblocks; | |
15375 | + | |
15376 | + retval = ext2fs_write_inode(fs, dir, &inode); | |
15377 | + if (retval) | |
15378 | + return retval; | |
15379 | + | |
15380 | + return 0; | |
15381 | +} | |
15382 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext2_err.h busybox/e2fsprogs/ext2fs/ext2_err.h | |
15383 | --- busybox-1.00/e2fsprogs/ext2fs/ext2_err.h 1970-01-01 01:00:00.000000000 +0100 | |
15384 | +++ busybox/e2fsprogs/ext2fs/ext2_err.h 2005-06-04 08:20:16.000000000 +0200 | |
15385 | @@ -0,0 +1,117 @@ | |
15386 | +/* | |
15387 | + * ext2_err.h: | |
15388 | + * This file is automatically generated; please do not edit it. | |
15389 | + */ | |
15390 | + | |
15391 | +#include <et/com_err.h> | |
15392 | + | |
15393 | +#define EXT2_ET_BASE (2133571328L) | |
15394 | +#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L) | |
15395 | +#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L) | |
15396 | +#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L) | |
15397 | +#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L) | |
15398 | +#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L) | |
15399 | +#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L) | |
15400 | +#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L) | |
15401 | +#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L) | |
15402 | +#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L) | |
15403 | +#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L) | |
15404 | +#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L) | |
15405 | +#define EXT2_ET_MAGIC_DBLIST (2133571340L) | |
15406 | +#define EXT2_ET_MAGIC_ICOUNT (2133571341L) | |
15407 | +#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L) | |
15408 | +#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L) | |
15409 | +#define EXT2_ET_MAGIC_E2IMAGE (2133571344L) | |
15410 | +#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L) | |
15411 | +#define EXT2_ET_MAGIC_RESERVED_9 (2133571346L) | |
15412 | +#define EXT2_ET_BAD_MAGIC (2133571347L) | |
15413 | +#define EXT2_ET_REV_TOO_HIGH (2133571348L) | |
15414 | +#define EXT2_ET_RO_FILSYS (2133571349L) | |
15415 | +#define EXT2_ET_GDESC_READ (2133571350L) | |
15416 | +#define EXT2_ET_GDESC_WRITE (2133571351L) | |
15417 | +#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L) | |
15418 | +#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L) | |
15419 | +#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L) | |
15420 | +#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L) | |
15421 | +#define EXT2_ET_INODE_BITMAP_READ (2133571356L) | |
15422 | +#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L) | |
15423 | +#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L) | |
15424 | +#define EXT2_ET_INODE_TABLE_WRITE (2133571359L) | |
15425 | +#define EXT2_ET_INODE_TABLE_READ (2133571360L) | |
15426 | +#define EXT2_ET_NEXT_INODE_READ (2133571361L) | |
15427 | +#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L) | |
15428 | +#define EXT2_ET_DIR_CORRUPTED (2133571363L) | |
15429 | +#define EXT2_ET_SHORT_READ (2133571364L) | |
15430 | +#define EXT2_ET_SHORT_WRITE (2133571365L) | |
15431 | +#define EXT2_ET_DIR_NO_SPACE (2133571366L) | |
15432 | +#define EXT2_ET_NO_INODE_BITMAP (2133571367L) | |
15433 | +#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L) | |
15434 | +#define EXT2_ET_BAD_INODE_NUM (2133571369L) | |
15435 | +#define EXT2_ET_BAD_BLOCK_NUM (2133571370L) | |
15436 | +#define EXT2_ET_EXPAND_DIR_ERR (2133571371L) | |
15437 | +#define EXT2_ET_TOOSMALL (2133571372L) | |
15438 | +#define EXT2_ET_BAD_BLOCK_MARK (2133571373L) | |
15439 | +#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L) | |
15440 | +#define EXT2_ET_BAD_BLOCK_TEST (2133571375L) | |
15441 | +#define EXT2_ET_BAD_INODE_MARK (2133571376L) | |
15442 | +#define EXT2_ET_BAD_INODE_UNMARK (2133571377L) | |
15443 | +#define EXT2_ET_BAD_INODE_TEST (2133571378L) | |
15444 | +#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L) | |
15445 | +#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L) | |
15446 | +#define EXT2_ET_BAD_IND_BLOCK (2133571381L) | |
15447 | +#define EXT2_ET_BAD_DIND_BLOCK (2133571382L) | |
15448 | +#define EXT2_ET_BAD_TIND_BLOCK (2133571383L) | |
15449 | +#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L) | |
15450 | +#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L) | |
15451 | +#define EXT2_ET_BAD_DEVICE_NAME (2133571386L) | |
15452 | +#define EXT2_ET_MISSING_INODE_TABLE (2133571387L) | |
15453 | +#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L) | |
15454 | +#define EXT2_ET_BAD_GENERIC_MARK (2133571389L) | |
15455 | +#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L) | |
15456 | +#define EXT2_ET_BAD_GENERIC_TEST (2133571391L) | |
15457 | +#define EXT2_ET_SYMLINK_LOOP (2133571392L) | |
15458 | +#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L) | |
15459 | +#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L) | |
15460 | +#define EXT2_ET_UNSUPP_FEATURE (2133571395L) | |
15461 | +#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L) | |
15462 | +#define EXT2_ET_LLSEEK_FAILED (2133571397L) | |
15463 | +#define EXT2_ET_NO_MEMORY (2133571398L) | |
15464 | +#define EXT2_ET_INVALID_ARGUMENT (2133571399L) | |
15465 | +#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L) | |
15466 | +#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L) | |
15467 | +#define EXT2_ET_NO_DIRECTORY (2133571402L) | |
15468 | +#define EXT2_ET_TOO_MANY_REFS (2133571403L) | |
15469 | +#define EXT2_ET_FILE_NOT_FOUND (2133571404L) | |
15470 | +#define EXT2_ET_FILE_RO (2133571405L) | |
15471 | +#define EXT2_ET_DB_NOT_FOUND (2133571406L) | |
15472 | +#define EXT2_ET_DIR_EXISTS (2133571407L) | |
15473 | +#define EXT2_ET_UNIMPLEMENTED (2133571408L) | |
15474 | +#define EXT2_ET_CANCEL_REQUESTED (2133571409L) | |
15475 | +#define EXT2_ET_FILE_TOO_BIG (2133571410L) | |
15476 | +#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L) | |
15477 | +#define EXT2_ET_NO_JOURNAL_SB (2133571412L) | |
15478 | +#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L) | |
15479 | +#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L) | |
15480 | +#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L) | |
15481 | +#define EXT2_ET_NO_JOURNAL (2133571416L) | |
15482 | +#define EXT2_ET_DIRHASH_UNSUPP (2133571417L) | |
15483 | +#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L) | |
15484 | +#define EXT2_ET_TOO_MANY_INODES (2133571419L) | |
15485 | +#define EXT2_ET_NOT_IMAGE_FILE (2133571420L) | |
15486 | +#define EXT2_ET_RES_GDT_BLOCKS (2133571421L) | |
15487 | +#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L) | |
15488 | +#define EXT2_ET_SET_BMAP_NO_IND (2133571423L) | |
15489 | + | |
15490 | +#if 0 | |
15491 | +extern const struct error_table et_ext2_error_table; | |
15492 | +extern void initialize_ext2_error_table(void); | |
15493 | + | |
15494 | +/* For compatibility with Heimdal */ | |
15495 | +extern void initialize_ext2_error_table_r(struct et_list **list); | |
15496 | + | |
15497 | +#define ERROR_TABLE_BASE_ext2 (2133571328L) | |
15498 | + | |
15499 | +/* for compatibility with older versions... */ | |
15500 | +#define init_ext2_err_tbl initialize_ext2_error_table | |
15501 | +#define ext2_err_base ERROR_TABLE_BASE_ext2 | |
15502 | +#endif | |
15503 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext2_ext_attr.h busybox/e2fsprogs/ext2fs/ext2_ext_attr.h | |
15504 | --- busybox-1.00/e2fsprogs/ext2fs/ext2_ext_attr.h 1970-01-01 01:00:00.000000000 +0100 | |
15505 | +++ busybox/e2fsprogs/ext2fs/ext2_ext_attr.h 2005-06-04 08:20:16.000000000 +0200 | |
15506 | @@ -0,0 +1,69 @@ | |
15507 | +/* | |
15508 | + File: linux/ext2_ext_attr.h | |
15509 | + | |
15510 | + On-disk format of extended attributes for the ext2 filesystem. | |
15511 | + | |
15512 | + (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org> | |
15513 | +*/ | |
15514 | + | |
15515 | +/* Magic value in attribute blocks */ | |
15516 | +#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000 | |
15517 | +#define EXT2_EXT_ATTR_MAGIC 0xEA020000 | |
15518 | + | |
15519 | +/* Maximum number of references to one attribute block */ | |
15520 | +#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024 | |
15521 | + | |
15522 | +struct ext2_ext_attr_header { | |
15523 | + __u32 h_magic; /* magic number for identification */ | |
15524 | + __u32 h_refcount; /* reference count */ | |
15525 | + __u32 h_blocks; /* number of disk blocks used */ | |
15526 | + __u32 h_hash; /* hash value of all attributes */ | |
15527 | + __u32 h_reserved[4]; /* zero right now */ | |
15528 | +}; | |
15529 | + | |
15530 | +struct ext2_ext_attr_entry { | |
15531 | + __u8 e_name_len; /* length of name */ | |
15532 | + __u8 e_name_index; /* attribute name index */ | |
15533 | + __u16 e_value_offs; /* offset in disk block of value */ | |
15534 | + __u32 e_value_block; /* disk block attribute is stored on (n/i) */ | |
15535 | + __u32 e_value_size; /* size of attribute value */ | |
15536 | + __u32 e_hash; /* hash value of name and value */ | |
15537 | +#if 0 | |
15538 | + char e_name[0]; /* attribute name */ | |
15539 | +#endif | |
15540 | +}; | |
15541 | + | |
15542 | +#define EXT2_EXT_ATTR_PAD_BITS 2 | |
15543 | +#define EXT2_EXT_ATTR_PAD (1<<EXT2_EXT_ATTR_PAD_BITS) | |
15544 | +#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1) | |
15545 | +#define EXT2_EXT_ATTR_LEN(name_len) \ | |
15546 | + (((name_len) + EXT2_EXT_ATTR_ROUND + \ | |
15547 | + sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND) | |
15548 | +#define EXT2_EXT_ATTR_NEXT(entry) \ | |
15549 | + ( (struct ext2_ext_attr_entry *)( \ | |
15550 | + (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) ) | |
15551 | +#define EXT2_EXT_ATTR_SIZE(size) \ | |
15552 | + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) | |
15553 | +#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL) | |
15554 | +#define EXT2_EXT_ATTR_NAME(entry) \ | |
15555 | + (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry)) | |
15556 | +#define EXT2_XATTR_LEN(name_len) \ | |
15557 | + (((name_len) + EXT2_EXT_ATTR_ROUND + \ | |
15558 | + sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND) | |
15559 | +#define EXT2_XATTR_SIZE(size) \ | |
15560 | + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) | |
15561 | + | |
15562 | +#ifdef __KERNEL__ | |
15563 | +# ifdef CONFIG_EXT2_FS_EXT_ATTR | |
15564 | +extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int); | |
15565 | +extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int); | |
15566 | +extern void ext2_ext_attr_free_inode(struct inode *inode); | |
15567 | +extern void ext2_ext_attr_put_super(struct super_block *sb); | |
15568 | +extern int ext2_ext_attr_init(void); | |
15569 | +extern void ext2_ext_attr_done(void); | |
15570 | +# else | |
15571 | +# define ext2_get_ext_attr NULL | |
15572 | +# define ext2_set_ext_attr NULL | |
15573 | +# endif | |
15574 | +#endif /* __KERNEL__ */ | |
15575 | + | |
15576 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext2_fs.h busybox/e2fsprogs/ext2fs/ext2_fs.h | |
15577 | --- busybox-1.00/e2fsprogs/ext2fs/ext2_fs.h 1970-01-01 01:00:00.000000000 +0100 | |
15578 | +++ busybox/e2fsprogs/ext2fs/ext2_fs.h 2005-06-04 08:20:16.000000000 +0200 | |
15579 | @@ -0,0 +1,644 @@ | |
15580 | +/* | |
15581 | + * linux/include/linux/ext2_fs.h | |
15582 | + * | |
15583 | + * Copyright (C) 1992, 1993, 1994, 1995 | |
15584 | + * Remy Card (card@masi.ibp.fr) | |
15585 | + * Laboratoire MASI - Institut Blaise Pascal | |
15586 | + * Universite Pierre et Marie Curie (Paris VI) | |
15587 | + * | |
15588 | + * from | |
15589 | + * | |
15590 | + * linux/include/linux/minix_fs.h | |
15591 | + * | |
15592 | + * Copyright (C) 1991, 1992 Linus Torvalds | |
15593 | + */ | |
15594 | + | |
15595 | +#ifndef _LINUX_EXT2_FS_H | |
15596 | +#define _LINUX_EXT2_FS_H | |
15597 | + | |
15598 | +#include <ext2fs/ext2_types.h> /* Changed from linux/types.h */ | |
15599 | + | |
15600 | +/* | |
15601 | + * The second extended filesystem constants/structures | |
15602 | + */ | |
15603 | + | |
15604 | +/* | |
15605 | + * Define EXT2FS_DEBUG to produce debug messages | |
15606 | + */ | |
15607 | +#undef EXT2FS_DEBUG | |
15608 | + | |
15609 | +/* | |
15610 | + * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files | |
15611 | + */ | |
15612 | +#define EXT2_PREALLOCATE | |
15613 | +#define EXT2_DEFAULT_PREALLOC_BLOCKS 8 | |
15614 | + | |
15615 | +/* | |
15616 | + * The second extended file system version | |
15617 | + */ | |
15618 | +#define EXT2FS_DATE "95/08/09" | |
15619 | +#define EXT2FS_VERSION "0.5b" | |
15620 | + | |
15621 | +/* | |
15622 | + * Special inode numbers | |
15623 | + */ | |
15624 | +#define EXT2_BAD_INO 1 /* Bad blocks inode */ | |
15625 | +#define EXT2_ROOT_INO 2 /* Root inode */ | |
15626 | +#define EXT2_ACL_IDX_INO 3 /* ACL inode */ | |
15627 | +#define EXT2_ACL_DATA_INO 4 /* ACL inode */ | |
15628 | +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ | |
15629 | +#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ | |
15630 | +#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */ | |
15631 | +#define EXT2_JOURNAL_INO 8 /* Journal inode */ | |
15632 | + | |
15633 | +/* First non-reserved inode for old ext2 filesystems */ | |
15634 | +#define EXT2_GOOD_OLD_FIRST_INO 11 | |
15635 | + | |
15636 | +/* | |
15637 | + * The second extended file system magic number | |
15638 | + */ | |
15639 | +#define EXT2_SUPER_MAGIC 0xEF53 | |
15640 | + | |
15641 | +#ifdef __KERNEL__ | |
15642 | +#define EXT2_SB(sb) (&((sb)->u.ext2_sb)) | |
15643 | +#else | |
15644 | +/* Assume that user mode programs are passing in an ext2fs superblock, not | |
15645 | + * a kernel struct super_block. This will allow us to call the feature-test | |
15646 | + * macros from user land. */ | |
15647 | +#define EXT2_SB(sb) (sb) | |
15648 | +#endif | |
15649 | + | |
15650 | +/* | |
15651 | + * Maximal count of links to a file | |
15652 | + */ | |
15653 | +#define EXT2_LINK_MAX 32000 | |
15654 | + | |
15655 | +/* | |
15656 | + * Macro-instructions used to manage several block sizes | |
15657 | + */ | |
15658 | +#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ | |
15659 | +#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ | |
15660 | +#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) | |
15661 | +#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) | |
15662 | +#ifdef __KERNEL__ | |
15663 | +#define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) | |
15664 | +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) | |
15665 | +#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->addr_per_block_bits) | |
15666 | +#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) | |
15667 | +#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) | |
15668 | +#else | |
15669 | +#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) | |
15670 | +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) | |
15671 | +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ | |
15672 | + EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size) | |
15673 | +#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ | |
15674 | + EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino) | |
15675 | +#endif | |
15676 | +#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32)) | |
15677 | + | |
15678 | +/* | |
15679 | + * Macro-instructions used to manage fragments | |
15680 | + */ | |
15681 | +#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE | |
15682 | +#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE | |
15683 | +#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE | |
15684 | +#ifdef __KERNEL__ | |
15685 | +# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->s_frag_size) | |
15686 | +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->s_frags_per_block) | |
15687 | +#else | |
15688 | +# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) | |
15689 | +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) | |
15690 | +#endif | |
15691 | + | |
15692 | +/* | |
15693 | + * ACL structures | |
15694 | + */ | |
15695 | +struct ext2_acl_header /* Header of Access Control Lists */ | |
15696 | +{ | |
15697 | + __u32 aclh_size; | |
15698 | + __u32 aclh_file_count; | |
15699 | + __u32 aclh_acle_count; | |
15700 | + __u32 aclh_first_acle; | |
15701 | +}; | |
15702 | + | |
15703 | +struct ext2_acl_entry /* Access Control List Entry */ | |
15704 | +{ | |
15705 | + __u32 acle_size; | |
15706 | + __u16 acle_perms; /* Access permissions */ | |
15707 | + __u16 acle_type; /* Type of entry */ | |
15708 | + __u16 acle_tag; /* User or group identity */ | |
15709 | + __u16 acle_pad1; | |
15710 | + __u32 acle_next; /* Pointer on next entry for the */ | |
15711 | + /* same inode or on next free entry */ | |
15712 | +}; | |
15713 | + | |
15714 | +/* | |
15715 | + * Structure of a blocks group descriptor | |
15716 | + */ | |
15717 | +struct ext2_group_desc | |
15718 | +{ | |
15719 | + __u32 bg_block_bitmap; /* Blocks bitmap block */ | |
15720 | + __u32 bg_inode_bitmap; /* Inodes bitmap block */ | |
15721 | + __u32 bg_inode_table; /* Inodes table block */ | |
15722 | + __u16 bg_free_blocks_count; /* Free blocks count */ | |
15723 | + __u16 bg_free_inodes_count; /* Free inodes count */ | |
15724 | + __u16 bg_used_dirs_count; /* Directories count */ | |
15725 | + __u16 bg_pad; | |
15726 | + __u32 bg_reserved[3]; | |
15727 | +}; | |
15728 | + | |
15729 | +/* | |
15730 | + * Data structures used by the directory indexing feature | |
15731 | + * | |
15732 | + * Note: all of the multibyte integer fields are little endian. | |
15733 | + */ | |
15734 | + | |
15735 | +/* | |
15736 | + * Note: dx_root_info is laid out so that if it should somehow get | |
15737 | + * overlaid by a dirent the two low bits of the hash version will be | |
15738 | + * zero. Therefore, the hash version mod 4 should never be 0. | |
15739 | + * Sincerely, the paranoia department. | |
15740 | + */ | |
15741 | +struct ext2_dx_root_info { | |
15742 | + __u32 reserved_zero; | |
15743 | + __u8 hash_version; /* 0 now, 1 at release */ | |
15744 | + __u8 info_length; /* 8 */ | |
15745 | + __u8 indirect_levels; | |
15746 | + __u8 unused_flags; | |
15747 | +}; | |
15748 | + | |
15749 | +#define EXT2_HASH_LEGACY 0 | |
15750 | +#define EXT2_HASH_HALF_MD4 1 | |
15751 | +#define EXT2_HASH_TEA 2 | |
15752 | + | |
15753 | +#define EXT2_HASH_FLAG_INCOMPAT 0x1 | |
15754 | + | |
15755 | +struct ext2_dx_entry { | |
15756 | + __u32 hash; | |
15757 | + __u32 block; | |
15758 | +}; | |
15759 | + | |
15760 | +struct ext2_dx_countlimit { | |
15761 | + __u16 limit; | |
15762 | + __u16 count; | |
15763 | +}; | |
15764 | + | |
15765 | + | |
15766 | +/* | |
15767 | + * Macro-instructions used to manage group descriptors | |
15768 | + */ | |
15769 | +#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) | |
15770 | +#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) | |
15771 | +#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) | |
15772 | +/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ | |
15773 | +#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) | |
15774 | +#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) | |
15775 | +#ifdef __KERNEL__ | |
15776 | +#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) | |
15777 | +#define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits) | |
15778 | +#else | |
15779 | +#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) | |
15780 | +#endif | |
15781 | + | |
15782 | +/* | |
15783 | + * Constants relative to the data blocks | |
15784 | + */ | |
15785 | +#define EXT2_NDIR_BLOCKS 12 | |
15786 | +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS | |
15787 | +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) | |
15788 | +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) | |
15789 | +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) | |
15790 | + | |
15791 | +/* | |
15792 | + * Inode flags | |
15793 | + */ | |
15794 | +#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ | |
15795 | +#define EXT2_UNRM_FL 0x00000002 /* Undelete */ | |
15796 | +#define EXT2_COMPR_FL 0x00000004 /* Compress file */ | |
15797 | +#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ | |
15798 | +#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ | |
15799 | +#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ | |
15800 | +#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ | |
15801 | +#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ | |
15802 | +/* Reserved for compression usage... */ | |
15803 | +#define EXT2_DIRTY_FL 0x00000100 | |
15804 | +#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ | |
15805 | +#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */ | |
15806 | +#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ | |
15807 | +/* End compression flags --- maybe not all used */ | |
15808 | +#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ | |
15809 | +#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ | |
15810 | +#define EXT2_IMAGIC_FL 0x00002000 | |
15811 | +#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ | |
15812 | +#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ | |
15813 | +#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ | |
15814 | +#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ | |
15815 | +#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ | |
15816 | +#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ | |
15817 | + | |
15818 | +#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ | |
15819 | +#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ | |
15820 | + | |
15821 | +/* | |
15822 | + * ioctl commands | |
15823 | + */ | |
15824 | +#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) | |
15825 | +#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) | |
15826 | +#define EXT2_IOC_GETVERSION _IOR('v', 1, long) | |
15827 | +#define EXT2_IOC_SETVERSION _IOW('v', 2, long) | |
15828 | + | |
15829 | +/* | |
15830 | + * Structure of an inode on the disk | |
15831 | + */ | |
15832 | +struct ext2_inode { | |
15833 | + __u16 i_mode; /* File mode */ | |
15834 | + __u16 i_uid; /* Low 16 bits of Owner Uid */ | |
15835 | + __u32 i_size; /* Size in bytes */ | |
15836 | + __u32 i_atime; /* Access time */ | |
15837 | + __u32 i_ctime; /* Creation time */ | |
15838 | + __u32 i_mtime; /* Modification time */ | |
15839 | + __u32 i_dtime; /* Deletion Time */ | |
15840 | + __u16 i_gid; /* Low 16 bits of Group Id */ | |
15841 | + __u16 i_links_count; /* Links count */ | |
15842 | + __u32 i_blocks; /* Blocks count */ | |
15843 | + __u32 i_flags; /* File flags */ | |
15844 | + union { | |
15845 | + struct { | |
15846 | + __u32 l_i_reserved1; | |
15847 | + } linux1; | |
15848 | + struct { | |
15849 | + __u32 h_i_translator; | |
15850 | + } hurd1; | |
15851 | + struct { | |
15852 | + __u32 m_i_reserved1; | |
15853 | + } masix1; | |
15854 | + } osd1; /* OS dependent 1 */ | |
15855 | + __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ | |
15856 | + __u32 i_generation; /* File version (for NFS) */ | |
15857 | + __u32 i_file_acl; /* File ACL */ | |
15858 | + __u32 i_dir_acl; /* Directory ACL */ | |
15859 | + __u32 i_faddr; /* Fragment address */ | |
15860 | + union { | |
15861 | + struct { | |
15862 | + __u8 l_i_frag; /* Fragment number */ | |
15863 | + __u8 l_i_fsize; /* Fragment size */ | |
15864 | + __u16 i_pad1; | |
15865 | + __u16 l_i_uid_high; /* these 2 fields */ | |
15866 | + __u16 l_i_gid_high; /* were reserved2[0] */ | |
15867 | + __u32 l_i_reserved2; | |
15868 | + } linux2; | |
15869 | + struct { | |
15870 | + __u8 h_i_frag; /* Fragment number */ | |
15871 | + __u8 h_i_fsize; /* Fragment size */ | |
15872 | + __u16 h_i_mode_high; | |
15873 | + __u16 h_i_uid_high; | |
15874 | + __u16 h_i_gid_high; | |
15875 | + __u32 h_i_author; | |
15876 | + } hurd2; | |
15877 | + struct { | |
15878 | + __u8 m_i_frag; /* Fragment number */ | |
15879 | + __u8 m_i_fsize; /* Fragment size */ | |
15880 | + __u16 m_pad1; | |
15881 | + __u32 m_i_reserved2[2]; | |
15882 | + } masix2; | |
15883 | + } osd2; /* OS dependent 2 */ | |
15884 | +}; | |
15885 | + | |
15886 | +/* | |
15887 | + * Permanent part of an large inode on the disk | |
15888 | + */ | |
15889 | +struct ext2_inode_large { | |
15890 | + __u16 i_mode; /* File mode */ | |
15891 | + __u16 i_uid; /* Low 16 bits of Owner Uid */ | |
15892 | + __u32 i_size; /* Size in bytes */ | |
15893 | + __u32 i_atime; /* Access time */ | |
15894 | + __u32 i_ctime; /* Creation time */ | |
15895 | + __u32 i_mtime; /* Modification time */ | |
15896 | + __u32 i_dtime; /* Deletion Time */ | |
15897 | + __u16 i_gid; /* Low 16 bits of Group Id */ | |
15898 | + __u16 i_links_count; /* Links count */ | |
15899 | + __u32 i_blocks; /* Blocks count */ | |
15900 | + __u32 i_flags; /* File flags */ | |
15901 | + union { | |
15902 | + struct { | |
15903 | + __u32 l_i_reserved1; | |
15904 | + } linux1; | |
15905 | + struct { | |
15906 | + __u32 h_i_translator; | |
15907 | + } hurd1; | |
15908 | + struct { | |
15909 | + __u32 m_i_reserved1; | |
15910 | + } masix1; | |
15911 | + } osd1; /* OS dependent 1 */ | |
15912 | + __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ | |
15913 | + __u32 i_generation; /* File version (for NFS) */ | |
15914 | + __u32 i_file_acl; /* File ACL */ | |
15915 | + __u32 i_dir_acl; /* Directory ACL */ | |
15916 | + __u32 i_faddr; /* Fragment address */ | |
15917 | + union { | |
15918 | + struct { | |
15919 | + __u8 l_i_frag; /* Fragment number */ | |
15920 | + __u8 l_i_fsize; /* Fragment size */ | |
15921 | + __u16 i_pad1; | |
15922 | + __u16 l_i_uid_high; /* these 2 fields */ | |
15923 | + __u16 l_i_gid_high; /* were reserved2[0] */ | |
15924 | + __u32 l_i_reserved2; | |
15925 | + } linux2; | |
15926 | + struct { | |
15927 | + __u8 h_i_frag; /* Fragment number */ | |
15928 | + __u8 h_i_fsize; /* Fragment size */ | |
15929 | + __u16 h_i_mode_high; | |
15930 | + __u16 h_i_uid_high; | |
15931 | + __u16 h_i_gid_high; | |
15932 | + __u32 h_i_author; | |
15933 | + } hurd2; | |
15934 | + struct { | |
15935 | + __u8 m_i_frag; /* Fragment number */ | |
15936 | + __u8 m_i_fsize; /* Fragment size */ | |
15937 | + __u16 m_pad1; | |
15938 | + __u32 m_i_reserved2[2]; | |
15939 | + } masix2; | |
15940 | + } osd2; /* OS dependent 2 */ | |
15941 | + __u16 i_extra_isize; | |
15942 | + __u16 i_pad1; | |
15943 | +}; | |
15944 | + | |
15945 | +#define i_size_high i_dir_acl | |
15946 | + | |
15947 | +#if defined(__KERNEL__) || defined(__linux__) | |
15948 | +#define i_reserved1 osd1.linux1.l_i_reserved1 | |
15949 | +#define i_frag osd2.linux2.l_i_frag | |
15950 | +#define i_fsize osd2.linux2.l_i_fsize | |
15951 | +#define i_uid_low i_uid | |
15952 | +#define i_gid_low i_gid | |
15953 | +#define i_uid_high osd2.linux2.l_i_uid_high | |
15954 | +#define i_gid_high osd2.linux2.l_i_gid_high | |
15955 | +#define i_reserved2 osd2.linux2.l_i_reserved2 | |
15956 | + | |
15957 | +#else | |
15958 | +#if defined(__GNU__) | |
15959 | + | |
15960 | +#define i_translator osd1.hurd1.h_i_translator | |
15961 | +#define i_frag osd2.hurd2.h_i_frag; | |
15962 | +#define i_fsize osd2.hurd2.h_i_fsize; | |
15963 | +#define i_uid_high osd2.hurd2.h_i_uid_high | |
15964 | +#define i_gid_high osd2.hurd2.h_i_gid_high | |
15965 | +#define i_author osd2.hurd2.h_i_author | |
15966 | + | |
15967 | +#else | |
15968 | +#if defined(__masix__) | |
15969 | + | |
15970 | +#define i_reserved1 osd1.masix1.m_i_reserved1 | |
15971 | +#define i_frag osd2.masix2.m_i_frag | |
15972 | +#define i_fsize osd2.masix2.m_i_fsize | |
15973 | +#define i_reserved2 osd2.masix2.m_i_reserved2 | |
15974 | + | |
15975 | +#endif /* __masix__ */ | |
15976 | +#endif /* __GNU__ */ | |
15977 | +#endif /* defined(__KERNEL__) || defined(__linux__) */ | |
15978 | + | |
15979 | +/* | |
15980 | + * File system states | |
15981 | + */ | |
15982 | +#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ | |
15983 | +#define EXT2_ERROR_FS 0x0002 /* Errors detected */ | |
15984 | + | |
15985 | +/* | |
15986 | + * Mount flags | |
15987 | + */ | |
15988 | +#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ | |
15989 | +#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ | |
15990 | +#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ | |
15991 | +#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ | |
15992 | +#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ | |
15993 | +#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ | |
15994 | +#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ | |
15995 | +#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ | |
15996 | + | |
15997 | +#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt | |
15998 | +#define set_opt(o, opt) o |= EXT2_MOUNT_##opt | |
15999 | +#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ | |
16000 | + EXT2_MOUNT_##opt) | |
16001 | +/* | |
16002 | + * Maximal mount counts between two filesystem checks | |
16003 | + */ | |
16004 | +#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ | |
16005 | +#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ | |
16006 | + | |
16007 | +/* | |
16008 | + * Behaviour when detecting errors | |
16009 | + */ | |
16010 | +#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ | |
16011 | +#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ | |
16012 | +#define EXT2_ERRORS_PANIC 3 /* Panic */ | |
16013 | +#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE | |
16014 | + | |
16015 | +/* | |
16016 | + * Structure of the super block | |
16017 | + */ | |
16018 | +struct ext2_super_block { | |
16019 | + __u32 s_inodes_count; /* Inodes count */ | |
16020 | + __u32 s_blocks_count; /* Blocks count */ | |
16021 | + __u32 s_r_blocks_count; /* Reserved blocks count */ | |
16022 | + __u32 s_free_blocks_count; /* Free blocks count */ | |
16023 | + __u32 s_free_inodes_count; /* Free inodes count */ | |
16024 | + __u32 s_first_data_block; /* First Data Block */ | |
16025 | + __u32 s_log_block_size; /* Block size */ | |
16026 | + __s32 s_log_frag_size; /* Fragment size */ | |
16027 | + __u32 s_blocks_per_group; /* # Blocks per group */ | |
16028 | + __u32 s_frags_per_group; /* # Fragments per group */ | |
16029 | + __u32 s_inodes_per_group; /* # Inodes per group */ | |
16030 | + __u32 s_mtime; /* Mount time */ | |
16031 | + __u32 s_wtime; /* Write time */ | |
16032 | + __u16 s_mnt_count; /* Mount count */ | |
16033 | + __s16 s_max_mnt_count; /* Maximal mount count */ | |
16034 | + __u16 s_magic; /* Magic signature */ | |
16035 | + __u16 s_state; /* File system state */ | |
16036 | + __u16 s_errors; /* Behaviour when detecting errors */ | |
16037 | + __u16 s_minor_rev_level; /* minor revision level */ | |
16038 | + __u32 s_lastcheck; /* time of last check */ | |
16039 | + __u32 s_checkinterval; /* max. time between checks */ | |
16040 | + __u32 s_creator_os; /* OS */ | |
16041 | + __u32 s_rev_level; /* Revision level */ | |
16042 | + __u16 s_def_resuid; /* Default uid for reserved blocks */ | |
16043 | + __u16 s_def_resgid; /* Default gid for reserved blocks */ | |
16044 | + /* | |
16045 | + * These fields are for EXT2_DYNAMIC_REV superblocks only. | |
16046 | + * | |
16047 | + * Note: the difference between the compatible feature set and | |
16048 | + * the incompatible feature set is that if there is a bit set | |
16049 | + * in the incompatible feature set that the kernel doesn't | |
16050 | + * know about, it should refuse to mount the filesystem. | |
16051 | + * | |
16052 | + * e2fsck's requirements are more strict; if it doesn't know | |
16053 | + * about a feature in either the compatible or incompatible | |
16054 | + * feature set, it must abort and not try to meddle with | |
16055 | + * things it doesn't understand... | |
16056 | + */ | |
16057 | + __u32 s_first_ino; /* First non-reserved inode */ | |
16058 | + __u16 s_inode_size; /* size of inode structure */ | |
16059 | + __u16 s_block_group_nr; /* block group # of this superblock */ | |
16060 | + __u32 s_feature_compat; /* compatible feature set */ | |
16061 | + __u32 s_feature_incompat; /* incompatible feature set */ | |
16062 | + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ | |
16063 | + __u8 s_uuid[16]; /* 128-bit uuid for volume */ | |
16064 | + char s_volume_name[16]; /* volume name */ | |
16065 | + char s_last_mounted[64]; /* directory where last mounted */ | |
16066 | + __u32 s_algorithm_usage_bitmap; /* For compression */ | |
16067 | + /* | |
16068 | + * Performance hints. Directory preallocation should only | |
16069 | + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. | |
16070 | + */ | |
16071 | + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ | |
16072 | + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ | |
16073 | + __u16 s_reserved_gdt_blocks; /* Per group table for online growth */ | |
16074 | + /* | |
16075 | + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. | |
16076 | + */ | |
16077 | + __u8 s_journal_uuid[16]; /* uuid of journal superblock */ | |
16078 | + __u32 s_journal_inum; /* inode number of journal file */ | |
16079 | + __u32 s_journal_dev; /* device number of journal file */ | |
16080 | + __u32 s_last_orphan; /* start of list of inodes to delete */ | |
16081 | + __u32 s_hash_seed[4]; /* HTREE hash seed */ | |
16082 | + __u8 s_def_hash_version; /* Default hash version to use */ | |
16083 | + __u8 s_jnl_backup_type; /* Default type of journal backup */ | |
16084 | + __u16 s_reserved_word_pad; | |
16085 | + __u32 s_default_mount_opts; | |
16086 | + __u32 s_first_meta_bg; /* First metablock group */ | |
16087 | + __u32 s_mkfs_time; /* When the filesystem was created */ | |
16088 | + __u32 s_jnl_blocks[17]; /* Backup of the journal inode */ | |
16089 | + __u32 s_reserved[172]; /* Padding to the end of the block */ | |
16090 | +}; | |
16091 | + | |
16092 | +/* | |
16093 | + * Codes for operating systems | |
16094 | + */ | |
16095 | +#define EXT2_OS_LINUX 0 | |
16096 | +#define EXT2_OS_HURD 1 | |
16097 | +#define EXT2_OS_MASIX 2 | |
16098 | +#define EXT2_OS_FREEBSD 3 | |
16099 | +#define EXT2_OS_LITES 4 | |
16100 | + | |
16101 | +/* | |
16102 | + * Revision levels | |
16103 | + */ | |
16104 | +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ | |
16105 | +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ | |
16106 | + | |
16107 | +#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV | |
16108 | +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV | |
16109 | + | |
16110 | +#define EXT2_GOOD_OLD_INODE_SIZE 128 | |
16111 | + | |
16112 | +/* | |
16113 | + * Journal inode backup types | |
16114 | + */ | |
16115 | +#define EXT3_JNL_BACKUP_BLOCKS 1 | |
16116 | + | |
16117 | +/* | |
16118 | + * Feature set definitions | |
16119 | + */ | |
16120 | + | |
16121 | +#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ | |
16122 | + ( EXT2_SB(sb)->s_feature_compat & (mask) ) | |
16123 | +#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ | |
16124 | + ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) | |
16125 | +#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ | |
16126 | + ( EXT2_SB(sb)->s_feature_incompat & (mask) ) | |
16127 | + | |
16128 | +#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 | |
16129 | +#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 | |
16130 | +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 | |
16131 | +#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 | |
16132 | +#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010 | |
16133 | +#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 | |
16134 | + | |
16135 | +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 | |
16136 | +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 | |
16137 | +/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ | |
16138 | + | |
16139 | +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 | |
16140 | +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 | |
16141 | +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ | |
16142 | +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ | |
16143 | +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 | |
16144 | +#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 | |
16145 | + | |
16146 | + | |
16147 | +#define EXT2_FEATURE_COMPAT_SUPP 0 | |
16148 | +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) | |
16149 | +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ | |
16150 | + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ | |
16151 | + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) | |
16152 | + | |
16153 | +/* | |
16154 | + * Default values for user and/or group using reserved blocks | |
16155 | + */ | |
16156 | +#define EXT2_DEF_RESUID 0 | |
16157 | +#define EXT2_DEF_RESGID 0 | |
16158 | + | |
16159 | +/* | |
16160 | + * Default mount options | |
16161 | + */ | |
16162 | +#define EXT2_DEFM_DEBUG 0x0001 | |
16163 | +#define EXT2_DEFM_BSDGROUPS 0x0002 | |
16164 | +#define EXT2_DEFM_XATTR_USER 0x0004 | |
16165 | +#define EXT2_DEFM_ACL 0x0008 | |
16166 | +#define EXT2_DEFM_UID16 0x0010 | |
16167 | +#define EXT3_DEFM_JMODE 0x0060 | |
16168 | +#define EXT3_DEFM_JMODE_DATA 0x0020 | |
16169 | +#define EXT3_DEFM_JMODE_ORDERED 0x0040 | |
16170 | +#define EXT3_DEFM_JMODE_WBACK 0x0060 | |
16171 | + | |
16172 | +/* | |
16173 | + * Structure of a directory entry | |
16174 | + */ | |
16175 | +#define EXT2_NAME_LEN 255 | |
16176 | + | |
16177 | +struct ext2_dir_entry { | |
16178 | + __u32 inode; /* Inode number */ | |
16179 | + __u16 rec_len; /* Directory entry length */ | |
16180 | + __u16 name_len; /* Name length */ | |
16181 | + char name[EXT2_NAME_LEN]; /* File name */ | |
16182 | +}; | |
16183 | + | |
16184 | +/* | |
16185 | + * The new version of the directory entry. Since EXT2 structures are | |
16186 | + * stored in intel byte order, and the name_len field could never be | |
16187 | + * bigger than 255 chars, it's safe to reclaim the extra byte for the | |
16188 | + * file_type field. | |
16189 | + */ | |
16190 | +struct ext2_dir_entry_2 { | |
16191 | + __u32 inode; /* Inode number */ | |
16192 | + __u16 rec_len; /* Directory entry length */ | |
16193 | + __u8 name_len; /* Name length */ | |
16194 | + __u8 file_type; | |
16195 | + char name[EXT2_NAME_LEN]; /* File name */ | |
16196 | +}; | |
16197 | + | |
16198 | +/* | |
16199 | + * Ext2 directory file types. Only the low 3 bits are used. The | |
16200 | + * other bits are reserved for now. | |
16201 | + */ | |
16202 | +#define EXT2_FT_UNKNOWN 0 | |
16203 | +#define EXT2_FT_REG_FILE 1 | |
16204 | +#define EXT2_FT_DIR 2 | |
16205 | +#define EXT2_FT_CHRDEV 3 | |
16206 | +#define EXT2_FT_BLKDEV 4 | |
16207 | +#define EXT2_FT_FIFO 5 | |
16208 | +#define EXT2_FT_SOCK 6 | |
16209 | +#define EXT2_FT_SYMLINK 7 | |
16210 | + | |
16211 | +#define EXT2_FT_MAX 8 | |
16212 | + | |
16213 | +/* | |
16214 | + * EXT2_DIR_PAD defines the directory entries boundaries | |
16215 | + * | |
16216 | + * NOTE: It must be a multiple of 4 | |
16217 | + */ | |
16218 | +#define EXT2_DIR_PAD 4 | |
16219 | +#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) | |
16220 | +#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ | |
16221 | + ~EXT2_DIR_ROUND) | |
16222 | + | |
16223 | +#endif /* _LINUX_EXT2_FS_H */ | |
16224 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext2_io.h busybox/e2fsprogs/ext2fs/ext2_io.h | |
16225 | --- busybox-1.00/e2fsprogs/ext2fs/ext2_io.h 1970-01-01 01:00:00.000000000 +0100 | |
16226 | +++ busybox/e2fsprogs/ext2fs/ext2_io.h 2005-06-04 08:20:16.000000000 +0200 | |
16227 | @@ -0,0 +1,108 @@ | |
16228 | +/* | |
16229 | + * io.h --- the I/O manager abstraction | |
16230 | + * | |
16231 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
16232 | + * | |
16233 | + * %Begin-Header% | |
16234 | + * This file may be redistributed under the terms of the GNU Public | |
16235 | + * License. | |
16236 | + * %End-Header% | |
16237 | + */ | |
16238 | + | |
16239 | +#ifndef _EXT2FS_EXT2_IO_H | |
16240 | +#define _EXT2FS_EXT2_IO_H | |
16241 | + | |
16242 | +/* | |
16243 | + * ext2_loff_t is defined here since unix_io.c needs it. | |
16244 | + */ | |
16245 | +#if defined(__GNUC__) || defined(HAS_LONG_LONG) | |
16246 | +typedef long long ext2_loff_t; | |
16247 | +#else | |
16248 | +typedef long ext2_loff_t; | |
16249 | +#endif | |
16250 | + | |
16251 | +/* llseek.c */ | |
16252 | +ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); | |
16253 | + | |
16254 | +typedef struct struct_io_manager *io_manager; | |
16255 | +typedef struct struct_io_channel *io_channel; | |
16256 | + | |
16257 | +#define CHANNEL_FLAGS_WRITETHROUGH 0x01 | |
16258 | + | |
16259 | +struct struct_io_channel { | |
16260 | + errcode_t magic; | |
16261 | + io_manager manager; | |
16262 | + char *name; | |
16263 | + int block_size; | |
16264 | + errcode_t (*read_error)(io_channel channel, | |
16265 | + unsigned long block, | |
16266 | + int count, | |
16267 | + void *data, | |
16268 | + size_t size, | |
16269 | + int actual_bytes_read, | |
16270 | + errcode_t error); | |
16271 | + errcode_t (*write_error)(io_channel channel, | |
16272 | + unsigned long block, | |
16273 | + int count, | |
16274 | + const void *data, | |
16275 | + size_t size, | |
16276 | + int actual_bytes_written, | |
16277 | + errcode_t error); | |
16278 | + int refcount; | |
16279 | + int flags; | |
16280 | + int reserved[14]; | |
16281 | + void *private_data; | |
16282 | + void *app_data; | |
16283 | +}; | |
16284 | + | |
16285 | +struct struct_io_manager { | |
16286 | + errcode_t magic; | |
16287 | + const char *name; | |
16288 | + errcode_t (*open)(const char *name, int flags, io_channel *channel); | |
16289 | + errcode_t (*close)(io_channel channel); | |
16290 | + errcode_t (*set_blksize)(io_channel channel, int blksize); | |
16291 | + errcode_t (*read_blk)(io_channel channel, unsigned long block, | |
16292 | + int count, void *data); | |
16293 | + errcode_t (*write_blk)(io_channel channel, unsigned long block, | |
16294 | + int count, const void *data); | |
16295 | + errcode_t (*flush)(io_channel channel); | |
16296 | + errcode_t (*write_byte)(io_channel channel, unsigned long offset, | |
16297 | + int count, const void *data); | |
16298 | + errcode_t (*set_option)(io_channel channel, const char *option, | |
16299 | + const char *arg); | |
16300 | + int reserved[14]; | |
16301 | +}; | |
16302 | + | |
16303 | +#define IO_FLAG_RW 1 | |
16304 | + | |
16305 | +/* | |
16306 | + * Convenience functions.... | |
16307 | + */ | |
16308 | +#define io_channel_close(c) ((c)->manager->close((c))) | |
16309 | +#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s)) | |
16310 | +#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d)) | |
16311 | +#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d)) | |
16312 | +#define io_channel_flush(c) ((c)->manager->flush((c))) | |
16313 | +#define io_channel_bumpcount(c) ((c)->refcount++) | |
16314 | + | |
16315 | +/* io_manager.c */ | |
16316 | +extern errcode_t io_channel_set_options(io_channel channel, | |
16317 | + const char *options); | |
16318 | +extern errcode_t io_channel_write_byte(io_channel channel, | |
16319 | + unsigned long offset, | |
16320 | + int count, const void *data); | |
16321 | + | |
16322 | +/* unix_io.c */ | |
16323 | +extern io_manager unix_io_manager; | |
16324 | + | |
16325 | +/* test_io.c */ | |
16326 | +extern io_manager test_io_manager, test_io_backing_manager; | |
16327 | +extern void (*test_io_cb_read_blk) | |
16328 | + (unsigned long block, int count, errcode_t err); | |
16329 | +extern void (*test_io_cb_write_blk) | |
16330 | + (unsigned long block, int count, errcode_t err); | |
16331 | +extern void (*test_io_cb_set_blksize) | |
16332 | + (int blksize, errcode_t err); | |
16333 | + | |
16334 | +#endif /* _EXT2FS_EXT2_IO_H */ | |
16335 | + | |
16336 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext2_types.h busybox/e2fsprogs/ext2fs/ext2_types.h | |
16337 | --- busybox-1.00/e2fsprogs/ext2fs/ext2_types.h 1970-01-01 01:00:00.000000000 +0100 | |
16338 | +++ busybox/e2fsprogs/ext2fs/ext2_types.h 2005-06-04 08:20:16.000000000 +0200 | |
16339 | @@ -0,0 +1 @@ | |
16340 | +#include <linux/types.h> | |
16341 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext2fs.h busybox/e2fsprogs/ext2fs/ext2fs.h | |
16342 | --- busybox-1.00/e2fsprogs/ext2fs/ext2fs.h 1970-01-01 01:00:00.000000000 +0100 | |
16343 | +++ busybox/e2fsprogs/ext2fs/ext2fs.h 2005-06-04 08:20:16.000000000 +0200 | |
16344 | @@ -0,0 +1,1137 @@ | |
16345 | +/* | |
16346 | + * ext2fs.h --- ext2fs | |
16347 | + * | |
16348 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
16349 | + * | |
16350 | + * %Begin-Header% | |
16351 | + * This file may be redistributed under the terms of the GNU Public | |
16352 | + * License. | |
16353 | + * %End-Header% | |
16354 | + */ | |
16355 | + | |
16356 | +#ifndef _EXT2FS_EXT2FS_H | |
16357 | +#define _EXT2FS_EXT2FS_H | |
16358 | + | |
16359 | +#ifdef __GNUC__ | |
16360 | +#define EXT2FS_ATTR(x) __attribute__(x) | |
16361 | +#else | |
16362 | +#define EXT2FS_ATTR(x) | |
16363 | +#endif | |
16364 | + | |
16365 | +#ifdef __cplusplus | |
16366 | +extern "C" { | |
16367 | +#endif | |
16368 | + | |
16369 | +/* | |
16370 | + * Non-GNU C compilers won't necessarily understand inline | |
16371 | + */ | |
16372 | +#if (!defined(__GNUC__) && !defined(__WATCOMC__)) | |
16373 | +#define NO_INLINE_FUNCS | |
16374 | +#endif | |
16375 | + | |
16376 | +/* | |
16377 | + * Build in support for byte-swapping filesystems if we the feature | |
16378 | + * has been configured or if we're being built on a CPU architecture | |
16379 | + * with a non-native byte order. | |
16380 | + */ | |
16381 | +#if defined(ENABLE_SWAPFS) || defined(WORDS_BIGENDIAN) | |
16382 | +#define EXT2FS_ENABLE_SWAPFS | |
16383 | +#endif | |
16384 | + | |
16385 | +/* | |
16386 | + * Where the master copy of the superblock is located, and how big | |
16387 | + * superblocks are supposed to be. We define SUPERBLOCK_SIZE because | |
16388 | + * the size of the superblock structure is not necessarily trustworthy | |
16389 | + * (some versions have the padding set up so that the superblock is | |
16390 | + * 1032 bytes long). | |
16391 | + */ | |
16392 | +#define SUPERBLOCK_OFFSET 1024 | |
16393 | +#define SUPERBLOCK_SIZE 1024 | |
16394 | + | |
16395 | +/* | |
16396 | + * The last ext2fs revision level that this version of the library is | |
16397 | + * able to support. | |
16398 | + */ | |
16399 | +#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV | |
16400 | + | |
16401 | +#ifdef HAVE_SYS_TYPES_H | |
16402 | +#include <sys/types.h> | |
16403 | +#endif | |
16404 | + | |
16405 | +#include <stdio.h> | |
16406 | +#include <stdlib.h> | |
16407 | + | |
16408 | +#if EXT2_FLAT_INCLUDES | |
16409 | +#include "e2_types.h" | |
16410 | +#include "ext2_fs.h" | |
16411 | +#else | |
16412 | +#include <ext2fs/ext2_types.h> | |
16413 | +#include <ext2fs/ext2_fs.h> | |
16414 | +#endif /* EXT2_FLAT_INCLUDES */ | |
16415 | + | |
16416 | +typedef __u32 ext2_ino_t; | |
16417 | +typedef __u32 blk_t; | |
16418 | +typedef __u32 dgrp_t; | |
16419 | +typedef __u32 ext2_off_t; | |
16420 | +typedef __s64 e2_blkcnt_t; | |
16421 | +typedef __u32 ext2_dirhash_t; | |
16422 | + | |
16423 | +#if EXT2_FLAT_INCLUDES | |
16424 | +#include "com_err.h" | |
16425 | +#include "ext2_io.h" | |
16426 | +#include "ext2_err.h" | |
16427 | +#else | |
16428 | +#include <et/com_err.h> | |
16429 | +#include <ext2fs/ext2_io.h> | |
16430 | +#include <ext2fs/ext2_err.h> | |
16431 | +#endif | |
16432 | + | |
16433 | +/* | |
16434 | + * Portability help for Microsoft Visual C++ | |
16435 | + */ | |
16436 | +#ifdef _MSC_VER | |
16437 | +#define EXT2_QSORT_TYPE int __cdecl | |
16438 | +#else | |
16439 | +#define EXT2_QSORT_TYPE int | |
16440 | +#endif | |
16441 | + | |
16442 | +typedef struct struct_ext2_filsys *ext2_filsys; | |
16443 | + | |
16444 | +struct ext2fs_struct_generic_bitmap { | |
16445 | + errcode_t magic; | |
16446 | + ext2_filsys fs; | |
16447 | + __u32 start, end; | |
16448 | + __u32 real_end; | |
16449 | + char * description; | |
16450 | + char * bitmap; | |
16451 | + errcode_t base_error_code; | |
16452 | + __u32 reserved[7]; | |
16453 | +}; | |
16454 | + | |
16455 | +#define EXT2FS_MARK_ERROR 0 | |
16456 | +#define EXT2FS_UNMARK_ERROR 1 | |
16457 | +#define EXT2FS_TEST_ERROR 2 | |
16458 | + | |
16459 | +typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap; | |
16460 | +typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap; | |
16461 | +typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap; | |
16462 | + | |
16463 | +#ifdef EXT2_DYNAMIC_REV | |
16464 | +#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s) | |
16465 | +#else | |
16466 | +#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO | |
16467 | +#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) | |
16468 | +#endif | |
16469 | + | |
16470 | +/* | |
16471 | + * badblocks list definitions | |
16472 | + */ | |
16473 | + | |
16474 | +typedef struct ext2_struct_u32_list *ext2_badblocks_list; | |
16475 | +typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate; | |
16476 | + | |
16477 | +typedef struct ext2_struct_u32_list *ext2_u32_list; | |
16478 | +typedef struct ext2_struct_u32_iterate *ext2_u32_iterate; | |
16479 | + | |
16480 | +/* old */ | |
16481 | +typedef struct ext2_struct_u32_list *badblocks_list; | |
16482 | +typedef struct ext2_struct_u32_iterate *badblocks_iterate; | |
16483 | + | |
16484 | +#define BADBLOCKS_FLAG_DIRTY 1 | |
16485 | + | |
16486 | +/* | |
16487 | + * ext2_dblist structure and abstractions (see dblist.c) | |
16488 | + */ | |
16489 | +struct ext2_db_entry { | |
16490 | + ext2_ino_t ino; | |
16491 | + blk_t blk; | |
16492 | + int blockcnt; | |
16493 | +}; | |
16494 | + | |
16495 | +typedef struct ext2_struct_dblist *ext2_dblist; | |
16496 | + | |
16497 | +#define DBLIST_ABORT 1 | |
16498 | + | |
16499 | +/* | |
16500 | + * ext2_fileio definitions | |
16501 | + */ | |
16502 | + | |
16503 | +#define EXT2_FILE_WRITE 0x0001 | |
16504 | +#define EXT2_FILE_CREATE 0x0002 | |
16505 | + | |
16506 | +#define EXT2_FILE_MASK 0x00FF | |
16507 | + | |
16508 | +#define EXT2_FILE_BUF_DIRTY 0x4000 | |
16509 | +#define EXT2_FILE_BUF_VALID 0x2000 | |
16510 | + | |
16511 | +typedef struct ext2_file *ext2_file_t; | |
16512 | + | |
16513 | +#define EXT2_SEEK_SET 0 | |
16514 | +#define EXT2_SEEK_CUR 1 | |
16515 | +#define EXT2_SEEK_END 2 | |
16516 | + | |
16517 | +/* | |
16518 | + * Flags for the ext2_filsys structure and for ext2fs_open() | |
16519 | + */ | |
16520 | +#define EXT2_FLAG_RW 0x01 | |
16521 | +#define EXT2_FLAG_CHANGED 0x02 | |
16522 | +#define EXT2_FLAG_DIRTY 0x04 | |
16523 | +#define EXT2_FLAG_VALID 0x08 | |
16524 | +#define EXT2_FLAG_IB_DIRTY 0x10 | |
16525 | +#define EXT2_FLAG_BB_DIRTY 0x20 | |
16526 | +#define EXT2_FLAG_SWAP_BYTES 0x40 | |
16527 | +#define EXT2_FLAG_SWAP_BYTES_READ 0x80 | |
16528 | +#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100 | |
16529 | +#define EXT2_FLAG_MASTER_SB_ONLY 0x200 | |
16530 | +#define EXT2_FLAG_FORCE 0x400 | |
16531 | +#define EXT2_FLAG_SUPER_ONLY 0x800 | |
16532 | +#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000 | |
16533 | +#define EXT2_FLAG_IMAGE_FILE 0x2000 | |
16534 | + | |
16535 | +/* | |
16536 | + * Special flag in the ext2 inode i_flag field that means that this is | |
16537 | + * a new inode. (So that ext2_write_inode() can clear extra fields.) | |
16538 | + */ | |
16539 | +#define EXT2_NEW_INODE_FL 0x80000000 | |
16540 | + | |
16541 | +/* | |
16542 | + * Flags for mkjournal | |
16543 | + * | |
16544 | + * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock | |
16545 | + */ | |
16546 | +#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 | |
16547 | + | |
16548 | +struct struct_ext2_filsys { | |
16549 | + errcode_t magic; | |
16550 | + io_channel io; | |
16551 | + int flags; | |
16552 | + char * device_name; | |
16553 | + struct ext2_super_block * super; | |
16554 | + unsigned int blocksize; | |
16555 | + int fragsize; | |
16556 | + dgrp_t group_desc_count; | |
16557 | + unsigned long desc_blocks; | |
16558 | + struct ext2_group_desc * group_desc; | |
16559 | + int inode_blocks_per_group; | |
16560 | + ext2fs_inode_bitmap inode_map; | |
16561 | + ext2fs_block_bitmap block_map; | |
16562 | + errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); | |
16563 | + errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino); | |
16564 | + errcode_t (*write_bitmaps)(ext2_filsys fs); | |
16565 | + errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino, | |
16566 | + struct ext2_inode *inode); | |
16567 | + errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino, | |
16568 | + struct ext2_inode *inode); | |
16569 | + ext2_badblocks_list badblocks; | |
16570 | + ext2_dblist dblist; | |
16571 | + __u32 stride; /* for mke2fs */ | |
16572 | + struct ext2_super_block * orig_super; | |
16573 | + struct ext2_image_hdr * image_header; | |
16574 | + __u32 umask; | |
16575 | + /* | |
16576 | + * Reserved for future expansion | |
16577 | + */ | |
16578 | + __u32 reserved[8]; | |
16579 | + | |
16580 | + /* | |
16581 | + * Reserved for the use of the calling application. | |
16582 | + */ | |
16583 | + void * priv_data; | |
16584 | + | |
16585 | + /* | |
16586 | + * Inode cache | |
16587 | + */ | |
16588 | + struct ext2_inode_cache *icache; | |
16589 | + io_channel image_io; | |
16590 | +}; | |
16591 | + | |
16592 | +#if EXT2_FLAT_INCLUDES | |
16593 | +#include "e2_bitops.h" | |
16594 | +#else | |
16595 | +#include <ext2fs/bitops.h> | |
16596 | +#endif | |
16597 | + | |
16598 | +/* | |
16599 | + * Return flags for the block iterator functions | |
16600 | + */ | |
16601 | +#define BLOCK_CHANGED 1 | |
16602 | +#define BLOCK_ABORT 2 | |
16603 | +#define BLOCK_ERROR 4 | |
16604 | + | |
16605 | +/* | |
16606 | + * Block interate flags | |
16607 | + * | |
16608 | + * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator | |
16609 | + * function should be called on blocks where the block number is zero. | |
16610 | + * This is used by ext2fs_expand_dir() to be able to add a new block | |
16611 | + * to an inode. It can also be used for programs that want to be able | |
16612 | + * to deal with files that contain "holes". | |
16613 | + * | |
16614 | + * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the | |
16615 | + * indirect, doubly indirect, etc. blocks should be called after all | |
16616 | + * of the blocks containined in the indirect blocks are processed. | |
16617 | + * This is useful if you are going to be deallocating blocks from an | |
16618 | + * inode. | |
16619 | + * | |
16620 | + * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be | |
16621 | + * called for data blocks only. | |
16622 | + * | |
16623 | + * BLOCK_FLAG_NO_LARGE is for internal use only. It informs | |
16624 | + * ext2fs_block_iterate2 that large files won't be accepted. | |
16625 | + */ | |
16626 | +#define BLOCK_FLAG_APPEND 1 | |
16627 | +#define BLOCK_FLAG_HOLE 1 | |
16628 | +#define BLOCK_FLAG_DEPTH_TRAVERSE 2 | |
16629 | +#define BLOCK_FLAG_DATA_ONLY 4 | |
16630 | + | |
16631 | +#define BLOCK_FLAG_NO_LARGE 0x1000 | |
16632 | + | |
16633 | +/* | |
16634 | + * Magic "block count" return values for the block iterator function. | |
16635 | + */ | |
16636 | +#define BLOCK_COUNT_IND (-1) | |
16637 | +#define BLOCK_COUNT_DIND (-2) | |
16638 | +#define BLOCK_COUNT_TIND (-3) | |
16639 | +#define BLOCK_COUNT_TRANSLATOR (-4) | |
16640 | + | |
16641 | +#if 0 | |
16642 | +/* | |
16643 | + * Flags for ext2fs_move_blocks | |
16644 | + */ | |
16645 | +#define EXT2_BMOVE_GET_DBLIST 0x0001 | |
16646 | +#define EXT2_BMOVE_DEBUG 0x0002 | |
16647 | +#endif | |
16648 | + | |
16649 | +/* | |
16650 | + * Flags for directory block reading and writing functions | |
16651 | + */ | |
16652 | +#define EXT2_DIRBLOCK_V2_STRUCT 0x0001 | |
16653 | + | |
16654 | +/* | |
16655 | + * Return flags for the directory iterator functions | |
16656 | + */ | |
16657 | +#define DIRENT_CHANGED 1 | |
16658 | +#define DIRENT_ABORT 2 | |
16659 | +#define DIRENT_ERROR 3 | |
16660 | + | |
16661 | +/* | |
16662 | + * Directory iterator flags | |
16663 | + */ | |
16664 | + | |
16665 | +#define DIRENT_FLAG_INCLUDE_EMPTY 1 | |
16666 | +#define DIRENT_FLAG_INCLUDE_REMOVED 2 | |
16667 | + | |
16668 | +#define DIRENT_DOT_FILE 1 | |
16669 | +#define DIRENT_DOT_DOT_FILE 2 | |
16670 | +#define DIRENT_OTHER_FILE 3 | |
16671 | +#define DIRENT_DELETED_FILE 4 | |
16672 | + | |
16673 | +/* | |
16674 | + * Inode scan definitions | |
16675 | + */ | |
16676 | +typedef struct ext2_struct_inode_scan *ext2_inode_scan; | |
16677 | + | |
16678 | +/* | |
16679 | + * ext2fs_scan flags | |
16680 | + */ | |
16681 | +#define EXT2_SF_CHK_BADBLOCKS 0x0001 | |
16682 | +#define EXT2_SF_BAD_INODE_BLK 0x0002 | |
16683 | +#define EXT2_SF_BAD_EXTRA_BYTES 0x0004 | |
16684 | +#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008 | |
16685 | + | |
16686 | +/* | |
16687 | + * ext2fs_check_if_mounted flags | |
16688 | + */ | |
16689 | +#define EXT2_MF_MOUNTED 1 | |
16690 | +#define EXT2_MF_ISROOT 2 | |
16691 | +#define EXT2_MF_READONLY 4 | |
16692 | +#define EXT2_MF_SWAP 8 | |
16693 | + | |
16694 | +/* | |
16695 | + * Ext2/linux mode flags. We define them here so that we don't need | |
16696 | + * to depend on the OS's sys/stat.h, since we may be compiling on a | |
16697 | + * non-Linux system. | |
16698 | + */ | |
16699 | +#define LINUX_S_IFMT 00170000 | |
16700 | +#define LINUX_S_IFSOCK 0140000 | |
16701 | +#define LINUX_S_IFLNK 0120000 | |
16702 | +#define LINUX_S_IFREG 0100000 | |
16703 | +#define LINUX_S_IFBLK 0060000 | |
16704 | +#define LINUX_S_IFDIR 0040000 | |
16705 | +#define LINUX_S_IFCHR 0020000 | |
16706 | +#define LINUX_S_IFIFO 0010000 | |
16707 | +#define LINUX_S_ISUID 0004000 | |
16708 | +#define LINUX_S_ISGID 0002000 | |
16709 | +#define LINUX_S_ISVTX 0001000 | |
16710 | + | |
16711 | +#define LINUX_S_IRWXU 00700 | |
16712 | +#define LINUX_S_IRUSR 00400 | |
16713 | +#define LINUX_S_IWUSR 00200 | |
16714 | +#define LINUX_S_IXUSR 00100 | |
16715 | + | |
16716 | +#define LINUX_S_IRWXG 00070 | |
16717 | +#define LINUX_S_IRGRP 00040 | |
16718 | +#define LINUX_S_IWGRP 00020 | |
16719 | +#define LINUX_S_IXGRP 00010 | |
16720 | + | |
16721 | +#define LINUX_S_IRWXO 00007 | |
16722 | +#define LINUX_S_IROTH 00004 | |
16723 | +#define LINUX_S_IWOTH 00002 | |
16724 | +#define LINUX_S_IXOTH 00001 | |
16725 | + | |
16726 | +#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK) | |
16727 | +#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG) | |
16728 | +#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR) | |
16729 | +#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR) | |
16730 | +#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK) | |
16731 | +#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO) | |
16732 | +#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK) | |
16733 | + | |
16734 | +/* | |
16735 | + * ext2 size of an inode | |
16736 | + */ | |
16737 | +#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32)) | |
16738 | + | |
16739 | +/* | |
16740 | + * ext2_icount_t abstraction | |
16741 | + */ | |
16742 | +#define EXT2_ICOUNT_OPT_INCREMENT 0x01 | |
16743 | + | |
16744 | +typedef struct ext2_icount *ext2_icount_t; | |
16745 | + | |
16746 | +/* | |
16747 | + * Flags for ext2fs_bmap | |
16748 | + */ | |
16749 | +#define BMAP_ALLOC 0x0001 | |
16750 | +#define BMAP_SET 0x0002 | |
16751 | + | |
16752 | +/* | |
16753 | + * Flags for imager.c functions | |
16754 | + */ | |
16755 | +#define IMAGER_FLAG_INODEMAP 1 | |
16756 | +#define IMAGER_FLAG_SPARSEWRITE 2 | |
16757 | + | |
16758 | +/* | |
16759 | + * For checking structure magic numbers... | |
16760 | + */ | |
16761 | + | |
16762 | +#define EXT2_CHECK_MAGIC(struct, code) \ | |
16763 | + if ((struct)->magic != (code)) return (code) | |
16764 | + | |
16765 | + | |
16766 | +/* | |
16767 | + * For ext2 compression support | |
16768 | + */ | |
16769 | +#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff) | |
16770 | +#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR) | |
16771 | + | |
16772 | +/* | |
16773 | + * Features supported by this version of the library | |
16774 | + */ | |
16775 | +#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\ | |
16776 | + EXT2_FEATURE_COMPAT_IMAGIC_INODES|\ | |
16777 | + EXT3_FEATURE_COMPAT_HAS_JOURNAL|\ | |
16778 | + EXT2_FEATURE_COMPAT_RESIZE_INODE|\ | |
16779 | + EXT2_FEATURE_COMPAT_DIR_INDEX|\ | |
16780 | + EXT2_FEATURE_COMPAT_EXT_ATTR) | |
16781 | + | |
16782 | +/* This #ifdef is temporary until compression is fully supported */ | |
16783 | +#ifdef ENABLE_COMPRESSION | |
16784 | +#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL | |
16785 | +/* If the below warning bugs you, then have | |
16786 | + `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your | |
16787 | + environment at configure time. */ | |
16788 | + #warning "Compression support is experimental" | |
16789 | +#endif | |
16790 | +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ | |
16791 | + EXT2_FEATURE_INCOMPAT_COMPRESSION|\ | |
16792 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ | |
16793 | + EXT2_FEATURE_INCOMPAT_META_BG|\ | |
16794 | + EXT3_FEATURE_INCOMPAT_RECOVER) | |
16795 | +#else | |
16796 | +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ | |
16797 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ | |
16798 | + EXT2_FEATURE_INCOMPAT_META_BG|\ | |
16799 | + EXT3_FEATURE_INCOMPAT_RECOVER) | |
16800 | +#endif | |
16801 | +#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ | |
16802 | + EXT2_FEATURE_RO_COMPAT_LARGE_FILE) | |
16803 | +/* | |
16804 | + * function prototypes | |
16805 | + */ | |
16806 | + | |
16807 | +/* alloc.c */ | |
16808 | +extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode, | |
16809 | + ext2fs_inode_bitmap map, ext2_ino_t *ret); | |
16810 | +extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, | |
16811 | + ext2fs_block_bitmap map, blk_t *ret); | |
16812 | +extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, | |
16813 | + blk_t finish, int num, | |
16814 | + ext2fs_block_bitmap map, | |
16815 | + blk_t *ret); | |
16816 | +extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, | |
16817 | + char *block_buf, blk_t *ret); | |
16818 | + | |
16819 | +/* alloc_sb.c */ | |
16820 | +extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs, | |
16821 | + dgrp_t group, | |
16822 | + ext2fs_block_bitmap bmap); | |
16823 | + | |
16824 | +/* alloc_stats.c */ | |
16825 | +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse); | |
16826 | +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, | |
16827 | + int inuse, int isdir); | |
16828 | +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse); | |
16829 | + | |
16830 | +/* alloc_tables.c */ | |
16831 | +extern errcode_t ext2fs_allocate_tables(ext2_filsys fs); | |
16832 | +extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, | |
16833 | + ext2fs_block_bitmap bmap); | |
16834 | + | |
16835 | +/* badblocks.c */ | |
16836 | +extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size); | |
16837 | +extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk); | |
16838 | +extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk); | |
16839 | +extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk); | |
16840 | +extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, | |
16841 | + ext2_u32_iterate *ret); | |
16842 | +extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk); | |
16843 | +extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter); | |
16844 | +extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest); | |
16845 | +extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2); | |
16846 | + | |
16847 | +extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, | |
16848 | + int size); | |
16849 | +extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, | |
16850 | + blk_t blk); | |
16851 | +extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb, | |
16852 | + blk_t blk); | |
16853 | +extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk); | |
16854 | +extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk); | |
16855 | +extern errcode_t | |
16856 | + ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, | |
16857 | + ext2_badblocks_iterate *ret); | |
16858 | +extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, | |
16859 | + blk_t *blk); | |
16860 | +extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter); | |
16861 | +extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, | |
16862 | + ext2_badblocks_list *dest); | |
16863 | +extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1, | |
16864 | + ext2_badblocks_list bb2); | |
16865 | +extern int ext2fs_u32_list_count(ext2_u32_list bb); | |
16866 | + | |
16867 | +/* bb_compat */ | |
16868 | +extern errcode_t badblocks_list_create(badblocks_list *ret, int size); | |
16869 | +extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk); | |
16870 | +extern int badblocks_list_test(badblocks_list bb, blk_t blk); | |
16871 | +extern errcode_t badblocks_list_iterate_begin(badblocks_list bb, | |
16872 | + badblocks_iterate *ret); | |
16873 | +extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk); | |
16874 | +extern void badblocks_list_iterate_end(badblocks_iterate iter); | |
16875 | +extern void badblocks_list_free(badblocks_list bb); | |
16876 | + | |
16877 | +/* bb_inode.c */ | |
16878 | +extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs, | |
16879 | + ext2_badblocks_list bb_list); | |
16880 | + | |
16881 | +/* bitmaps.c */ | |
16882 | +extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs); | |
16883 | +extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs); | |
16884 | +extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs); | |
16885 | +extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs); | |
16886 | +extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start, | |
16887 | + __u32 end, | |
16888 | + __u32 real_end, | |
16889 | + const char *descr, | |
16890 | + ext2fs_generic_bitmap *ret); | |
16891 | +extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, | |
16892 | + const char *descr, | |
16893 | + ext2fs_block_bitmap *ret); | |
16894 | +extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, | |
16895 | + const char *descr, | |
16896 | + ext2fs_inode_bitmap *ret); | |
16897 | +extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, | |
16898 | + ext2_ino_t end, ext2_ino_t *oend); | |
16899 | +extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, | |
16900 | + blk_t end, blk_t *oend); | |
16901 | +extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap); | |
16902 | +extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap); | |
16903 | +extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs); | |
16904 | +extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs); | |
16905 | + | |
16906 | +/* block.c */ | |
16907 | +extern errcode_t ext2fs_block_iterate(ext2_filsys fs, | |
16908 | + ext2_ino_t ino, | |
16909 | + int flags, | |
16910 | + char *block_buf, | |
16911 | + int (*func)(ext2_filsys fs, | |
16912 | + blk_t *blocknr, | |
16913 | + int blockcnt, | |
16914 | + void *priv_data), | |
16915 | + void *priv_data); | |
16916 | +errcode_t ext2fs_block_iterate2(ext2_filsys fs, | |
16917 | + ext2_ino_t ino, | |
16918 | + int flags, | |
16919 | + char *block_buf, | |
16920 | + int (*func)(ext2_filsys fs, | |
16921 | + blk_t *blocknr, | |
16922 | + e2_blkcnt_t blockcnt, | |
16923 | + blk_t ref_blk, | |
16924 | + int ref_offset, | |
16925 | + void *priv_data), | |
16926 | + void *priv_data); | |
16927 | + | |
16928 | +/* bmap.c */ | |
16929 | +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, | |
16930 | + struct ext2_inode *inode, | |
16931 | + char *block_buf, int bmap_flags, | |
16932 | + blk_t block, blk_t *phys_blk); | |
16933 | + | |
16934 | + | |
16935 | +#if 0 | |
16936 | +/* bmove.c */ | |
16937 | +extern errcode_t ext2fs_move_blocks(ext2_filsys fs, | |
16938 | + ext2fs_block_bitmap reserve, | |
16939 | + ext2fs_block_bitmap alloc_map, | |
16940 | + int flags); | |
16941 | +#endif | |
16942 | + | |
16943 | +/* check_desc.c */ | |
16944 | +extern errcode_t ext2fs_check_desc(ext2_filsys fs); | |
16945 | + | |
16946 | +/* closefs.c */ | |
16947 | +extern errcode_t ext2fs_close(ext2_filsys fs); | |
16948 | +extern errcode_t ext2fs_flush(ext2_filsys fs); | |
16949 | +extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block); | |
16950 | +extern int ext2fs_super_and_bgd_loc(ext2_filsys fs, | |
16951 | + dgrp_t group, | |
16952 | + blk_t *ret_super_blk, | |
16953 | + blk_t *ret_old_desc_blk, | |
16954 | + blk_t *ret_new_desc_blk, | |
16955 | + int *ret_meta_bg); | |
16956 | +extern void ext2fs_update_dynamic_rev(ext2_filsys fs); | |
16957 | + | |
16958 | +/* cmp_bitmaps.c */ | |
16959 | +extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, | |
16960 | + ext2fs_block_bitmap bm2); | |
16961 | +extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, | |
16962 | + ext2fs_inode_bitmap bm2); | |
16963 | + | |
16964 | +/* dblist.c */ | |
16965 | + | |
16966 | +extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs); | |
16967 | +extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist); | |
16968 | +extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, | |
16969 | + blk_t blk, int blockcnt); | |
16970 | +extern void ext2fs_dblist_sort(ext2_dblist dblist, | |
16971 | + EXT2_QSORT_TYPE (*sortfunc)(const void *, | |
16972 | + const void *)); | |
16973 | +extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, | |
16974 | + int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info, | |
16975 | + void *priv_data), | |
16976 | + void *priv_data); | |
16977 | +extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, | |
16978 | + blk_t blk, int blockcnt); | |
16979 | +extern errcode_t ext2fs_copy_dblist(ext2_dblist src, | |
16980 | + ext2_dblist *dest); | |
16981 | +extern int ext2fs_dblist_count(ext2_dblist dblist); | |
16982 | + | |
16983 | +/* dblist_dir.c */ | |
16984 | +extern errcode_t | |
16985 | + ext2fs_dblist_dir_iterate(ext2_dblist dblist, | |
16986 | + int flags, | |
16987 | + char *block_buf, | |
16988 | + int (*func)(ext2_ino_t dir, | |
16989 | + int entry, | |
16990 | + struct ext2_dir_entry *dirent, | |
16991 | + int offset, | |
16992 | + int blocksize, | |
16993 | + char *buf, | |
16994 | + void *priv_data), | |
16995 | + void *priv_data); | |
16996 | + | |
16997 | +/* dirblock.c */ | |
16998 | +extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, | |
16999 | + void *buf); | |
17000 | +extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, | |
17001 | + void *buf, int flags); | |
17002 | +extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, | |
17003 | + void *buf); | |
17004 | +extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, | |
17005 | + void *buf, int flags); | |
17006 | + | |
17007 | +/* dirhash.c */ | |
17008 | +extern errcode_t ext2fs_dirhash(int version, const char *name, int len, | |
17009 | + const __u32 *seed, | |
17010 | + ext2_dirhash_t *ret_hash, | |
17011 | + ext2_dirhash_t *ret_minor_hash); | |
17012 | + | |
17013 | + | |
17014 | +/* dir_iterate.c */ | |
17015 | +extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, | |
17016 | + ext2_ino_t dir, | |
17017 | + int flags, | |
17018 | + char *block_buf, | |
17019 | + int (*func)(struct ext2_dir_entry *dirent, | |
17020 | + int offset, | |
17021 | + int blocksize, | |
17022 | + char *buf, | |
17023 | + void *priv_data), | |
17024 | + void *priv_data); | |
17025 | +extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs, | |
17026 | + ext2_ino_t dir, | |
17027 | + int flags, | |
17028 | + char *block_buf, | |
17029 | + int (*func)(ext2_ino_t dir, | |
17030 | + int entry, | |
17031 | + struct ext2_dir_entry *dirent, | |
17032 | + int offset, | |
17033 | + int blocksize, | |
17034 | + char *buf, | |
17035 | + void *priv_data), | |
17036 | + void *priv_data); | |
17037 | + | |
17038 | +/* dupfs.c */ | |
17039 | +extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest); | |
17040 | + | |
17041 | +/* expanddir.c */ | |
17042 | +extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); | |
17043 | + | |
17044 | +/* ext_attr.c */ | |
17045 | +extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf); | |
17046 | +extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, | |
17047 | + void *buf); | |
17048 | +extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, | |
17049 | + char *block_buf, | |
17050 | + int adjust, __u32 *newcount); | |
17051 | + | |
17052 | +/* fileio.c */ | |
17053 | +extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, | |
17054 | + struct ext2_inode *inode, | |
17055 | + int flags, ext2_file_t *ret); | |
17056 | +extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, | |
17057 | + int flags, ext2_file_t *ret); | |
17058 | +extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file); | |
17059 | +extern errcode_t ext2fs_file_close(ext2_file_t file); | |
17060 | +extern errcode_t ext2fs_file_flush(ext2_file_t file); | |
17061 | +extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf, | |
17062 | + unsigned int wanted, unsigned int *got); | |
17063 | +extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, | |
17064 | + unsigned int nbytes, unsigned int *written); | |
17065 | +extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, | |
17066 | + int whence, __u64 *ret_pos); | |
17067 | +extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, | |
17068 | + int whence, ext2_off_t *ret_pos); | |
17069 | +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size); | |
17070 | +extern ext2_off_t ext2fs_file_get_size(ext2_file_t file); | |
17071 | +extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size); | |
17072 | + | |
17073 | +/* finddev.c */ | |
17074 | +extern char *ext2fs_find_block_device(dev_t device); | |
17075 | + | |
17076 | +/* flushb.c */ | |
17077 | +extern errcode_t ext2fs_sync_device(int fd, int flushb); | |
17078 | + | |
17079 | +/* freefs.c */ | |
17080 | +extern void ext2fs_free(ext2_filsys fs); | |
17081 | +extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap); | |
17082 | +extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap); | |
17083 | +extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap); | |
17084 | +extern void ext2fs_free_dblist(ext2_dblist dblist); | |
17085 | +extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb); | |
17086 | +extern void ext2fs_u32_list_free(ext2_u32_list bb); | |
17087 | + | |
17088 | +/* getsize.c */ | |
17089 | +extern errcode_t ext2fs_get_device_size(const char *file, int blocksize, | |
17090 | + blk_t *retblocks); | |
17091 | + | |
17092 | +/* getsectsize.c */ | |
17093 | +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize); | |
17094 | + | |
17095 | +/* imager.c */ | |
17096 | +extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags); | |
17097 | +extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags); | |
17098 | +extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags); | |
17099 | +extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags); | |
17100 | +extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags); | |
17101 | +extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags); | |
17102 | + | |
17103 | +/* ind_block.c */ | |
17104 | +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf); | |
17105 | +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf); | |
17106 | + | |
17107 | +/* initialize.c */ | |
17108 | +extern errcode_t ext2fs_initialize(const char *name, int flags, | |
17109 | + struct ext2_super_block *param, | |
17110 | + io_manager manager, ext2_filsys *ret_fs); | |
17111 | + | |
17112 | +/* icount.c */ | |
17113 | +extern void ext2fs_free_icount(ext2_icount_t icount); | |
17114 | +extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, | |
17115 | + unsigned int size, | |
17116 | + ext2_icount_t hint, ext2_icount_t *ret); | |
17117 | +extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, | |
17118 | + unsigned int size, | |
17119 | + ext2_icount_t *ret); | |
17120 | +extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, | |
17121 | + __u16 *ret); | |
17122 | +extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, | |
17123 | + __u16 *ret); | |
17124 | +extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, | |
17125 | + __u16 *ret); | |
17126 | +extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, | |
17127 | + __u16 count); | |
17128 | +extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount); | |
17129 | +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); | |
17130 | + | |
17131 | +/* inode.c */ | |
17132 | +extern errcode_t ext2fs_flush_icache(ext2_filsys fs); | |
17133 | +extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, | |
17134 | + ext2_ino_t *ino, | |
17135 | + struct ext2_inode *inode, | |
17136 | + int bufsize); | |
17137 | +extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, | |
17138 | + ext2_inode_scan *ret_scan); | |
17139 | +extern void ext2fs_close_inode_scan(ext2_inode_scan scan); | |
17140 | +extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, | |
17141 | + struct ext2_inode *inode); | |
17142 | +extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, | |
17143 | + int group); | |
17144 | +extern void ext2fs_set_inode_callback | |
17145 | + (ext2_inode_scan scan, | |
17146 | + errcode_t (*done_group)(ext2_filsys fs, | |
17147 | + ext2_inode_scan scan, | |
17148 | + dgrp_t group, | |
17149 | + void * priv_data), | |
17150 | + void *done_group_data); | |
17151 | +extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, | |
17152 | + int clear_flags); | |
17153 | +extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, | |
17154 | + struct ext2_inode * inode, | |
17155 | + int bufsize); | |
17156 | +extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, | |
17157 | + struct ext2_inode * inode); | |
17158 | +extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, | |
17159 | + struct ext2_inode * inode, | |
17160 | + int bufsize); | |
17161 | +extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, | |
17162 | + struct ext2_inode * inode); | |
17163 | +extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, | |
17164 | + struct ext2_inode * inode); | |
17165 | +extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); | |
17166 | +extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino); | |
17167 | + | |
17168 | +/* inode_io.c */ | |
17169 | +extern io_manager inode_io_manager; | |
17170 | +extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, | |
17171 | + char **name); | |
17172 | +extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino, | |
17173 | + struct ext2_inode *inode, | |
17174 | + char **name); | |
17175 | + | |
17176 | +/* ismounted.c */ | |
17177 | +extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags); | |
17178 | +extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, | |
17179 | + char *mtpt, int mtlen); | |
17180 | + | |
17181 | +/* namei.c */ | |
17182 | +extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, | |
17183 | + int namelen, char *buf, ext2_ino_t *inode); | |
17184 | +extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, | |
17185 | + const char *name, ext2_ino_t *inode); | |
17186 | +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, | |
17187 | + const char *name, ext2_ino_t *inode); | |
17188 | +extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, | |
17189 | + ext2_ino_t inode, ext2_ino_t *res_inode); | |
17190 | + | |
17191 | +/* native.c */ | |
17192 | +int ext2fs_native_flag(void); | |
17193 | + | |
17194 | +/* newdir.c */ | |
17195 | +extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, | |
17196 | + ext2_ino_t parent_ino, char **block); | |
17197 | + | |
17198 | +/* mkdir.c */ | |
17199 | +extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | |
17200 | + const char *name); | |
17201 | + | |
17202 | +/* mkjournal.c */ | |
17203 | +extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, | |
17204 | + __u32 size, int flags, | |
17205 | + char **ret_jsb); | |
17206 | +extern errcode_t ext2fs_add_journal_device(ext2_filsys fs, | |
17207 | + ext2_filsys journal_dev); | |
17208 | +extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, | |
17209 | + int flags); | |
17210 | + | |
17211 | +/* openfs.c */ | |
17212 | +extern errcode_t ext2fs_open(const char *name, int flags, int superblock, | |
17213 | + unsigned int block_size, io_manager manager, | |
17214 | + ext2_filsys *ret_fs); | |
17215 | +extern errcode_t ext2fs_open2(const char *name, const char *io_options, | |
17216 | + int flags, int superblock, | |
17217 | + unsigned int block_size, io_manager manager, | |
17218 | + ext2_filsys *ret_fs); | |
17219 | +extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, | |
17220 | + dgrp_t i); | |
17221 | +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io); | |
17222 | +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io); | |
17223 | +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io); | |
17224 | + | |
17225 | +/* get_pathname.c */ | |
17226 | +extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, | |
17227 | + char **name); | |
17228 | + | |
17229 | +/* link.c */ | |
17230 | +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, | |
17231 | + ext2_ino_t ino, int flags); | |
17232 | +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name, | |
17233 | + ext2_ino_t ino, int flags); | |
17234 | + | |
17235 | +/* read_bb.c */ | |
17236 | +extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs, | |
17237 | + ext2_badblocks_list *bb_list); | |
17238 | + | |
17239 | +/* read_bb_file.c */ | |
17240 | +extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, | |
17241 | + ext2_badblocks_list *bb_list, | |
17242 | + void *priv_data, | |
17243 | + void (*invalid)(ext2_filsys fs, | |
17244 | + blk_t blk, | |
17245 | + char *badstr, | |
17246 | + void *priv_data)); | |
17247 | +extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, | |
17248 | + ext2_badblocks_list *bb_list, | |
17249 | + void (*invalid)(ext2_filsys fs, | |
17250 | + blk_t blk)); | |
17251 | + | |
17252 | +/* res_gdt.c */ | |
17253 | +extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs); | |
17254 | + | |
17255 | +/* rs_bitmap.c */ | |
17256 | +extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, | |
17257 | + __u32 new_real_end, | |
17258 | + ext2fs_generic_bitmap bmap); | |
17259 | +extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, | |
17260 | + ext2fs_inode_bitmap bmap); | |
17261 | +extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, | |
17262 | + ext2fs_block_bitmap bmap); | |
17263 | +extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, | |
17264 | + ext2fs_generic_bitmap *dest); | |
17265 | + | |
17266 | +/* swapfs.c */ | |
17267 | +extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, | |
17268 | + int has_header); | |
17269 | +extern void ext2fs_swap_super(struct ext2_super_block * super); | |
17270 | +extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp); | |
17271 | +extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, | |
17272 | + struct ext2_inode_large *f, int hostorder, | |
17273 | + int bufsize); | |
17274 | +extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t, | |
17275 | + struct ext2_inode *f, int hostorder); | |
17276 | + | |
17277 | +/* valid_blk.c */ | |
17278 | +extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode); | |
17279 | + | |
17280 | +/* version.c */ | |
17281 | +extern int ext2fs_parse_version_string(const char *ver_string); | |
17282 | +extern int ext2fs_get_library_version(const char **ver_string, | |
17283 | + const char **date_string); | |
17284 | + | |
17285 | +/* write_bb_file.c */ | |
17286 | +extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, | |
17287 | + unsigned int flags, | |
17288 | + FILE *f); | |
17289 | + | |
17290 | + | |
17291 | +/* inline functions */ | |
17292 | +extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr); | |
17293 | +extern errcode_t ext2fs_free_mem(void *ptr); | |
17294 | +extern errcode_t ext2fs_resize_mem(unsigned long old_size, | |
17295 | + unsigned long size, void *ptr); | |
17296 | +extern void ext2fs_mark_super_dirty(ext2_filsys fs); | |
17297 | +extern void ext2fs_mark_changed(ext2_filsys fs); | |
17298 | +extern int ext2fs_test_changed(ext2_filsys fs); | |
17299 | +extern void ext2fs_mark_valid(ext2_filsys fs); | |
17300 | +extern void ext2fs_unmark_valid(ext2_filsys fs); | |
17301 | +extern int ext2fs_test_valid(ext2_filsys fs); | |
17302 | +extern void ext2fs_mark_ib_dirty(ext2_filsys fs); | |
17303 | +extern void ext2fs_mark_bb_dirty(ext2_filsys fs); | |
17304 | +extern int ext2fs_test_ib_dirty(ext2_filsys fs); | |
17305 | +extern int ext2fs_test_bb_dirty(ext2_filsys fs); | |
17306 | +extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk); | |
17307 | +extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino); | |
17308 | +extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs, | |
17309 | + struct ext2_inode *inode); | |
17310 | + | |
17311 | +/* | |
17312 | + * The actual inlined functions definitions themselves... | |
17313 | + * | |
17314 | + * If NO_INLINE_FUNCS is defined, then we won't try to do inline | |
17315 | + * functions at all! | |
17316 | + */ | |
17317 | +#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) | |
17318 | +#ifdef INCLUDE_INLINE_FUNCS | |
17319 | +#define _INLINE_ extern | |
17320 | +#else | |
17321 | +#ifdef __GNUC__ | |
17322 | +#define _INLINE_ extern __inline__ | |
17323 | +#else /* For Watcom C */ | |
17324 | +#define _INLINE_ extern inline | |
17325 | +#endif | |
17326 | +#endif | |
17327 | + | |
17328 | +#ifndef EXT2_CUSTOM_MEMORY_ROUTINES | |
17329 | +/* | |
17330 | + * Allocate memory | |
17331 | + */ | |
17332 | +_INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr) | |
17333 | +{ | |
17334 | + void **pp = (void **)ptr; | |
17335 | + | |
17336 | + *pp = malloc(size); | |
17337 | + if (!*pp) | |
17338 | + return EXT2_ET_NO_MEMORY; | |
17339 | + return 0; | |
17340 | +} | |
17341 | + | |
17342 | +/* | |
17343 | + * Free memory | |
17344 | + */ | |
17345 | +_INLINE_ errcode_t ext2fs_free_mem(void *ptr) | |
17346 | +{ | |
17347 | + void **pp = (void **)ptr; | |
17348 | + | |
17349 | + free(*pp); | |
17350 | + *pp = 0; | |
17351 | + return 0; | |
17352 | +} | |
17353 | + | |
17354 | +/* | |
17355 | + * Resize memory | |
17356 | + */ | |
17357 | +_INLINE_ errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size, | |
17358 | + unsigned long size, void *ptr) | |
17359 | +{ | |
17360 | + void *p; | |
17361 | + void **pp = (void **)ptr; | |
17362 | + | |
17363 | + p = realloc(*pp, size); | |
17364 | + if (!p) | |
17365 | + return EXT2_ET_NO_MEMORY; | |
17366 | + *pp = p; | |
17367 | + return 0; | |
17368 | +} | |
17369 | +#endif /* Custom memory routines */ | |
17370 | + | |
17371 | +/* | |
17372 | + * Mark a filesystem superblock as dirty | |
17373 | + */ | |
17374 | +_INLINE_ void ext2fs_mark_super_dirty(ext2_filsys fs) | |
17375 | +{ | |
17376 | + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED; | |
17377 | +} | |
17378 | + | |
17379 | +/* | |
17380 | + * Mark a filesystem as changed | |
17381 | + */ | |
17382 | +_INLINE_ void ext2fs_mark_changed(ext2_filsys fs) | |
17383 | +{ | |
17384 | + fs->flags |= EXT2_FLAG_CHANGED; | |
17385 | +} | |
17386 | + | |
17387 | +/* | |
17388 | + * Check to see if a filesystem has changed | |
17389 | + */ | |
17390 | +_INLINE_ int ext2fs_test_changed(ext2_filsys fs) | |
17391 | +{ | |
17392 | + return (fs->flags & EXT2_FLAG_CHANGED); | |
17393 | +} | |
17394 | + | |
17395 | +/* | |
17396 | + * Mark a filesystem as valid | |
17397 | + */ | |
17398 | +_INLINE_ void ext2fs_mark_valid(ext2_filsys fs) | |
17399 | +{ | |
17400 | + fs->flags |= EXT2_FLAG_VALID; | |
17401 | +} | |
17402 | + | |
17403 | +/* | |
17404 | + * Mark a filesystem as NOT valid | |
17405 | + */ | |
17406 | +_INLINE_ void ext2fs_unmark_valid(ext2_filsys fs) | |
17407 | +{ | |
17408 | + fs->flags &= ~EXT2_FLAG_VALID; | |
17409 | +} | |
17410 | + | |
17411 | +/* | |
17412 | + * Check to see if a filesystem is valid | |
17413 | + */ | |
17414 | +_INLINE_ int ext2fs_test_valid(ext2_filsys fs) | |
17415 | +{ | |
17416 | + return (fs->flags & EXT2_FLAG_VALID); | |
17417 | +} | |
17418 | + | |
17419 | +/* | |
17420 | + * Mark the inode bitmap as dirty | |
17421 | + */ | |
17422 | +_INLINE_ void ext2fs_mark_ib_dirty(ext2_filsys fs) | |
17423 | +{ | |
17424 | + fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED; | |
17425 | +} | |
17426 | + | |
17427 | +/* | |
17428 | + * Mark the block bitmap as dirty | |
17429 | + */ | |
17430 | +_INLINE_ void ext2fs_mark_bb_dirty(ext2_filsys fs) | |
17431 | +{ | |
17432 | + fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED; | |
17433 | +} | |
17434 | + | |
17435 | +/* | |
17436 | + * Check to see if a filesystem's inode bitmap is dirty | |
17437 | + */ | |
17438 | +_INLINE_ int ext2fs_test_ib_dirty(ext2_filsys fs) | |
17439 | +{ | |
17440 | + return (fs->flags & EXT2_FLAG_IB_DIRTY); | |
17441 | +} | |
17442 | + | |
17443 | +/* | |
17444 | + * Check to see if a filesystem's block bitmap is dirty | |
17445 | + */ | |
17446 | +_INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs) | |
17447 | +{ | |
17448 | + return (fs->flags & EXT2_FLAG_BB_DIRTY); | |
17449 | +} | |
17450 | + | |
17451 | +/* | |
17452 | + * Return the group # of a block | |
17453 | + */ | |
17454 | +_INLINE_ int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk) | |
17455 | +{ | |
17456 | + return (blk - fs->super->s_first_data_block) / | |
17457 | + fs->super->s_blocks_per_group; | |
17458 | +} | |
17459 | + | |
17460 | +/* | |
17461 | + * Return the group # of an inode number | |
17462 | + */ | |
17463 | +_INLINE_ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino) | |
17464 | +{ | |
17465 | + return (ino - 1) / fs->super->s_inodes_per_group; | |
17466 | +} | |
17467 | + | |
17468 | +_INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs, | |
17469 | + struct ext2_inode *inode) | |
17470 | +{ | |
17471 | + return inode->i_blocks - | |
17472 | + (inode->i_file_acl ? fs->blocksize >> 9 : 0); | |
17473 | +} | |
17474 | +#undef _INLINE_ | |
17475 | +#endif | |
17476 | + | |
17477 | +#ifdef __cplusplus | |
17478 | +} | |
17479 | +#endif | |
17480 | + | |
17481 | +#endif /* _EXT2FS_EXT2FS_H */ | |
17482 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext2fsP.h busybox/e2fsprogs/ext2fs/ext2fsP.h | |
17483 | --- busybox-1.00/e2fsprogs/ext2fs/ext2fsP.h 1970-01-01 01:00:00.000000000 +0100 | |
17484 | +++ busybox/e2fsprogs/ext2fs/ext2fsP.h 2005-06-04 08:20:16.000000000 +0200 | |
17485 | @@ -0,0 +1,88 @@ | |
17486 | +/* | |
17487 | + * ext2fsP.h --- private header file for ext2 library | |
17488 | + * | |
17489 | + * Copyright (C) 1997 Theodore Ts'o. | |
17490 | + * | |
17491 | + * %Begin-Header% | |
17492 | + * This file may be redistributed under the terms of the GNU Public | |
17493 | + * License. | |
17494 | + * %End-Header% | |
17495 | + */ | |
17496 | + | |
17497 | +#include "ext2fs.h" | |
17498 | + | |
17499 | +/* | |
17500 | + * Badblocks list | |
17501 | + */ | |
17502 | +struct ext2_struct_u32_list { | |
17503 | + int magic; | |
17504 | + int num; | |
17505 | + int size; | |
17506 | + __u32 *list; | |
17507 | + int badblocks_flags; | |
17508 | +}; | |
17509 | + | |
17510 | +struct ext2_struct_u32_iterate { | |
17511 | + int magic; | |
17512 | + ext2_u32_list bb; | |
17513 | + int ptr; | |
17514 | +}; | |
17515 | + | |
17516 | + | |
17517 | +/* | |
17518 | + * Directory block iterator definition | |
17519 | + */ | |
17520 | +struct ext2_struct_dblist { | |
17521 | + int magic; | |
17522 | + ext2_filsys fs; | |
17523 | + ext2_ino_t size; | |
17524 | + ext2_ino_t count; | |
17525 | + int sorted; | |
17526 | + struct ext2_db_entry * list; | |
17527 | +}; | |
17528 | + | |
17529 | +/* | |
17530 | + * For directory iterators | |
17531 | + */ | |
17532 | +struct dir_context { | |
17533 | + ext2_ino_t dir; | |
17534 | + int flags; | |
17535 | + char *buf; | |
17536 | + int (*func)(ext2_ino_t dir, | |
17537 | + int entry, | |
17538 | + struct ext2_dir_entry *dirent, | |
17539 | + int offset, | |
17540 | + int blocksize, | |
17541 | + char *buf, | |
17542 | + void *priv_data); | |
17543 | + void *priv_data; | |
17544 | + errcode_t errcode; | |
17545 | +}; | |
17546 | + | |
17547 | +/* | |
17548 | + * Inode cache structure | |
17549 | + */ | |
17550 | +struct ext2_inode_cache { | |
17551 | + void * buffer; | |
17552 | + blk_t buffer_blk; | |
17553 | + int cache_last; | |
17554 | + int cache_size; | |
17555 | + int refcount; | |
17556 | + struct ext2_inode_cache_ent *cache; | |
17557 | +}; | |
17558 | + | |
17559 | +struct ext2_inode_cache_ent { | |
17560 | + ext2_ino_t ino; | |
17561 | + struct ext2_inode inode; | |
17562 | +}; | |
17563 | + | |
17564 | +/* Function prototypes */ | |
17565 | + | |
17566 | +extern int ext2fs_process_dir_block(ext2_filsys fs, | |
17567 | + blk_t *blocknr, | |
17568 | + e2_blkcnt_t blockcnt, | |
17569 | + blk_t ref_block, | |
17570 | + int ref_offset, | |
17571 | + void *priv_data); | |
17572 | + | |
17573 | + | |
17574 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ext_attr.c busybox/e2fsprogs/ext2fs/ext_attr.c | |
17575 | --- busybox-1.00/e2fsprogs/ext2fs/ext_attr.c 1970-01-01 01:00:00.000000000 +0100 | |
17576 | +++ busybox/e2fsprogs/ext2fs/ext_attr.c 2005-06-04 08:20:16.000000000 +0200 | |
17577 | @@ -0,0 +1,105 @@ | |
17578 | +/* | |
17579 | + * ext_attr.c --- extended attribute blocks | |
17580 | + * | |
17581 | + * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org> | |
17582 | + * | |
17583 | + * Copyright (C) 2002 Theodore Ts'o. | |
17584 | + * | |
17585 | + * %Begin-Header% | |
17586 | + * This file may be redistributed under the terms of the GNU Public | |
17587 | + * License. | |
17588 | + * %End-Header% | |
17589 | + */ | |
17590 | + | |
17591 | +#include <stdio.h> | |
17592 | +#if HAVE_UNISTD_H | |
17593 | +#include <unistd.h> | |
17594 | +#endif | |
17595 | +#include <string.h> | |
17596 | +#include <time.h> | |
17597 | + | |
17598 | +#include "ext2_fs.h" | |
17599 | +#include "ext2_ext_attr.h" | |
17600 | + | |
17601 | +#include "ext2fs.h" | |
17602 | + | |
17603 | +errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf) | |
17604 | +{ | |
17605 | + errcode_t retval; | |
17606 | + | |
17607 | + retval = io_channel_read_blk(fs->io, block, 1, buf); | |
17608 | + if (retval) | |
17609 | + return retval; | |
17610 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
17611 | + if ((fs->flags & (EXT2_FLAG_SWAP_BYTES| | |
17612 | + EXT2_FLAG_SWAP_BYTES_READ)) != 0) | |
17613 | + ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1); | |
17614 | +#endif | |
17615 | + return 0; | |
17616 | +} | |
17617 | + | |
17618 | +errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf) | |
17619 | +{ | |
17620 | + errcode_t retval; | |
17621 | + char *write_buf; | |
17622 | + char *buf = NULL; | |
17623 | + | |
17624 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
17625 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
17626 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) { | |
17627 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
17628 | + if (retval) | |
17629 | + return retval; | |
17630 | + write_buf = buf; | |
17631 | + ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1); | |
17632 | + } else | |
17633 | +#endif | |
17634 | + write_buf = (char *) inbuf; | |
17635 | + retval = io_channel_write_blk(fs->io, block, 1, write_buf); | |
17636 | + if (buf) | |
17637 | + ext2fs_free_mem(&buf); | |
17638 | + if (!retval) | |
17639 | + ext2fs_mark_changed(fs); | |
17640 | + return retval; | |
17641 | +} | |
17642 | + | |
17643 | +/* | |
17644 | + * This function adjusts the reference count of the EA block. | |
17645 | + */ | |
17646 | +errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, | |
17647 | + char *block_buf, int adjust, | |
17648 | + __u32 *newcount) | |
17649 | +{ | |
17650 | + errcode_t retval; | |
17651 | + struct ext2_ext_attr_header *header; | |
17652 | + char *buf = 0; | |
17653 | + | |
17654 | + if ((blk >= fs->super->s_blocks_count) || | |
17655 | + (blk < fs->super->s_first_data_block)) | |
17656 | + return EXT2_ET_BAD_EA_BLOCK_NUM; | |
17657 | + | |
17658 | + if (!block_buf) { | |
17659 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
17660 | + if (retval) | |
17661 | + return retval; | |
17662 | + block_buf = buf; | |
17663 | + } | |
17664 | + | |
17665 | + retval = ext2fs_read_ext_attr(fs, blk, block_buf); | |
17666 | + if (retval) | |
17667 | + goto errout; | |
17668 | + | |
17669 | + header = (struct ext2_ext_attr_header *) block_buf; | |
17670 | + header->h_refcount += adjust; | |
17671 | + if (newcount) | |
17672 | + *newcount = header->h_refcount; | |
17673 | + | |
17674 | + retval = ext2fs_write_ext_attr(fs, blk, block_buf); | |
17675 | + if (retval) | |
17676 | + goto errout; | |
17677 | + | |
17678 | +errout: | |
17679 | + if (buf) | |
17680 | + ext2fs_free_mem(&buf); | |
17681 | + return retval; | |
17682 | +} | |
17683 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/fileio.c busybox/e2fsprogs/ext2fs/fileio.c | |
17684 | --- busybox-1.00/e2fsprogs/ext2fs/fileio.c 1970-01-01 01:00:00.000000000 +0100 | |
17685 | +++ busybox/e2fsprogs/ext2fs/fileio.c 2005-06-04 08:20:16.000000000 +0200 | |
17686 | @@ -0,0 +1,378 @@ | |
17687 | +/* | |
17688 | + * fileio.c --- Simple file I/O routines | |
17689 | + * | |
17690 | + * Copyright (C) 1997 Theodore Ts'o. | |
17691 | + * | |
17692 | + * %Begin-Header% | |
17693 | + * This file may be redistributed under the terms of the GNU Public | |
17694 | + * License. | |
17695 | + * %End-Header% | |
17696 | + */ | |
17697 | + | |
17698 | +#include <stdio.h> | |
17699 | +#include <string.h> | |
17700 | +#if HAVE_UNISTD_H | |
17701 | +#include <unistd.h> | |
17702 | +#endif | |
17703 | + | |
17704 | +#include "ext2_fs.h" | |
17705 | +#include "ext2fs.h" | |
17706 | + | |
17707 | +struct ext2_file { | |
17708 | + errcode_t magic; | |
17709 | + ext2_filsys fs; | |
17710 | + ext2_ino_t ino; | |
17711 | + struct ext2_inode inode; | |
17712 | + int flags; | |
17713 | + __u64 pos; | |
17714 | + blk_t blockno; | |
17715 | + blk_t physblock; | |
17716 | + char *buf; | |
17717 | +}; | |
17718 | + | |
17719 | +#define BMAP_BUFFER (file->buf + fs->blocksize) | |
17720 | + | |
17721 | +errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, | |
17722 | + struct ext2_inode *inode, | |
17723 | + int flags, ext2_file_t *ret) | |
17724 | +{ | |
17725 | + ext2_file_t file; | |
17726 | + errcode_t retval; | |
17727 | + | |
17728 | + /* | |
17729 | + * Don't let caller create or open a file for writing if the | |
17730 | + * filesystem is read-only. | |
17731 | + */ | |
17732 | + if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) && | |
17733 | + !(fs->flags & EXT2_FLAG_RW)) | |
17734 | + return EXT2_ET_RO_FILSYS; | |
17735 | + | |
17736 | + retval = ext2fs_get_mem(sizeof(struct ext2_file), &file); | |
17737 | + if (retval) | |
17738 | + return retval; | |
17739 | + | |
17740 | + memset(file, 0, sizeof(struct ext2_file)); | |
17741 | + file->magic = EXT2_ET_MAGIC_EXT2_FILE; | |
17742 | + file->fs = fs; | |
17743 | + file->ino = ino; | |
17744 | + file->flags = flags & EXT2_FILE_MASK; | |
17745 | + | |
17746 | + if (inode) { | |
17747 | + memcpy(&file->inode, inode, sizeof(struct ext2_inode)); | |
17748 | + } else { | |
17749 | + retval = ext2fs_read_inode(fs, ino, &file->inode); | |
17750 | + if (retval) | |
17751 | + goto fail; | |
17752 | + } | |
17753 | + | |
17754 | + retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf); | |
17755 | + if (retval) | |
17756 | + goto fail; | |
17757 | + | |
17758 | + *ret = file; | |
17759 | + return 0; | |
17760 | + | |
17761 | +fail: | |
17762 | + if (file->buf) | |
17763 | + ext2fs_free_mem(&file->buf); | |
17764 | + ext2fs_free_mem(&file); | |
17765 | + return retval; | |
17766 | +} | |
17767 | + | |
17768 | +errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, | |
17769 | + int flags, ext2_file_t *ret) | |
17770 | +{ | |
17771 | + return ext2fs_file_open2(fs, ino, NULL, flags, ret); | |
17772 | +} | |
17773 | + | |
17774 | +/* | |
17775 | + * This function returns the filesystem handle of a file from the structure | |
17776 | + */ | |
17777 | +ext2_filsys ext2fs_file_get_fs(ext2_file_t file) | |
17778 | +{ | |
17779 | + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) | |
17780 | + return 0; | |
17781 | + return file->fs; | |
17782 | +} | |
17783 | + | |
17784 | +/* | |
17785 | + * This function flushes the dirty block buffer out to disk if | |
17786 | + * necessary. | |
17787 | + */ | |
17788 | +errcode_t ext2fs_file_flush(ext2_file_t file) | |
17789 | +{ | |
17790 | + errcode_t retval; | |
17791 | + ext2_filsys fs; | |
17792 | + | |
17793 | + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); | |
17794 | + fs = file->fs; | |
17795 | + | |
17796 | + if (!(file->flags & EXT2_FILE_BUF_VALID) || | |
17797 | + !(file->flags & EXT2_FILE_BUF_DIRTY)) | |
17798 | + return 0; | |
17799 | + | |
17800 | + /* | |
17801 | + * OK, the physical block hasn't been allocated yet. | |
17802 | + * Allocate it. | |
17803 | + */ | |
17804 | + if (!file->physblock) { | |
17805 | + retval = ext2fs_bmap(fs, file->ino, &file->inode, | |
17806 | + BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0, | |
17807 | + file->blockno, &file->physblock); | |
17808 | + if (retval) | |
17809 | + return retval; | |
17810 | + } | |
17811 | + | |
17812 | + retval = io_channel_write_blk(fs->io, file->physblock, | |
17813 | + 1, file->buf); | |
17814 | + if (retval) | |
17815 | + return retval; | |
17816 | + | |
17817 | + file->flags &= ~EXT2_FILE_BUF_DIRTY; | |
17818 | + | |
17819 | + return retval; | |
17820 | +} | |
17821 | + | |
17822 | +/* | |
17823 | + * This function synchronizes the file's block buffer and the current | |
17824 | + * file position, possibly invalidating block buffer if necessary | |
17825 | + */ | |
17826 | +static errcode_t sync_buffer_position(ext2_file_t file) | |
17827 | +{ | |
17828 | + blk_t b; | |
17829 | + errcode_t retval; | |
17830 | + | |
17831 | + b = file->pos / file->fs->blocksize; | |
17832 | + if (b != file->blockno) { | |
17833 | + retval = ext2fs_file_flush(file); | |
17834 | + if (retval) | |
17835 | + return retval; | |
17836 | + file->flags &= ~EXT2_FILE_BUF_VALID; | |
17837 | + } | |
17838 | + file->blockno = b; | |
17839 | + return 0; | |
17840 | +} | |
17841 | + | |
17842 | +/* | |
17843 | + * This function loads the file's block buffer with valid data from | |
17844 | + * the disk as necessary. | |
17845 | + * | |
17846 | + * If dontfill is true, then skip initializing the buffer since we're | |
17847 | + * going to be replacing its entire contents anyway. If set, then the | |
17848 | + * function basically only sets file->physblock and EXT2_FILE_BUF_VALID | |
17849 | + */ | |
17850 | +#define DONTFILL 1 | |
17851 | +static errcode_t load_buffer(ext2_file_t file, int dontfill) | |
17852 | +{ | |
17853 | + ext2_filsys fs = file->fs; | |
17854 | + errcode_t retval; | |
17855 | + | |
17856 | + if (!(file->flags & EXT2_FILE_BUF_VALID)) { | |
17857 | + retval = ext2fs_bmap(fs, file->ino, &file->inode, | |
17858 | + BMAP_BUFFER, 0, file->blockno, | |
17859 | + &file->physblock); | |
17860 | + if (retval) | |
17861 | + return retval; | |
17862 | + if (!dontfill) { | |
17863 | + if (file->physblock) { | |
17864 | + retval = io_channel_read_blk(fs->io, | |
17865 | + file->physblock, | |
17866 | + 1, file->buf); | |
17867 | + if (retval) | |
17868 | + return retval; | |
17869 | + } else | |
17870 | + memset(file->buf, 0, fs->blocksize); | |
17871 | + } | |
17872 | + file->flags |= EXT2_FILE_BUF_VALID; | |
17873 | + } | |
17874 | + return 0; | |
17875 | +} | |
17876 | + | |
17877 | + | |
17878 | +errcode_t ext2fs_file_close(ext2_file_t file) | |
17879 | +{ | |
17880 | + errcode_t retval; | |
17881 | + | |
17882 | + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); | |
17883 | + | |
17884 | + retval = ext2fs_file_flush(file); | |
17885 | + | |
17886 | + if (file->buf) | |
17887 | + ext2fs_free_mem(&file->buf); | |
17888 | + ext2fs_free_mem(&file); | |
17889 | + | |
17890 | + return retval; | |
17891 | +} | |
17892 | + | |
17893 | + | |
17894 | +errcode_t ext2fs_file_read(ext2_file_t file, void *buf, | |
17895 | + unsigned int wanted, unsigned int *got) | |
17896 | +{ | |
17897 | + ext2_filsys fs; | |
17898 | + errcode_t retval = 0; | |
17899 | + unsigned int start, c, count = 0; | |
17900 | + __u64 left; | |
17901 | + char *ptr = (char *) buf; | |
17902 | + | |
17903 | + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); | |
17904 | + fs = file->fs; | |
17905 | + | |
17906 | + while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) { | |
17907 | + retval = sync_buffer_position(file); | |
17908 | + if (retval) | |
17909 | + goto fail; | |
17910 | + retval = load_buffer(file, 0); | |
17911 | + if (retval) | |
17912 | + goto fail; | |
17913 | + | |
17914 | + start = file->pos % fs->blocksize; | |
17915 | + c = fs->blocksize - start; | |
17916 | + if (c > wanted) | |
17917 | + c = wanted; | |
17918 | + left = EXT2_I_SIZE(&file->inode) - file->pos ; | |
17919 | + if (c > left) | |
17920 | + c = left; | |
17921 | + | |
17922 | + memcpy(ptr, file->buf+start, c); | |
17923 | + file->pos += c; | |
17924 | + ptr += c; | |
17925 | + count += c; | |
17926 | + wanted -= c; | |
17927 | + } | |
17928 | + | |
17929 | +fail: | |
17930 | + if (got) | |
17931 | + *got = count; | |
17932 | + return retval; | |
17933 | +} | |
17934 | + | |
17935 | + | |
17936 | +errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, | |
17937 | + unsigned int nbytes, unsigned int *written) | |
17938 | +{ | |
17939 | + ext2_filsys fs; | |
17940 | + errcode_t retval = 0; | |
17941 | + unsigned int start, c, count = 0; | |
17942 | + const char *ptr = (const char *) buf; | |
17943 | + | |
17944 | + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); | |
17945 | + fs = file->fs; | |
17946 | + | |
17947 | + if (!(file->flags & EXT2_FILE_WRITE)) | |
17948 | + return EXT2_ET_FILE_RO; | |
17949 | + | |
17950 | + while (nbytes > 0) { | |
17951 | + retval = sync_buffer_position(file); | |
17952 | + if (retval) | |
17953 | + goto fail; | |
17954 | + | |
17955 | + start = file->pos % fs->blocksize; | |
17956 | + c = fs->blocksize - start; | |
17957 | + if (c > nbytes) | |
17958 | + c = nbytes; | |
17959 | + | |
17960 | + /* | |
17961 | + * We only need to do a read-modify-update cycle if | |
17962 | + * we're doing a partial write. | |
17963 | + */ | |
17964 | + retval = load_buffer(file, (c == fs->blocksize)); | |
17965 | + if (retval) | |
17966 | + goto fail; | |
17967 | + | |
17968 | + file->flags |= EXT2_FILE_BUF_DIRTY; | |
17969 | + memcpy(file->buf+start, ptr, c); | |
17970 | + file->pos += c; | |
17971 | + ptr += c; | |
17972 | + count += c; | |
17973 | + nbytes -= c; | |
17974 | + } | |
17975 | + | |
17976 | +fail: | |
17977 | + if (written) | |
17978 | + *written = count; | |
17979 | + return retval; | |
17980 | +} | |
17981 | + | |
17982 | +errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, | |
17983 | + int whence, __u64 *ret_pos) | |
17984 | +{ | |
17985 | + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); | |
17986 | + | |
17987 | + if (whence == EXT2_SEEK_SET) | |
17988 | + file->pos = offset; | |
17989 | + else if (whence == EXT2_SEEK_CUR) | |
17990 | + file->pos += offset; | |
17991 | + else if (whence == EXT2_SEEK_END) | |
17992 | + file->pos = EXT2_I_SIZE(&file->inode) + offset; | |
17993 | + else | |
17994 | + return EXT2_ET_INVALID_ARGUMENT; | |
17995 | + | |
17996 | + if (ret_pos) | |
17997 | + *ret_pos = file->pos; | |
17998 | + | |
17999 | + return 0; | |
18000 | +} | |
18001 | + | |
18002 | +errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, | |
18003 | + int whence, ext2_off_t *ret_pos) | |
18004 | +{ | |
18005 | + __u64 loffset, ret_loffset; | |
18006 | + errcode_t retval; | |
18007 | + | |
18008 | + loffset = offset; | |
18009 | + retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset); | |
18010 | + if (ret_pos) | |
18011 | + *ret_pos = (ext2_off_t) ret_loffset; | |
18012 | + return retval; | |
18013 | +} | |
18014 | + | |
18015 | + | |
18016 | +/* | |
18017 | + * This function returns the size of the file, according to the inode | |
18018 | + */ | |
18019 | +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size) | |
18020 | +{ | |
18021 | + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) | |
18022 | + return EXT2_ET_MAGIC_EXT2_FILE; | |
18023 | + *ret_size = EXT2_I_SIZE(&file->inode); | |
18024 | + return 0; | |
18025 | +} | |
18026 | + | |
18027 | +/* | |
18028 | + * This function returns the size of the file, according to the inode | |
18029 | + */ | |
18030 | +ext2_off_t ext2fs_file_get_size(ext2_file_t file) | |
18031 | +{ | |
18032 | + __u64 size; | |
18033 | + | |
18034 | + if (ext2fs_file_get_lsize(file, &size)) | |
18035 | + return 0; | |
18036 | + if ((size >> 32) != 0) | |
18037 | + return 0; | |
18038 | + return size; | |
18039 | +} | |
18040 | + | |
18041 | +/* | |
18042 | + * This function sets the size of the file, truncating it if necessary | |
18043 | + * | |
18044 | + * XXX still need to call truncate | |
18045 | + */ | |
18046 | +errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size) | |
18047 | +{ | |
18048 | + errcode_t retval; | |
18049 | + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); | |
18050 | + | |
18051 | + file->inode.i_size = size; | |
18052 | + file->inode.i_size_high = 0; | |
18053 | + if (file->ino) { | |
18054 | + retval = ext2fs_write_inode(file->fs, file->ino, &file->inode); | |
18055 | + if (retval) | |
18056 | + return retval; | |
18057 | + } | |
18058 | + | |
18059 | + /* | |
18060 | + * XXX truncate inode if necessary | |
18061 | + */ | |
18062 | + | |
18063 | + return 0; | |
18064 | +} | |
18065 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/finddev.c busybox/e2fsprogs/ext2fs/finddev.c | |
18066 | --- busybox-1.00/e2fsprogs/ext2fs/finddev.c 1970-01-01 01:00:00.000000000 +0100 | |
18067 | +++ busybox/e2fsprogs/ext2fs/finddev.c 2005-06-04 08:20:16.000000000 +0200 | |
18068 | @@ -0,0 +1,208 @@ | |
18069 | +/* | |
18070 | + * finddev.c -- this routine attempts to find a particular device in | |
18071 | + * /dev | |
18072 | + * | |
18073 | + * Copyright (C) 2000 Theodore Ts'o. | |
18074 | + * | |
18075 | + * %Begin-Header% | |
18076 | + * This file may be redistributed under the terms of the GNU Public | |
18077 | + * License. | |
18078 | + * %End-Header% | |
18079 | + */ | |
18080 | + | |
18081 | +#include <stdio.h> | |
18082 | +#include <string.h> | |
18083 | +#if HAVE_UNISTD_H | |
18084 | +#include <unistd.h> | |
18085 | +#endif | |
18086 | +#include <stdlib.h> | |
18087 | +#include <string.h> | |
18088 | +#if HAVE_SYS_TYPES_H | |
18089 | +#include <sys/types.h> | |
18090 | +#endif | |
18091 | +#if HAVE_SYS_STAT_H | |
18092 | +#include <sys/stat.h> | |
18093 | +#endif | |
18094 | +#include <dirent.h> | |
18095 | +#if HAVE_ERRNO_H | |
18096 | +#include <errno.h> | |
18097 | +#endif | |
18098 | +#if HAVE_SYS_MKDEV_H | |
18099 | +#include <sys/mkdev.h> | |
18100 | +#endif | |
18101 | + | |
18102 | +#include "ext2_fs.h" | |
18103 | +#include "ext2fs.h" | |
18104 | + | |
18105 | +struct dir_list { | |
18106 | + char *name; | |
18107 | + struct dir_list *next; | |
18108 | +}; | |
18109 | + | |
18110 | +/* | |
18111 | + * This function adds an entry to the directory list | |
18112 | + */ | |
18113 | +static void add_to_dirlist(const char *name, struct dir_list **list) | |
18114 | +{ | |
18115 | + struct dir_list *dp; | |
18116 | + | |
18117 | + dp = malloc(sizeof(struct dir_list)); | |
18118 | + if (!dp) | |
18119 | + return; | |
18120 | + dp->name = malloc(strlen(name)+1); | |
18121 | + if (!dp->name) { | |
18122 | + free(dp); | |
18123 | + return; | |
18124 | + } | |
18125 | + strcpy(dp->name, name); | |
18126 | + dp->next = *list; | |
18127 | + *list = dp; | |
18128 | +} | |
18129 | + | |
18130 | +/* | |
18131 | + * This function frees a directory list | |
18132 | + */ | |
18133 | +static void free_dirlist(struct dir_list **list) | |
18134 | +{ | |
18135 | + struct dir_list *dp, *next; | |
18136 | + | |
18137 | + for (dp = *list; dp; dp = next) { | |
18138 | + next = dp->next; | |
18139 | + free(dp->name); | |
18140 | + free(dp); | |
18141 | + } | |
18142 | + *list = 0; | |
18143 | +} | |
18144 | + | |
18145 | +static int scan_dir(char *dir_name, dev_t device, struct dir_list **list, | |
18146 | + char **ret_path) | |
18147 | +{ | |
18148 | + DIR *dir; | |
18149 | + struct dirent *dp; | |
18150 | + char path[1024], *cp; | |
18151 | + int dirlen; | |
18152 | + struct stat st; | |
18153 | + | |
18154 | + dirlen = strlen(dir_name); | |
18155 | + if ((dir = opendir(dir_name)) == NULL) | |
18156 | + return errno; | |
18157 | + dp = readdir(dir); | |
18158 | + while (dp) { | |
18159 | + if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path)) | |
18160 | + goto skip_to_next; | |
18161 | + if (dp->d_name[0] == '.' && | |
18162 | + ((dp->d_name[1] == 0) || | |
18163 | + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) | |
18164 | + goto skip_to_next; | |
18165 | + sprintf(path, "%s/%s", dir_name, dp->d_name); | |
18166 | + if (stat(path, &st) < 0) | |
18167 | + goto skip_to_next; | |
18168 | + if (S_ISDIR(st.st_mode)) | |
18169 | + add_to_dirlist(path, list); | |
18170 | + if (S_ISBLK(st.st_mode) && st.st_rdev == device) { | |
18171 | + cp = malloc(strlen(path)+1); | |
18172 | + if (!cp) { | |
18173 | + closedir(dir); | |
18174 | + return ENOMEM; | |
18175 | + } | |
18176 | + strcpy(cp, path); | |
18177 | + *ret_path = cp; | |
18178 | + goto success; | |
18179 | + } | |
18180 | + skip_to_next: | |
18181 | + dp = readdir(dir); | |
18182 | + } | |
18183 | +success: | |
18184 | + closedir(dir); | |
18185 | + return 0; | |
18186 | +} | |
18187 | + | |
18188 | +/* | |
18189 | + * This function finds the pathname to a block device with a given | |
18190 | + * device number. It returns a pointer to allocated memory to the | |
18191 | + * pathname on success, and NULL on failure. | |
18192 | + */ | |
18193 | +char *ext2fs_find_block_device(dev_t device) | |
18194 | +{ | |
18195 | + struct dir_list *list = 0, *new_list = 0; | |
18196 | + struct dir_list *current; | |
18197 | + char *ret_path = 0; | |
18198 | + | |
18199 | + /* | |
18200 | + * Add the starting directories to search... | |
18201 | + */ | |
18202 | + add_to_dirlist("/devices", &list); | |
18203 | + add_to_dirlist("/devfs", &list); | |
18204 | + add_to_dirlist("/dev", &list); | |
18205 | + | |
18206 | + while (list) { | |
18207 | + current = list; | |
18208 | + list = list->next; | |
18209 | +#ifdef DEBUG | |
18210 | + printf("Scanning directory %s\n", current->name); | |
18211 | +#endif | |
18212 | + scan_dir(current->name, device, &new_list, &ret_path); | |
18213 | + free(current->name); | |
18214 | + free(current); | |
18215 | + if (ret_path) | |
18216 | + break; | |
18217 | + /* | |
18218 | + * If we're done checking at this level, descend to | |
18219 | + * the next level of subdirectories. (breadth-first) | |
18220 | + */ | |
18221 | + if (list == 0) { | |
18222 | + list = new_list; | |
18223 | + new_list = 0; | |
18224 | + } | |
18225 | + } | |
18226 | + free_dirlist(&list); | |
18227 | + free_dirlist(&new_list); | |
18228 | + return ret_path; | |
18229 | +} | |
18230 | + | |
18231 | + | |
18232 | +#ifdef DEBUG | |
18233 | +int main(int argc, char** argv) | |
18234 | +{ | |
18235 | + char *devname, *tmp; | |
18236 | + int major, minor; | |
18237 | + dev_t device; | |
18238 | + const char *errmsg = "Couldn't parse %s: %s\n"; | |
18239 | + | |
18240 | + if ((argc != 2) && (argc != 3)) { | |
18241 | + fprintf(stderr, "Usage: %s device_number\n", argv[0]); | |
18242 | + fprintf(stderr, "\t: %s major minor\n", argv[0]); | |
18243 | + exit(1); | |
18244 | + } | |
18245 | + if (argc == 2) { | |
18246 | + device = strtoul(argv[1], &tmp, 0); | |
18247 | + if (*tmp) { | |
18248 | + fprintf(stderr, errmsg, "device number", argv[1]); | |
18249 | + exit(1); | |
18250 | + } | |
18251 | + } else { | |
18252 | + major = strtoul(argv[1], &tmp, 0); | |
18253 | + if (*tmp) { | |
18254 | + fprintf(stderr, errmsg, "major number", argv[1]); | |
18255 | + exit(1); | |
18256 | + } | |
18257 | + minor = strtoul(argv[2], &tmp, 0); | |
18258 | + if (*tmp) { | |
18259 | + fprintf(stderr, errmsg, "minor number", argv[2]); | |
18260 | + exit(1); | |
18261 | + } | |
18262 | + device = makedev(major, minor); | |
18263 | + printf("Looking for device 0x%04x (%d:%d)\n", device, | |
18264 | + major, minor); | |
18265 | + } | |
18266 | + devname = ext2fs_find_block_device(device); | |
18267 | + if (devname) { | |
18268 | + printf("Found device! %s\n", devname); | |
18269 | + free(devname); | |
18270 | + } else { | |
18271 | + printf("Couldn't find device.\n"); | |
18272 | + } | |
18273 | + return 0; | |
18274 | +} | |
18275 | + | |
18276 | +#endif | |
18277 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/flushb.c busybox/e2fsprogs/ext2fs/flushb.c | |
18278 | --- busybox-1.00/e2fsprogs/ext2fs/flushb.c 1970-01-01 01:00:00.000000000 +0100 | |
18279 | +++ busybox/e2fsprogs/ext2fs/flushb.c 2005-06-04 08:20:16.000000000 +0200 | |
18280 | @@ -0,0 +1,82 @@ | |
18281 | +/* | |
18282 | + * flushb.c --- Hides system-dependent information for both syncing a | |
18283 | + * device to disk and to flush any buffers from disk cache. | |
18284 | + * | |
18285 | + * Copyright (C) 2000 Theodore Ts'o. | |
18286 | + * | |
18287 | + * %Begin-Header% | |
18288 | + * This file may be redistributed under the terms of the GNU Public | |
18289 | + * License. | |
18290 | + * %End-Header% | |
18291 | + */ | |
18292 | + | |
18293 | +#include <stdio.h> | |
18294 | +#if HAVE_ERRNO_H | |
18295 | +#include <errno.h> | |
18296 | +#endif | |
18297 | +#if HAVE_UNISTD_H | |
18298 | +#include <unistd.h> | |
18299 | +#endif | |
18300 | +#if HAVE_SYS_IOCTL_H | |
18301 | +#include <sys/ioctl.h> | |
18302 | +#endif | |
18303 | +#if HAVE_SYS_MOUNT_H | |
18304 | +#include <sys/param.h> | |
18305 | +#include <sys/mount.h> /* This may define BLKFLSBUF */ | |
18306 | +#endif | |
18307 | + | |
18308 | +#include "ext2_fs.h" | |
18309 | +#include "ext2fs.h" | |
18310 | + | |
18311 | +/* | |
18312 | + * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since | |
18313 | + * not all portable header file does so for us. This really should be | |
18314 | + * fixed in the glibc header files. (Recent glibcs appear to define | |
18315 | + * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be | |
18316 | + * defined anywhere portable.) Until then.... | |
18317 | + */ | |
18318 | +#ifdef __linux__ | |
18319 | +#ifndef BLKFLSBUF | |
18320 | +#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ | |
18321 | +#endif | |
18322 | +#ifndef FDFLUSH | |
18323 | +#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */ | |
18324 | +#endif | |
18325 | +#endif | |
18326 | + | |
18327 | +/* | |
18328 | + * This function will sync a device/file, and optionally attempt to | |
18329 | + * flush the buffer cache. The latter is basically only useful for | |
18330 | + * system benchmarks and for torturing systems in burn-in tests. :) | |
18331 | + */ | |
18332 | +errcode_t ext2fs_sync_device(int fd, int flushb) | |
18333 | +{ | |
18334 | + /* | |
18335 | + * We always sync the device in case we're running on old | |
18336 | + * kernels for which we can lose data if we don't. (There | |
18337 | + * still is a race condition for those kernels, but this | |
18338 | + * reduces it greatly.) | |
18339 | + */ | |
18340 | + if (fsync (fd) == -1) | |
18341 | + return errno; | |
18342 | + | |
18343 | + if (flushb) { | |
18344 | + | |
18345 | +#ifdef BLKFLSBUF | |
18346 | + if (ioctl (fd, BLKFLSBUF, 0) == 0) | |
18347 | + return 0; | |
18348 | +#else | |
18349 | +#ifdef __GNUC__ | |
18350 | + #warning BLKFLSBUF not defined | |
18351 | +#endif /* __GNUC__ */ | |
18352 | +#endif | |
18353 | +#ifdef FDFLUSH | |
18354 | + ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */ | |
18355 | +#else | |
18356 | +#ifdef __GNUC__ | |
18357 | + #warning FDFLUSH not defined | |
18358 | +#endif /* __GNUC__ */ | |
18359 | +#endif | |
18360 | + } | |
18361 | + return 0; | |
18362 | +} | |
18363 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/freefs.c busybox/e2fsprogs/ext2fs/freefs.c | |
18364 | --- busybox-1.00/e2fsprogs/ext2fs/freefs.c 1970-01-01 01:00:00.000000000 +0100 | |
18365 | +++ busybox/e2fsprogs/ext2fs/freefs.c 2005-06-04 08:20:16.000000000 +0200 | |
18366 | @@ -0,0 +1,147 @@ | |
18367 | +/* | |
18368 | + * freefs.c --- free an ext2 filesystem | |
18369 | + * | |
18370 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
18371 | + * | |
18372 | + * %Begin-Header% | |
18373 | + * This file may be redistributed under the terms of the GNU Public | |
18374 | + * License. | |
18375 | + * %End-Header% | |
18376 | + */ | |
18377 | + | |
18378 | +#include <stdio.h> | |
18379 | +#if HAVE_UNISTD_H | |
18380 | +#include <unistd.h> | |
18381 | +#endif | |
18382 | + | |
18383 | +#include "ext2_fs.h" | |
18384 | +#include "ext2fsP.h" | |
18385 | + | |
18386 | +static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache); | |
18387 | + | |
18388 | +void ext2fs_free(ext2_filsys fs) | |
18389 | +{ | |
18390 | + if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)) | |
18391 | + return; | |
18392 | + if (fs->image_io != fs->io) { | |
18393 | + if (fs->image_io) | |
18394 | + io_channel_close(fs->image_io); | |
18395 | + } | |
18396 | + if (fs->io) { | |
18397 | + io_channel_close(fs->io); | |
18398 | + } | |
18399 | + if (fs->device_name) | |
18400 | + ext2fs_free_mem(&fs->device_name); | |
18401 | + if (fs->super) | |
18402 | + ext2fs_free_mem(&fs->super); | |
18403 | + if (fs->orig_super) | |
18404 | + ext2fs_free_mem(&fs->orig_super); | |
18405 | + if (fs->group_desc) | |
18406 | + ext2fs_free_mem(&fs->group_desc); | |
18407 | + if (fs->block_map) | |
18408 | + ext2fs_free_block_bitmap(fs->block_map); | |
18409 | + if (fs->inode_map) | |
18410 | + ext2fs_free_inode_bitmap(fs->inode_map); | |
18411 | + | |
18412 | + if (fs->badblocks) | |
18413 | + ext2fs_badblocks_list_free(fs->badblocks); | |
18414 | + fs->badblocks = 0; | |
18415 | + | |
18416 | + if (fs->dblist) | |
18417 | + ext2fs_free_dblist(fs->dblist); | |
18418 | + | |
18419 | + if (fs->icache) | |
18420 | + ext2fs_free_inode_cache(fs->icache); | |
18421 | + | |
18422 | + fs->magic = 0; | |
18423 | + | |
18424 | + ext2fs_free_mem(&fs); | |
18425 | +} | |
18426 | + | |
18427 | +void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap) | |
18428 | +{ | |
18429 | + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP)) | |
18430 | + return; | |
18431 | + | |
18432 | + bitmap->magic = 0; | |
18433 | + if (bitmap->description) { | |
18434 | + ext2fs_free_mem(&bitmap->description); | |
18435 | + bitmap->description = 0; | |
18436 | + } | |
18437 | + if (bitmap->bitmap) { | |
18438 | + ext2fs_free_mem(&bitmap->bitmap); | |
18439 | + bitmap->bitmap = 0; | |
18440 | + } | |
18441 | + ext2fs_free_mem(&bitmap); | |
18442 | +} | |
18443 | + | |
18444 | +void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap) | |
18445 | +{ | |
18446 | + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP)) | |
18447 | + return; | |
18448 | + | |
18449 | + bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; | |
18450 | + ext2fs_free_generic_bitmap(bitmap); | |
18451 | +} | |
18452 | + | |
18453 | +void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap) | |
18454 | +{ | |
18455 | + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP)) | |
18456 | + return; | |
18457 | + | |
18458 | + bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; | |
18459 | + ext2fs_free_generic_bitmap(bitmap); | |
18460 | +} | |
18461 | + | |
18462 | +/* | |
18463 | + * Free the inode cache structure | |
18464 | + */ | |
18465 | +static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache) | |
18466 | +{ | |
18467 | + if (--icache->refcount) | |
18468 | + return; | |
18469 | + if (icache->buffer) | |
18470 | + ext2fs_free_mem(&icache->buffer); | |
18471 | + if (icache->cache) | |
18472 | + ext2fs_free_mem(&icache->cache); | |
18473 | + icache->buffer_blk = 0; | |
18474 | + ext2fs_free_mem(&icache); | |
18475 | +} | |
18476 | + | |
18477 | +/* | |
18478 | + * This procedure frees a badblocks list. | |
18479 | + */ | |
18480 | +void ext2fs_u32_list_free(ext2_u32_list bb) | |
18481 | +{ | |
18482 | + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) | |
18483 | + return; | |
18484 | + | |
18485 | + if (bb->list) | |
18486 | + ext2fs_free_mem(&bb->list); | |
18487 | + bb->list = 0; | |
18488 | + ext2fs_free_mem(&bb); | |
18489 | +} | |
18490 | + | |
18491 | +void ext2fs_badblocks_list_free(ext2_badblocks_list bb) | |
18492 | +{ | |
18493 | + ext2fs_u32_list_free((ext2_u32_list) bb); | |
18494 | +} | |
18495 | + | |
18496 | + | |
18497 | +/* | |
18498 | + * Free a directory block list | |
18499 | + */ | |
18500 | +void ext2fs_free_dblist(ext2_dblist dblist) | |
18501 | +{ | |
18502 | + if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST)) | |
18503 | + return; | |
18504 | + | |
18505 | + if (dblist->list) | |
18506 | + ext2fs_free_mem(&dblist->list); | |
18507 | + dblist->list = 0; | |
18508 | + if (dblist->fs && dblist->fs->dblist == dblist) | |
18509 | + dblist->fs->dblist = 0; | |
18510 | + dblist->magic = 0; | |
18511 | + ext2fs_free_mem(&dblist); | |
18512 | +} | |
18513 | + | |
18514 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/gen_bitmap.c busybox/e2fsprogs/ext2fs/gen_bitmap.c | |
18515 | --- busybox-1.00/e2fsprogs/ext2fs/gen_bitmap.c 1970-01-01 01:00:00.000000000 +0100 | |
18516 | +++ busybox/e2fsprogs/ext2fs/gen_bitmap.c 2005-06-04 08:20:16.000000000 +0200 | |
18517 | @@ -0,0 +1,48 @@ | |
18518 | +/* | |
18519 | + * gen_bitmap.c --- Generic bitmap routines that used to be inlined. | |
18520 | + * | |
18521 | + * Copyright (C) 2001 Theodore Ts'o. | |
18522 | + * | |
18523 | + * %Begin-Header% | |
18524 | + * This file may be redistributed under the terms of the GNU Public | |
18525 | + * License. | |
18526 | + * %End-Header% | |
18527 | + */ | |
18528 | + | |
18529 | + | |
18530 | +#include <stdio.h> | |
18531 | +#include <string.h> | |
18532 | +#if HAVE_UNISTD_H | |
18533 | +#include <unistd.h> | |
18534 | +#endif | |
18535 | +#include <fcntl.h> | |
18536 | +#include <time.h> | |
18537 | +#if HAVE_SYS_STAT_H | |
18538 | +#include <sys/stat.h> | |
18539 | +#endif | |
18540 | +#if HAVE_SYS_TYPES_H | |
18541 | +#include <sys/types.h> | |
18542 | +#endif | |
18543 | + | |
18544 | +#include "ext2_fs.h" | |
18545 | +#include "ext2fs.h" | |
18546 | + | |
18547 | +int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, | |
18548 | + __u32 bitno) | |
18549 | +{ | |
18550 | + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { | |
18551 | + ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno); | |
18552 | + return 0; | |
18553 | + } | |
18554 | + return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap); | |
18555 | +} | |
18556 | + | |
18557 | +int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, | |
18558 | + blk_t bitno) | |
18559 | +{ | |
18560 | + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { | |
18561 | + ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno); | |
18562 | + return 0; | |
18563 | + } | |
18564 | + return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap); | |
18565 | +} | |
18566 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/get_pathname.c busybox/e2fsprogs/ext2fs/get_pathname.c | |
18567 | --- busybox-1.00/e2fsprogs/ext2fs/get_pathname.c 1970-01-01 01:00:00.000000000 +0100 | |
18568 | +++ busybox/e2fsprogs/ext2fs/get_pathname.c 2005-06-04 08:20:16.000000000 +0200 | |
18569 | @@ -0,0 +1,157 @@ | |
18570 | +/* | |
18571 | + * get_pathname.c --- do directry/inode -> name translation | |
18572 | + * | |
18573 | + * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. | |
18574 | + * | |
18575 | + * %Begin-Header% | |
18576 | + * This file may be redistributed under the terms of the GNU Public | |
18577 | + * License. | |
18578 | + * %End-Header% | |
18579 | + * | |
18580 | + * ext2fs_get_pathname(fs, dir, ino, name) | |
18581 | + * | |
18582 | + * This function translates takes two inode numbers into a | |
18583 | + * string, placing the result in <name>. <dir> is the containing | |
18584 | + * directory inode, and <ino> is the inode number itself. If | |
18585 | + * <ino> is zero, then ext2fs_get_pathname will return pathname | |
18586 | + * of the the directory <dir>. | |
18587 | + * | |
18588 | + */ | |
18589 | + | |
18590 | +#include <stdio.h> | |
18591 | +#include <string.h> | |
18592 | +#if HAVE_UNISTD_H | |
18593 | +#include <unistd.h> | |
18594 | +#endif | |
18595 | + | |
18596 | +#include "ext2_fs.h" | |
18597 | +#include "ext2fs.h" | |
18598 | + | |
18599 | +struct get_pathname_struct { | |
18600 | + ext2_ino_t search_ino; | |
18601 | + ext2_ino_t parent; | |
18602 | + char *name; | |
18603 | + errcode_t errcode; | |
18604 | +}; | |
18605 | + | |
18606 | +#ifdef __TURBOC__ | |
18607 | + #pragma argsused | |
18608 | +#endif | |
18609 | +static int get_pathname_proc(struct ext2_dir_entry *dirent, | |
18610 | + int offset EXT2FS_ATTR((unused)), | |
18611 | + int blocksize EXT2FS_ATTR((unused)), | |
18612 | + char *buf EXT2FS_ATTR((unused)), | |
18613 | + void *priv_data) | |
18614 | +{ | |
18615 | + struct get_pathname_struct *gp; | |
18616 | + errcode_t retval; | |
18617 | + | |
18618 | + gp = (struct get_pathname_struct *) priv_data; | |
18619 | + | |
18620 | + if (((dirent->name_len & 0xFF) == 2) && | |
18621 | + !strncmp(dirent->name, "..", 2)) | |
18622 | + gp->parent = dirent->inode; | |
18623 | + if (dirent->inode == gp->search_ino) { | |
18624 | + retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1, | |
18625 | + &gp->name); | |
18626 | + if (retval) { | |
18627 | + gp->errcode = retval; | |
18628 | + return DIRENT_ABORT; | |
18629 | + } | |
18630 | + strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF)); | |
18631 | + gp->name[dirent->name_len & 0xFF] = '\0'; | |
18632 | + return DIRENT_ABORT; | |
18633 | + } | |
18634 | + return 0; | |
18635 | +} | |
18636 | + | |
18637 | +static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir, | |
18638 | + ext2_ino_t ino, int maxdepth, | |
18639 | + char *buf, char **name) | |
18640 | +{ | |
18641 | + struct get_pathname_struct gp; | |
18642 | + char *parent_name, *ret; | |
18643 | + errcode_t retval; | |
18644 | + | |
18645 | + if (dir == ino) { | |
18646 | + retval = ext2fs_get_mem(2, name); | |
18647 | + if (retval) | |
18648 | + return retval; | |
18649 | + strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : "."); | |
18650 | + return 0; | |
18651 | + } | |
18652 | + | |
18653 | + if (!dir || (maxdepth < 0)) { | |
18654 | + retval = ext2fs_get_mem(4, name); | |
18655 | + if (retval) | |
18656 | + return retval; | |
18657 | + strcpy(*name, "..."); | |
18658 | + return 0; | |
18659 | + } | |
18660 | + | |
18661 | + gp.search_ino = ino; | |
18662 | + gp.parent = 0; | |
18663 | + gp.name = 0; | |
18664 | + gp.errcode = 0; | |
18665 | + | |
18666 | + retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp); | |
18667 | + if (retval) | |
18668 | + goto cleanup; | |
18669 | + if (gp.errcode) { | |
18670 | + retval = gp.errcode; | |
18671 | + goto cleanup; | |
18672 | + } | |
18673 | + | |
18674 | + retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1, | |
18675 | + buf, &parent_name); | |
18676 | + if (retval) | |
18677 | + goto cleanup; | |
18678 | + if (!ino) { | |
18679 | + *name = parent_name; | |
18680 | + return 0; | |
18681 | + } | |
18682 | + | |
18683 | + if (gp.name) | |
18684 | + retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2, | |
18685 | + &ret); | |
18686 | + else | |
18687 | + retval = ext2fs_get_mem(strlen(parent_name)+5, &ret); | |
18688 | + if (retval) | |
18689 | + goto cleanup; | |
18690 | + | |
18691 | + ret[0] = 0; | |
18692 | + if (parent_name[1]) | |
18693 | + strcat(ret, parent_name); | |
18694 | + strcat(ret, "/"); | |
18695 | + if (gp.name) | |
18696 | + strcat(ret, gp.name); | |
18697 | + else | |
18698 | + strcat(ret, "???"); | |
18699 | + *name = ret; | |
18700 | + ext2fs_free_mem(&parent_name); | |
18701 | + retval = 0; | |
18702 | + | |
18703 | +cleanup: | |
18704 | + if (gp.name) | |
18705 | + ext2fs_free_mem(&gp.name); | |
18706 | + return retval; | |
18707 | +} | |
18708 | + | |
18709 | +errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, | |
18710 | + char **name) | |
18711 | +{ | |
18712 | + char *buf; | |
18713 | + errcode_t retval; | |
18714 | + | |
18715 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
18716 | + | |
18717 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
18718 | + if (retval) | |
18719 | + return retval; | |
18720 | + if (dir == ino) | |
18721 | + ino = 0; | |
18722 | + retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name); | |
18723 | + ext2fs_free_mem(&buf); | |
18724 | + return retval; | |
18725 | + | |
18726 | +} | |
18727 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/getsectsize.c busybox/e2fsprogs/ext2fs/getsectsize.c | |
18728 | --- busybox-1.00/e2fsprogs/ext2fs/getsectsize.c 1970-01-01 01:00:00.000000000 +0100 | |
18729 | +++ busybox/e2fsprogs/ext2fs/getsectsize.c 2005-06-04 08:20:16.000000000 +0200 | |
18730 | @@ -0,0 +1,57 @@ | |
18731 | +/* | |
18732 | + * getsectsize.c --- get the sector size of a device. | |
18733 | + * | |
18734 | + * Copyright (C) 1995, 1995 Theodore Ts'o. | |
18735 | + * Copyright (C) 2003 VMware, Inc. | |
18736 | + * | |
18737 | + * %Begin-Header% | |
18738 | + * This file may be redistributed under the terms of the GNU Public | |
18739 | + * License. | |
18740 | + * %End-Header% | |
18741 | + */ | |
18742 | + | |
18743 | +#include <stdio.h> | |
18744 | +#if HAVE_UNISTD_H | |
18745 | +#include <unistd.h> | |
18746 | +#endif | |
18747 | +#if HAVE_ERRNO_H | |
18748 | +#include <errno.h> | |
18749 | +#endif | |
18750 | +#include <fcntl.h> | |
18751 | +#ifdef HAVE_LINUX_FD_H | |
18752 | +#include <sys/ioctl.h> | |
18753 | +#include <linux/fd.h> | |
18754 | +#endif | |
18755 | + | |
18756 | +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) | |
18757 | +#define BLKSSZGET _IO(0x12,104)/* get block device sector size */ | |
18758 | +#endif | |
18759 | + | |
18760 | +#include "ext2_fs.h" | |
18761 | +#include "ext2fs.h" | |
18762 | + | |
18763 | +/* | |
18764 | + * Returns the number of blocks in a partition | |
18765 | + */ | |
18766 | +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize) | |
18767 | +{ | |
18768 | + int fd; | |
18769 | + | |
18770 | +#ifdef CONFIG_LFS | |
18771 | + fd = open64(file, O_RDONLY); | |
18772 | +#else | |
18773 | + fd = open(file, O_RDONLY); | |
18774 | +#endif | |
18775 | + if (fd < 0) | |
18776 | + return errno; | |
18777 | + | |
18778 | +#ifdef BLKSSZGET | |
18779 | + if (ioctl(fd, BLKSSZGET, sectsize) >= 0) { | |
18780 | + close(fd); | |
18781 | + return 0; | |
18782 | + } | |
18783 | +#endif | |
18784 | + *sectsize = 0; | |
18785 | + close(fd); | |
18786 | + return 0; | |
18787 | +} | |
18788 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/getsize.c busybox/e2fsprogs/ext2fs/getsize.c | |
18789 | --- busybox-1.00/e2fsprogs/ext2fs/getsize.c 1970-01-01 01:00:00.000000000 +0100 | |
18790 | +++ busybox/e2fsprogs/ext2fs/getsize.c 2005-06-04 08:20:16.000000000 +0200 | |
18791 | @@ -0,0 +1,290 @@ | |
18792 | +/* | |
18793 | + * getsize.c --- get the size of a partition. | |
18794 | + * | |
18795 | + * Copyright (C) 1995, 1995 Theodore Ts'o. | |
18796 | + * Copyright (C) 2003 VMware, Inc. | |
18797 | + * | |
18798 | + * Windows version of ext2fs_get_device_size by Chris Li, VMware. | |
18799 | + * | |
18800 | + * %Begin-Header% | |
18801 | + * This file may be redistributed under the terms of the GNU Public | |
18802 | + * License. | |
18803 | + * %End-Header% | |
18804 | + */ | |
18805 | + | |
18806 | +#include <stdio.h> | |
18807 | +#if HAVE_UNISTD_H | |
18808 | +#include <unistd.h> | |
18809 | +#endif | |
18810 | +#if HAVE_ERRNO_H | |
18811 | +#include <errno.h> | |
18812 | +#endif | |
18813 | +#include <fcntl.h> | |
18814 | +#ifdef HAVE_SYS_IOCTL_H | |
18815 | +#include <sys/ioctl.h> | |
18816 | +#endif | |
18817 | +#ifdef HAVE_LINUX_FD_H | |
18818 | +#include <linux/fd.h> | |
18819 | +#endif | |
18820 | +#ifdef HAVE_SYS_DISKLABEL_H | |
18821 | +#include <sys/disklabel.h> | |
18822 | +#endif | |
18823 | +#ifdef HAVE_SYS_DISK_H | |
18824 | +#ifdef HAVE_SYS_QUEUE_H | |
18825 | +#include <sys/queue.h> /* for LIST_HEAD */ | |
18826 | +#endif | |
18827 | +#include <sys/disk.h> | |
18828 | +#endif | |
18829 | +#ifdef __linux__ | |
18830 | +#include <sys/utsname.h> | |
18831 | +#endif | |
18832 | + | |
18833 | +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) | |
18834 | +#define BLKGETSIZE _IO(0x12,96) /* return device size */ | |
18835 | +#endif | |
18836 | + | |
18837 | +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) | |
18838 | +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ | |
18839 | +#endif | |
18840 | + | |
18841 | +#ifdef APPLE_DARWIN | |
18842 | +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 | |
18843 | +#endif /* APPLE_DARWIN */ | |
18844 | + | |
18845 | +#include "ext2_fs.h" | |
18846 | +#include "ext2fs.h" | |
18847 | + | |
18848 | +#if defined(__CYGWIN__) || defined (WIN32) | |
18849 | +#include "windows.h" | |
18850 | +#include "winioctl.h" | |
18851 | + | |
18852 | +#if (_WIN32_WINNT >= 0x0500) | |
18853 | +#define HAVE_GET_FILE_SIZE_EX 1 | |
18854 | +#endif | |
18855 | + | |
18856 | +errcode_t ext2fs_get_device_size(const char *file, int blocksize, | |
18857 | + blk_t *retblocks) | |
18858 | +{ | |
18859 | + HANDLE dev; | |
18860 | + PARTITION_INFORMATION pi; | |
18861 | + DISK_GEOMETRY gi; | |
18862 | + DWORD retbytes; | |
18863 | +#ifdef HAVE_GET_FILE_SIZE_EX | |
18864 | + LARGE_INTEGER filesize; | |
18865 | +#else | |
18866 | + DWORD filesize; | |
18867 | +#endif /* HAVE_GET_FILE_SIZE_EX */ | |
18868 | + | |
18869 | + dev = CreateFile(file, GENERIC_READ, | |
18870 | + FILE_SHARE_READ | FILE_SHARE_WRITE , | |
18871 | + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
18872 | + | |
18873 | + if (dev == INVALID_HANDLE_VALUE) | |
18874 | + return EBADF; | |
18875 | + if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, | |
18876 | + &pi, sizeof(PARTITION_INFORMATION), | |
18877 | + &pi, sizeof(PARTITION_INFORMATION), | |
18878 | + &retbytes, NULL)) { | |
18879 | + | |
18880 | + *retblocks = pi.PartitionLength.QuadPart / blocksize; | |
18881 | + | |
18882 | + } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, | |
18883 | + &gi, sizeof(DISK_GEOMETRY), | |
18884 | + &gi, sizeof(DISK_GEOMETRY), | |
18885 | + &retbytes, NULL)) { | |
18886 | + | |
18887 | + *retblocks = gi.BytesPerSector * | |
18888 | + gi.SectorsPerTrack * | |
18889 | + gi.TracksPerCylinder * | |
18890 | + gi.Cylinders.QuadPart / blocksize; | |
18891 | + | |
18892 | +#ifdef HAVE_GET_FILE_SIZE_EX | |
18893 | + } else if (GetFileSizeEx(dev, &filesize)) { | |
18894 | + *retblocks = filesize.QuadPart / blocksize; | |
18895 | + } | |
18896 | +#else | |
18897 | + } else { | |
18898 | + filesize = GetFileSize(dev, NULL); | |
18899 | + if (INVALID_FILE_SIZE != filesize) { | |
18900 | + *retblocks = filesize / blocksize; | |
18901 | + } | |
18902 | + } | |
18903 | +#endif /* HAVE_GET_FILE_SIZE_EX */ | |
18904 | + | |
18905 | + CloseHandle(dev); | |
18906 | + return 0; | |
18907 | +} | |
18908 | + | |
18909 | +#else | |
18910 | + | |
18911 | +static int valid_offset (int fd, ext2_loff_t offset) | |
18912 | +{ | |
18913 | + char ch; | |
18914 | + | |
18915 | + if (ext2fs_llseek (fd, offset, 0) < 0) | |
18916 | + return 0; | |
18917 | + if (read (fd, &ch, 1) < 1) | |
18918 | + return 0; | |
18919 | + return 1; | |
18920 | +} | |
18921 | + | |
18922 | +/* | |
18923 | + * Returns the number of blocks in a partition | |
18924 | + */ | |
18925 | +errcode_t ext2fs_get_device_size(const char *file, int blocksize, | |
18926 | + blk_t *retblocks) | |
18927 | +{ | |
18928 | + int fd; | |
18929 | + int valid_blkgetsize64 = 1; | |
18930 | +#ifdef __linux__ | |
18931 | + struct utsname ut; | |
18932 | +#endif | |
18933 | + unsigned long long size64; | |
18934 | + unsigned long size; | |
18935 | + ext2_loff_t high, low; | |
18936 | +#ifdef FDGETPRM | |
18937 | + struct floppy_struct this_floppy; | |
18938 | +#endif | |
18939 | +#ifdef HAVE_SYS_DISKLABEL_H | |
18940 | + int part; | |
18941 | + struct disklabel lab; | |
18942 | + struct partition *pp; | |
18943 | + char ch; | |
18944 | +#endif /* HAVE_SYS_DISKLABEL_H */ | |
18945 | + | |
18946 | +#ifdef CONFIG_LFS | |
18947 | + fd = open64(file, O_RDONLY); | |
18948 | +#else | |
18949 | + fd = open(file, O_RDONLY); | |
18950 | +#endif | |
18951 | + if (fd < 0) | |
18952 | + return errno; | |
18953 | + | |
18954 | +#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ | |
18955 | + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { | |
18956 | + if ((sizeof(*retblocks) < sizeof(unsigned long long)) | |
18957 | + && ((size64 / (blocksize / 512)) > 0xFFFFFFFF)) | |
18958 | + return EFBIG; | |
18959 | + close(fd); | |
18960 | + *retblocks = size64 / (blocksize / 512); | |
18961 | + return 0; | |
18962 | + } | |
18963 | +#endif | |
18964 | + | |
18965 | +#ifdef BLKGETSIZE64 | |
18966 | +#ifdef __linux__ | |
18967 | + if ((uname(&ut) == 0) && | |
18968 | + ((ut.release[0] == '2') && (ut.release[1] == '.') && | |
18969 | + (ut.release[2] < '6') && (ut.release[3] == '.'))) | |
18970 | + valid_blkgetsize64 = 0; | |
18971 | +#endif | |
18972 | + if (valid_blkgetsize64 && | |
18973 | + ioctl(fd, BLKGETSIZE64, &size64) >= 0) { | |
18974 | + if ((sizeof(*retblocks) < sizeof(unsigned long long)) | |
18975 | + && ((size64 / blocksize) > 0xFFFFFFFF)) | |
18976 | + return EFBIG; | |
18977 | + close(fd); | |
18978 | + *retblocks = size64 / blocksize; | |
18979 | + return 0; | |
18980 | + } | |
18981 | +#endif | |
18982 | + | |
18983 | +#ifdef BLKGETSIZE | |
18984 | + if (ioctl(fd, BLKGETSIZE, &size) >= 0) { | |
18985 | + close(fd); | |
18986 | + *retblocks = size / (blocksize / 512); | |
18987 | + return 0; | |
18988 | + } | |
18989 | +#endif | |
18990 | + | |
18991 | +#ifdef FDGETPRM | |
18992 | + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { | |
18993 | + close(fd); | |
18994 | + *retblocks = this_floppy.size / (blocksize / 512); | |
18995 | + return 0; | |
18996 | + } | |
18997 | +#endif | |
18998 | + | |
18999 | +#ifdef HAVE_SYS_DISKLABEL_H | |
19000 | +#if defined(DIOCGMEDIASIZE) | |
19001 | + { | |
19002 | + off_t ms; | |
19003 | + u_int bs; | |
19004 | + if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) { | |
19005 | + *retblocks = ms / blocksize; | |
19006 | + return 0; | |
19007 | + } | |
19008 | + } | |
19009 | +#elif defined(DIOCGDINFO) | |
19010 | + /* old disklabel interface */ | |
19011 | + part = strlen(file) - 1; | |
19012 | + if (part >= 0) { | |
19013 | + ch = file[part]; | |
19014 | + if (isdigit(ch)) | |
19015 | + part = 0; | |
19016 | + else if (ch >= 'a' && ch <= 'h') | |
19017 | + part = ch - 'a'; | |
19018 | + else | |
19019 | + part = -1; | |
19020 | + } | |
19021 | + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { | |
19022 | + pp = &lab.d_partitions[part]; | |
19023 | + if (pp->p_size) { | |
19024 | + close(fd); | |
19025 | + *retblocks = pp->p_size / (blocksize / 512); | |
19026 | + return 0; | |
19027 | + } | |
19028 | + } | |
19029 | +#endif /* defined(DIOCG*) */ | |
19030 | +#endif /* HAVE_SYS_DISKLABEL_H */ | |
19031 | + | |
19032 | + /* | |
19033 | + * OK, we couldn't figure it out by using a specialized ioctl, | |
19034 | + * which is generally the best way. So do binary search to | |
19035 | + * find the size of the partition. | |
19036 | + */ | |
19037 | + low = 0; | |
19038 | + for (high = 1024; valid_offset (fd, high); high *= 2) | |
19039 | + low = high; | |
19040 | + while (low < high - 1) | |
19041 | + { | |
19042 | + const ext2_loff_t mid = (low + high) / 2; | |
19043 | + | |
19044 | + if (valid_offset (fd, mid)) | |
19045 | + low = mid; | |
19046 | + else | |
19047 | + high = mid; | |
19048 | + } | |
19049 | + valid_offset (fd, 0); | |
19050 | + close(fd); | |
19051 | + size64 = low + 1; | |
19052 | + if ((sizeof(*retblocks) < sizeof(unsigned long long)) | |
19053 | + && ((size64 / blocksize) > 0xFFFFFFFF)) | |
19054 | + return EFBIG; | |
19055 | + *retblocks = size64 / blocksize; | |
19056 | + return 0; | |
19057 | +} | |
19058 | + | |
19059 | +#endif /* WIN32 */ | |
19060 | + | |
19061 | +#ifdef DEBUG | |
19062 | +int main(int argc, char **argv) | |
19063 | +{ | |
19064 | + blk_t blocks; | |
19065 | + int retval; | |
19066 | + | |
19067 | + if (argc < 2) { | |
19068 | + fprintf(stderr, "Usage: %s device\n", argv[0]); | |
19069 | + exit(1); | |
19070 | + } | |
19071 | + | |
19072 | + retval = ext2fs_get_device_size(argv[1], 1024, &blocks); | |
19073 | + if (retval) { | |
19074 | + com_err(argv[0], retval, | |
19075 | + "while calling ext2fs_get_device_size"); | |
19076 | + exit(1); | |
19077 | + } | |
19078 | + printf("Device %s has %d 1k blocks.\n", argv[1], blocks); | |
19079 | + exit(0); | |
19080 | +} | |
19081 | +#endif | |
19082 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/icount.c busybox/e2fsprogs/ext2fs/icount.c | |
19083 | --- busybox-1.00/e2fsprogs/ext2fs/icount.c 1970-01-01 01:00:00.000000000 +0100 | |
19084 | +++ busybox/e2fsprogs/ext2fs/icount.c 2005-06-04 08:20:16.000000000 +0200 | |
19085 | @@ -0,0 +1,483 @@ | |
19086 | +/* | |
19087 | + * icount.c --- an efficient inode count abstraction | |
19088 | + * | |
19089 | + * Copyright (C) 1997 Theodore Ts'o. | |
19090 | + * | |
19091 | + * %Begin-Header% | |
19092 | + * This file may be redistributed under the terms of the GNU Public | |
19093 | + * License. | |
19094 | + * %End-Header% | |
19095 | + */ | |
19096 | + | |
19097 | +#if HAVE_UNISTD_H | |
19098 | +#include <unistd.h> | |
19099 | +#endif | |
19100 | +#include <string.h> | |
19101 | +#include <stdio.h> | |
19102 | + | |
19103 | +#include "ext2_fs.h" | |
19104 | +#include "ext2fs.h" | |
19105 | + | |
19106 | +/* | |
19107 | + * The data storage strategy used by icount relies on the observation | |
19108 | + * that most inode counts are either zero (for non-allocated inodes), | |
19109 | + * one (for most files), and only a few that are two or more | |
19110 | + * (directories and files that are linked to more than one directory). | |
19111 | + * | |
19112 | + * Also, e2fsck tends to load the icount data sequentially. | |
19113 | + * | |
19114 | + * So, we use an inode bitmap to indicate which inodes have a count of | |
19115 | + * one, and then use a sorted list to store the counts for inodes | |
19116 | + * which are greater than one. | |
19117 | + * | |
19118 | + * We also use an optional bitmap to indicate which inodes are already | |
19119 | + * in the sorted list, to speed up the use of this abstraction by | |
19120 | + * e2fsck's pass 2. Pass 2 increments inode counts as it finds them, | |
19121 | + * so this extra bitmap avoids searching the sorted list to see if a | |
19122 | + * particular inode is on the sorted list already. | |
19123 | + */ | |
19124 | + | |
19125 | +struct ext2_icount_el { | |
19126 | + ext2_ino_t ino; | |
19127 | + __u16 count; | |
19128 | +}; | |
19129 | + | |
19130 | +struct ext2_icount { | |
19131 | + errcode_t magic; | |
19132 | + ext2fs_inode_bitmap single; | |
19133 | + ext2fs_inode_bitmap multiple; | |
19134 | + ext2_ino_t count; | |
19135 | + ext2_ino_t size; | |
19136 | + ext2_ino_t num_inodes; | |
19137 | + ext2_ino_t cursor; | |
19138 | + struct ext2_icount_el *list; | |
19139 | +}; | |
19140 | + | |
19141 | +void ext2fs_free_icount(ext2_icount_t icount) | |
19142 | +{ | |
19143 | + if (!icount) | |
19144 | + return; | |
19145 | + | |
19146 | + icount->magic = 0; | |
19147 | + if (icount->list) | |
19148 | + ext2fs_free_mem(&icount->list); | |
19149 | + if (icount->single) | |
19150 | + ext2fs_free_inode_bitmap(icount->single); | |
19151 | + if (icount->multiple) | |
19152 | + ext2fs_free_inode_bitmap(icount->multiple); | |
19153 | + ext2fs_free_mem(&icount); | |
19154 | +} | |
19155 | + | |
19156 | +errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size, | |
19157 | + ext2_icount_t hint, ext2_icount_t *ret) | |
19158 | +{ | |
19159 | + ext2_icount_t icount; | |
19160 | + errcode_t retval; | |
19161 | + size_t bytes; | |
19162 | + ext2_ino_t i; | |
19163 | + | |
19164 | + if (hint) { | |
19165 | + EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT); | |
19166 | + if (hint->size > size) | |
19167 | + size = (size_t) hint->size; | |
19168 | + } | |
19169 | + | |
19170 | + retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount); | |
19171 | + if (retval) | |
19172 | + return retval; | |
19173 | + memset(icount, 0, sizeof(struct ext2_icount)); | |
19174 | + | |
19175 | + retval = ext2fs_allocate_inode_bitmap(fs, 0, | |
19176 | + &icount->single); | |
19177 | + if (retval) | |
19178 | + goto errout; | |
19179 | + | |
19180 | + if (flags & EXT2_ICOUNT_OPT_INCREMENT) { | |
19181 | + retval = ext2fs_allocate_inode_bitmap(fs, 0, | |
19182 | + &icount->multiple); | |
19183 | + if (retval) | |
19184 | + goto errout; | |
19185 | + } else | |
19186 | + icount->multiple = 0; | |
19187 | + | |
19188 | + if (size) { | |
19189 | + icount->size = size; | |
19190 | + } else { | |
19191 | + /* | |
19192 | + * Figure out how many special case inode counts we will | |
19193 | + * have. We know we will need one for each directory; | |
19194 | + * we also need to reserve some extra room for file links | |
19195 | + */ | |
19196 | + retval = ext2fs_get_num_dirs(fs, &icount->size); | |
19197 | + if (retval) | |
19198 | + goto errout; | |
19199 | + icount->size += fs->super->s_inodes_count / 50; | |
19200 | + } | |
19201 | + | |
19202 | + bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el)); | |
19203 | +#if 0 | |
19204 | + printf("Icount allocated %d entries, %d bytes.\n", | |
19205 | + icount->size, bytes); | |
19206 | +#endif | |
19207 | + retval = ext2fs_get_mem(bytes, &icount->list); | |
19208 | + if (retval) | |
19209 | + goto errout; | |
19210 | + memset(icount->list, 0, bytes); | |
19211 | + | |
19212 | + icount->magic = EXT2_ET_MAGIC_ICOUNT; | |
19213 | + icount->count = 0; | |
19214 | + icount->cursor = 0; | |
19215 | + icount->num_inodes = fs->super->s_inodes_count; | |
19216 | + | |
19217 | + /* | |
19218 | + * Populate the sorted list with those entries which were | |
19219 | + * found in the hint icount (since those are ones which will | |
19220 | + * likely need to be in the sorted list this time around). | |
19221 | + */ | |
19222 | + if (hint) { | |
19223 | + for (i=0; i < hint->count; i++) | |
19224 | + icount->list[i].ino = hint->list[i].ino; | |
19225 | + icount->count = hint->count; | |
19226 | + } | |
19227 | + | |
19228 | + *ret = icount; | |
19229 | + return 0; | |
19230 | + | |
19231 | +errout: | |
19232 | + ext2fs_free_icount(icount); | |
19233 | + return(retval); | |
19234 | +} | |
19235 | + | |
19236 | +errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, | |
19237 | + unsigned int size, | |
19238 | + ext2_icount_t *ret) | |
19239 | +{ | |
19240 | + return ext2fs_create_icount2(fs, flags, size, 0, ret); | |
19241 | +} | |
19242 | + | |
19243 | +/* | |
19244 | + * insert_icount_el() --- Insert a new entry into the sorted list at a | |
19245 | + * specified position. | |
19246 | + */ | |
19247 | +static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount, | |
19248 | + ext2_ino_t ino, int pos) | |
19249 | +{ | |
19250 | + struct ext2_icount_el *el; | |
19251 | + errcode_t retval; | |
19252 | + ext2_ino_t new_size = 0; | |
19253 | + int num; | |
19254 | + | |
19255 | + if (icount->count >= icount->size) { | |
19256 | + if (icount->count) { | |
19257 | + new_size = icount->list[(unsigned)icount->count-1].ino; | |
19258 | + new_size = (ext2_ino_t) (icount->count * | |
19259 | + ((float) icount->num_inodes / new_size)); | |
19260 | + } | |
19261 | + if (new_size < (icount->size + 100)) | |
19262 | + new_size = icount->size + 100; | |
19263 | +#if 0 | |
19264 | + printf("Reallocating icount %d entries...\n", new_size); | |
19265 | +#endif | |
19266 | + retval = ext2fs_resize_mem((size_t) icount->size * | |
19267 | + sizeof(struct ext2_icount_el), | |
19268 | + (size_t) new_size * | |
19269 | + sizeof(struct ext2_icount_el), | |
19270 | + &icount->list); | |
19271 | + if (retval) | |
19272 | + return 0; | |
19273 | + icount->size = new_size; | |
19274 | + } | |
19275 | + num = (int) icount->count - pos; | |
19276 | + if (num < 0) | |
19277 | + return 0; /* should never happen */ | |
19278 | + if (num) { | |
19279 | + memmove(&icount->list[pos+1], &icount->list[pos], | |
19280 | + sizeof(struct ext2_icount_el) * num); | |
19281 | + } | |
19282 | + icount->count++; | |
19283 | + el = &icount->list[pos]; | |
19284 | + el->count = 0; | |
19285 | + el->ino = ino; | |
19286 | + return el; | |
19287 | +} | |
19288 | + | |
19289 | +/* | |
19290 | + * get_icount_el() --- given an inode number, try to find icount | |
19291 | + * information in the sorted list. If the create flag is set, | |
19292 | + * and we can't find an entry, create one in the sorted list. | |
19293 | + */ | |
19294 | +static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, | |
19295 | + ext2_ino_t ino, int create) | |
19296 | +{ | |
19297 | + float range; | |
19298 | + int low, high, mid; | |
19299 | + ext2_ino_t lowval, highval; | |
19300 | + | |
19301 | + if (!icount || !icount->list) | |
19302 | + return 0; | |
19303 | + | |
19304 | + if (create && ((icount->count == 0) || | |
19305 | + (ino > icount->list[(unsigned)icount->count-1].ino))) { | |
19306 | + return insert_icount_el(icount, ino, (unsigned) icount->count); | |
19307 | + } | |
19308 | + if (icount->count == 0) | |
19309 | + return 0; | |
19310 | + | |
19311 | + if (icount->cursor >= icount->count) | |
19312 | + icount->cursor = 0; | |
19313 | + if (ino == icount->list[icount->cursor].ino) | |
19314 | + return &icount->list[icount->cursor++]; | |
19315 | +#if 0 | |
19316 | + printf("Non-cursor get_icount_el: %u\n", ino); | |
19317 | +#endif | |
19318 | + low = 0; | |
19319 | + high = (int) icount->count-1; | |
19320 | + while (low <= high) { | |
19321 | +#if 0 | |
19322 | + mid = (low+high)/2; | |
19323 | +#else | |
19324 | + if (low == high) | |
19325 | + mid = low; | |
19326 | + else { | |
19327 | + /* Interpolate for efficiency */ | |
19328 | + lowval = icount->list[low].ino; | |
19329 | + highval = icount->list[high].ino; | |
19330 | + | |
19331 | + if (ino < lowval) | |
19332 | + range = 0; | |
19333 | + else if (ino > highval) | |
19334 | + range = 1; | |
19335 | + else | |
19336 | + range = ((float) (ino - lowval)) / | |
19337 | + (highval - lowval); | |
19338 | + mid = low + ((int) (range * (high-low))); | |
19339 | + } | |
19340 | +#endif | |
19341 | + if (ino == icount->list[mid].ino) { | |
19342 | + icount->cursor = mid+1; | |
19343 | + return &icount->list[mid]; | |
19344 | + } | |
19345 | + if (ino < icount->list[mid].ino) | |
19346 | + high = mid-1; | |
19347 | + else | |
19348 | + low = mid+1; | |
19349 | + } | |
19350 | + /* | |
19351 | + * If we need to create a new entry, it should be right at | |
19352 | + * low (where high will be left at low-1). | |
19353 | + */ | |
19354 | + if (create) | |
19355 | + return insert_icount_el(icount, ino, low); | |
19356 | + return 0; | |
19357 | +} | |
19358 | + | |
19359 | +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) | |
19360 | +{ | |
19361 | + errcode_t ret = 0; | |
19362 | + unsigned int i; | |
19363 | + const char *bad = "bad icount"; | |
19364 | + | |
19365 | + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); | |
19366 | + | |
19367 | + if (icount->count > icount->size) { | |
19368 | + fprintf(out, "%s: count > size\n", bad); | |
19369 | + return EXT2_ET_INVALID_ARGUMENT; | |
19370 | + } | |
19371 | + for (i=1; i < icount->count; i++) { | |
19372 | + if (icount->list[i-1].ino >= icount->list[i].ino) { | |
19373 | + fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n", | |
19374 | + bad, i-1, icount->list[i-1].ino, | |
19375 | + i, icount->list[i].ino); | |
19376 | + ret = EXT2_ET_INVALID_ARGUMENT; | |
19377 | + } | |
19378 | + } | |
19379 | + return ret; | |
19380 | +} | |
19381 | + | |
19382 | +errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) | |
19383 | +{ | |
19384 | + struct ext2_icount_el *el; | |
19385 | + | |
19386 | + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); | |
19387 | + | |
19388 | + if (!ino || (ino > icount->num_inodes)) | |
19389 | + return EXT2_ET_INVALID_ARGUMENT; | |
19390 | + | |
19391 | + if (ext2fs_test_inode_bitmap(icount->single, ino)) { | |
19392 | + *ret = 1; | |
19393 | + return 0; | |
19394 | + } | |
19395 | + if (icount->multiple && | |
19396 | + !ext2fs_test_inode_bitmap(icount->multiple, ino)) { | |
19397 | + *ret = 0; | |
19398 | + return 0; | |
19399 | + } | |
19400 | + el = get_icount_el(icount, ino, 0); | |
19401 | + if (!el) { | |
19402 | + *ret = 0; | |
19403 | + return 0; | |
19404 | + } | |
19405 | + *ret = el->count; | |
19406 | + return 0; | |
19407 | +} | |
19408 | + | |
19409 | +errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, | |
19410 | + __u16 *ret) | |
19411 | +{ | |
19412 | + struct ext2_icount_el *el; | |
19413 | + | |
19414 | + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); | |
19415 | + | |
19416 | + if (!ino || (ino > icount->num_inodes)) | |
19417 | + return EXT2_ET_INVALID_ARGUMENT; | |
19418 | + | |
19419 | + if (ext2fs_test_inode_bitmap(icount->single, ino)) { | |
19420 | + /* | |
19421 | + * If the existing count is 1, then we know there is | |
19422 | + * no entry in the list. | |
19423 | + */ | |
19424 | + el = get_icount_el(icount, ino, 1); | |
19425 | + if (!el) | |
19426 | + return EXT2_ET_NO_MEMORY; | |
19427 | + ext2fs_unmark_inode_bitmap(icount->single, ino); | |
19428 | + el->count = 2; | |
19429 | + } else if (icount->multiple) { | |
19430 | + /* | |
19431 | + * The count is either zero or greater than 1; if the | |
19432 | + * inode is set in icount->multiple, then there should | |
19433 | + * be an entry in the list, so find it using | |
19434 | + * get_icount_el(). | |
19435 | + */ | |
19436 | + if (ext2fs_test_inode_bitmap(icount->multiple, ino)) { | |
19437 | + el = get_icount_el(icount, ino, 1); | |
19438 | + if (!el) | |
19439 | + return EXT2_ET_NO_MEMORY; | |
19440 | + el->count++; | |
19441 | + } else { | |
19442 | + /* | |
19443 | + * The count was zero; mark the single bitmap | |
19444 | + * and return. | |
19445 | + */ | |
19446 | + zero_count: | |
19447 | + ext2fs_mark_inode_bitmap(icount->single, ino); | |
19448 | + if (ret) | |
19449 | + *ret = 1; | |
19450 | + return 0; | |
19451 | + } | |
19452 | + } else { | |
19453 | + /* | |
19454 | + * The count is either zero or greater than 1; try to | |
19455 | + * find an entry in the list to determine which. | |
19456 | + */ | |
19457 | + el = get_icount_el(icount, ino, 0); | |
19458 | + if (!el) { | |
19459 | + /* No entry means the count was zero */ | |
19460 | + goto zero_count; | |
19461 | + } | |
19462 | + el = get_icount_el(icount, ino, 1); | |
19463 | + if (!el) | |
19464 | + return EXT2_ET_NO_MEMORY; | |
19465 | + el->count++; | |
19466 | + } | |
19467 | + if (icount->multiple) | |
19468 | + ext2fs_mark_inode_bitmap(icount->multiple, ino); | |
19469 | + if (ret) | |
19470 | + *ret = el->count; | |
19471 | + return 0; | |
19472 | +} | |
19473 | + | |
19474 | +errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, | |
19475 | + __u16 *ret) | |
19476 | +{ | |
19477 | + struct ext2_icount_el *el; | |
19478 | + | |
19479 | + if (!ino || (ino > icount->num_inodes)) | |
19480 | + return EXT2_ET_INVALID_ARGUMENT; | |
19481 | + | |
19482 | + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); | |
19483 | + | |
19484 | + if (ext2fs_test_inode_bitmap(icount->single, ino)) { | |
19485 | + ext2fs_unmark_inode_bitmap(icount->single, ino); | |
19486 | + if (icount->multiple) | |
19487 | + ext2fs_unmark_inode_bitmap(icount->multiple, ino); | |
19488 | + else { | |
19489 | + el = get_icount_el(icount, ino, 0); | |
19490 | + if (el) | |
19491 | + el->count = 0; | |
19492 | + } | |
19493 | + if (ret) | |
19494 | + *ret = 0; | |
19495 | + return 0; | |
19496 | + } | |
19497 | + | |
19498 | + if (icount->multiple && | |
19499 | + !ext2fs_test_inode_bitmap(icount->multiple, ino)) | |
19500 | + return EXT2_ET_INVALID_ARGUMENT; | |
19501 | + | |
19502 | + el = get_icount_el(icount, ino, 0); | |
19503 | + if (!el || el->count == 0) | |
19504 | + return EXT2_ET_INVALID_ARGUMENT; | |
19505 | + | |
19506 | + el->count--; | |
19507 | + if (el->count == 1) | |
19508 | + ext2fs_mark_inode_bitmap(icount->single, ino); | |
19509 | + if ((el->count == 0) && icount->multiple) | |
19510 | + ext2fs_unmark_inode_bitmap(icount->multiple, ino); | |
19511 | + | |
19512 | + if (ret) | |
19513 | + *ret = el->count; | |
19514 | + return 0; | |
19515 | +} | |
19516 | + | |
19517 | +errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, | |
19518 | + __u16 count) | |
19519 | +{ | |
19520 | + struct ext2_icount_el *el; | |
19521 | + | |
19522 | + if (!ino || (ino > icount->num_inodes)) | |
19523 | + return EXT2_ET_INVALID_ARGUMENT; | |
19524 | + | |
19525 | + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); | |
19526 | + | |
19527 | + if (count == 1) { | |
19528 | + ext2fs_mark_inode_bitmap(icount->single, ino); | |
19529 | + if (icount->multiple) | |
19530 | + ext2fs_unmark_inode_bitmap(icount->multiple, ino); | |
19531 | + return 0; | |
19532 | + } | |
19533 | + if (count == 0) { | |
19534 | + ext2fs_unmark_inode_bitmap(icount->single, ino); | |
19535 | + if (icount->multiple) { | |
19536 | + /* | |
19537 | + * If the icount->multiple bitmap is enabled, | |
19538 | + * we can just clear both bitmaps and we're done | |
19539 | + */ | |
19540 | + ext2fs_unmark_inode_bitmap(icount->multiple, ino); | |
19541 | + } else { | |
19542 | + el = get_icount_el(icount, ino, 0); | |
19543 | + if (el) | |
19544 | + el->count = 0; | |
19545 | + } | |
19546 | + return 0; | |
19547 | + } | |
19548 | + | |
19549 | + /* | |
19550 | + * Get the icount element | |
19551 | + */ | |
19552 | + el = get_icount_el(icount, ino, 1); | |
19553 | + if (!el) | |
19554 | + return EXT2_ET_NO_MEMORY; | |
19555 | + el->count = count; | |
19556 | + ext2fs_unmark_inode_bitmap(icount->single, ino); | |
19557 | + if (icount->multiple) | |
19558 | + ext2fs_mark_inode_bitmap(icount->multiple, ino); | |
19559 | + return 0; | |
19560 | +} | |
19561 | + | |
19562 | +ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount) | |
19563 | +{ | |
19564 | + if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT) | |
19565 | + return 0; | |
19566 | + | |
19567 | + return icount->size; | |
19568 | +} | |
19569 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/imager.c busybox/e2fsprogs/ext2fs/imager.c | |
19570 | --- busybox-1.00/e2fsprogs/ext2fs/imager.c 1970-01-01 01:00:00.000000000 +0100 | |
19571 | +++ busybox/e2fsprogs/ext2fs/imager.c 2005-06-04 08:20:16.000000000 +0200 | |
19572 | @@ -0,0 +1,387 @@ | |
19573 | +/* | |
19574 | + * image.c --- writes out the critical parts of the filesystem as a | |
19575 | + * flat file. | |
19576 | + * | |
19577 | + * Copyright (C) 2000 Theodore Ts'o. | |
19578 | + * | |
19579 | + * Note: this uses the POSIX IO interfaces, unlike most of the other | |
19580 | + * functions in this library. So sue me. | |
19581 | + * | |
19582 | + * %Begin-Header% | |
19583 | + * This file may be redistributed under the terms of the GNU Public | |
19584 | + * License. | |
19585 | + * %End-Header% | |
19586 | + */ | |
19587 | + | |
19588 | +#include <stdio.h> | |
19589 | +#include <string.h> | |
19590 | +#if HAVE_UNISTD_H | |
19591 | +#include <unistd.h> | |
19592 | +#endif | |
19593 | +#if HAVE_ERRNO_H | |
19594 | +#include <errno.h> | |
19595 | +#endif | |
19596 | +#include <fcntl.h> | |
19597 | +#include <time.h> | |
19598 | +#if HAVE_SYS_STAT_H | |
19599 | +#include <sys/stat.h> | |
19600 | +#endif | |
19601 | +#if HAVE_SYS_TYPES_H | |
19602 | +#include <sys/types.h> | |
19603 | +#endif | |
19604 | + | |
19605 | +#include "ext2_fs.h" | |
19606 | +#include "ext2fs.h" | |
19607 | + | |
19608 | +#ifndef HAVE_TYPE_SSIZE_T | |
19609 | +typedef int ssize_t; | |
19610 | +#endif | |
19611 | + | |
19612 | +/* | |
19613 | + * This function returns 1 if the specified block is all zeros | |
19614 | + */ | |
19615 | +static int check_zero_block(char *buf, int blocksize) | |
19616 | +{ | |
19617 | + char *cp = buf; | |
19618 | + int left = blocksize; | |
19619 | + | |
19620 | + while (left > 0) { | |
19621 | + if (*cp++) | |
19622 | + return 0; | |
19623 | + left--; | |
19624 | + } | |
19625 | + return 1; | |
19626 | +} | |
19627 | + | |
19628 | +/* | |
19629 | + * Write the inode table out as a single block. | |
19630 | + */ | |
19631 | +#define BUF_BLOCKS 32 | |
19632 | + | |
19633 | +errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags) | |
19634 | +{ | |
19635 | + unsigned int group, left, c, d; | |
19636 | + char *buf, *cp; | |
19637 | + blk_t blk; | |
19638 | + ssize_t actual; | |
19639 | + errcode_t retval; | |
19640 | + | |
19641 | + buf = malloc(fs->blocksize * BUF_BLOCKS); | |
19642 | + if (!buf) | |
19643 | + return ENOMEM; | |
19644 | + | |
19645 | + for (group = 0; group < fs->group_desc_count; group++) { | |
19646 | + blk = fs->group_desc[(unsigned)group].bg_inode_table; | |
19647 | + if (!blk) | |
19648 | + return EXT2_ET_MISSING_INODE_TABLE; | |
19649 | + left = fs->inode_blocks_per_group; | |
19650 | + while (left) { | |
19651 | + c = BUF_BLOCKS; | |
19652 | + if (c > left) | |
19653 | + c = left; | |
19654 | + retval = io_channel_read_blk(fs->io, blk, c, buf); | |
19655 | + if (retval) | |
19656 | + goto errout; | |
19657 | + cp = buf; | |
19658 | + while (c) { | |
19659 | + if (!(flags & IMAGER_FLAG_SPARSEWRITE)) { | |
19660 | + d = c; | |
19661 | + goto skip_sparse; | |
19662 | + } | |
19663 | + /* Skip zero blocks */ | |
19664 | + if (check_zero_block(cp, fs->blocksize)) { | |
19665 | + c--; | |
19666 | + blk++; | |
19667 | + left--; | |
19668 | + cp += fs->blocksize; | |
19669 | + lseek(fd, fs->blocksize, SEEK_CUR); | |
19670 | + continue; | |
19671 | + } | |
19672 | + /* Find non-zero blocks */ | |
19673 | + for (d=1; d < c; d++) { | |
19674 | + if (check_zero_block(cp + d*fs->blocksize, fs->blocksize)) | |
19675 | + break; | |
19676 | + } | |
19677 | + skip_sparse: | |
19678 | + actual = write(fd, cp, fs->blocksize * d); | |
19679 | + if (actual == -1) { | |
19680 | + retval = errno; | |
19681 | + goto errout; | |
19682 | + } | |
19683 | + if (actual != (ssize_t) (fs->blocksize * d)) { | |
19684 | + retval = EXT2_ET_SHORT_WRITE; | |
19685 | + goto errout; | |
19686 | + } | |
19687 | + blk += d; | |
19688 | + left -= d; | |
19689 | + cp += fs->blocksize * d; | |
19690 | + c -= d; | |
19691 | + } | |
19692 | + } | |
19693 | + } | |
19694 | + retval = 0; | |
19695 | + | |
19696 | +errout: | |
19697 | + free(buf); | |
19698 | + return retval; | |
19699 | +} | |
19700 | + | |
19701 | +/* | |
19702 | + * Read in the inode table and stuff it into place | |
19703 | + */ | |
19704 | +errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, | |
19705 | + int flags EXT2FS_ATTR((unused))) | |
19706 | +{ | |
19707 | + unsigned int group, c, left; | |
19708 | + char *buf; | |
19709 | + blk_t blk; | |
19710 | + ssize_t actual; | |
19711 | + errcode_t retval; | |
19712 | + | |
19713 | + buf = malloc(fs->blocksize * BUF_BLOCKS); | |
19714 | + if (!buf) | |
19715 | + return ENOMEM; | |
19716 | + | |
19717 | + for (group = 0; group < fs->group_desc_count; group++) { | |
19718 | + blk = fs->group_desc[(unsigned)group].bg_inode_table; | |
19719 | + if (!blk) { | |
19720 | + retval = EXT2_ET_MISSING_INODE_TABLE; | |
19721 | + goto errout; | |
19722 | + } | |
19723 | + left = fs->inode_blocks_per_group; | |
19724 | + while (left) { | |
19725 | + c = BUF_BLOCKS; | |
19726 | + if (c > left) | |
19727 | + c = left; | |
19728 | + actual = read(fd, buf, fs->blocksize * c); | |
19729 | + if (actual == -1) { | |
19730 | + retval = errno; | |
19731 | + goto errout; | |
19732 | + } | |
19733 | + if (actual != (ssize_t) (fs->blocksize * c)) { | |
19734 | + retval = EXT2_ET_SHORT_READ; | |
19735 | + goto errout; | |
19736 | + } | |
19737 | + retval = io_channel_write_blk(fs->io, blk, c, buf); | |
19738 | + if (retval) | |
19739 | + goto errout; | |
19740 | + | |
19741 | + blk += c; | |
19742 | + left -= c; | |
19743 | + } | |
19744 | + } | |
19745 | + retval = ext2fs_flush_icache(fs); | |
19746 | + | |
19747 | +errout: | |
19748 | + free(buf); | |
19749 | + return retval; | |
19750 | +} | |
19751 | + | |
19752 | +/* | |
19753 | + * Write out superblock and group descriptors | |
19754 | + */ | |
19755 | +errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, | |
19756 | + int flags EXT2FS_ATTR((unused))) | |
19757 | +{ | |
19758 | + char *buf, *cp; | |
19759 | + ssize_t actual; | |
19760 | + errcode_t retval; | |
19761 | + | |
19762 | + buf = malloc(fs->blocksize); | |
19763 | + if (!buf) | |
19764 | + return ENOMEM; | |
19765 | + | |
19766 | + /* | |
19767 | + * Write out the superblock | |
19768 | + */ | |
19769 | + memset(buf, 0, fs->blocksize); | |
19770 | + memcpy(buf, fs->super, SUPERBLOCK_SIZE); | |
19771 | + actual = write(fd, buf, fs->blocksize); | |
19772 | + if (actual == -1) { | |
19773 | + retval = errno; | |
19774 | + goto errout; | |
19775 | + } | |
19776 | + if (actual != (ssize_t) fs->blocksize) { | |
19777 | + retval = EXT2_ET_SHORT_WRITE; | |
19778 | + goto errout; | |
19779 | + } | |
19780 | + | |
19781 | + /* | |
19782 | + * Now write out the block group descriptors | |
19783 | + */ | |
19784 | + cp = (char *) fs->group_desc; | |
19785 | + actual = write(fd, cp, fs->blocksize * fs->desc_blocks); | |
19786 | + if (actual == -1) { | |
19787 | + retval = errno; | |
19788 | + goto errout; | |
19789 | + } | |
19790 | + if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) { | |
19791 | + retval = EXT2_ET_SHORT_WRITE; | |
19792 | + goto errout; | |
19793 | + } | |
19794 | + | |
19795 | + retval = 0; | |
19796 | + | |
19797 | +errout: | |
19798 | + free(buf); | |
19799 | + return retval; | |
19800 | +} | |
19801 | + | |
19802 | +/* | |
19803 | + * Read the superblock and group descriptors and overwrite them. | |
19804 | + */ | |
19805 | +errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, | |
19806 | + int flags EXT2FS_ATTR((unused))) | |
19807 | +{ | |
19808 | + char *buf; | |
19809 | + ssize_t actual, size; | |
19810 | + errcode_t retval; | |
19811 | + | |
19812 | + size = fs->blocksize * (fs->group_desc_count + 1); | |
19813 | + buf = malloc(size); | |
19814 | + if (!buf) | |
19815 | + return ENOMEM; | |
19816 | + | |
19817 | + /* | |
19818 | + * Read it all in. | |
19819 | + */ | |
19820 | + actual = read(fd, buf, size); | |
19821 | + if (actual == -1) { | |
19822 | + retval = errno; | |
19823 | + goto errout; | |
19824 | + } | |
19825 | + if (actual != size) { | |
19826 | + retval = EXT2_ET_SHORT_READ; | |
19827 | + goto errout; | |
19828 | + } | |
19829 | + | |
19830 | + /* | |
19831 | + * Now copy in the superblock and group descriptors | |
19832 | + */ | |
19833 | + memcpy(fs->super, buf, SUPERBLOCK_SIZE); | |
19834 | + | |
19835 | + memcpy(fs->group_desc, buf + fs->blocksize, | |
19836 | + fs->blocksize * fs->group_desc_count); | |
19837 | + | |
19838 | + retval = 0; | |
19839 | + | |
19840 | +errout: | |
19841 | + free(buf); | |
19842 | + return retval; | |
19843 | +} | |
19844 | + | |
19845 | +/* | |
19846 | + * Write the block/inode bitmaps. | |
19847 | + */ | |
19848 | +errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) | |
19849 | +{ | |
19850 | + char *ptr; | |
19851 | + int c, size; | |
19852 | + char zero_buf[1024]; | |
19853 | + ssize_t actual; | |
19854 | + errcode_t retval; | |
19855 | + | |
19856 | + if (flags & IMAGER_FLAG_INODEMAP) { | |
19857 | + if (!fs->inode_map) { | |
19858 | + retval = ext2fs_read_inode_bitmap(fs); | |
19859 | + if (retval) | |
19860 | + return retval; | |
19861 | + } | |
19862 | + ptr = fs->inode_map->bitmap; | |
19863 | + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); | |
19864 | + } else { | |
19865 | + if (!fs->block_map) { | |
19866 | + retval = ext2fs_read_block_bitmap(fs); | |
19867 | + if (retval) | |
19868 | + return retval; | |
19869 | + } | |
19870 | + ptr = fs->block_map->bitmap; | |
19871 | + size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; | |
19872 | + } | |
19873 | + size = size * fs->group_desc_count; | |
19874 | + | |
19875 | + actual = write(fd, ptr, size); | |
19876 | + if (actual == -1) { | |
19877 | + retval = errno; | |
19878 | + goto errout; | |
19879 | + } | |
19880 | + if (actual != size) { | |
19881 | + retval = EXT2_ET_SHORT_WRITE; | |
19882 | + goto errout; | |
19883 | + } | |
19884 | + size = size % fs->blocksize; | |
19885 | + memset(zero_buf, 0, sizeof(zero_buf)); | |
19886 | + if (size) { | |
19887 | + size = fs->blocksize - size; | |
19888 | + while (size) { | |
19889 | + c = size; | |
19890 | + if (c > (int) sizeof(zero_buf)) | |
19891 | + c = sizeof(zero_buf); | |
19892 | + actual = write(fd, zero_buf, c); | |
19893 | + if (actual == -1) { | |
19894 | + retval = errno; | |
19895 | + goto errout; | |
19896 | + } | |
19897 | + if (actual != c) { | |
19898 | + retval = EXT2_ET_SHORT_WRITE; | |
19899 | + goto errout; | |
19900 | + } | |
19901 | + size -= c; | |
19902 | + } | |
19903 | + } | |
19904 | + retval = 0; | |
19905 | +errout: | |
19906 | + return (retval); | |
19907 | +} | |
19908 | + | |
19909 | + | |
19910 | +/* | |
19911 | + * Read the block/inode bitmaps. | |
19912 | + */ | |
19913 | +errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) | |
19914 | +{ | |
19915 | + char *ptr, *buf = 0; | |
19916 | + int size; | |
19917 | + ssize_t actual; | |
19918 | + errcode_t retval; | |
19919 | + | |
19920 | + if (flags & IMAGER_FLAG_INODEMAP) { | |
19921 | + if (!fs->inode_map) { | |
19922 | + retval = ext2fs_read_inode_bitmap(fs); | |
19923 | + if (retval) | |
19924 | + return retval; | |
19925 | + } | |
19926 | + ptr = fs->inode_map->bitmap; | |
19927 | + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); | |
19928 | + } else { | |
19929 | + if (!fs->block_map) { | |
19930 | + retval = ext2fs_read_block_bitmap(fs); | |
19931 | + if (retval) | |
19932 | + return retval; | |
19933 | + } | |
19934 | + ptr = fs->block_map->bitmap; | |
19935 | + size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; | |
19936 | + } | |
19937 | + size = size * fs->group_desc_count; | |
19938 | + | |
19939 | + buf = malloc(size); | |
19940 | + if (!buf) | |
19941 | + return ENOMEM; | |
19942 | + | |
19943 | + actual = read(fd, buf, size); | |
19944 | + if (actual == -1) { | |
19945 | + retval = errno; | |
19946 | + goto errout; | |
19947 | + } | |
19948 | + if (actual != size) { | |
19949 | + retval = EXT2_ET_SHORT_WRITE; | |
19950 | + goto errout; | |
19951 | + } | |
19952 | + memcpy(ptr, buf, size); | |
19953 | + | |
19954 | + retval = 0; | |
19955 | +errout: | |
19956 | + if (buf) | |
19957 | + free(buf); | |
19958 | + return (retval); | |
19959 | +} | |
19960 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ind_block.c busybox/e2fsprogs/ext2fs/ind_block.c | |
19961 | --- busybox-1.00/e2fsprogs/ext2fs/ind_block.c 1970-01-01 01:00:00.000000000 +0100 | |
19962 | +++ busybox/e2fsprogs/ext2fs/ind_block.c 2005-06-04 08:20:16.000000000 +0200 | |
19963 | @@ -0,0 +1,66 @@ | |
19964 | +/* | |
19965 | + * ind_block.c --- indirect block I/O routines | |
19966 | + * | |
19967 | + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, | |
19968 | + * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o. | |
19969 | + * | |
19970 | + * %Begin-Header% | |
19971 | + * This file may be redistributed under the terms of the GNU Public | |
19972 | + * License. | |
19973 | + * %End-Header% | |
19974 | + */ | |
19975 | + | |
19976 | +#include <stdio.h> | |
19977 | +#include <string.h> | |
19978 | +#if HAVE_UNISTD_H | |
19979 | +#include <unistd.h> | |
19980 | +#endif | |
19981 | + | |
19982 | +#include "ext2_fs.h" | |
19983 | +#include "ext2fs.h" | |
19984 | + | |
19985 | +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf) | |
19986 | +{ | |
19987 | + errcode_t retval; | |
19988 | + blk_t *block_nr; | |
19989 | + int i; | |
19990 | + int limit = fs->blocksize >> 2; | |
19991 | + | |
19992 | + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) && | |
19993 | + (fs->io != fs->image_io)) | |
19994 | + memset(buf, 0, fs->blocksize); | |
19995 | + else { | |
19996 | + retval = io_channel_read_blk(fs->io, blk, 1, buf); | |
19997 | + if (retval) | |
19998 | + return retval; | |
19999 | + } | |
20000 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
20001 | + if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) { | |
20002 | + block_nr = (blk_t *) buf; | |
20003 | + for (i = 0; i < limit; i++, block_nr++) | |
20004 | + *block_nr = ext2fs_swab32(*block_nr); | |
20005 | + } | |
20006 | +#endif | |
20007 | + return 0; | |
20008 | +} | |
20009 | + | |
20010 | +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf) | |
20011 | +{ | |
20012 | + blk_t *block_nr; | |
20013 | + int i; | |
20014 | + int limit = fs->blocksize >> 2; | |
20015 | + | |
20016 | + if (fs->flags & EXT2_FLAG_IMAGE_FILE) | |
20017 | + return 0; | |
20018 | + | |
20019 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
20020 | + if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) { | |
20021 | + block_nr = (blk_t *) buf; | |
20022 | + for (i = 0; i < limit; i++, block_nr++) | |
20023 | + *block_nr = ext2fs_swab32(*block_nr); | |
20024 | + } | |
20025 | +#endif | |
20026 | + return io_channel_write_blk(fs->io, blk, 1, buf); | |
20027 | +} | |
20028 | + | |
20029 | + | |
20030 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/initialize.c busybox/e2fsprogs/ext2fs/initialize.c | |
20031 | --- busybox-1.00/e2fsprogs/ext2fs/initialize.c 1970-01-01 01:00:00.000000000 +0100 | |
20032 | +++ busybox/e2fsprogs/ext2fs/initialize.c 2005-06-04 08:20:16.000000000 +0200 | |
20033 | @@ -0,0 +1,387 @@ | |
20034 | +/* | |
20035 | + * initialize.c --- initialize a filesystem handle given superblock | |
20036 | + * parameters. Used by mke2fs when initializing a filesystem. | |
20037 | + * | |
20038 | + * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. | |
20039 | + * | |
20040 | + * %Begin-Header% | |
20041 | + * This file may be redistributed under the terms of the GNU Public | |
20042 | + * License. | |
20043 | + * %End-Header% | |
20044 | + */ | |
20045 | + | |
20046 | +#include <stdio.h> | |
20047 | +#include <string.h> | |
20048 | +#if HAVE_UNISTD_H | |
20049 | +#include <unistd.h> | |
20050 | +#endif | |
20051 | +#include <fcntl.h> | |
20052 | +#include <time.h> | |
20053 | +#if HAVE_SYS_STAT_H | |
20054 | +#include <sys/stat.h> | |
20055 | +#endif | |
20056 | +#if HAVE_SYS_TYPES_H | |
20057 | +#include <sys/types.h> | |
20058 | +#endif | |
20059 | + | |
20060 | +#include "ext2_fs.h" | |
20061 | +#include "ext2fs.h" | |
20062 | + | |
20063 | +#if defined(__linux__) && defined(EXT2_OS_LINUX) | |
20064 | +#define CREATOR_OS EXT2_OS_LINUX | |
20065 | +#else | |
20066 | +#if defined(__GNU__) && defined(EXT2_OS_HURD) | |
20067 | +#define CREATOR_OS EXT2_OS_HURD | |
20068 | +#else | |
20069 | +#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) | |
20070 | +#define CREATOR_OS EXT2_OS_FREEBSD | |
20071 | +#else | |
20072 | +#if defined(LITES) && defined(EXT2_OS_LITES) | |
20073 | +#define CREATOR_OS EXT2_OS_LITES | |
20074 | +#else | |
20075 | +#define CREATOR_OS EXT2_OS_LINUX /* by default */ | |
20076 | +#endif /* defined(LITES) && defined(EXT2_OS_LITES) */ | |
20077 | +#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */ | |
20078 | +#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */ | |
20079 | +#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */ | |
20080 | + | |
20081 | +/* | |
20082 | + * Note we override the kernel include file's idea of what the default | |
20083 | + * check interval (never) should be. It's a good idea to check at | |
20084 | + * least *occasionally*, specially since servers will never rarely get | |
20085 | + * to reboot, since Linux is so robust these days. :-) | |
20086 | + * | |
20087 | + * 180 days (six months) seems like a good value. | |
20088 | + */ | |
20089 | +#ifdef EXT2_DFL_CHECKINTERVAL | |
20090 | +#undef EXT2_DFL_CHECKINTERVAL | |
20091 | +#endif | |
20092 | +#define EXT2_DFL_CHECKINTERVAL (86400L * 180L) | |
20093 | + | |
20094 | +/* | |
20095 | + * Calculate the number of GDT blocks to reserve for online filesystem growth. | |
20096 | + * The absolute maximum number of GDT blocks we can reserve is determined by | |
20097 | + * the number of block pointers that can fit into a single block. | |
20098 | + */ | |
20099 | +static int calc_reserved_gdt_blocks(ext2_filsys fs) | |
20100 | +{ | |
20101 | + struct ext2_super_block *sb = fs->super; | |
20102 | + unsigned long bpg = sb->s_blocks_per_group; | |
20103 | + unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc); | |
20104 | + unsigned long max_blocks = 0xffffffff; | |
20105 | + unsigned long rsv_groups; | |
20106 | + int rsv_gdb; | |
20107 | + | |
20108 | + /* We set it at 1024x the current filesystem size, or | |
20109 | + * the upper block count limit (2^32), whichever is lower. | |
20110 | + */ | |
20111 | + if (sb->s_blocks_count < max_blocks / 1024) | |
20112 | + max_blocks = sb->s_blocks_count * 1024; | |
20113 | + rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg; | |
20114 | + rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks; | |
20115 | + if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb)) | |
20116 | + rsv_gdb = EXT2_ADDR_PER_BLOCK(sb); | |
20117 | +#ifdef RES_GDT_DEBUG | |
20118 | + printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %lu\n", | |
20119 | + max_blocks, rsv_groups, rsv_gdb); | |
20120 | +#endif | |
20121 | + | |
20122 | + return rsv_gdb; | |
20123 | +} | |
20124 | + | |
20125 | +errcode_t ext2fs_initialize(const char *name, int flags, | |
20126 | + struct ext2_super_block *param, | |
20127 | + io_manager manager, ext2_filsys *ret_fs) | |
20128 | +{ | |
20129 | + ext2_filsys fs; | |
20130 | + errcode_t retval; | |
20131 | + struct ext2_super_block *super; | |
20132 | + int frags_per_block; | |
20133 | + unsigned int rem; | |
20134 | + unsigned int overhead = 0; | |
20135 | + blk_t group_block; | |
20136 | + unsigned int ipg; | |
20137 | + dgrp_t i; | |
20138 | + blk_t numblocks; | |
20139 | + int rsv_gdt; | |
20140 | + char *buf; | |
20141 | + | |
20142 | + if (!param || !param->s_blocks_count) | |
20143 | + return EXT2_ET_INVALID_ARGUMENT; | |
20144 | + | |
20145 | + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); | |
20146 | + if (retval) | |
20147 | + return retval; | |
20148 | + | |
20149 | + memset(fs, 0, sizeof(struct struct_ext2_filsys)); | |
20150 | + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; | |
20151 | + fs->flags = flags | EXT2_FLAG_RW; | |
20152 | + fs->umask = 022; | |
20153 | +#ifdef WORDS_BIGENDIAN | |
20154 | + fs->flags |= EXT2_FLAG_SWAP_BYTES; | |
20155 | +#endif | |
20156 | + retval = manager->open(name, IO_FLAG_RW, &fs->io); | |
20157 | + if (retval) | |
20158 | + goto cleanup; | |
20159 | + fs->image_io = fs->io; | |
20160 | + fs->io->app_data = fs; | |
20161 | + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); | |
20162 | + if (retval) | |
20163 | + goto cleanup; | |
20164 | + | |
20165 | + strcpy(fs->device_name, name); | |
20166 | + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super); | |
20167 | + if (retval) | |
20168 | + goto cleanup; | |
20169 | + fs->super = super; | |
20170 | + | |
20171 | + memset(super, 0, SUPERBLOCK_SIZE); | |
20172 | + | |
20173 | +#define set_field(field, default) (super->field = param->field ? \ | |
20174 | + param->field : (default)) | |
20175 | + | |
20176 | + super->s_magic = EXT2_SUPER_MAGIC; | |
20177 | + super->s_state = EXT2_VALID_FS; | |
20178 | + | |
20179 | + set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */ | |
20180 | + set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */ | |
20181 | + set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); | |
20182 | + set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT); | |
20183 | + set_field(s_errors, EXT2_ERRORS_DEFAULT); | |
20184 | + set_field(s_feature_compat, 0); | |
20185 | + set_field(s_feature_incompat, 0); | |
20186 | + set_field(s_feature_ro_compat, 0); | |
20187 | + set_field(s_first_meta_bg, 0); | |
20188 | + if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { | |
20189 | + retval = EXT2_ET_UNSUPP_FEATURE; | |
20190 | + goto cleanup; | |
20191 | + } | |
20192 | + if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) { | |
20193 | + retval = EXT2_ET_RO_UNSUPP_FEATURE; | |
20194 | + goto cleanup; | |
20195 | + } | |
20196 | + | |
20197 | + set_field(s_rev_level, EXT2_GOOD_OLD_REV); | |
20198 | + if (super->s_rev_level >= EXT2_DYNAMIC_REV) { | |
20199 | + set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO); | |
20200 | + set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE); | |
20201 | + } | |
20202 | + | |
20203 | + set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL); | |
20204 | + super->s_mkfs_time = super->s_lastcheck = time(NULL); | |
20205 | + | |
20206 | + super->s_creator_os = CREATOR_OS; | |
20207 | + | |
20208 | + fs->blocksize = EXT2_BLOCK_SIZE(super); | |
20209 | + fs->fragsize = EXT2_FRAG_SIZE(super); | |
20210 | + frags_per_block = fs->blocksize / fs->fragsize; | |
20211 | + | |
20212 | + /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */ | |
20213 | + set_field(s_blocks_per_group, fs->blocksize * 8); | |
20214 | + if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super)) | |
20215 | + super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super); | |
20216 | + super->s_frags_per_group = super->s_blocks_per_group * frags_per_block; | |
20217 | + | |
20218 | + super->s_blocks_count = param->s_blocks_count; | |
20219 | + super->s_r_blocks_count = param->s_r_blocks_count; | |
20220 | + if (super->s_r_blocks_count >= param->s_blocks_count) { | |
20221 | + retval = EXT2_ET_INVALID_ARGUMENT; | |
20222 | + goto cleanup; | |
20223 | + } | |
20224 | + | |
20225 | + /* | |
20226 | + * If we're creating an external journal device, we don't need | |
20227 | + * to bother with the rest. | |
20228 | + */ | |
20229 | + if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { | |
20230 | + fs->group_desc_count = 0; | |
20231 | + ext2fs_mark_super_dirty(fs); | |
20232 | + *ret_fs = fs; | |
20233 | + return 0; | |
20234 | + } | |
20235 | + | |
20236 | +retry: | |
20237 | + fs->group_desc_count = (super->s_blocks_count - | |
20238 | + super->s_first_data_block + | |
20239 | + EXT2_BLOCKS_PER_GROUP(super) - 1) | |
20240 | + / EXT2_BLOCKS_PER_GROUP(super); | |
20241 | + if (fs->group_desc_count == 0) { | |
20242 | + retval = EXT2_ET_TOOSMALL; | |
20243 | + goto cleanup; | |
20244 | + } | |
20245 | + fs->desc_blocks = (fs->group_desc_count + | |
20246 | + EXT2_DESC_PER_BLOCK(super) - 1) | |
20247 | + / EXT2_DESC_PER_BLOCK(super); | |
20248 | + | |
20249 | + i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize; | |
20250 | + set_field(s_inodes_count, super->s_blocks_count / i); | |
20251 | + | |
20252 | + /* | |
20253 | + * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so | |
20254 | + * that we have enough inodes for the filesystem(!) | |
20255 | + */ | |
20256 | + if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1) | |
20257 | + super->s_inodes_count = EXT2_FIRST_INODE(super)+1; | |
20258 | + | |
20259 | + /* | |
20260 | + * There should be at least as many inodes as the user | |
20261 | + * requested. Figure out how many inodes per group that | |
20262 | + * should be. But make sure that we don't allocate more than | |
20263 | + * one bitmap's worth of inodes each group. | |
20264 | + */ | |
20265 | + ipg = (super->s_inodes_count + fs->group_desc_count - 1) / | |
20266 | + fs->group_desc_count; | |
20267 | + if (ipg > fs->blocksize * 8) { | |
20268 | + if (super->s_blocks_per_group >= 256) { | |
20269 | + /* Try again with slightly different parameters */ | |
20270 | + super->s_blocks_per_group -= 8; | |
20271 | + super->s_blocks_count = param->s_blocks_count; | |
20272 | + super->s_frags_per_group = super->s_blocks_per_group * | |
20273 | + frags_per_block; | |
20274 | + goto retry; | |
20275 | + } else | |
20276 | + return EXT2_ET_TOO_MANY_INODES; | |
20277 | + } | |
20278 | + | |
20279 | + if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super)) | |
20280 | + ipg = EXT2_MAX_INODES_PER_GROUP(super); | |
20281 | + | |
20282 | + super->s_inodes_per_group = ipg; | |
20283 | + if (super->s_inodes_count > ipg * fs->group_desc_count) | |
20284 | + super->s_inodes_count = ipg * fs->group_desc_count; | |
20285 | + | |
20286 | + /* | |
20287 | + * Make sure the number of inodes per group completely fills | |
20288 | + * the inode table blocks in the descriptor. If not, add some | |
20289 | + * additional inodes/group. Waste not, want not... | |
20290 | + */ | |
20291 | + fs->inode_blocks_per_group = (((super->s_inodes_per_group * | |
20292 | + EXT2_INODE_SIZE(super)) + | |
20293 | + EXT2_BLOCK_SIZE(super) - 1) / | |
20294 | + EXT2_BLOCK_SIZE(super)); | |
20295 | + super->s_inodes_per_group = ((fs->inode_blocks_per_group * | |
20296 | + EXT2_BLOCK_SIZE(super)) / | |
20297 | + EXT2_INODE_SIZE(super)); | |
20298 | + /* | |
20299 | + * Finally, make sure the number of inodes per group is a | |
20300 | + * multiple of 8. This is needed to simplify the bitmap | |
20301 | + * splicing code. | |
20302 | + */ | |
20303 | + super->s_inodes_per_group &= ~7; | |
20304 | + fs->inode_blocks_per_group = (((super->s_inodes_per_group * | |
20305 | + EXT2_INODE_SIZE(super)) + | |
20306 | + EXT2_BLOCK_SIZE(super) - 1) / | |
20307 | + EXT2_BLOCK_SIZE(super)); | |
20308 | + | |
20309 | + /* | |
20310 | + * adjust inode count to reflect the adjusted inodes_per_group | |
20311 | + */ | |
20312 | + super->s_inodes_count = super->s_inodes_per_group * | |
20313 | + fs->group_desc_count; | |
20314 | + super->s_free_inodes_count = super->s_inodes_count; | |
20315 | + | |
20316 | + /* | |
20317 | + * check the number of reserved group descriptor table blocks | |
20318 | + */ | |
20319 | + if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) | |
20320 | + rsv_gdt = calc_reserved_gdt_blocks(fs); | |
20321 | + else | |
20322 | + rsv_gdt = 0; | |
20323 | + set_field(s_reserved_gdt_blocks, rsv_gdt); | |
20324 | + if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) { | |
20325 | + retval = EXT2_ET_RES_GDT_BLOCKS; | |
20326 | + goto cleanup; | |
20327 | + } | |
20328 | + | |
20329 | + /* | |
20330 | + * Overhead is the number of bookkeeping blocks per group. It | |
20331 | + * includes the superblock backup, the group descriptor | |
20332 | + * backups, the inode bitmap, the block bitmap, and the inode | |
20333 | + * table. | |
20334 | + */ | |
20335 | + | |
20336 | + overhead = (int) (2 + fs->inode_blocks_per_group); | |
20337 | + | |
20338 | + if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1)) | |
20339 | + overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks; | |
20340 | + | |
20341 | + /* This can only happen if the user requested too many inodes */ | |
20342 | + if (overhead > super->s_blocks_per_group) | |
20343 | + return EXT2_ET_TOO_MANY_INODES; | |
20344 | + | |
20345 | + /* | |
20346 | + * See if the last group is big enough to support the | |
20347 | + * necessary data structures. If not, we need to get rid of | |
20348 | + * it. | |
20349 | + */ | |
20350 | + rem = ((super->s_blocks_count - super->s_first_data_block) % | |
20351 | + super->s_blocks_per_group); | |
20352 | + if ((fs->group_desc_count == 1) && rem && (rem < overhead)) | |
20353 | + return EXT2_ET_TOOSMALL; | |
20354 | + if (rem && (rem < overhead+50)) { | |
20355 | + super->s_blocks_count -= rem; | |
20356 | + goto retry; | |
20357 | + } | |
20358 | + | |
20359 | + /* | |
20360 | + * At this point we know how big the filesystem will be. So | |
20361 | + * we can do any and all allocations that depend on the block | |
20362 | + * count. | |
20363 | + */ | |
20364 | + | |
20365 | + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); | |
20366 | + if (retval) | |
20367 | + goto cleanup; | |
20368 | + | |
20369 | + sprintf(buf, "block bitmap for %s", fs->device_name); | |
20370 | + retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); | |
20371 | + if (retval) | |
20372 | + goto cleanup; | |
20373 | + | |
20374 | + sprintf(buf, "inode bitmap for %s", fs->device_name); | |
20375 | + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); | |
20376 | + if (retval) | |
20377 | + goto cleanup; | |
20378 | + | |
20379 | + ext2fs_free_mem(&buf); | |
20380 | + | |
20381 | + retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, | |
20382 | + &fs->group_desc); | |
20383 | + if (retval) | |
20384 | + goto cleanup; | |
20385 | + | |
20386 | + memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize); | |
20387 | + | |
20388 | + /* | |
20389 | + * Reserve the superblock and group descriptors for each | |
20390 | + * group, and fill in the correct group statistics for group. | |
20391 | + * Note that although the block bitmap, inode bitmap, and | |
20392 | + * inode table have not been allocated (and in fact won't be | |
20393 | + * by this routine), they are accounted for nevertheless. | |
20394 | + */ | |
20395 | + group_block = super->s_first_data_block; | |
20396 | + super->s_free_blocks_count = 0; | |
20397 | + for (i = 0; i < fs->group_desc_count; i++) { | |
20398 | + numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map); | |
20399 | + | |
20400 | + super->s_free_blocks_count += numblocks; | |
20401 | + fs->group_desc[i].bg_free_blocks_count = numblocks; | |
20402 | + fs->group_desc[i].bg_free_inodes_count = | |
20403 | + fs->super->s_inodes_per_group; | |
20404 | + fs->group_desc[i].bg_used_dirs_count = 0; | |
20405 | + | |
20406 | + group_block += super->s_blocks_per_group; | |
20407 | + } | |
20408 | + | |
20409 | + ext2fs_mark_super_dirty(fs); | |
20410 | + ext2fs_mark_bb_dirty(fs); | |
20411 | + ext2fs_mark_ib_dirty(fs); | |
20412 | + | |
20413 | + io_channel_set_blksize(fs->io, fs->blocksize); | |
20414 | + | |
20415 | + *ret_fs = fs; | |
20416 | + return 0; | |
20417 | +cleanup: | |
20418 | + ext2fs_free(fs); | |
20419 | + return retval; | |
20420 | +} | |
20421 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/inline.c busybox/e2fsprogs/ext2fs/inline.c | |
20422 | --- busybox-1.00/e2fsprogs/ext2fs/inline.c 1970-01-01 01:00:00.000000000 +0100 | |
20423 | +++ busybox/e2fsprogs/ext2fs/inline.c 2005-06-04 08:20:16.000000000 +0200 | |
20424 | @@ -0,0 +1,32 @@ | |
20425 | +/* | |
20426 | + * inline.c --- Includes the inlined functions defined in the header | |
20427 | + * files as standalone functions, in case the application program | |
20428 | + * is compiled with inlining turned off. | |
20429 | + * | |
20430 | + * Copyright (C) 1993, 1994 Theodore Ts'o. | |
20431 | + * | |
20432 | + * %Begin-Header% | |
20433 | + * This file may be redistributed under the terms of the GNU Public | |
20434 | + * License. | |
20435 | + * %End-Header% | |
20436 | + */ | |
20437 | + | |
20438 | + | |
20439 | +#include <stdio.h> | |
20440 | +#include <string.h> | |
20441 | +#if HAVE_UNISTD_H | |
20442 | +#include <unistd.h> | |
20443 | +#endif | |
20444 | +#include <fcntl.h> | |
20445 | +#include <time.h> | |
20446 | +#if HAVE_SYS_STAT_H | |
20447 | +#include <sys/stat.h> | |
20448 | +#endif | |
20449 | +#if HAVE_SYS_TYPES_H | |
20450 | +#include <sys/types.h> | |
20451 | +#endif | |
20452 | + | |
20453 | +#include "ext2_fs.h" | |
20454 | +#define INCLUDE_INLINE_FUNCS | |
20455 | +#include "ext2fs.h" | |
20456 | + | |
20457 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/inode.c busybox/e2fsprogs/ext2fs/inode.c | |
20458 | --- busybox-1.00/e2fsprogs/ext2fs/inode.c 1970-01-01 01:00:00.000000000 +0100 | |
20459 | +++ busybox/e2fsprogs/ext2fs/inode.c 2005-06-04 08:20:16.000000000 +0200 | |
20460 | @@ -0,0 +1,794 @@ | |
20461 | +/* | |
20462 | + * inode.c --- utility routines to read and write inodes | |
20463 | + * | |
20464 | + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. | |
20465 | + * | |
20466 | + * %Begin-Header% | |
20467 | + * This file may be redistributed under the terms of the GNU Public | |
20468 | + * License. | |
20469 | + * %End-Header% | |
20470 | + */ | |
20471 | + | |
20472 | +#include <stdio.h> | |
20473 | +#include <string.h> | |
20474 | +#if HAVE_UNISTD_H | |
20475 | +#include <unistd.h> | |
20476 | +#endif | |
20477 | +#if HAVE_ERRNO_H | |
20478 | +#include <errno.h> | |
20479 | +#endif | |
20480 | +#if HAVE_SYS_STAT_H | |
20481 | +#include <sys/stat.h> | |
20482 | +#endif | |
20483 | +#if HAVE_SYS_TYPES_H | |
20484 | +#include <sys/types.h> | |
20485 | +#endif | |
20486 | + | |
20487 | +#include "ext2_fs.h" | |
20488 | +#include "ext2fsP.h" | |
20489 | +#include "e2image.h" | |
20490 | + | |
20491 | +struct ext2_struct_inode_scan { | |
20492 | + errcode_t magic; | |
20493 | + ext2_filsys fs; | |
20494 | + ext2_ino_t current_inode; | |
20495 | + blk_t current_block; | |
20496 | + dgrp_t current_group; | |
20497 | + ext2_ino_t inodes_left; | |
20498 | + blk_t blocks_left; | |
20499 | + dgrp_t groups_left; | |
20500 | + blk_t inode_buffer_blocks; | |
20501 | + char * inode_buffer; | |
20502 | + int inode_size; | |
20503 | + char * ptr; | |
20504 | + int bytes_left; | |
20505 | + char *temp_buffer; | |
20506 | + errcode_t (*done_group)(ext2_filsys fs, | |
20507 | + ext2_inode_scan scan, | |
20508 | + dgrp_t group, | |
20509 | + void * priv_data); | |
20510 | + void * done_group_data; | |
20511 | + int bad_block_ptr; | |
20512 | + int scan_flags; | |
20513 | + int reserved[6]; | |
20514 | +}; | |
20515 | + | |
20516 | +/* | |
20517 | + * This routine flushes the icache, if it exists. | |
20518 | + */ | |
20519 | +errcode_t ext2fs_flush_icache(ext2_filsys fs) | |
20520 | +{ | |
20521 | + int i; | |
20522 | + | |
20523 | + if (!fs->icache) | |
20524 | + return 0; | |
20525 | + | |
20526 | + for (i=0; i < fs->icache->cache_size; i++) | |
20527 | + fs->icache->cache[i].ino = 0; | |
20528 | + | |
20529 | + fs->icache->buffer_blk = 0; | |
20530 | + return 0; | |
20531 | +} | |
20532 | + | |
20533 | +static errcode_t create_icache(ext2_filsys fs) | |
20534 | +{ | |
20535 | + errcode_t retval; | |
20536 | + | |
20537 | + if (fs->icache) | |
20538 | + return 0; | |
20539 | + retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache); | |
20540 | + if (retval) | |
20541 | + return retval; | |
20542 | + | |
20543 | + memset(fs->icache, 0, sizeof(struct ext2_inode_cache)); | |
20544 | + retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer); | |
20545 | + if (retval) { | |
20546 | + ext2fs_free_mem(&fs->icache); | |
20547 | + return retval; | |
20548 | + } | |
20549 | + fs->icache->buffer_blk = 0; | |
20550 | + fs->icache->cache_last = -1; | |
20551 | + fs->icache->cache_size = 4; | |
20552 | + fs->icache->refcount = 1; | |
20553 | + retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent) | |
20554 | + * fs->icache->cache_size, | |
20555 | + &fs->icache->cache); | |
20556 | + if (retval) { | |
20557 | + ext2fs_free_mem(&fs->icache->buffer); | |
20558 | + ext2fs_free_mem(&fs->icache); | |
20559 | + return retval; | |
20560 | + } | |
20561 | + ext2fs_flush_icache(fs); | |
20562 | + return 0; | |
20563 | +} | |
20564 | + | |
20565 | +errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, | |
20566 | + ext2_inode_scan *ret_scan) | |
20567 | +{ | |
20568 | + ext2_inode_scan scan; | |
20569 | + errcode_t retval; | |
20570 | + errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); | |
20571 | + | |
20572 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
20573 | + | |
20574 | + /* | |
20575 | + * If fs->badblocks isn't set, then set it --- since the inode | |
20576 | + * scanning functions require it. | |
20577 | + */ | |
20578 | + if (fs->badblocks == 0) { | |
20579 | + /* | |
20580 | + * Temporarly save fs->get_blocks and set it to zero, | |
20581 | + * for compatibility with old e2fsck's. | |
20582 | + */ | |
20583 | + save_get_blocks = fs->get_blocks; | |
20584 | + fs->get_blocks = 0; | |
20585 | + retval = ext2fs_read_bb_inode(fs, &fs->badblocks); | |
20586 | + if (retval && fs->badblocks) { | |
20587 | + ext2fs_badblocks_list_free(fs->badblocks); | |
20588 | + fs->badblocks = 0; | |
20589 | + } | |
20590 | + fs->get_blocks = save_get_blocks; | |
20591 | + } | |
20592 | + | |
20593 | + retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); | |
20594 | + if (retval) | |
20595 | + return retval; | |
20596 | + memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); | |
20597 | + | |
20598 | + scan->magic = EXT2_ET_MAGIC_INODE_SCAN; | |
20599 | + scan->fs = fs; | |
20600 | + scan->inode_size = EXT2_INODE_SIZE(fs->super); | |
20601 | + scan->bytes_left = 0; | |
20602 | + scan->current_group = 0; | |
20603 | + scan->groups_left = fs->group_desc_count - 1; | |
20604 | + scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8; | |
20605 | + scan->current_block = scan->fs-> | |
20606 | + group_desc[scan->current_group].bg_inode_table; | |
20607 | + scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); | |
20608 | + scan->blocks_left = scan->fs->inode_blocks_per_group; | |
20609 | + retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks * | |
20610 | + fs->blocksize), | |
20611 | + &scan->inode_buffer); | |
20612 | + scan->done_group = 0; | |
20613 | + scan->done_group_data = 0; | |
20614 | + scan->bad_block_ptr = 0; | |
20615 | + if (retval) { | |
20616 | + ext2fs_free_mem(&scan); | |
20617 | + return retval; | |
20618 | + } | |
20619 | + retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer); | |
20620 | + if (retval) { | |
20621 | + ext2fs_free_mem(&scan->inode_buffer); | |
20622 | + ext2fs_free_mem(&scan); | |
20623 | + return retval; | |
20624 | + } | |
20625 | + if (scan->fs->badblocks && scan->fs->badblocks->num) | |
20626 | + scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; | |
20627 | + *ret_scan = scan; | |
20628 | + return 0; | |
20629 | +} | |
20630 | + | |
20631 | +void ext2fs_close_inode_scan(ext2_inode_scan scan) | |
20632 | +{ | |
20633 | + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) | |
20634 | + return; | |
20635 | + | |
20636 | + ext2fs_free_mem(&scan->inode_buffer); | |
20637 | + scan->inode_buffer = NULL; | |
20638 | + ext2fs_free_mem(&scan->temp_buffer); | |
20639 | + scan->temp_buffer = NULL; | |
20640 | + ext2fs_free_mem(&scan); | |
20641 | + return; | |
20642 | +} | |
20643 | + | |
20644 | +void ext2fs_set_inode_callback(ext2_inode_scan scan, | |
20645 | + errcode_t (*done_group)(ext2_filsys fs, | |
20646 | + ext2_inode_scan scan, | |
20647 | + dgrp_t group, | |
20648 | + void * priv_data), | |
20649 | + void *done_group_data) | |
20650 | +{ | |
20651 | + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) | |
20652 | + return; | |
20653 | + | |
20654 | + scan->done_group = done_group; | |
20655 | + scan->done_group_data = done_group_data; | |
20656 | +} | |
20657 | + | |
20658 | +int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, | |
20659 | + int clear_flags) | |
20660 | +{ | |
20661 | + int old_flags; | |
20662 | + | |
20663 | + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) | |
20664 | + return 0; | |
20665 | + | |
20666 | + old_flags = scan->scan_flags; | |
20667 | + scan->scan_flags &= ~clear_flags; | |
20668 | + scan->scan_flags |= set_flags; | |
20669 | + return old_flags; | |
20670 | +} | |
20671 | + | |
20672 | +/* | |
20673 | + * This function is called by ext2fs_get_next_inode when it needs to | |
20674 | + * get ready to read in a new blockgroup. | |
20675 | + */ | |
20676 | +static errcode_t get_next_blockgroup(ext2_inode_scan scan) | |
20677 | +{ | |
20678 | + scan->current_group++; | |
20679 | + scan->groups_left--; | |
20680 | + | |
20681 | + scan->current_block = scan->fs-> | |
20682 | + group_desc[scan->current_group].bg_inode_table; | |
20683 | + | |
20684 | + scan->current_inode = scan->current_group * | |
20685 | + EXT2_INODES_PER_GROUP(scan->fs->super); | |
20686 | + | |
20687 | + scan->bytes_left = 0; | |
20688 | + scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); | |
20689 | + scan->blocks_left = scan->fs->inode_blocks_per_group; | |
20690 | + return 0; | |
20691 | +} | |
20692 | + | |
20693 | +errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, | |
20694 | + int group) | |
20695 | +{ | |
20696 | + scan->current_group = group - 1; | |
20697 | + scan->groups_left = scan->fs->group_desc_count - group; | |
20698 | + return get_next_blockgroup(scan); | |
20699 | +} | |
20700 | + | |
20701 | +/* | |
20702 | + * This function is called by get_next_blocks() to check for bad | |
20703 | + * blocks in the inode table. | |
20704 | + * | |
20705 | + * This function assumes that badblocks_list->list is sorted in | |
20706 | + * increasing order. | |
20707 | + */ | |
20708 | +static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, | |
20709 | + blk_t *num_blocks) | |
20710 | +{ | |
20711 | + blk_t blk = scan->current_block; | |
20712 | + badblocks_list bb = scan->fs->badblocks; | |
20713 | + | |
20714 | + /* | |
20715 | + * If the inode table is missing, then obviously there are no | |
20716 | + * bad blocks. :-) | |
20717 | + */ | |
20718 | + if (blk == 0) | |
20719 | + return 0; | |
20720 | + | |
20721 | + /* | |
20722 | + * If the current block is greater than the bad block listed | |
20723 | + * in the bad block list, then advance the pointer until this | |
20724 | + * is no longer the case. If we run out of bad blocks, then | |
20725 | + * we don't need to do any more checking! | |
20726 | + */ | |
20727 | + while (blk > bb->list[scan->bad_block_ptr]) { | |
20728 | + if (++scan->bad_block_ptr >= bb->num) { | |
20729 | + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; | |
20730 | + return 0; | |
20731 | + } | |
20732 | + } | |
20733 | + | |
20734 | + /* | |
20735 | + * If the current block is equal to the bad block listed in | |
20736 | + * the bad block list, then handle that one block specially. | |
20737 | + * (We could try to handle runs of bad blocks, but that | |
20738 | + * only increases CPU efficiency by a small amount, at the | |
20739 | + * expense of a huge expense of code complexity, and for an | |
20740 | + * uncommon case at that.) | |
20741 | + */ | |
20742 | + if (blk == bb->list[scan->bad_block_ptr]) { | |
20743 | + scan->scan_flags |= EXT2_SF_BAD_INODE_BLK; | |
20744 | + *num_blocks = 1; | |
20745 | + if (++scan->bad_block_ptr >= bb->num) | |
20746 | + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; | |
20747 | + return 0; | |
20748 | + } | |
20749 | + | |
20750 | + /* | |
20751 | + * If there is a bad block in the range that we're about to | |
20752 | + * read in, adjust the number of blocks to read so that we we | |
20753 | + * don't read in the bad block. (Then the next block to read | |
20754 | + * will be the bad block, which is handled in the above case.) | |
20755 | + */ | |
20756 | + if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr]) | |
20757 | + *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk); | |
20758 | + | |
20759 | + return 0; | |
20760 | +} | |
20761 | + | |
20762 | +/* | |
20763 | + * This function is called by ext2fs_get_next_inode when it needs to | |
20764 | + * read in more blocks from the current blockgroup's inode table. | |
20765 | + */ | |
20766 | +static errcode_t get_next_blocks(ext2_inode_scan scan) | |
20767 | +{ | |
20768 | + blk_t num_blocks; | |
20769 | + errcode_t retval; | |
20770 | + | |
20771 | + /* | |
20772 | + * Figure out how many blocks to read; we read at most | |
20773 | + * inode_buffer_blocks, and perhaps less if there aren't that | |
20774 | + * many blocks left to read. | |
20775 | + */ | |
20776 | + num_blocks = scan->inode_buffer_blocks; | |
20777 | + if (num_blocks > scan->blocks_left) | |
20778 | + num_blocks = scan->blocks_left; | |
20779 | + | |
20780 | + /* | |
20781 | + * If the past block "read" was a bad block, then mark the | |
20782 | + * left-over extra bytes as also being bad. | |
20783 | + */ | |
20784 | + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) { | |
20785 | + if (scan->bytes_left) | |
20786 | + scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES; | |
20787 | + scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK; | |
20788 | + } | |
20789 | + | |
20790 | + /* | |
20791 | + * Do inode bad block processing, if necessary. | |
20792 | + */ | |
20793 | + if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) { | |
20794 | + retval = check_for_inode_bad_blocks(scan, &num_blocks); | |
20795 | + if (retval) | |
20796 | + return retval; | |
20797 | + } | |
20798 | + | |
20799 | + if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) || | |
20800 | + (scan->current_block == 0)) { | |
20801 | + memset(scan->inode_buffer, 0, | |
20802 | + (size_t) num_blocks * scan->fs->blocksize); | |
20803 | + } else { | |
20804 | + retval = io_channel_read_blk(scan->fs->io, | |
20805 | + scan->current_block, | |
20806 | + (int) num_blocks, | |
20807 | + scan->inode_buffer); | |
20808 | + if (retval) | |
20809 | + return EXT2_ET_NEXT_INODE_READ; | |
20810 | + } | |
20811 | + scan->ptr = scan->inode_buffer; | |
20812 | + scan->bytes_left = num_blocks * scan->fs->blocksize; | |
20813 | + | |
20814 | + scan->blocks_left -= num_blocks; | |
20815 | + if (scan->current_block) | |
20816 | + scan->current_block += num_blocks; | |
20817 | + return 0; | |
20818 | +} | |
20819 | + | |
20820 | +#if 0 | |
20821 | +/* | |
20822 | + * Returns 1 if the entire inode_buffer has a non-zero size and | |
20823 | + * contains all zeros. (Not just deleted inodes, since that means | |
20824 | + * that part of the inode table was used at one point; we want all | |
20825 | + * zeros, which means that the inode table is pristine.) | |
20826 | + */ | |
20827 | +static inline int is_empty_scan(ext2_inode_scan scan) | |
20828 | +{ | |
20829 | + int i; | |
20830 | + | |
20831 | + if (scan->bytes_left == 0) | |
20832 | + return 0; | |
20833 | + | |
20834 | + for (i=0; i < scan->bytes_left; i++) | |
20835 | + if (scan->ptr[i]) | |
20836 | + return 0; | |
20837 | + return 1; | |
20838 | +} | |
20839 | +#endif | |
20840 | + | |
20841 | +errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino, | |
20842 | + struct ext2_inode *inode, int bufsize) | |
20843 | +{ | |
20844 | + errcode_t retval; | |
20845 | + int extra_bytes = 0; | |
20846 | + | |
20847 | + EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN); | |
20848 | + | |
20849 | + /* | |
20850 | + * Do we need to start reading a new block group? | |
20851 | + */ | |
20852 | + if (scan->inodes_left <= 0) { | |
20853 | + force_new_group: | |
20854 | + if (scan->done_group) { | |
20855 | + retval = (scan->done_group) | |
20856 | + (scan->fs, scan, scan->current_group, | |
20857 | + scan->done_group_data); | |
20858 | + if (retval) | |
20859 | + return retval; | |
20860 | + } | |
20861 | + if (scan->groups_left <= 0) { | |
20862 | + *ino = 0; | |
20863 | + return 0; | |
20864 | + } | |
20865 | + retval = get_next_blockgroup(scan); | |
20866 | + if (retval) | |
20867 | + return retval; | |
20868 | + } | |
20869 | + /* | |
20870 | + * This is done outside the above if statement so that the | |
20871 | + * check can be done for block group #0. | |
20872 | + */ | |
20873 | + if (scan->current_block == 0) { | |
20874 | + if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { | |
20875 | + goto force_new_group; | |
20876 | + } else | |
20877 | + return EXT2_ET_MISSING_INODE_TABLE; | |
20878 | + } | |
20879 | + | |
20880 | + | |
20881 | + /* | |
20882 | + * Have we run out of space in the inode buffer? If so, we | |
20883 | + * need to read in more blocks. | |
20884 | + */ | |
20885 | + if (scan->bytes_left < scan->inode_size) { | |
20886 | + memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); | |
20887 | + extra_bytes = scan->bytes_left; | |
20888 | + | |
20889 | + retval = get_next_blocks(scan); | |
20890 | + if (retval) | |
20891 | + return retval; | |
20892 | +#if 0 | |
20893 | + /* | |
20894 | + * XXX test Need check for used inode somehow. | |
20895 | + * (Note: this is hard.) | |
20896 | + */ | |
20897 | + if (is_empty_scan(scan)) | |
20898 | + goto force_new_group; | |
20899 | +#endif | |
20900 | + } | |
20901 | + | |
20902 | + retval = 0; | |
20903 | + if (extra_bytes) { | |
20904 | + memcpy(scan->temp_buffer+extra_bytes, scan->ptr, | |
20905 | + scan->inode_size - extra_bytes); | |
20906 | + scan->ptr += scan->inode_size - extra_bytes; | |
20907 | + scan->bytes_left -= scan->inode_size - extra_bytes; | |
20908 | + | |
20909 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
20910 | + if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
20911 | + (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) | |
20912 | + ext2fs_swap_inode_full(scan->fs, | |
20913 | + (struct ext2_inode_large *) inode, | |
20914 | + (struct ext2_inode_large *) scan->temp_buffer, | |
20915 | + 0, bufsize); | |
20916 | + else | |
20917 | +#endif | |
20918 | + *inode = *((struct ext2_inode *) scan->temp_buffer); | |
20919 | + if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) | |
20920 | + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; | |
20921 | + scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; | |
20922 | + } else { | |
20923 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
20924 | + if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
20925 | + (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) | |
20926 | + ext2fs_swap_inode_full(scan->fs, | |
20927 | + (struct ext2_inode_large *) inode, | |
20928 | + (struct ext2_inode_large *) scan->ptr, | |
20929 | + 0, bufsize); | |
20930 | + else | |
20931 | +#endif | |
20932 | + memcpy(inode, scan->ptr, bufsize); | |
20933 | + scan->ptr += scan->inode_size; | |
20934 | + scan->bytes_left -= scan->inode_size; | |
20935 | + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) | |
20936 | + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; | |
20937 | + } | |
20938 | + | |
20939 | + scan->inodes_left--; | |
20940 | + scan->current_inode++; | |
20941 | + *ino = scan->current_inode; | |
20942 | + return retval; | |
20943 | +} | |
20944 | + | |
20945 | +errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, | |
20946 | + struct ext2_inode *inode) | |
20947 | +{ | |
20948 | + return ext2fs_get_next_inode_full(scan, ino, inode, | |
20949 | + sizeof(struct ext2_inode)); | |
20950 | +} | |
20951 | + | |
20952 | +/* | |
20953 | + * Functions to read and write a single inode. | |
20954 | + */ | |
20955 | +errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, | |
20956 | + struct ext2_inode * inode, int bufsize) | |
20957 | +{ | |
20958 | + unsigned long group, block, block_nr, offset; | |
20959 | + char *ptr; | |
20960 | + errcode_t retval; | |
20961 | + int clen, i, inodes_per_block, length; | |
20962 | + io_channel io; | |
20963 | + | |
20964 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
20965 | + | |
20966 | + /* Check to see if user has an override function */ | |
20967 | + if (fs->read_inode) { | |
20968 | + retval = (fs->read_inode)(fs, ino, inode); | |
20969 | + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) | |
20970 | + return retval; | |
20971 | + } | |
20972 | + /* Create inode cache if not present */ | |
20973 | + if (!fs->icache) { | |
20974 | + retval = create_icache(fs); | |
20975 | + if (retval) | |
20976 | + return retval; | |
20977 | + } | |
20978 | + /* Check to see if it's in the inode cache */ | |
20979 | + if (bufsize == sizeof(struct ext2_inode)) { | |
20980 | + /* only old good inode can be retrieve from the cache */ | |
20981 | + for (i=0; i < fs->icache->cache_size; i++) { | |
20982 | + if (fs->icache->cache[i].ino == ino) { | |
20983 | + *inode = fs->icache->cache[i].inode; | |
20984 | + return 0; | |
20985 | + } | |
20986 | + } | |
20987 | + } | |
20988 | + if ((ino == 0) || (ino > fs->super->s_inodes_count)) | |
20989 | + return EXT2_ET_BAD_INODE_NUM; | |
20990 | + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { | |
20991 | + inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); | |
20992 | + block_nr = fs->image_header->offset_inode / fs->blocksize; | |
20993 | + block_nr += (ino - 1) / inodes_per_block; | |
20994 | + offset = ((ino - 1) % inodes_per_block) * | |
20995 | + EXT2_INODE_SIZE(fs->super); | |
20996 | + io = fs->image_io; | |
20997 | + } else { | |
20998 | + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); | |
20999 | + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * | |
21000 | + EXT2_INODE_SIZE(fs->super); | |
21001 | + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); | |
21002 | + if (!fs->group_desc[(unsigned)group].bg_inode_table) | |
21003 | + return EXT2_ET_MISSING_INODE_TABLE; | |
21004 | + block_nr = fs->group_desc[(unsigned)group].bg_inode_table + | |
21005 | + block; | |
21006 | + io = fs->io; | |
21007 | + } | |
21008 | + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); | |
21009 | + | |
21010 | + length = EXT2_INODE_SIZE(fs->super); | |
21011 | + if (bufsize < length) | |
21012 | + length = bufsize; | |
21013 | + | |
21014 | + ptr = (char *) inode; | |
21015 | + while (length) { | |
21016 | + clen = length; | |
21017 | + if ((offset + length) > fs->blocksize) | |
21018 | + clen = fs->blocksize - offset; | |
21019 | + | |
21020 | + if (block_nr != fs->icache->buffer_blk) { | |
21021 | + retval = io_channel_read_blk(io, block_nr, 1, | |
21022 | + fs->icache->buffer); | |
21023 | + if (retval) | |
21024 | + return retval; | |
21025 | + fs->icache->buffer_blk = block_nr; | |
21026 | + } | |
21027 | + | |
21028 | + memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, | |
21029 | + clen); | |
21030 | + | |
21031 | + offset = 0; | |
21032 | + length -= clen; | |
21033 | + ptr += clen; | |
21034 | + block_nr++; | |
21035 | + } | |
21036 | + | |
21037 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
21038 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
21039 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) | |
21040 | + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode, | |
21041 | + (struct ext2_inode_large *) inode, | |
21042 | + 0, length); | |
21043 | +#endif | |
21044 | + | |
21045 | + /* Update the inode cache */ | |
21046 | + fs->icache->cache_last = (fs->icache->cache_last + 1) % | |
21047 | + fs->icache->cache_size; | |
21048 | + fs->icache->cache[fs->icache->cache_last].ino = ino; | |
21049 | + fs->icache->cache[fs->icache->cache_last].inode = *inode; | |
21050 | + | |
21051 | + return 0; | |
21052 | +} | |
21053 | + | |
21054 | +errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, | |
21055 | + struct ext2_inode * inode) | |
21056 | +{ | |
21057 | + return ext2fs_read_inode_full(fs, ino, inode, | |
21058 | + sizeof(struct ext2_inode)); | |
21059 | +} | |
21060 | + | |
21061 | +errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, | |
21062 | + struct ext2_inode * inode, int bufsize) | |
21063 | +{ | |
21064 | + unsigned long group, block, block_nr, offset; | |
21065 | + errcode_t retval = 0; | |
21066 | + struct ext2_inode_large temp_inode, *w_inode; | |
21067 | + char *ptr; | |
21068 | + int clen, i, length; | |
21069 | + | |
21070 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
21071 | + | |
21072 | + /* Check to see if user provided an override function */ | |
21073 | + if (fs->write_inode) { | |
21074 | + retval = (fs->write_inode)(fs, ino, inode); | |
21075 | + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) | |
21076 | + return retval; | |
21077 | + } | |
21078 | + | |
21079 | + /* Check to see if the inode cache needs to be updated */ | |
21080 | + if (fs->icache) { | |
21081 | + for (i=0; i < fs->icache->cache_size; i++) { | |
21082 | + if (fs->icache->cache[i].ino == ino) { | |
21083 | + fs->icache->cache[i].inode = *inode; | |
21084 | + break; | |
21085 | + } | |
21086 | + } | |
21087 | + } else { | |
21088 | + retval = create_icache(fs); | |
21089 | + if (retval) | |
21090 | + return retval; | |
21091 | + } | |
21092 | + | |
21093 | + if (!(fs->flags & EXT2_FLAG_RW)) | |
21094 | + return EXT2_ET_RO_FILSYS; | |
21095 | + | |
21096 | + if ((ino == 0) || (ino > fs->super->s_inodes_count)) | |
21097 | + return EXT2_ET_BAD_INODE_NUM; | |
21098 | + | |
21099 | + length = bufsize; | |
21100 | + if (length < EXT2_INODE_SIZE(fs->super)) | |
21101 | + length = EXT2_INODE_SIZE(fs->super); | |
21102 | + | |
21103 | + if (length > (int) sizeof(struct ext2_inode_large)) { | |
21104 | + w_inode = malloc(length); | |
21105 | + if (!w_inode) | |
21106 | + return ENOMEM; | |
21107 | + } else | |
21108 | + w_inode = &temp_inode; | |
21109 | + memset(w_inode, 0, length); | |
21110 | + | |
21111 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
21112 | + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
21113 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) | |
21114 | + ext2fs_swap_inode_full(fs, w_inode, | |
21115 | + (struct ext2_inode_large *) inode, | |
21116 | + 1, bufsize); | |
21117 | + else | |
21118 | +#endif | |
21119 | + memcpy(w_inode, inode, bufsize); | |
21120 | + | |
21121 | + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); | |
21122 | + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * | |
21123 | + EXT2_INODE_SIZE(fs->super); | |
21124 | + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); | |
21125 | + if (!fs->group_desc[(unsigned) group].bg_inode_table) | |
21126 | + return EXT2_ET_MISSING_INODE_TABLE; | |
21127 | + block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block; | |
21128 | + | |
21129 | + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); | |
21130 | + | |
21131 | + length = EXT2_INODE_SIZE(fs->super); | |
21132 | + if (length > bufsize) | |
21133 | + length = bufsize; | |
21134 | + | |
21135 | + ptr = (char *) w_inode; | |
21136 | + | |
21137 | + while (length) { | |
21138 | + clen = length; | |
21139 | + if ((offset + length) > fs->blocksize) | |
21140 | + clen = fs->blocksize - offset; | |
21141 | + | |
21142 | + if (fs->icache->buffer_blk != block_nr) { | |
21143 | + retval = io_channel_read_blk(fs->io, block_nr, 1, | |
21144 | + fs->icache->buffer); | |
21145 | + if (retval) | |
21146 | + goto errout; | |
21147 | + fs->icache->buffer_blk = block_nr; | |
21148 | + } | |
21149 | + | |
21150 | + | |
21151 | + memcpy((char *) fs->icache->buffer + (unsigned) offset, | |
21152 | + ptr, clen); | |
21153 | + | |
21154 | + retval = io_channel_write_blk(fs->io, block_nr, 1, | |
21155 | + fs->icache->buffer); | |
21156 | + if (retval) | |
21157 | + goto errout; | |
21158 | + | |
21159 | + offset = 0; | |
21160 | + ptr += clen; | |
21161 | + length -= clen; | |
21162 | + block_nr++; | |
21163 | + } | |
21164 | + | |
21165 | + fs->flags |= EXT2_FLAG_CHANGED; | |
21166 | +errout: | |
21167 | + if (w_inode && w_inode != &temp_inode) | |
21168 | + free(w_inode); | |
21169 | + return retval; | |
21170 | +} | |
21171 | + | |
21172 | +errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, | |
21173 | + struct ext2_inode *inode) | |
21174 | +{ | |
21175 | + return ext2fs_write_inode_full(fs, ino, inode, | |
21176 | + sizeof(struct ext2_inode)); | |
21177 | +} | |
21178 | + | |
21179 | +/* | |
21180 | + * This function should be called when writing a new inode. It makes | |
21181 | + * sure that extra part of large inodes is initialized properly. | |
21182 | + */ | |
21183 | +errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, | |
21184 | + struct ext2_inode *inode) | |
21185 | +{ | |
21186 | + struct ext2_inode *buf; | |
21187 | + int size = EXT2_INODE_SIZE(fs->super); | |
21188 | + struct ext2_inode_large *large_inode; | |
21189 | + | |
21190 | + if (size == sizeof(struct ext2_inode)) | |
21191 | + return ext2fs_write_inode_full(fs, ino, inode, | |
21192 | + sizeof(struct ext2_inode)); | |
21193 | + | |
21194 | + buf = malloc(size); | |
21195 | + if (!buf) | |
21196 | + return ENOMEM; | |
21197 | + | |
21198 | + memset(buf, 0, size); | |
21199 | + *buf = *inode; | |
21200 | + | |
21201 | + large_inode = (struct ext2_inode_large *) buf; | |
21202 | + large_inode->i_extra_isize = sizeof(struct ext2_inode_large) - | |
21203 | + EXT2_GOOD_OLD_INODE_SIZE; | |
21204 | + | |
21205 | + return ext2fs_write_inode_full(fs, ino, buf, size); | |
21206 | +} | |
21207 | + | |
21208 | + | |
21209 | +errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks) | |
21210 | +{ | |
21211 | + struct ext2_inode inode; | |
21212 | + int i; | |
21213 | + errcode_t retval; | |
21214 | + | |
21215 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
21216 | + | |
21217 | + if (ino > fs->super->s_inodes_count) | |
21218 | + return EXT2_ET_BAD_INODE_NUM; | |
21219 | + | |
21220 | + if (fs->get_blocks) { | |
21221 | + if (!(*fs->get_blocks)(fs, ino, blocks)) | |
21222 | + return 0; | |
21223 | + } | |
21224 | + retval = ext2fs_read_inode(fs, ino, &inode); | |
21225 | + if (retval) | |
21226 | + return retval; | |
21227 | + for (i=0; i < EXT2_N_BLOCKS; i++) | |
21228 | + blocks[i] = inode.i_block[i]; | |
21229 | + return 0; | |
21230 | +} | |
21231 | + | |
21232 | +errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino) | |
21233 | +{ | |
21234 | + struct ext2_inode inode; | |
21235 | + errcode_t retval; | |
21236 | + | |
21237 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
21238 | + | |
21239 | + if (ino > fs->super->s_inodes_count) | |
21240 | + return EXT2_ET_BAD_INODE_NUM; | |
21241 | + | |
21242 | + if (fs->check_directory) { | |
21243 | + retval = (fs->check_directory)(fs, ino); | |
21244 | + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) | |
21245 | + return retval; | |
21246 | + } | |
21247 | + retval = ext2fs_read_inode(fs, ino, &inode); | |
21248 | + if (retval) | |
21249 | + return retval; | |
21250 | + if (!LINUX_S_ISDIR(inode.i_mode)) | |
21251 | + return EXT2_ET_NO_DIRECTORY; | |
21252 | + return 0; | |
21253 | +} | |
21254 | + | |
21255 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/inode_io.c busybox/e2fsprogs/ext2fs/inode_io.c | |
21256 | --- busybox-1.00/e2fsprogs/ext2fs/inode_io.c 1970-01-01 01:00:00.000000000 +0100 | |
21257 | +++ busybox/e2fsprogs/ext2fs/inode_io.c 2005-06-04 08:20:16.000000000 +0200 | |
21258 | @@ -0,0 +1,270 @@ | |
21259 | +/* | |
21260 | + * inode_io.c --- This is allows an inode in an ext2 filesystem image | |
21261 | + * to be accessed via the I/O manager interface. | |
21262 | + * | |
21263 | + * Copyright (C) 2002 Theodore Ts'o. | |
21264 | + * | |
21265 | + * %Begin-Header% | |
21266 | + * This file may be redistributed under the terms of the GNU Public | |
21267 | + * License. | |
21268 | + * %End-Header% | |
21269 | + */ | |
21270 | + | |
21271 | +#include <stdio.h> | |
21272 | +#include <string.h> | |
21273 | +#if HAVE_UNISTD_H | |
21274 | +#include <unistd.h> | |
21275 | +#endif | |
21276 | +#if HAVE_ERRNO_H | |
21277 | +#include <errno.h> | |
21278 | +#endif | |
21279 | +#include <time.h> | |
21280 | + | |
21281 | +#include "ext2_fs.h" | |
21282 | +#include "ext2fs.h" | |
21283 | + | |
21284 | +/* | |
21285 | + * For checking structure magic numbers... | |
21286 | + */ | |
21287 | + | |
21288 | +#define EXT2_CHECK_MAGIC(struct, code) \ | |
21289 | + if ((struct)->magic != (code)) return (code) | |
21290 | + | |
21291 | +struct inode_private_data { | |
21292 | + int magic; | |
21293 | + char name[32]; | |
21294 | + ext2_file_t file; | |
21295 | + ext2_filsys fs; | |
21296 | + ext2_ino_t ino; | |
21297 | + struct ext2_inode inode; | |
21298 | + int flags; | |
21299 | + struct inode_private_data *next; | |
21300 | +}; | |
21301 | + | |
21302 | +#define CHANNEL_HAS_INODE 0x8000 | |
21303 | + | |
21304 | +static struct inode_private_data *top_intern; | |
21305 | +static int ino_unique = 0; | |
21306 | + | |
21307 | +static errcode_t inode_open(const char *name, int flags, io_channel *channel); | |
21308 | +static errcode_t inode_close(io_channel channel); | |
21309 | +static errcode_t inode_set_blksize(io_channel channel, int blksize); | |
21310 | +static errcode_t inode_read_blk(io_channel channel, unsigned long block, | |
21311 | + int count, void *data); | |
21312 | +static errcode_t inode_write_blk(io_channel channel, unsigned long block, | |
21313 | + int count, const void *data); | |
21314 | +static errcode_t inode_flush(io_channel channel); | |
21315 | +static errcode_t inode_write_byte(io_channel channel, unsigned long offset, | |
21316 | + int size, const void *data); | |
21317 | + | |
21318 | +static struct struct_io_manager struct_inode_manager = { | |
21319 | + EXT2_ET_MAGIC_IO_MANAGER, | |
21320 | + "Inode I/O Manager", | |
21321 | + inode_open, | |
21322 | + inode_close, | |
21323 | + inode_set_blksize, | |
21324 | + inode_read_blk, | |
21325 | + inode_write_blk, | |
21326 | + inode_flush, | |
21327 | + inode_write_byte | |
21328 | +}; | |
21329 | + | |
21330 | +io_manager inode_io_manager = &struct_inode_manager; | |
21331 | + | |
21332 | +errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino, | |
21333 | + struct ext2_inode *inode, | |
21334 | + char **name) | |
21335 | +{ | |
21336 | + struct inode_private_data *data; | |
21337 | + errcode_t retval; | |
21338 | + | |
21339 | + if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data), | |
21340 | + &data))) | |
21341 | + return retval; | |
21342 | + data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL; | |
21343 | + sprintf(data->name, "%u:%d", ino, ino_unique++); | |
21344 | + data->file = 0; | |
21345 | + data->fs = fs; | |
21346 | + data->ino = ino; | |
21347 | + data->flags = 0; | |
21348 | + if (inode) { | |
21349 | + memcpy(&data->inode, inode, sizeof(struct ext2_inode)); | |
21350 | + data->flags |= CHANNEL_HAS_INODE; | |
21351 | + } | |
21352 | + data->next = top_intern; | |
21353 | + top_intern = data; | |
21354 | + *name = data->name; | |
21355 | + return 0; | |
21356 | +} | |
21357 | + | |
21358 | +errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, | |
21359 | + char **name) | |
21360 | +{ | |
21361 | + return ext2fs_inode_io_intern2(fs, ino, NULL, name); | |
21362 | +} | |
21363 | + | |
21364 | + | |
21365 | +static errcode_t inode_open(const char *name, int flags, io_channel *channel) | |
21366 | +{ | |
21367 | + io_channel io = NULL; | |
21368 | + struct inode_private_data *prev, *data = NULL; | |
21369 | + errcode_t retval; | |
21370 | + int open_flags; | |
21371 | + | |
21372 | + if (name == 0) | |
21373 | + return EXT2_ET_BAD_DEVICE_NAME; | |
21374 | + | |
21375 | + for (data = top_intern, prev = NULL; data; | |
21376 | + prev = data, data = data->next) | |
21377 | + if (strcmp(name, data->name) == 0) | |
21378 | + break; | |
21379 | + if (!data) | |
21380 | + return ENOENT; | |
21381 | + if (prev) | |
21382 | + prev->next = data->next; | |
21383 | + else | |
21384 | + top_intern = data->next; | |
21385 | + | |
21386 | + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); | |
21387 | + if (retval) | |
21388 | + goto cleanup; | |
21389 | + memset(io, 0, sizeof(struct struct_io_channel)); | |
21390 | + | |
21391 | + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; | |
21392 | + io->manager = inode_io_manager; | |
21393 | + retval = ext2fs_get_mem(strlen(name)+1, &io->name); | |
21394 | + if (retval) | |
21395 | + goto cleanup; | |
21396 | + | |
21397 | + strcpy(io->name, name); | |
21398 | + io->private_data = data; | |
21399 | + io->block_size = 1024; | |
21400 | + io->read_error = 0; | |
21401 | + io->write_error = 0; | |
21402 | + io->refcount = 1; | |
21403 | + | |
21404 | + open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0; | |
21405 | + retval = ext2fs_file_open2(data->fs, data->ino, | |
21406 | + (data->flags & CHANNEL_HAS_INODE) ? | |
21407 | + &data->inode : 0, open_flags, | |
21408 | + &data->file); | |
21409 | + if (retval) | |
21410 | + goto cleanup; | |
21411 | + | |
21412 | + *channel = io; | |
21413 | + return 0; | |
21414 | + | |
21415 | +cleanup: | |
21416 | + if (data) { | |
21417 | + ext2fs_free_mem(&data); | |
21418 | + } | |
21419 | + if (io) | |
21420 | + ext2fs_free_mem(&io); | |
21421 | + return retval; | |
21422 | +} | |
21423 | + | |
21424 | +static errcode_t inode_close(io_channel channel) | |
21425 | +{ | |
21426 | + struct inode_private_data *data; | |
21427 | + errcode_t retval = 0; | |
21428 | + | |
21429 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21430 | + data = (struct inode_private_data *) channel->private_data; | |
21431 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); | |
21432 | + | |
21433 | + if (--channel->refcount > 0) | |
21434 | + return 0; | |
21435 | + | |
21436 | + retval = ext2fs_file_close(data->file); | |
21437 | + | |
21438 | + ext2fs_free_mem(&channel->private_data); | |
21439 | + if (channel->name) | |
21440 | + ext2fs_free_mem(&channel->name); | |
21441 | + ext2fs_free_mem(&channel); | |
21442 | + return retval; | |
21443 | +} | |
21444 | + | |
21445 | +static errcode_t inode_set_blksize(io_channel channel, int blksize) | |
21446 | +{ | |
21447 | + struct inode_private_data *data; | |
21448 | + | |
21449 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21450 | + data = (struct inode_private_data *) channel->private_data; | |
21451 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); | |
21452 | + | |
21453 | + channel->block_size = blksize; | |
21454 | + return 0; | |
21455 | +} | |
21456 | + | |
21457 | + | |
21458 | +static errcode_t inode_read_blk(io_channel channel, unsigned long block, | |
21459 | + int count, void *buf) | |
21460 | +{ | |
21461 | + struct inode_private_data *data; | |
21462 | + errcode_t retval; | |
21463 | + | |
21464 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21465 | + data = (struct inode_private_data *) channel->private_data; | |
21466 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); | |
21467 | + | |
21468 | + if ((retval = ext2fs_file_lseek(data->file, | |
21469 | + block * channel->block_size, | |
21470 | + EXT2_SEEK_SET, 0))) | |
21471 | + return retval; | |
21472 | + | |
21473 | + count = (count < 0) ? -count : (count * channel->block_size); | |
21474 | + | |
21475 | + return ext2fs_file_read(data->file, buf, count, 0); | |
21476 | +} | |
21477 | + | |
21478 | +static errcode_t inode_write_blk(io_channel channel, unsigned long block, | |
21479 | + int count, const void *buf) | |
21480 | +{ | |
21481 | + struct inode_private_data *data; | |
21482 | + errcode_t retval; | |
21483 | + | |
21484 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21485 | + data = (struct inode_private_data *) channel->private_data; | |
21486 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); | |
21487 | + | |
21488 | + if ((retval = ext2fs_file_lseek(data->file, | |
21489 | + block * channel->block_size, | |
21490 | + EXT2_SEEK_SET, 0))) | |
21491 | + return retval; | |
21492 | + | |
21493 | + count = (count < 0) ? -count : (count * channel->block_size); | |
21494 | + | |
21495 | + return ext2fs_file_write(data->file, buf, count, 0); | |
21496 | +} | |
21497 | + | |
21498 | +static errcode_t inode_write_byte(io_channel channel, unsigned long offset, | |
21499 | + int size, const void *buf) | |
21500 | +{ | |
21501 | + struct inode_private_data *data; | |
21502 | + errcode_t retval = 0; | |
21503 | + | |
21504 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21505 | + data = (struct inode_private_data *) channel->private_data; | |
21506 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); | |
21507 | + | |
21508 | + if ((retval = ext2fs_file_lseek(data->file, offset, | |
21509 | + EXT2_SEEK_SET, 0))) | |
21510 | + return retval; | |
21511 | + | |
21512 | + return ext2fs_file_write(data->file, buf, size, 0); | |
21513 | +} | |
21514 | + | |
21515 | +/* | |
21516 | + * Flush data buffers to disk. | |
21517 | + */ | |
21518 | +static errcode_t inode_flush(io_channel channel) | |
21519 | +{ | |
21520 | + struct inode_private_data *data; | |
21521 | + | |
21522 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21523 | + data = (struct inode_private_data *) channel->private_data; | |
21524 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); | |
21525 | + | |
21526 | + return ext2fs_file_flush(data->file); | |
21527 | +} | |
21528 | + | |
21529 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/io_manager.c busybox/e2fsprogs/ext2fs/io_manager.c | |
21530 | --- busybox-1.00/e2fsprogs/ext2fs/io_manager.c 1970-01-01 01:00:00.000000000 +0100 | |
21531 | +++ busybox/e2fsprogs/ext2fs/io_manager.c 2005-06-04 08:20:16.000000000 +0200 | |
21532 | @@ -0,0 +1,69 @@ | |
21533 | +/* | |
21534 | + * io_manager.c --- the I/O manager abstraction | |
21535 | + */ | |
21536 | + | |
21537 | +#include <stdio.h> | |
21538 | +#include <string.h> | |
21539 | +#if HAVE_UNISTD_H | |
21540 | +#include <unistd.h> | |
21541 | +#endif | |
21542 | +#include <fcntl.h> | |
21543 | +#include <time.h> | |
21544 | +#if HAVE_SYS_STAT_H | |
21545 | +#include <sys/stat.h> | |
21546 | +#endif | |
21547 | +#if HAVE_SYS_TYPES_H | |
21548 | +#include <sys/types.h> | |
21549 | +#endif | |
21550 | + | |
21551 | +#include "ext2_fs.h" | |
21552 | +#include "ext2fs.h" | |
21553 | + | |
21554 | +errcode_t io_channel_set_options(io_channel channel, const char *opts) | |
21555 | +{ | |
21556 | + errcode_t retval = 0; | |
21557 | + char *next, *ptr, *options, *arg; | |
21558 | + | |
21559 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21560 | + | |
21561 | + if (!opts) | |
21562 | + return 0; | |
21563 | + | |
21564 | + if (!channel->manager->set_option) | |
21565 | + return EXT2_ET_INVALID_ARGUMENT; | |
21566 | + | |
21567 | + options = malloc(strlen(opts)+1); | |
21568 | + if (!options) | |
21569 | + return EXT2_ET_NO_MEMORY; | |
21570 | + strcpy(options, opts); | |
21571 | + ptr = options; | |
21572 | + | |
21573 | + while (ptr && *ptr) { | |
21574 | + next = strchr(ptr, '&'); | |
21575 | + if (next) | |
21576 | + *next++ = 0; | |
21577 | + | |
21578 | + arg = strchr(ptr, '='); | |
21579 | + if (arg) | |
21580 | + *arg++ = 0; | |
21581 | + | |
21582 | + retval = (channel->manager->set_option)(channel, ptr, arg); | |
21583 | + if (retval) | |
21584 | + break; | |
21585 | + ptr = next; | |
21586 | + } | |
21587 | + free(options); | |
21588 | + return retval; | |
21589 | +} | |
21590 | + | |
21591 | +errcode_t io_channel_write_byte(io_channel channel, unsigned long offset, | |
21592 | + int count, const void *data) | |
21593 | +{ | |
21594 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
21595 | + | |
21596 | + if (channel->manager->write_byte) | |
21597 | + return channel->manager->write_byte(channel, offset, | |
21598 | + count, data); | |
21599 | + | |
21600 | + return EXT2_ET_UNIMPLEMENTED; | |
21601 | +} | |
21602 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/irel.h busybox/e2fsprogs/ext2fs/irel.h | |
21603 | --- busybox-1.00/e2fsprogs/ext2fs/irel.h 1970-01-01 01:00:00.000000000 +0100 | |
21604 | +++ busybox/e2fsprogs/ext2fs/irel.h 2005-06-04 08:20:16.000000000 +0200 | |
21605 | @@ -0,0 +1,114 @@ | |
21606 | +/* | |
21607 | + * irel.h | |
21608 | + * | |
21609 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
21610 | + * | |
21611 | + * %Begin-Header% | |
21612 | + * This file may be redistributed under the terms of the GNU Public | |
21613 | + * License. | |
21614 | + * %End-Header% | |
21615 | + */ | |
21616 | + | |
21617 | +struct ext2_inode_reference { | |
21618 | + blk_t block; | |
21619 | + __u16 offset; | |
21620 | +}; | |
21621 | + | |
21622 | +struct ext2_inode_relocate_entry { | |
21623 | + ext2_ino_t new; | |
21624 | + ext2_ino_t orig; | |
21625 | + __u16 flags; | |
21626 | + __u16 max_refs; | |
21627 | +}; | |
21628 | + | |
21629 | +typedef struct ext2_inode_relocation_table *ext2_irel; | |
21630 | + | |
21631 | +struct ext2_inode_relocation_table { | |
21632 | + __u32 magic; | |
21633 | + char *name; | |
21634 | + ext2_ino_t current; | |
21635 | + void *priv_data; | |
21636 | + | |
21637 | + /* | |
21638 | + * Add an inode relocation entry. | |
21639 | + */ | |
21640 | + errcode_t (*put)(ext2_irel irel, ext2_ino_t old, | |
21641 | + struct ext2_inode_relocate_entry *ent); | |
21642 | + /* | |
21643 | + * Get an inode relocation entry. | |
21644 | + */ | |
21645 | + errcode_t (*get)(ext2_irel irel, ext2_ino_t old, | |
21646 | + struct ext2_inode_relocate_entry *ent); | |
21647 | + | |
21648 | + /* | |
21649 | + * Get an inode relocation entry by its original inode number | |
21650 | + */ | |
21651 | + errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, | |
21652 | + struct ext2_inode_relocate_entry *ent); | |
21653 | + | |
21654 | + /* | |
21655 | + * Initialize for iterating over the inode relocation entries. | |
21656 | + */ | |
21657 | + errcode_t (*start_iter)(ext2_irel irel); | |
21658 | + | |
21659 | + /* | |
21660 | + * The iterator function for the inode relocation entries. | |
21661 | + * Returns an inode number of 0 when out of entries. | |
21662 | + */ | |
21663 | + errcode_t (*next)(ext2_irel irel, ext2_ino_t *old, | |
21664 | + struct ext2_inode_relocate_entry *ent); | |
21665 | + | |
21666 | + /* | |
21667 | + * Add an inode reference (i.e., note the fact that a | |
21668 | + * particular block/offset contains a reference to an inode) | |
21669 | + */ | |
21670 | + errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino, | |
21671 | + struct ext2_inode_reference *ref); | |
21672 | + | |
21673 | + /* | |
21674 | + * Initialize for iterating over the inode references for a | |
21675 | + * particular inode. | |
21676 | + */ | |
21677 | + errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino); | |
21678 | + | |
21679 | + /* | |
21680 | + * The iterator function for the inode references for an | |
21681 | + * inode. The references for only one inode can be interator | |
21682 | + * over at a time, as the iterator state is stored in ext2_irel. | |
21683 | + */ | |
21684 | + errcode_t (*next_ref)(ext2_irel irel, | |
21685 | + struct ext2_inode_reference *ref); | |
21686 | + | |
21687 | + /* | |
21688 | + * Move the inode relocation table from one inode number to | |
21689 | + * another. Note that the inode references also must move. | |
21690 | + */ | |
21691 | + errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); | |
21692 | + | |
21693 | + /* | |
21694 | + * Remove an inode relocation entry, along with all of the | |
21695 | + * inode references. | |
21696 | + */ | |
21697 | + errcode_t (*delete)(ext2_irel irel, ext2_ino_t old); | |
21698 | + | |
21699 | + /* | |
21700 | + * Free the inode relocation table. | |
21701 | + */ | |
21702 | + errcode_t (*free)(ext2_irel irel); | |
21703 | +}; | |
21704 | + | |
21705 | +errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, | |
21706 | + ext2_irel *irel); | |
21707 | + | |
21708 | +#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent)) | |
21709 | +#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent)) | |
21710 | +#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \ | |
21711 | + ((irel)->get_by_orig((irel), orig, old, ent)) | |
21712 | +#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel))) | |
21713 | +#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent)) | |
21714 | +#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref)) | |
21715 | +#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino)) | |
21716 | +#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref)) | |
21717 | +#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new)) | |
21718 | +#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old)) | |
21719 | +#define ext2fs_irel_free(irel) ((irel)->free((irel))) | |
21720 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/irel_ma.c busybox/e2fsprogs/ext2fs/irel_ma.c | |
21721 | --- busybox-1.00/e2fsprogs/ext2fs/irel_ma.c 1970-01-01 01:00:00.000000000 +0100 | |
21722 | +++ busybox/e2fsprogs/ext2fs/irel_ma.c 2005-06-04 08:20:16.000000000 +0200 | |
21723 | @@ -0,0 +1,372 @@ | |
21724 | +/* | |
21725 | + * irel_ma.c | |
21726 | + * | |
21727 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
21728 | + * | |
21729 | + * %Begin-Header% | |
21730 | + * This file may be redistributed under the terms of the GNU Public | |
21731 | + * License. | |
21732 | + * %End-Header% | |
21733 | + */ | |
21734 | + | |
21735 | +#include <fcntl.h> | |
21736 | +#include <stdio.h> | |
21737 | +#include <string.h> | |
21738 | +#if HAVE_UNISTD_H | |
21739 | +#include <unistd.h> | |
21740 | +#endif | |
21741 | +#if HAVE_ERRNO_H | |
21742 | +#include <errno.h> | |
21743 | +#endif | |
21744 | + | |
21745 | +#include "ext2_fs.h" | |
21746 | +#include "ext2fs.h" | |
21747 | +#include "irel.h" | |
21748 | + | |
21749 | +static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, | |
21750 | + struct ext2_inode_relocate_entry *ent); | |
21751 | +static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, | |
21752 | + struct ext2_inode_relocate_entry *ent); | |
21753 | +static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, | |
21754 | + struct ext2_inode_relocate_entry *ent); | |
21755 | +static errcode_t ima_start_iter(ext2_irel irel); | |
21756 | +static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, | |
21757 | + struct ext2_inode_relocate_entry *ent); | |
21758 | +static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, | |
21759 | + struct ext2_inode_reference *ref); | |
21760 | +static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino); | |
21761 | +static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref); | |
21762 | +static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); | |
21763 | +static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old); | |
21764 | +static errcode_t ima_free(ext2_irel irel); | |
21765 | + | |
21766 | +/* | |
21767 | + * This data structure stores the array of inode references; there is | |
21768 | + * a structure for each inode. | |
21769 | + */ | |
21770 | +struct inode_reference_entry { | |
21771 | + __u16 num; | |
21772 | + struct ext2_inode_reference *refs; | |
21773 | +}; | |
21774 | + | |
21775 | +struct irel_ma { | |
21776 | + __u32 magic; | |
21777 | + ext2_ino_t max_inode; | |
21778 | + ext2_ino_t ref_current; | |
21779 | + int ref_iter; | |
21780 | + ext2_ino_t *orig_map; | |
21781 | + struct ext2_inode_relocate_entry *entries; | |
21782 | + struct inode_reference_entry *ref_entries; | |
21783 | +}; | |
21784 | + | |
21785 | +errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, | |
21786 | + ext2_irel *new_irel) | |
21787 | +{ | |
21788 | + ext2_irel irel = 0; | |
21789 | + errcode_t retval; | |
21790 | + struct irel_ma *ma = 0; | |
21791 | + size_t size; | |
21792 | + | |
21793 | + *new_irel = 0; | |
21794 | + | |
21795 | + /* | |
21796 | + * Allocate memory structures | |
21797 | + */ | |
21798 | + retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table), | |
21799 | + &irel); | |
21800 | + if (retval) | |
21801 | + goto errout; | |
21802 | + memset(irel, 0, sizeof(struct ext2_inode_relocation_table)); | |
21803 | + | |
21804 | + retval = ext2fs_get_mem(strlen(name)+1, &irel->name); | |
21805 | + if (retval) | |
21806 | + goto errout; | |
21807 | + strcpy(irel->name, name); | |
21808 | + | |
21809 | + retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma); | |
21810 | + if (retval) | |
21811 | + goto errout; | |
21812 | + memset(ma, 0, sizeof(struct irel_ma)); | |
21813 | + irel->priv_data = ma; | |
21814 | + | |
21815 | + size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1)); | |
21816 | + retval = ext2fs_get_mem(size, &ma->orig_map); | |
21817 | + if (retval) | |
21818 | + goto errout; | |
21819 | + memset(ma->orig_map, 0, size); | |
21820 | + | |
21821 | + size = (size_t) (sizeof(struct ext2_inode_relocate_entry) * | |
21822 | + (max_inode+1)); | |
21823 | + retval = ext2fs_get_mem(size, &ma->entries); | |
21824 | + if (retval) | |
21825 | + goto errout; | |
21826 | + memset(ma->entries, 0, size); | |
21827 | + | |
21828 | + size = (size_t) (sizeof(struct inode_reference_entry) * | |
21829 | + (max_inode+1)); | |
21830 | + retval = ext2fs_get_mem(size, &ma->ref_entries); | |
21831 | + if (retval) | |
21832 | + goto errout; | |
21833 | + memset(ma->ref_entries, 0, size); | |
21834 | + ma->max_inode = max_inode; | |
21835 | + | |
21836 | + /* | |
21837 | + * Fill in the irel data structure | |
21838 | + */ | |
21839 | + irel->put = ima_put; | |
21840 | + irel->get = ima_get; | |
21841 | + irel->get_by_orig = ima_get_by_orig; | |
21842 | + irel->start_iter = ima_start_iter; | |
21843 | + irel->next = ima_next; | |
21844 | + irel->add_ref = ima_add_ref; | |
21845 | + irel->start_iter_ref = ima_start_iter_ref; | |
21846 | + irel->next_ref = ima_next_ref; | |
21847 | + irel->move = ima_move; | |
21848 | + irel->delete = ima_delete; | |
21849 | + irel->free = ima_free; | |
21850 | + | |
21851 | + *new_irel = irel; | |
21852 | + return 0; | |
21853 | + | |
21854 | +errout: | |
21855 | + ima_free(irel); | |
21856 | + return retval; | |
21857 | +} | |
21858 | + | |
21859 | +static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, | |
21860 | + struct ext2_inode_relocate_entry *ent) | |
21861 | +{ | |
21862 | + struct inode_reference_entry *ref_ent; | |
21863 | + struct irel_ma *ma; | |
21864 | + errcode_t retval; | |
21865 | + size_t size, old_size; | |
21866 | + | |
21867 | + ma = irel->priv_data; | |
21868 | + if (old > ma->max_inode) | |
21869 | + return EXT2_ET_INVALID_ARGUMENT; | |
21870 | + | |
21871 | + /* | |
21872 | + * Force the orig field to the correct value; the application | |
21873 | + * program shouldn't be messing with this field. | |
21874 | + */ | |
21875 | + if (ma->entries[(unsigned) old].new == 0) | |
21876 | + ent->orig = old; | |
21877 | + else | |
21878 | + ent->orig = ma->entries[(unsigned) old].orig; | |
21879 | + | |
21880 | + /* | |
21881 | + * If max_refs has changed, reallocate the refs array | |
21882 | + */ | |
21883 | + ref_ent = ma->ref_entries + (unsigned) old; | |
21884 | + if (ref_ent->refs && ent->max_refs != | |
21885 | + ma->entries[(unsigned) old].max_refs) { | |
21886 | + size = (sizeof(struct ext2_inode_reference) * ent->max_refs); | |
21887 | + old_size = (sizeof(struct ext2_inode_reference) * | |
21888 | + ma->entries[(unsigned) old].max_refs); | |
21889 | + retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs); | |
21890 | + if (retval) | |
21891 | + return retval; | |
21892 | + } | |
21893 | + | |
21894 | + ma->entries[(unsigned) old] = *ent; | |
21895 | + ma->orig_map[(unsigned) ent->orig] = old; | |
21896 | + return 0; | |
21897 | +} | |
21898 | + | |
21899 | +static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, | |
21900 | + struct ext2_inode_relocate_entry *ent) | |
21901 | +{ | |
21902 | + struct irel_ma *ma; | |
21903 | + | |
21904 | + ma = irel->priv_data; | |
21905 | + if (old > ma->max_inode) | |
21906 | + return EXT2_ET_INVALID_ARGUMENT; | |
21907 | + if (ma->entries[(unsigned) old].new == 0) | |
21908 | + return ENOENT; | |
21909 | + *ent = ma->entries[(unsigned) old]; | |
21910 | + return 0; | |
21911 | +} | |
21912 | + | |
21913 | +static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, | |
21914 | + struct ext2_inode_relocate_entry *ent) | |
21915 | +{ | |
21916 | + struct irel_ma *ma; | |
21917 | + ext2_ino_t ino; | |
21918 | + | |
21919 | + ma = irel->priv_data; | |
21920 | + if (orig > ma->max_inode) | |
21921 | + return EXT2_ET_INVALID_ARGUMENT; | |
21922 | + ino = ma->orig_map[(unsigned) orig]; | |
21923 | + if (ino == 0) | |
21924 | + return ENOENT; | |
21925 | + *old = ino; | |
21926 | + *ent = ma->entries[(unsigned) ino]; | |
21927 | + return 0; | |
21928 | +} | |
21929 | + | |
21930 | +static errcode_t ima_start_iter(ext2_irel irel) | |
21931 | +{ | |
21932 | + irel->current = 0; | |
21933 | + return 0; | |
21934 | +} | |
21935 | + | |
21936 | +static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, | |
21937 | + struct ext2_inode_relocate_entry *ent) | |
21938 | +{ | |
21939 | + struct irel_ma *ma; | |
21940 | + | |
21941 | + ma = irel->priv_data; | |
21942 | + while (++irel->current < ma->max_inode) { | |
21943 | + if (ma->entries[(unsigned) irel->current].new == 0) | |
21944 | + continue; | |
21945 | + *old = irel->current; | |
21946 | + *ent = ma->entries[(unsigned) irel->current]; | |
21947 | + return 0; | |
21948 | + } | |
21949 | + *old = 0; | |
21950 | + return 0; | |
21951 | +} | |
21952 | + | |
21953 | +static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, | |
21954 | + struct ext2_inode_reference *ref) | |
21955 | +{ | |
21956 | + struct irel_ma *ma; | |
21957 | + size_t size; | |
21958 | + struct inode_reference_entry *ref_ent; | |
21959 | + struct ext2_inode_relocate_entry *ent; | |
21960 | + errcode_t retval; | |
21961 | + | |
21962 | + ma = irel->priv_data; | |
21963 | + if (ino > ma->max_inode) | |
21964 | + return EXT2_ET_INVALID_ARGUMENT; | |
21965 | + | |
21966 | + ref_ent = ma->ref_entries + (unsigned) ino; | |
21967 | + ent = ma->entries + (unsigned) ino; | |
21968 | + | |
21969 | + /* | |
21970 | + * If the inode reference array doesn't exist, create it. | |
21971 | + */ | |
21972 | + if (ref_ent->refs == 0) { | |
21973 | + size = (size_t) ((sizeof(struct ext2_inode_reference) * | |
21974 | + ent->max_refs)); | |
21975 | + retval = ext2fs_get_mem(size, &ref_ent->refs); | |
21976 | + if (retval) | |
21977 | + return retval; | |
21978 | + memset(ref_ent->refs, 0, size); | |
21979 | + ref_ent->num = 0; | |
21980 | + } | |
21981 | + | |
21982 | + if (ref_ent->num >= ent->max_refs) | |
21983 | + return EXT2_ET_TOO_MANY_REFS; | |
21984 | + | |
21985 | + ref_ent->refs[(unsigned) ref_ent->num++] = *ref; | |
21986 | + return 0; | |
21987 | +} | |
21988 | + | |
21989 | +static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) | |
21990 | +{ | |
21991 | + struct irel_ma *ma; | |
21992 | + | |
21993 | + ma = irel->priv_data; | |
21994 | + if (ino > ma->max_inode) | |
21995 | + return EXT2_ET_INVALID_ARGUMENT; | |
21996 | + if (ma->entries[(unsigned) ino].new == 0) | |
21997 | + return ENOENT; | |
21998 | + ma->ref_current = ino; | |
21999 | + ma->ref_iter = 0; | |
22000 | + return 0; | |
22001 | +} | |
22002 | + | |
22003 | +static errcode_t ima_next_ref(ext2_irel irel, | |
22004 | + struct ext2_inode_reference *ref) | |
22005 | +{ | |
22006 | + struct irel_ma *ma; | |
22007 | + struct inode_reference_entry *ref_ent; | |
22008 | + | |
22009 | + ma = irel->priv_data; | |
22010 | + | |
22011 | + ref_ent = ma->ref_entries + ma->ref_current; | |
22012 | + | |
22013 | + if ((ref_ent->refs == NULL) || | |
22014 | + (ma->ref_iter >= ref_ent->num)) { | |
22015 | + ref->block = 0; | |
22016 | + ref->offset = 0; | |
22017 | + return 0; | |
22018 | + } | |
22019 | + *ref = ref_ent->refs[ma->ref_iter++]; | |
22020 | + return 0; | |
22021 | +} | |
22022 | + | |
22023 | + | |
22024 | +static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) | |
22025 | +{ | |
22026 | + struct irel_ma *ma; | |
22027 | + | |
22028 | + ma = irel->priv_data; | |
22029 | + if ((old > ma->max_inode) || (new > ma->max_inode)) | |
22030 | + return EXT2_ET_INVALID_ARGUMENT; | |
22031 | + if (ma->entries[(unsigned) old].new == 0) | |
22032 | + return ENOENT; | |
22033 | + | |
22034 | + ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; | |
22035 | + if (ma->ref_entries[(unsigned) new].refs) | |
22036 | + ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs); | |
22037 | + ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; | |
22038 | + | |
22039 | + ma->entries[(unsigned) old].new = 0; | |
22040 | + ma->ref_entries[(unsigned) old].num = 0; | |
22041 | + ma->ref_entries[(unsigned) old].refs = 0; | |
22042 | + | |
22043 | + ma->orig_map[ma->entries[new].orig] = new; | |
22044 | + return 0; | |
22045 | +} | |
22046 | + | |
22047 | +static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) | |
22048 | +{ | |
22049 | + struct irel_ma *ma; | |
22050 | + | |
22051 | + ma = irel->priv_data; | |
22052 | + if (old > ma->max_inode) | |
22053 | + return EXT2_ET_INVALID_ARGUMENT; | |
22054 | + if (ma->entries[(unsigned) old].new == 0) | |
22055 | + return ENOENT; | |
22056 | + | |
22057 | + ma->entries[old].new = 0; | |
22058 | + if (ma->ref_entries[(unsigned) old].refs) | |
22059 | + ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs); | |
22060 | + ma->orig_map[ma->entries[(unsigned) old].orig] = 0; | |
22061 | + | |
22062 | + ma->ref_entries[(unsigned) old].num = 0; | |
22063 | + ma->ref_entries[(unsigned) old].refs = 0; | |
22064 | + return 0; | |
22065 | +} | |
22066 | + | |
22067 | +static errcode_t ima_free(ext2_irel irel) | |
22068 | +{ | |
22069 | + struct irel_ma *ma; | |
22070 | + ext2_ino_t ino; | |
22071 | + | |
22072 | + if (!irel) | |
22073 | + return 0; | |
22074 | + | |
22075 | + ma = irel->priv_data; | |
22076 | + | |
22077 | + if (ma) { | |
22078 | + if (ma->orig_map) | |
22079 | + ext2fs_free_mem(&ma->orig_map); | |
22080 | + if (ma->entries) | |
22081 | + ext2fs_free_mem(&ma->entries); | |
22082 | + if (ma->ref_entries) { | |
22083 | + for (ino = 0; ino <= ma->max_inode; ino++) { | |
22084 | + if (ma->ref_entries[(unsigned) ino].refs) | |
22085 | + ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs); | |
22086 | + } | |
22087 | + ext2fs_free_mem(&ma->ref_entries); | |
22088 | + } | |
22089 | + ext2fs_free_mem(&ma); | |
22090 | + } | |
22091 | + if (irel->name) | |
22092 | + ext2fs_free_mem(&irel->name); | |
22093 | + ext2fs_free_mem(&irel); | |
22094 | + return 0; | |
22095 | +} | |
22096 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/ismounted.c busybox/e2fsprogs/ext2fs/ismounted.c | |
22097 | --- busybox-1.00/e2fsprogs/ext2fs/ismounted.c 1970-01-01 01:00:00.000000000 +0100 | |
22098 | +++ busybox/e2fsprogs/ext2fs/ismounted.c 2005-06-04 08:20:16.000000000 +0200 | |
22099 | @@ -0,0 +1,358 @@ | |
22100 | +/* | |
22101 | + * ismounted.c --- Check to see if the filesystem was mounted | |
22102 | + * | |
22103 | + * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o. | |
22104 | + * | |
22105 | + * %Begin-Header% | |
22106 | + * This file may be redistributed under the terms of the GNU Public | |
22107 | + * License. | |
22108 | + * %End-Header% | |
22109 | + */ | |
22110 | + | |
22111 | +#include <stdio.h> | |
22112 | +#if HAVE_UNISTD_H | |
22113 | +#include <unistd.h> | |
22114 | +#endif | |
22115 | +#if HAVE_ERRNO_H | |
22116 | +#include <errno.h> | |
22117 | +#endif | |
22118 | +#include <fcntl.h> | |
22119 | +#ifdef HAVE_LINUX_FD_H | |
22120 | +#include <linux/fd.h> | |
22121 | +#endif | |
22122 | +#ifdef HAVE_MNTENT_H | |
22123 | +#include <mntent.h> | |
22124 | +#endif | |
22125 | +#ifdef HAVE_GETMNTINFO | |
22126 | +#include <paths.h> | |
22127 | +#include <sys/param.h> | |
22128 | +#include <sys/mount.h> | |
22129 | +#endif /* HAVE_GETMNTINFO */ | |
22130 | +#include <string.h> | |
22131 | +#include <sys/stat.h> | |
22132 | + | |
22133 | +#include "ext2_fs.h" | |
22134 | +#include "ext2fs.h" | |
22135 | + | |
22136 | +#ifdef HAVE_MNTENT_H | |
22137 | +/* | |
22138 | + * Helper function which checks a file in /etc/mtab format to see if a | |
22139 | + * filesystem is mounted. Returns an error if the file doesn't exist | |
22140 | + * or can't be opened. | |
22141 | + */ | |
22142 | +static errcode_t check_mntent_file(const char *mtab_file, const char *file, | |
22143 | + int *mount_flags, char *mtpt, int mtlen) | |
22144 | +{ | |
22145 | + struct mntent *mnt; | |
22146 | + struct stat st_buf; | |
22147 | + errcode_t retval = 0; | |
22148 | + dev_t file_dev=0, file_rdev=0; | |
22149 | + ino_t file_ino=0; | |
22150 | + FILE *f; | |
22151 | + int fd; | |
22152 | + | |
22153 | + *mount_flags = 0; | |
22154 | + if ((f = setmntent (mtab_file, "r")) == NULL) | |
22155 | + return errno; | |
22156 | + if (stat(file, &st_buf) == 0) { | |
22157 | + if (S_ISBLK(st_buf.st_mode)) { | |
22158 | +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ | |
22159 | + file_rdev = st_buf.st_rdev; | |
22160 | +#endif /* __GNU__ */ | |
22161 | + } else { | |
22162 | + file_dev = st_buf.st_dev; | |
22163 | + file_ino = st_buf.st_ino; | |
22164 | + } | |
22165 | + } | |
22166 | + while ((mnt = getmntent (f)) != NULL) { | |
22167 | + if (strcmp(file, mnt->mnt_fsname) == 0) | |
22168 | + break; | |
22169 | + if (stat(mnt->mnt_fsname, &st_buf) == 0) { | |
22170 | + if (S_ISBLK(st_buf.st_mode)) { | |
22171 | +#ifndef __GNU__ | |
22172 | + if (file_rdev && (file_rdev == st_buf.st_rdev)) | |
22173 | + break; | |
22174 | +#endif /* __GNU__ */ | |
22175 | + } else { | |
22176 | + if (file_dev && ((file_dev == st_buf.st_dev) && | |
22177 | + (file_ino == st_buf.st_ino))) | |
22178 | + break; | |
22179 | + } | |
22180 | + } | |
22181 | + } | |
22182 | + | |
22183 | + if (mnt == 0) { | |
22184 | +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ | |
22185 | + /* | |
22186 | + * Do an extra check to see if this is the root device. We | |
22187 | + * can't trust /etc/mtab, and /proc/mounts will only list | |
22188 | + * /dev/root for the root filesystem. Argh. Instead we | |
22189 | + * check if the given device has the same major/minor number | |
22190 | + * as the device that the root directory is on. | |
22191 | + */ | |
22192 | + if (file_rdev && stat("/", &st_buf) == 0) { | |
22193 | + if (st_buf.st_dev == file_rdev) { | |
22194 | + *mount_flags = EXT2_MF_MOUNTED; | |
22195 | + if (mtpt) | |
22196 | + strncpy(mtpt, "/", mtlen); | |
22197 | + goto is_root; | |
22198 | + } | |
22199 | + } | |
22200 | +#endif /* __GNU__ */ | |
22201 | + goto errout; | |
22202 | + } | |
22203 | +#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */ | |
22204 | + /* Validate the entry in case /etc/mtab is out of date */ | |
22205 | + /* | |
22206 | + * We need to be paranoid, because some broken distributions | |
22207 | + * (read: Slackware) don't initialize /etc/mtab before checking | |
22208 | + * all of the non-root filesystems on the disk. | |
22209 | + */ | |
22210 | + if (stat(mnt->mnt_dir, &st_buf) < 0) { | |
22211 | + retval = errno; | |
22212 | + if (retval == ENOENT) { | |
22213 | +#ifdef DEBUG | |
22214 | + printf("Bogus entry in %s! (%s does not exist)\n", | |
22215 | + mtab_file, mnt->mnt_dir); | |
22216 | +#endif /* DEBUG */ | |
22217 | + retval = 0; | |
22218 | + } | |
22219 | + goto errout; | |
22220 | + } | |
22221 | + if (file_rdev && (st_buf.st_dev != file_rdev)) { | |
22222 | +#ifdef DEBUG | |
22223 | + printf("Bogus entry in %s! (%s not mounted on %s)\n", | |
22224 | + mtab_file, file, mnt->mnt_dir); | |
22225 | +#endif /* DEBUG */ | |
22226 | + goto errout; | |
22227 | + } | |
22228 | +#endif /* __GNU__ */ | |
22229 | + *mount_flags = EXT2_MF_MOUNTED; | |
22230 | + | |
22231 | +#ifdef MNTOPT_RO | |
22232 | + /* Check to see if the ro option is set */ | |
22233 | + if (hasmntopt(mnt, MNTOPT_RO)) | |
22234 | + *mount_flags |= EXT2_MF_READONLY; | |
22235 | +#endif | |
22236 | + | |
22237 | + if (mtpt) | |
22238 | + strncpy(mtpt, mnt->mnt_dir, mtlen); | |
22239 | + /* | |
22240 | + * Check to see if we're referring to the root filesystem. | |
22241 | + * If so, do a manual check to see if we can open /etc/mtab | |
22242 | + * read/write, since if the root is mounted read/only, the | |
22243 | + * contents of /etc/mtab may not be accurate. | |
22244 | + */ | |
22245 | + if (!strcmp(mnt->mnt_dir, "/")) { | |
22246 | +is_root: | |
22247 | +#define TEST_FILE "/.ismount-test-file" | |
22248 | + *mount_flags |= EXT2_MF_ISROOT; | |
22249 | + fd = open(TEST_FILE, O_RDWR|O_CREAT); | |
22250 | + if (fd < 0) { | |
22251 | + if (errno == EROFS) | |
22252 | + *mount_flags |= EXT2_MF_READONLY; | |
22253 | + } else | |
22254 | + close(fd); | |
22255 | + (void) unlink(TEST_FILE); | |
22256 | + } | |
22257 | + retval = 0; | |
22258 | +errout: | |
22259 | + endmntent (f); | |
22260 | + return retval; | |
22261 | +} | |
22262 | + | |
22263 | +static errcode_t check_mntent(const char *file, int *mount_flags, | |
22264 | + char *mtpt, int mtlen) | |
22265 | +{ | |
22266 | + errcode_t retval; | |
22267 | + | |
22268 | +#ifdef DEBUG | |
22269 | + retval = check_mntent_file("/tmp/mtab", file, mount_flags, | |
22270 | + mtpt, mtlen); | |
22271 | + if (retval == 0) | |
22272 | + return 0; | |
22273 | +#endif /* DEBUG */ | |
22274 | +#ifdef __linux__ | |
22275 | + retval = check_mntent_file("/proc/mounts", file, mount_flags, | |
22276 | + mtpt, mtlen); | |
22277 | + if (retval == 0 && (*mount_flags != 0)) | |
22278 | + return 0; | |
22279 | +#endif /* __linux__ */ | |
22280 | +#if defined(MOUNTED) || defined(_PATH_MOUNTED) | |
22281 | +#ifndef MOUNTED | |
22282 | +#define MOUNTED _PATH_MOUNTED | |
22283 | +#endif /* MOUNTED */ | |
22284 | + retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen); | |
22285 | + return retval; | |
22286 | +#else | |
22287 | + *mount_flags = 0; | |
22288 | + return 0; | |
22289 | +#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */ | |
22290 | +} | |
22291 | + | |
22292 | +#else | |
22293 | +#if defined(HAVE_GETMNTINFO) | |
22294 | + | |
22295 | +static errcode_t check_getmntinfo(const char *file, int *mount_flags, | |
22296 | + char *mtpt, int mtlen) | |
22297 | +{ | |
22298 | + struct statfs *mp; | |
22299 | + int len, n; | |
22300 | + const char *s1; | |
22301 | + char *s2; | |
22302 | + | |
22303 | + n = getmntinfo(&mp, MNT_NOWAIT); | |
22304 | + if (n == 0) | |
22305 | + return errno; | |
22306 | + | |
22307 | + len = sizeof(_PATH_DEV) - 1; | |
22308 | + s1 = file; | |
22309 | + if (strncmp(_PATH_DEV, s1, len) == 0) | |
22310 | + s1 += len; | |
22311 | + | |
22312 | + *mount_flags = 0; | |
22313 | + while (--n >= 0) { | |
22314 | + s2 = mp->f_mntfromname; | |
22315 | + if (strncmp(_PATH_DEV, s2, len) == 0) { | |
22316 | + s2 += len - 1; | |
22317 | + *s2 = 'r'; | |
22318 | + } | |
22319 | + if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) { | |
22320 | + *mount_flags = EXT2_MF_MOUNTED; | |
22321 | + break; | |
22322 | + } | |
22323 | + ++mp; | |
22324 | + } | |
22325 | + if (mtpt) | |
22326 | + strncpy(mtpt, mp->f_mntonname, mtlen); | |
22327 | + return 0; | |
22328 | +} | |
22329 | +#endif /* HAVE_GETMNTINFO */ | |
22330 | +#endif /* HAVE_MNTENT_H */ | |
22331 | + | |
22332 | +/* | |
22333 | + * Check to see if we're dealing with the swap device. | |
22334 | + */ | |
22335 | +static int is_swap_device(const char *file) | |
22336 | +{ | |
22337 | + FILE *f; | |
22338 | + char buf[1024], *cp; | |
22339 | + dev_t file_dev; | |
22340 | + struct stat st_buf; | |
22341 | + int ret = 0; | |
22342 | + | |
22343 | + file_dev = 0; | |
22344 | +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ | |
22345 | + if ((stat(file, &st_buf) == 0) && | |
22346 | + S_ISBLK(st_buf.st_mode)) | |
22347 | + file_dev = st_buf.st_rdev; | |
22348 | +#endif /* __GNU__ */ | |
22349 | + | |
22350 | + if (!(f = fopen("/proc/swaps", "r"))) | |
22351 | + return 0; | |
22352 | + /* Skip the first line */ | |
22353 | + fgets(buf, sizeof(buf), f); | |
22354 | + while (!feof(f)) { | |
22355 | + if (!fgets(buf, sizeof(buf), f)) | |
22356 | + break; | |
22357 | + if ((cp = strchr(buf, ' ')) != NULL) | |
22358 | + *cp = 0; | |
22359 | + if ((cp = strchr(buf, '\t')) != NULL) | |
22360 | + *cp = 0; | |
22361 | + if (strcmp(buf, file) == 0) { | |
22362 | + ret++; | |
22363 | + break; | |
22364 | + } | |
22365 | +#ifndef __GNU__ | |
22366 | + if (file_dev && (stat(buf, &st_buf) == 0) && | |
22367 | + S_ISBLK(st_buf.st_mode) && | |
22368 | + file_dev == st_buf.st_rdev) { | |
22369 | + ret++; | |
22370 | + break; | |
22371 | + } | |
22372 | +#endif /* __GNU__ */ | |
22373 | + } | |
22374 | + fclose(f); | |
22375 | + return ret; | |
22376 | +} | |
22377 | + | |
22378 | + | |
22379 | +/* | |
22380 | + * ext2fs_check_mount_point() returns 1 if the device is mounted, 0 | |
22381 | + * otherwise. If mtpt is non-NULL, the directory where the device is | |
22382 | + * mounted is copied to where mtpt is pointing, up to mtlen | |
22383 | + * characters. | |
22384 | + */ | |
22385 | +#ifdef __TURBOC__ | |
22386 | + #pragma argsused | |
22387 | +#endif | |
22388 | +errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, | |
22389 | + char *mtpt, int mtlen) | |
22390 | +{ | |
22391 | + if (is_swap_device(device)) { | |
22392 | + *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP; | |
22393 | + strncpy(mtpt, "<swap>", mtlen); | |
22394 | + return 0; | |
22395 | + } | |
22396 | +#ifdef HAVE_MNTENT_H | |
22397 | + return check_mntent(device, mount_flags, mtpt, mtlen); | |
22398 | +#else | |
22399 | +#ifdef HAVE_GETMNTINFO | |
22400 | + return check_getmntinfo(device, mount_flags, mtpt, mtlen); | |
22401 | +#else | |
22402 | +#ifdef __GNUC__ | |
22403 | + #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!" | |
22404 | +#endif | |
22405 | + *mount_flags = 0; | |
22406 | + return 0; | |
22407 | +#endif /* HAVE_GETMNTINFO */ | |
22408 | +#endif /* HAVE_MNTENT_H */ | |
22409 | +} | |
22410 | + | |
22411 | +/* | |
22412 | + * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED, | |
22413 | + * EXT2_MF_READONLY, and EXT2_MF_ROOT | |
22414 | + * | |
22415 | + */ | |
22416 | +errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags) | |
22417 | +{ | |
22418 | + return ext2fs_check_mount_point(file, mount_flags, NULL, 0); | |
22419 | +} | |
22420 | + | |
22421 | +#ifdef DEBUG | |
22422 | +int main(int argc, char **argv) | |
22423 | +{ | |
22424 | + int retval, mount_flags; | |
22425 | + char mntpt[80]; | |
22426 | + | |
22427 | + if (argc < 2) { | |
22428 | + fprintf(stderr, "Usage: %s device\n", argv[0]); | |
22429 | + exit(1); | |
22430 | + } | |
22431 | + | |
22432 | + mntpt[0] = 0; | |
22433 | + retval = ext2fs_check_mount_point(argv[1], &mount_flags, | |
22434 | + mntpt, sizeof(mntpt)); | |
22435 | + if (retval) { | |
22436 | + com_err(argv[0], retval, | |
22437 | + "while calling ext2fs_check_if_mounted"); | |
22438 | + exit(1); | |
22439 | + } | |
22440 | + printf("Device %s reports flags %02x\n", argv[1], mount_flags); | |
22441 | + if (mount_flags & EXT2_MF_MOUNTED) | |
22442 | + printf("\t%s is mounted.\n", argv[1]); | |
22443 | + | |
22444 | + if (mount_flags & EXT2_MF_SWAP) | |
22445 | + printf("\t%s is a swap device.\n", argv[1]); | |
22446 | + | |
22447 | + if (mount_flags & EXT2_MF_READONLY) | |
22448 | + printf("\t%s is read-only.\n", argv[1]); | |
22449 | + | |
22450 | + if (mount_flags & EXT2_MF_ISROOT) | |
22451 | + printf("\t%s is the root filesystem.\n", argv[1]); | |
22452 | + if (mntpt[0]) | |
22453 | + printf("\t%s is mounted on %s.\n", argv[1], mntpt); | |
22454 | + | |
22455 | + exit(0); | |
22456 | +} | |
22457 | +#endif /* DEBUG */ | |
22458 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/jfs_compat.h busybox/e2fsprogs/ext2fs/jfs_compat.h | |
22459 | --- busybox-1.00/e2fsprogs/ext2fs/jfs_compat.h 1970-01-01 01:00:00.000000000 +0100 | |
22460 | +++ busybox/e2fsprogs/ext2fs/jfs_compat.h 2005-06-04 08:20:16.000000000 +0200 | |
22461 | @@ -0,0 +1,67 @@ | |
22462 | + | |
22463 | +#ifndef _JFS_COMPAT_H | |
22464 | +#define _JFS_COMPAT_H | |
22465 | + | |
22466 | +#include "kernel-list.h" | |
22467 | +#include <errno.h> | |
22468 | +#ifdef HAVE_NETINET_IN_H | |
22469 | +#include <netinet/in.h> | |
22470 | +#endif | |
22471 | + | |
22472 | +#define printk printf | |
22473 | +#define KERN_ERR "" | |
22474 | +#define KERN_DEBUG "" | |
22475 | + | |
22476 | +#define READ 0 | |
22477 | +#define WRITE 1 | |
22478 | + | |
22479 | +#define cpu_to_be32(n) htonl(n) | |
22480 | +#define be32_to_cpu(n) ntohl(n) | |
22481 | + | |
22482 | +typedef unsigned int tid_t; | |
22483 | +typedef struct journal_s journal_t; | |
22484 | + | |
22485 | +struct buffer_head; | |
22486 | +struct inode; | |
22487 | + | |
22488 | +struct journal_s | |
22489 | +{ | |
22490 | + unsigned long j_flags; | |
22491 | + int j_errno; | |
22492 | + struct buffer_head * j_sb_buffer; | |
22493 | + struct journal_superblock_s *j_superblock; | |
22494 | + int j_format_version; | |
22495 | + unsigned long j_head; | |
22496 | + unsigned long j_tail; | |
22497 | + unsigned long j_free; | |
22498 | + unsigned long j_first, j_last; | |
22499 | + kdev_t j_dev; | |
22500 | + kdev_t j_fs_dev; | |
22501 | + int j_blocksize; | |
22502 | + unsigned int j_blk_offset; | |
22503 | + unsigned int j_maxlen; | |
22504 | + struct inode * j_inode; | |
22505 | + tid_t j_tail_sequence; | |
22506 | + tid_t j_transaction_sequence; | |
22507 | + __u8 j_uuid[16]; | |
22508 | + struct jbd_revoke_table_s *j_revoke; | |
22509 | +}; | |
22510 | + | |
22511 | +#define J_ASSERT(assert) \ | |
22512 | + do { if (!(assert)) { \ | |
22513 | + printf ("Assertion failure in %s() at %s line %d: " \ | |
22514 | + "\"%s\"\n", \ | |
22515 | + __FUNCTION__, __FILE__, __LINE__, # assert); \ | |
22516 | + fatal_error(e2fsck_global_ctx, 0); \ | |
22517 | + } } while (0) | |
22518 | + | |
22519 | +#define is_journal_abort(x) 0 | |
22520 | + | |
22521 | +#define BUFFER_TRACE(bh, info) do {} while (0) | |
22522 | + | |
22523 | +/* Need this so we can compile with configure --enable-gcc-wall */ | |
22524 | +#ifdef NO_INLINE_FUNCS | |
22525 | +#define inline | |
22526 | +#endif | |
22527 | + | |
22528 | +#endif /* _JFS_COMPAT_H */ | |
22529 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/jfs_dat.h busybox/e2fsprogs/ext2fs/jfs_dat.h | |
22530 | --- busybox-1.00/e2fsprogs/ext2fs/jfs_dat.h 1970-01-01 01:00:00.000000000 +0100 | |
22531 | +++ busybox/e2fsprogs/ext2fs/jfs_dat.h 2005-06-04 08:20:16.000000000 +0200 | |
22532 | @@ -0,0 +1,64 @@ | |
22533 | +/* | |
22534 | + * jfs_dat.h --- stripped down header file which only contains the JFS | |
22535 | + * on-disk data structures | |
22536 | + */ | |
22537 | + | |
22538 | +#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ | |
22539 | + | |
22540 | +/* | |
22541 | + * On-disk structures | |
22542 | + */ | |
22543 | + | |
22544 | +/* | |
22545 | + * Descriptor block types: | |
22546 | + */ | |
22547 | + | |
22548 | +#define JFS_DESCRIPTOR_BLOCK 1 | |
22549 | +#define JFS_COMMIT_BLOCK 2 | |
22550 | +#define JFS_SUPERBLOCK 3 | |
22551 | + | |
22552 | +/* | |
22553 | + * Standard header for all descriptor blocks: | |
22554 | + */ | |
22555 | +typedef struct journal_header_s | |
22556 | +{ | |
22557 | + __u32 h_magic; | |
22558 | + __u32 h_blocktype; | |
22559 | + __u32 h_sequence; | |
22560 | +} journal_header_t; | |
22561 | + | |
22562 | + | |
22563 | +/* | |
22564 | + * The block tag: used to describe a single buffer in the journal | |
22565 | + */ | |
22566 | +typedef struct journal_block_tag_s | |
22567 | +{ | |
22568 | + __u32 t_blocknr; /* The on-disk block number */ | |
22569 | + __u32 t_flags; /* See below */ | |
22570 | +} journal_block_tag_t; | |
22571 | + | |
22572 | +/* Definitions for the journal tag flags word: */ | |
22573 | +#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ | |
22574 | +#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ | |
22575 | +#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ | |
22576 | +#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ | |
22577 | + | |
22578 | + | |
22579 | +/* | |
22580 | + * The journal superblock | |
22581 | + */ | |
22582 | +typedef struct journal_superblock_s | |
22583 | +{ | |
22584 | + journal_header_t s_header; | |
22585 | + | |
22586 | + /* Static information describing the journal */ | |
22587 | + __u32 s_blocksize; /* journal device blocksize */ | |
22588 | + __u32 s_maxlen; /* total blocks in journal file */ | |
22589 | + __u32 s_first; /* first block of log information */ | |
22590 | + | |
22591 | + /* Dynamic information describing the current state of the log */ | |
22592 | + __u32 s_sequence; /* first commit ID expected in log */ | |
22593 | + __u32 s_start; /* blocknr of start of log */ | |
22594 | + | |
22595 | +} journal_superblock_t; | |
22596 | + | |
22597 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/jfs_user.h busybox/e2fsprogs/ext2fs/jfs_user.h | |
22598 | --- busybox-1.00/e2fsprogs/ext2fs/jfs_user.h 1970-01-01 01:00:00.000000000 +0100 | |
22599 | +++ busybox/e2fsprogs/ext2fs/jfs_user.h 2005-06-04 08:20:16.000000000 +0200 | |
22600 | @@ -0,0 +1,8 @@ | |
22601 | +#ifndef _JFS_USER_H | |
22602 | +#define _JFS_USER_H | |
22603 | + | |
22604 | +typedef unsigned short kdev_t; | |
22605 | + | |
22606 | +#include "kernel-jbd.h" | |
22607 | + | |
22608 | +#endif /* _JFS_USER_H */ | |
22609 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/kernel-jbd.h busybox/e2fsprogs/ext2fs/kernel-jbd.h | |
22610 | --- busybox-1.00/e2fsprogs/ext2fs/kernel-jbd.h 1970-01-01 01:00:00.000000000 +0100 | |
22611 | +++ busybox/e2fsprogs/ext2fs/kernel-jbd.h 2005-06-04 08:20:16.000000000 +0200 | |
22612 | @@ -0,0 +1,910 @@ | |
22613 | +/* | |
22614 | + * linux/include/linux/jbd.h | |
22615 | + * | |
22616 | + * Written by Stephen C. Tweedie <sct@redhat.com> | |
22617 | + * | |
22618 | + * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved | |
22619 | + * | |
22620 | + * This file is part of the Linux kernel and is made available under | |
22621 | + * the terms of the GNU General Public License, version 2, or at your | |
22622 | + * option, any later version, incorporated herein by reference. | |
22623 | + * | |
22624 | + * Definitions for transaction data structures for the buffer cache | |
22625 | + * filesystem journaling support. | |
22626 | + */ | |
22627 | + | |
22628 | +#ifndef _LINUX_JBD_H | |
22629 | +#define _LINUX_JBD_H | |
22630 | + | |
22631 | +#if defined(CONFIG_JBD) || defined(CONFIG_JBD_MODULE) || !defined(__KERNEL__) | |
22632 | + | |
22633 | +/* Allow this file to be included directly into e2fsprogs */ | |
22634 | +#ifndef __KERNEL__ | |
22635 | +#include "jfs_compat.h" | |
22636 | +#define JFS_DEBUG | |
22637 | +#define jfs_debug jbd_debug | |
22638 | +#else | |
22639 | + | |
22640 | +#include <linux/journal-head.h> | |
22641 | +#include <linux/stddef.h> | |
22642 | +#include <asm/semaphore.h> | |
22643 | +#endif | |
22644 | + | |
22645 | +#ifndef __GNUC__ | |
22646 | +#define __FUNCTION__ "" | |
22647 | +#endif | |
22648 | + | |
22649 | +#define journal_oom_retry 1 | |
22650 | + | |
22651 | +#ifdef __STDC__ | |
22652 | +#ifdef __CONFIG_JBD_DEBUG__E2FS | |
22653 | +/* | |
22654 | + * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal | |
22655 | + * consistency checks. By default we don't do this unless | |
22656 | + * __CONFIG_JBD_DEBUG__E2FS is on. | |
22657 | + */ | |
22658 | +#define JBD_EXPENSIVE_CHECKING | |
22659 | +extern int journal_enable_debug; | |
22660 | + | |
22661 | +#define jbd_debug(n, f, a...) \ | |
22662 | + do { \ | |
22663 | + if ((n) <= journal_enable_debug) { \ | |
22664 | + printk (KERN_DEBUG "(%s, %d): %s: ", \ | |
22665 | + __FILE__, __LINE__, __FUNCTION__); \ | |
22666 | + printk (f, ## a); \ | |
22667 | + } \ | |
22668 | + } while (0) | |
22669 | +#else | |
22670 | +#ifdef __GNUC__ | |
22671 | +#define jbd_debug(f, a...) /**/ | |
22672 | +#else | |
22673 | +#define jbd_debug(f, ...) /**/ | |
22674 | +#endif | |
22675 | +#endif | |
22676 | +#else | |
22677 | +#define jbd_debug(x) /* AIX doesn't do STDC */ | |
22678 | +#endif | |
22679 | + | |
22680 | +extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); | |
22681 | +#define jbd_kmalloc(size, flags) \ | |
22682 | + __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry) | |
22683 | +#define jbd_rep_kmalloc(size, flags) \ | |
22684 | + __jbd_kmalloc(__FUNCTION__, (size), (flags), 1) | |
22685 | + | |
22686 | +#define JFS_MIN_JOURNAL_BLOCKS 1024 | |
22687 | + | |
22688 | +#ifdef __KERNEL__ | |
22689 | +typedef struct handle_s handle_t; /* Atomic operation type */ | |
22690 | +typedef struct journal_s journal_t; /* Journal control structure */ | |
22691 | +#endif | |
22692 | + | |
22693 | +/* | |
22694 | + * Internal structures used by the logging mechanism: | |
22695 | + */ | |
22696 | + | |
22697 | +#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ | |
22698 | + | |
22699 | +/* | |
22700 | + * On-disk structures | |
22701 | + */ | |
22702 | + | |
22703 | +/* | |
22704 | + * Descriptor block types: | |
22705 | + */ | |
22706 | + | |
22707 | +#define JFS_DESCRIPTOR_BLOCK 1 | |
22708 | +#define JFS_COMMIT_BLOCK 2 | |
22709 | +#define JFS_SUPERBLOCK_V1 3 | |
22710 | +#define JFS_SUPERBLOCK_V2 4 | |
22711 | +#define JFS_REVOKE_BLOCK 5 | |
22712 | + | |
22713 | +/* | |
22714 | + * Standard header for all descriptor blocks: | |
22715 | + */ | |
22716 | +typedef struct journal_header_s | |
22717 | +{ | |
22718 | + __u32 h_magic; | |
22719 | + __u32 h_blocktype; | |
22720 | + __u32 h_sequence; | |
22721 | +} journal_header_t; | |
22722 | + | |
22723 | + | |
22724 | +/* | |
22725 | + * The block tag: used to describe a single buffer in the journal | |
22726 | + */ | |
22727 | +typedef struct journal_block_tag_s | |
22728 | +{ | |
22729 | + __u32 t_blocknr; /* The on-disk block number */ | |
22730 | + __u32 t_flags; /* See below */ | |
22731 | +} journal_block_tag_t; | |
22732 | + | |
22733 | +/* | |
22734 | + * The revoke descriptor: used on disk to describe a series of blocks to | |
22735 | + * be revoked from the log | |
22736 | + */ | |
22737 | +typedef struct journal_revoke_header_s | |
22738 | +{ | |
22739 | + journal_header_t r_header; | |
22740 | + int r_count; /* Count of bytes used in the block */ | |
22741 | +} journal_revoke_header_t; | |
22742 | + | |
22743 | + | |
22744 | +/* Definitions for the journal tag flags word: */ | |
22745 | +#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ | |
22746 | +#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ | |
22747 | +#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ | |
22748 | +#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ | |
22749 | + | |
22750 | + | |
22751 | +/* | |
22752 | + * The journal superblock. All fields are in big-endian byte order. | |
22753 | + */ | |
22754 | +typedef struct journal_superblock_s | |
22755 | +{ | |
22756 | +/* 0x0000 */ | |
22757 | + journal_header_t s_header; | |
22758 | + | |
22759 | +/* 0x000C */ | |
22760 | + /* Static information describing the journal */ | |
22761 | + __u32 s_blocksize; /* journal device blocksize */ | |
22762 | + __u32 s_maxlen; /* total blocks in journal file */ | |
22763 | + __u32 s_first; /* first block of log information */ | |
22764 | + | |
22765 | +/* 0x0018 */ | |
22766 | + /* Dynamic information describing the current state of the log */ | |
22767 | + __u32 s_sequence; /* first commit ID expected in log */ | |
22768 | + __u32 s_start; /* blocknr of start of log */ | |
22769 | + | |
22770 | +/* 0x0020 */ | |
22771 | + /* Error value, as set by journal_abort(). */ | |
22772 | + __s32 s_errno; | |
22773 | + | |
22774 | +/* 0x0024 */ | |
22775 | + /* Remaining fields are only valid in a version-2 superblock */ | |
22776 | + __u32 s_feature_compat; /* compatible feature set */ | |
22777 | + __u32 s_feature_incompat; /* incompatible feature set */ | |
22778 | + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ | |
22779 | +/* 0x0030 */ | |
22780 | + __u8 s_uuid[16]; /* 128-bit uuid for journal */ | |
22781 | + | |
22782 | +/* 0x0040 */ | |
22783 | + __u32 s_nr_users; /* Nr of filesystems sharing log */ | |
22784 | + | |
22785 | + __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ | |
22786 | + | |
22787 | +/* 0x0048 */ | |
22788 | + __u32 s_max_transaction; /* Limit of journal blocks per trans.*/ | |
22789 | + __u32 s_max_trans_data; /* Limit of data blocks per trans. */ | |
22790 | + | |
22791 | +/* 0x0050 */ | |
22792 | + __u32 s_padding[44]; | |
22793 | + | |
22794 | +/* 0x0100 */ | |
22795 | + __u8 s_users[16*48]; /* ids of all fs'es sharing the log */ | |
22796 | +/* 0x0400 */ | |
22797 | +} journal_superblock_t; | |
22798 | + | |
22799 | +#define JFS_HAS_COMPAT_FEATURE(j,mask) \ | |
22800 | + ((j)->j_format_version >= 2 && \ | |
22801 | + ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) | |
22802 | +#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \ | |
22803 | + ((j)->j_format_version >= 2 && \ | |
22804 | + ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask)))) | |
22805 | +#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \ | |
22806 | + ((j)->j_format_version >= 2 && \ | |
22807 | + ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) | |
22808 | + | |
22809 | +#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001 | |
22810 | + | |
22811 | +/* Features known to this kernel version: */ | |
22812 | +#define JFS_KNOWN_COMPAT_FEATURES 0 | |
22813 | +#define JFS_KNOWN_ROCOMPAT_FEATURES 0 | |
22814 | +#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE | |
22815 | + | |
22816 | +#ifdef __KERNEL__ | |
22817 | + | |
22818 | +#include <linux/fs.h> | |
22819 | +#include <linux/sched.h> | |
22820 | + | |
22821 | +#define JBD_ASSERTIONS | |
22822 | +#ifdef JBD_ASSERTIONS | |
22823 | +#define J_ASSERT(assert) \ | |
22824 | +do { \ | |
22825 | + if (!(assert)) { \ | |
22826 | + printk (KERN_EMERG \ | |
22827 | + "Assertion failure in %s() at %s:%d: \"%s\"\n", \ | |
22828 | + __FUNCTION__, __FILE__, __LINE__, # assert); \ | |
22829 | + BUG(); \ | |
22830 | + } \ | |
22831 | +} while (0) | |
22832 | + | |
22833 | +#if defined(CONFIG_BUFFER_DEBUG) | |
22834 | +void buffer_assertion_failure(struct buffer_head *bh); | |
22835 | +#define J_ASSERT_BH(bh, expr) \ | |
22836 | + do { \ | |
22837 | + if (!(expr)) \ | |
22838 | + buffer_assertion_failure(bh); \ | |
22839 | + J_ASSERT(expr); \ | |
22840 | + } while (0) | |
22841 | +#define J_ASSERT_JH(jh, expr) J_ASSERT_BH(jh2bh(jh), expr) | |
22842 | +#else | |
22843 | +#define J_ASSERT_BH(bh, expr) J_ASSERT(expr) | |
22844 | +#define J_ASSERT_JH(jh, expr) J_ASSERT(expr) | |
22845 | +#endif | |
22846 | + | |
22847 | +#else | |
22848 | +#define J_ASSERT(assert) | |
22849 | +#endif /* JBD_ASSERTIONS */ | |
22850 | + | |
22851 | +enum jbd_state_bits { | |
22852 | + BH_JWrite | |
22853 | + = BH_PrivateStart, /* 1 if being written to log (@@@ DEBUGGING) */ | |
22854 | + BH_Freed, /* 1 if buffer has been freed (truncated) */ | |
22855 | + BH_Revoked, /* 1 if buffer has been revoked from the log */ | |
22856 | + BH_RevokeValid, /* 1 if buffer revoked flag is valid */ | |
22857 | + BH_JBDDirty, /* 1 if buffer is dirty but journaled */ | |
22858 | +}; | |
22859 | + | |
22860 | +/* Return true if the buffer is one which JBD is managing */ | |
22861 | +static inline int buffer_jbd(struct buffer_head *bh) | |
22862 | +{ | |
22863 | + return __buffer_state(bh, JBD); | |
22864 | +} | |
22865 | + | |
22866 | +static inline struct buffer_head *jh2bh(struct journal_head *jh) | |
22867 | +{ | |
22868 | + return jh->b_bh; | |
22869 | +} | |
22870 | + | |
22871 | +static inline struct journal_head *bh2jh(struct buffer_head *bh) | |
22872 | +{ | |
22873 | + return bh->b_private; | |
22874 | +} | |
22875 | + | |
22876 | +struct jbd_revoke_table_s; | |
22877 | + | |
22878 | +/* The handle_t type represents a single atomic update being performed | |
22879 | + * by some process. All filesystem modifications made by the process go | |
22880 | + * through this handle. Recursive operations (such as quota operations) | |
22881 | + * are gathered into a single update. | |
22882 | + * | |
22883 | + * The buffer credits field is used to account for journaled buffers | |
22884 | + * being modified by the running process. To ensure that there is | |
22885 | + * enough log space for all outstanding operations, we need to limit the | |
22886 | + * number of outstanding buffers possible at any time. When the | |
22887 | + * operation completes, any buffer credits not used are credited back to | |
22888 | + * the transaction, so that at all times we know how many buffers the | |
22889 | + * outstanding updates on a transaction might possibly touch. */ | |
22890 | + | |
22891 | +struct handle_s | |
22892 | +{ | |
22893 | + /* Which compound transaction is this update a part of? */ | |
22894 | + transaction_t * h_transaction; | |
22895 | + | |
22896 | + /* Number of remaining buffers we are allowed to dirty: */ | |
22897 | + int h_buffer_credits; | |
22898 | + | |
22899 | + /* Reference count on this handle */ | |
22900 | + int h_ref; | |
22901 | + | |
22902 | + /* Field for caller's use to track errors through large fs | |
22903 | + operations */ | |
22904 | + int h_err; | |
22905 | + | |
22906 | + /* Flags */ | |
22907 | + unsigned int h_sync: 1; /* sync-on-close */ | |
22908 | + unsigned int h_jdata: 1; /* force data journaling */ | |
22909 | + unsigned int h_aborted: 1; /* fatal error on handle */ | |
22910 | +}; | |
22911 | + | |
22912 | + | |
22913 | +/* The transaction_t type is the guts of the journaling mechanism. It | |
22914 | + * tracks a compound transaction through its various states: | |
22915 | + * | |
22916 | + * RUNNING: accepting new updates | |
22917 | + * LOCKED: Updates still running but we don't accept new ones | |
22918 | + * RUNDOWN: Updates are tidying up but have finished requesting | |
22919 | + * new buffers to modify (state not used for now) | |
22920 | + * FLUSH: All updates complete, but we are still writing to disk | |
22921 | + * COMMIT: All data on disk, writing commit record | |
22922 | + * FINISHED: We still have to keep the transaction for checkpointing. | |
22923 | + * | |
22924 | + * The transaction keeps track of all of the buffers modified by a | |
22925 | + * running transaction, and all of the buffers committed but not yet | |
22926 | + * flushed to home for finished transactions. | |
22927 | + */ | |
22928 | + | |
22929 | +struct transaction_s | |
22930 | +{ | |
22931 | + /* Pointer to the journal for this transaction. */ | |
22932 | + journal_t * t_journal; | |
22933 | + | |
22934 | + /* Sequence number for this transaction */ | |
22935 | + tid_t t_tid; | |
22936 | + | |
22937 | + /* Transaction's current state */ | |
22938 | + enum { | |
22939 | + T_RUNNING, | |
22940 | + T_LOCKED, | |
22941 | + T_RUNDOWN, | |
22942 | + T_FLUSH, | |
22943 | + T_COMMIT, | |
22944 | + T_FINISHED | |
22945 | + } t_state; | |
22946 | + | |
22947 | + /* Where in the log does this transaction's commit start? */ | |
22948 | + unsigned long t_log_start; | |
22949 | + | |
22950 | + /* Doubly-linked circular list of all inodes owned by this | |
22951 | + transaction */ /* AKPM: unused */ | |
22952 | + struct inode * t_ilist; | |
22953 | + | |
22954 | + /* Number of buffers on the t_buffers list */ | |
22955 | + int t_nr_buffers; | |
22956 | + | |
22957 | + /* Doubly-linked circular list of all buffers reserved but not | |
22958 | + yet modified by this transaction */ | |
22959 | + struct journal_head * t_reserved_list; | |
22960 | + | |
22961 | + /* Doubly-linked circular list of all metadata buffers owned by this | |
22962 | + transaction */ | |
22963 | + struct journal_head * t_buffers; | |
22964 | + | |
22965 | + /* | |
22966 | + * Doubly-linked circular list of all data buffers still to be | |
22967 | + * flushed before this transaction can be committed. | |
22968 | + * Protected by journal_datalist_lock. | |
22969 | + */ | |
22970 | + struct journal_head * t_sync_datalist; | |
22971 | + | |
22972 | + /* | |
22973 | + * Doubly-linked circular list of all writepage data buffers | |
22974 | + * still to be written before this transaction can be committed. | |
22975 | + * Protected by journal_datalist_lock. | |
22976 | + */ | |
22977 | + struct journal_head * t_async_datalist; | |
22978 | + | |
22979 | + /* Doubly-linked circular list of all forget buffers (superceded | |
22980 | + buffers which we can un-checkpoint once this transaction | |
22981 | + commits) */ | |
22982 | + struct journal_head * t_forget; | |
22983 | + | |
22984 | + /* | |
22985 | + * Doubly-linked circular list of all buffers still to be | |
22986 | + * flushed before this transaction can be checkpointed. | |
22987 | + */ | |
22988 | + /* Protected by journal_datalist_lock */ | |
22989 | + struct journal_head * t_checkpoint_list; | |
22990 | + | |
22991 | + /* Doubly-linked circular list of temporary buffers currently | |
22992 | + undergoing IO in the log */ | |
22993 | + struct journal_head * t_iobuf_list; | |
22994 | + | |
22995 | + /* Doubly-linked circular list of metadata buffers being | |
22996 | + shadowed by log IO. The IO buffers on the iobuf list and the | |
22997 | + shadow buffers on this list match each other one for one at | |
22998 | + all times. */ | |
22999 | + struct journal_head * t_shadow_list; | |
23000 | + | |
23001 | + /* Doubly-linked circular list of control buffers being written | |
23002 | + to the log. */ | |
23003 | + struct journal_head * t_log_list; | |
23004 | + | |
23005 | + /* Number of outstanding updates running on this transaction */ | |
23006 | + int t_updates; | |
23007 | + | |
23008 | + /* Number of buffers reserved for use by all handles in this | |
23009 | + * transaction handle but not yet modified. */ | |
23010 | + int t_outstanding_credits; | |
23011 | + | |
23012 | + /* | |
23013 | + * Forward and backward links for the circular list of all | |
23014 | + * transactions awaiting checkpoint. | |
23015 | + */ | |
23016 | + /* Protected by journal_datalist_lock */ | |
23017 | + transaction_t *t_cpnext, *t_cpprev; | |
23018 | + | |
23019 | + /* When will the transaction expire (become due for commit), in | |
23020 | + * jiffies ? */ | |
23021 | + unsigned long t_expires; | |
23022 | + | |
23023 | + /* How many handles used this transaction? */ | |
23024 | + int t_handle_count; | |
23025 | +}; | |
23026 | + | |
23027 | + | |
23028 | +/* The journal_t maintains all of the journaling state information for a | |
23029 | + * single filesystem. It is linked to from the fs superblock structure. | |
23030 | + * | |
23031 | + * We use the journal_t to keep track of all outstanding transaction | |
23032 | + * activity on the filesystem, and to manage the state of the log | |
23033 | + * writing process. */ | |
23034 | + | |
23035 | +struct journal_s | |
23036 | +{ | |
23037 | + /* General journaling state flags */ | |
23038 | + unsigned long j_flags; | |
23039 | + | |
23040 | + /* Is there an outstanding uncleared error on the journal (from | |
23041 | + * a prior abort)? */ | |
23042 | + int j_errno; | |
23043 | + | |
23044 | + /* The superblock buffer */ | |
23045 | + struct buffer_head * j_sb_buffer; | |
23046 | + journal_superblock_t * j_superblock; | |
23047 | + | |
23048 | + /* Version of the superblock format */ | |
23049 | + int j_format_version; | |
23050 | + | |
23051 | + /* Number of processes waiting to create a barrier lock */ | |
23052 | + int j_barrier_count; | |
23053 | + | |
23054 | + /* The barrier lock itself */ | |
23055 | + struct semaphore j_barrier; | |
23056 | + | |
23057 | + /* Transactions: The current running transaction... */ | |
23058 | + transaction_t * j_running_transaction; | |
23059 | + | |
23060 | + /* ... the transaction we are pushing to disk ... */ | |
23061 | + transaction_t * j_committing_transaction; | |
23062 | + | |
23063 | + /* ... and a linked circular list of all transactions waiting | |
23064 | + * for checkpointing. */ | |
23065 | + /* Protected by journal_datalist_lock */ | |
23066 | + transaction_t * j_checkpoint_transactions; | |
23067 | + | |
23068 | + /* Wait queue for waiting for a locked transaction to start | |
23069 | + committing, or for a barrier lock to be released */ | |
23070 | + wait_queue_head_t j_wait_transaction_locked; | |
23071 | + | |
23072 | + /* Wait queue for waiting for checkpointing to complete */ | |
23073 | + wait_queue_head_t j_wait_logspace; | |
23074 | + | |
23075 | + /* Wait queue for waiting for commit to complete */ | |
23076 | + wait_queue_head_t j_wait_done_commit; | |
23077 | + | |
23078 | + /* Wait queue to trigger checkpointing */ | |
23079 | + wait_queue_head_t j_wait_checkpoint; | |
23080 | + | |
23081 | + /* Wait queue to trigger commit */ | |
23082 | + wait_queue_head_t j_wait_commit; | |
23083 | + | |
23084 | + /* Wait queue to wait for updates to complete */ | |
23085 | + wait_queue_head_t j_wait_updates; | |
23086 | + | |
23087 | + /* Semaphore for locking against concurrent checkpoints */ | |
23088 | + struct semaphore j_checkpoint_sem; | |
23089 | + | |
23090 | + /* The main journal lock, used by lock_journal() */ | |
23091 | + struct semaphore j_sem; | |
23092 | + | |
23093 | + /* Journal head: identifies the first unused block in the journal. */ | |
23094 | + unsigned long j_head; | |
23095 | + | |
23096 | + /* Journal tail: identifies the oldest still-used block in the | |
23097 | + * journal. */ | |
23098 | + unsigned long j_tail; | |
23099 | + | |
23100 | + /* Journal free: how many free blocks are there in the journal? */ | |
23101 | + unsigned long j_free; | |
23102 | + | |
23103 | + /* Journal start and end: the block numbers of the first usable | |
23104 | + * block and one beyond the last usable block in the journal. */ | |
23105 | + unsigned long j_first, j_last; | |
23106 | + | |
23107 | + /* Device, blocksize and starting block offset for the location | |
23108 | + * where we store the journal. */ | |
23109 | + kdev_t j_dev; | |
23110 | + int j_blocksize; | |
23111 | + unsigned int j_blk_offset; | |
23112 | + | |
23113 | + /* Device which holds the client fs. For internal journal this | |
23114 | + * will be equal to j_dev. */ | |
23115 | + kdev_t j_fs_dev; | |
23116 | + | |
23117 | + /* Total maximum capacity of the journal region on disk. */ | |
23118 | + unsigned int j_maxlen; | |
23119 | + | |
23120 | + /* Optional inode where we store the journal. If present, all | |
23121 | + * journal block numbers are mapped into this inode via | |
23122 | + * bmap(). */ | |
23123 | + struct inode * j_inode; | |
23124 | + | |
23125 | + /* Sequence number of the oldest transaction in the log */ | |
23126 | + tid_t j_tail_sequence; | |
23127 | + /* Sequence number of the next transaction to grant */ | |
23128 | + tid_t j_transaction_sequence; | |
23129 | + /* Sequence number of the most recently committed transaction */ | |
23130 | + tid_t j_commit_sequence; | |
23131 | + /* Sequence number of the most recent transaction wanting commit */ | |
23132 | + tid_t j_commit_request; | |
23133 | + | |
23134 | + /* Journal uuid: identifies the object (filesystem, LVM volume | |
23135 | + * etc) backed by this journal. This will eventually be | |
23136 | + * replaced by an array of uuids, allowing us to index multiple | |
23137 | + * devices within a single journal and to perform atomic updates | |
23138 | + * across them. */ | |
23139 | + | |
23140 | + __u8 j_uuid[16]; | |
23141 | + | |
23142 | + /* Pointer to the current commit thread for this journal */ | |
23143 | + struct task_struct * j_task; | |
23144 | + | |
23145 | + /* Maximum number of metadata buffers to allow in a single | |
23146 | + * compound commit transaction */ | |
23147 | + int j_max_transaction_buffers; | |
23148 | + | |
23149 | + /* What is the maximum transaction lifetime before we begin a | |
23150 | + * commit? */ | |
23151 | + unsigned long j_commit_interval; | |
23152 | + | |
23153 | + /* The timer used to wakeup the commit thread: */ | |
23154 | + struct timer_list * j_commit_timer; | |
23155 | + int j_commit_timer_active; | |
23156 | + | |
23157 | + /* Link all journals together - system-wide */ | |
23158 | + struct list_head j_all_journals; | |
23159 | + | |
23160 | + /* The revoke table: maintains the list of revoked blocks in the | |
23161 | + current transaction. */ | |
23162 | + struct jbd_revoke_table_s *j_revoke; | |
23163 | +}; | |
23164 | + | |
23165 | +/* | |
23166 | + * Journal flag definitions | |
23167 | + */ | |
23168 | +#define JFS_UNMOUNT 0x001 /* Journal thread is being destroyed */ | |
23169 | +#define JFS_ABORT 0x002 /* Journaling has been aborted for errors. */ | |
23170 | +#define JFS_ACK_ERR 0x004 /* The errno in the sb has been acked */ | |
23171 | +#define JFS_FLUSHED 0x008 /* The journal superblock has been flushed */ | |
23172 | +#define JFS_LOADED 0x010 /* The journal superblock has been loaded */ | |
23173 | + | |
23174 | +/* | |
23175 | + * Function declarations for the journaling transaction and buffer | |
23176 | + * management | |
23177 | + */ | |
23178 | + | |
23179 | +/* Filing buffers */ | |
23180 | +extern void __journal_unfile_buffer(struct journal_head *); | |
23181 | +extern void journal_unfile_buffer(struct journal_head *); | |
23182 | +extern void __journal_refile_buffer(struct journal_head *); | |
23183 | +extern void journal_refile_buffer(struct journal_head *); | |
23184 | +extern void __journal_file_buffer(struct journal_head *, transaction_t *, int); | |
23185 | +extern void __journal_free_buffer(struct journal_head *bh); | |
23186 | +extern void journal_file_buffer(struct journal_head *, transaction_t *, int); | |
23187 | +extern void __journal_clean_data_list(transaction_t *transaction); | |
23188 | + | |
23189 | +/* Log buffer allocation */ | |
23190 | +extern struct journal_head * journal_get_descriptor_buffer(journal_t *); | |
23191 | +extern unsigned long journal_next_log_block(journal_t *); | |
23192 | + | |
23193 | +/* Commit management */ | |
23194 | +extern void journal_commit_transaction(journal_t *); | |
23195 | + | |
23196 | +/* Checkpoint list management */ | |
23197 | +int __journal_clean_checkpoint_list(journal_t *journal); | |
23198 | +extern void journal_remove_checkpoint(struct journal_head *); | |
23199 | +extern void __journal_remove_checkpoint(struct journal_head *); | |
23200 | +extern void journal_insert_checkpoint(struct journal_head *, transaction_t *); | |
23201 | +extern void __journal_insert_checkpoint(struct journal_head *,transaction_t *); | |
23202 | + | |
23203 | +/* Buffer IO */ | |
23204 | +extern int | |
23205 | +journal_write_metadata_buffer(transaction_t *transaction, | |
23206 | + struct journal_head *jh_in, | |
23207 | + struct journal_head **jh_out, | |
23208 | + int blocknr); | |
23209 | + | |
23210 | +/* Transaction locking */ | |
23211 | +extern void __wait_on_journal (journal_t *); | |
23212 | + | |
23213 | +/* | |
23214 | + * Journal locking. | |
23215 | + * | |
23216 | + * We need to lock the journal during transaction state changes so that | |
23217 | + * nobody ever tries to take a handle on the running transaction while | |
23218 | + * we are in the middle of moving it to the commit phase. | |
23219 | + * | |
23220 | + * Note that the locking is completely interrupt unsafe. We never touch | |
23221 | + * journal structures from interrupts. | |
23222 | + * | |
23223 | + * In 2.2, the BKL was required for lock_journal. This is no longer | |
23224 | + * the case. | |
23225 | + */ | |
23226 | + | |
23227 | +static inline void lock_journal(journal_t *journal) | |
23228 | +{ | |
23229 | + down(&journal->j_sem); | |
23230 | +} | |
23231 | + | |
23232 | +/* This returns zero if we acquired the semaphore */ | |
23233 | +static inline int try_lock_journal(journal_t * journal) | |
23234 | +{ | |
23235 | + return down_trylock(&journal->j_sem); | |
23236 | +} | |
23237 | + | |
23238 | +static inline void unlock_journal(journal_t * journal) | |
23239 | +{ | |
23240 | + up(&journal->j_sem); | |
23241 | +} | |
23242 | + | |
23243 | + | |
23244 | +static inline handle_t *journal_current_handle(void) | |
23245 | +{ | |
23246 | + return current->journal_info; | |
23247 | +} | |
23248 | + | |
23249 | +/* The journaling code user interface: | |
23250 | + * | |
23251 | + * Create and destroy handles | |
23252 | + * Register buffer modifications against the current transaction. | |
23253 | + */ | |
23254 | + | |
23255 | +extern handle_t *journal_start(journal_t *, int nblocks); | |
23256 | +extern handle_t *journal_try_start(journal_t *, int nblocks); | |
23257 | +extern int journal_restart (handle_t *, int nblocks); | |
23258 | +extern int journal_extend (handle_t *, int nblocks); | |
23259 | +extern int journal_get_write_access (handle_t *, struct buffer_head *); | |
23260 | +extern int journal_get_create_access (handle_t *, struct buffer_head *); | |
23261 | +extern int journal_get_undo_access (handle_t *, struct buffer_head *); | |
23262 | +extern int journal_dirty_data (handle_t *, | |
23263 | + struct buffer_head *, int async); | |
23264 | +extern int journal_dirty_metadata (handle_t *, struct buffer_head *); | |
23265 | +extern void journal_release_buffer (handle_t *, struct buffer_head *); | |
23266 | +extern void journal_forget (handle_t *, struct buffer_head *); | |
23267 | +extern void journal_sync_buffer (struct buffer_head *); | |
23268 | +extern int journal_flushpage(journal_t *, struct page *, unsigned long); | |
23269 | +extern int journal_try_to_free_buffers(journal_t *, struct page *, int); | |
23270 | +extern int journal_stop(handle_t *); | |
23271 | +extern int journal_flush (journal_t *); | |
23272 | + | |
23273 | +extern void journal_lock_updates (journal_t *); | |
23274 | +extern void journal_unlock_updates (journal_t *); | |
23275 | + | |
23276 | +extern journal_t * journal_init_dev(kdev_t dev, kdev_t fs_dev, | |
23277 | + int start, int len, int bsize); | |
23278 | +extern journal_t * journal_init_inode (struct inode *); | |
23279 | +extern int journal_update_format (journal_t *); | |
23280 | +extern int journal_check_used_features | |
23281 | + (journal_t *, unsigned long, unsigned long, unsigned long); | |
23282 | +extern int journal_check_available_features | |
23283 | + (journal_t *, unsigned long, unsigned long, unsigned long); | |
23284 | +extern int journal_set_features | |
23285 | + (journal_t *, unsigned long, unsigned long, unsigned long); | |
23286 | +extern int journal_create (journal_t *); | |
23287 | +extern int journal_load (journal_t *journal); | |
23288 | +extern void journal_destroy (journal_t *); | |
23289 | +extern int journal_recover (journal_t *journal); | |
23290 | +extern int journal_wipe (journal_t *, int); | |
23291 | +extern int journal_skip_recovery (journal_t *); | |
23292 | +extern void journal_update_superblock (journal_t *, int); | |
23293 | +extern void __journal_abort (journal_t *); | |
23294 | +extern void journal_abort (journal_t *, int); | |
23295 | +extern int journal_errno (journal_t *); | |
23296 | +extern void journal_ack_err (journal_t *); | |
23297 | +extern int journal_clear_err (journal_t *); | |
23298 | +extern unsigned long journal_bmap(journal_t *journal, unsigned long blocknr); | |
23299 | +extern int journal_force_commit(journal_t *journal); | |
23300 | + | |
23301 | +/* | |
23302 | + * journal_head management | |
23303 | + */ | |
23304 | +extern struct journal_head | |
23305 | + *journal_add_journal_head(struct buffer_head *bh); | |
23306 | +extern void journal_remove_journal_head(struct buffer_head *bh); | |
23307 | +extern void __journal_remove_journal_head(struct buffer_head *bh); | |
23308 | +extern void journal_unlock_journal_head(struct journal_head *jh); | |
23309 | + | |
23310 | +/* Primary revoke support */ | |
23311 | +#define JOURNAL_REVOKE_DEFAULT_HASH 256 | |
23312 | +extern int journal_init_revoke(journal_t *, int); | |
23313 | +extern void journal_destroy_revoke_caches(void); | |
23314 | +extern int journal_init_revoke_caches(void); | |
23315 | + | |
23316 | +extern void journal_destroy_revoke(journal_t *); | |
23317 | +extern int journal_revoke (handle_t *, | |
23318 | + unsigned long, struct buffer_head *); | |
23319 | +extern int journal_cancel_revoke(handle_t *, struct journal_head *); | |
23320 | +extern void journal_write_revoke_records(journal_t *, transaction_t *); | |
23321 | + | |
23322 | +/* Recovery revoke support */ | |
23323 | +extern int journal_set_revoke(journal_t *, unsigned long, tid_t); | |
23324 | +extern int journal_test_revoke(journal_t *, unsigned long, tid_t); | |
23325 | +extern void journal_clear_revoke(journal_t *); | |
23326 | +extern void journal_brelse_array(struct buffer_head *b[], int n); | |
23327 | + | |
23328 | +/* The log thread user interface: | |
23329 | + * | |
23330 | + * Request space in the current transaction, and force transaction commit | |
23331 | + * transitions on demand. | |
23332 | + */ | |
23333 | + | |
23334 | +extern int log_space_left (journal_t *); /* Called with journal locked */ | |
23335 | +extern tid_t log_start_commit (journal_t *, transaction_t *); | |
23336 | +extern void log_wait_commit (journal_t *, tid_t); | |
23337 | +extern int log_do_checkpoint (journal_t *, int); | |
23338 | + | |
23339 | +extern void log_wait_for_space(journal_t *, int nblocks); | |
23340 | +extern void __journal_drop_transaction(journal_t *, transaction_t *); | |
23341 | +extern int cleanup_journal_tail(journal_t *); | |
23342 | + | |
23343 | +/* Reduce journal memory usage by flushing */ | |
23344 | +extern void shrink_journal_memory(void); | |
23345 | + | |
23346 | +/* Debugging code only: */ | |
23347 | + | |
23348 | +#define jbd_ENOSYS() \ | |
23349 | +do { \ | |
23350 | + printk (KERN_ERR "JBD unimplemented function " __FUNCTION__); \ | |
23351 | + current->state = TASK_UNINTERRUPTIBLE; \ | |
23352 | + schedule(); \ | |
23353 | +} while (1) | |
23354 | + | |
23355 | +/* | |
23356 | + * is_journal_abort | |
23357 | + * | |
23358 | + * Simple test wrapper function to test the JFS_ABORT state flag. This | |
23359 | + * bit, when set, indicates that we have had a fatal error somewhere, | |
23360 | + * either inside the journaling layer or indicated to us by the client | |
23361 | + * (eg. ext3), and that we and should not commit any further | |
23362 | + * transactions. | |
23363 | + */ | |
23364 | + | |
23365 | +static inline int is_journal_aborted(journal_t *journal) | |
23366 | +{ | |
23367 | + return journal->j_flags & JFS_ABORT; | |
23368 | +} | |
23369 | + | |
23370 | +static inline int is_handle_aborted(handle_t *handle) | |
23371 | +{ | |
23372 | + if (handle->h_aborted) | |
23373 | + return 1; | |
23374 | + return is_journal_aborted(handle->h_transaction->t_journal); | |
23375 | +} | |
23376 | + | |
23377 | +static inline void journal_abort_handle(handle_t *handle) | |
23378 | +{ | |
23379 | + handle->h_aborted = 1; | |
23380 | +} | |
23381 | + | |
23382 | +/* Not all architectures define BUG() */ | |
23383 | +#ifndef BUG | |
23384 | +#define BUG() do { \ | |
23385 | + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ | |
23386 | + * ((char *) 0) = 0; \ | |
23387 | + } while (0) | |
23388 | +#endif /* BUG */ | |
23389 | + | |
23390 | +#else | |
23391 | + | |
23392 | +extern int journal_recover (journal_t *journal); | |
23393 | +extern int journal_skip_recovery (journal_t *); | |
23394 | + | |
23395 | +/* Primary revoke support */ | |
23396 | +extern int journal_init_revoke(journal_t *, int); | |
23397 | +extern void journal_destroy_revoke_caches(void); | |
23398 | +extern int journal_init_revoke_caches(void); | |
23399 | + | |
23400 | +/* Recovery revoke support */ | |
23401 | +extern int journal_set_revoke(journal_t *, unsigned long, tid_t); | |
23402 | +extern int journal_test_revoke(journal_t *, unsigned long, tid_t); | |
23403 | +extern void journal_clear_revoke(journal_t *); | |
23404 | +extern void journal_brelse_array(struct buffer_head *b[], int n); | |
23405 | + | |
23406 | +extern void journal_destroy_revoke(journal_t *); | |
23407 | +#endif /* __KERNEL__ */ | |
23408 | + | |
23409 | +/* Comparison functions for transaction IDs: perform comparisons using | |
23410 | + * modulo arithmetic so that they work over sequence number wraps. */ | |
23411 | + | |
23412 | +static inline int tid_gt(tid_t x, tid_t y) | |
23413 | +{ | |
23414 | + int difference = (x - y); | |
23415 | + return (difference > 0); | |
23416 | +} | |
23417 | + | |
23418 | +static inline int tid_geq(tid_t x, tid_t y) | |
23419 | +{ | |
23420 | + int difference = (x - y); | |
23421 | + return (difference >= 0); | |
23422 | +} | |
23423 | + | |
23424 | +extern int journal_blocks_per_page(struct inode *inode); | |
23425 | + | |
23426 | +/* | |
23427 | + * Definitions which augment the buffer_head layer | |
23428 | + */ | |
23429 | + | |
23430 | +/* journaling buffer types */ | |
23431 | +#define BJ_None 0 /* Not journaled */ | |
23432 | +#define BJ_SyncData 1 /* Normal data: flush before commit */ | |
23433 | +#define BJ_AsyncData 2 /* writepage data: wait on it before commit */ | |
23434 | +#define BJ_Metadata 3 /* Normal journaled metadata */ | |
23435 | +#define BJ_Forget 4 /* Buffer superceded by this transaction */ | |
23436 | +#define BJ_IO 5 /* Buffer is for temporary IO use */ | |
23437 | +#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */ | |
23438 | +#define BJ_LogCtl 7 /* Buffer contains log descriptors */ | |
23439 | +#define BJ_Reserved 8 /* Buffer is reserved for access by journal */ | |
23440 | +#define BJ_Types 9 | |
23441 | + | |
23442 | +extern int jbd_blocks_per_page(struct inode *inode); | |
23443 | + | |
23444 | +#ifdef __KERNEL__ | |
23445 | + | |
23446 | +extern spinlock_t jh_splice_lock; | |
23447 | +/* | |
23448 | + * Once `expr1' has been found true, take jh_splice_lock | |
23449 | + * and then reevaluate everything. | |
23450 | + */ | |
23451 | +#define SPLICE_LOCK(expr1, expr2) \ | |
23452 | + ({ \ | |
23453 | + int ret = (expr1); \ | |
23454 | + if (ret) { \ | |
23455 | + spin_lock(&jh_splice_lock); \ | |
23456 | + ret = (expr1) && (expr2); \ | |
23457 | + spin_unlock(&jh_splice_lock); \ | |
23458 | + } \ | |
23459 | + ret; \ | |
23460 | + }) | |
23461 | + | |
23462 | +/* | |
23463 | + * A number of buffer state predicates. They test for | |
23464 | + * buffer_jbd() because they are used in core kernel code. | |
23465 | + * | |
23466 | + * These will be racy on SMP unless we're *sure* that the | |
23467 | + * buffer won't be detached from the journalling system | |
23468 | + * in parallel. | |
23469 | + */ | |
23470 | + | |
23471 | +/* Return true if the buffer is on journal list `list' */ | |
23472 | +static inline int buffer_jlist_eq(struct buffer_head *bh, int list) | |
23473 | +{ | |
23474 | + return SPLICE_LOCK(buffer_jbd(bh), bh2jh(bh)->b_jlist == list); | |
23475 | +} | |
23476 | + | |
23477 | +/* Return true if this bufer is dirty wrt the journal */ | |
23478 | +static inline int buffer_jdirty(struct buffer_head *bh) | |
23479 | +{ | |
23480 | + return buffer_jbd(bh) && __buffer_state(bh, JBDDirty); | |
23481 | +} | |
23482 | + | |
23483 | +/* Return true if it's a data buffer which journalling is managing */ | |
23484 | +static inline int buffer_jbd_data(struct buffer_head *bh) | |
23485 | +{ | |
23486 | + return SPLICE_LOCK(buffer_jbd(bh), | |
23487 | + bh2jh(bh)->b_jlist == BJ_SyncData || | |
23488 | + bh2jh(bh)->b_jlist == BJ_AsyncData); | |
23489 | +} | |
23490 | + | |
23491 | +#ifdef CONFIG_SMP | |
23492 | +#define assert_spin_locked(lock) J_ASSERT(spin_is_locked(lock)) | |
23493 | +#else | |
23494 | +#define assert_spin_locked(lock) do {} while(0) | |
23495 | +#endif | |
23496 | + | |
23497 | +#define buffer_trace_init(bh) do {} while (0) | |
23498 | +#define print_buffer_fields(bh) do {} while (0) | |
23499 | +#define print_buffer_trace(bh) do {} while (0) | |
23500 | +#define BUFFER_TRACE(bh, info) do {} while (0) | |
23501 | +#define BUFFER_TRACE2(bh, bh2, info) do {} while (0) | |
23502 | +#define JBUFFER_TRACE(jh, info) do {} while (0) | |
23503 | + | |
23504 | +#endif /* __KERNEL__ */ | |
23505 | + | |
23506 | +#endif /* CONFIG_JBD || CONFIG_JBD_MODULE || !__KERNEL__ */ | |
23507 | + | |
23508 | +/* | |
23509 | + * Compatibility no-ops which allow the kernel to compile without CONFIG_JBD | |
23510 | + * go here. | |
23511 | + */ | |
23512 | + | |
23513 | +#if defined(__KERNEL__) && !(defined(CONFIG_JBD) || defined(CONFIG_JBD_MODULE)) | |
23514 | + | |
23515 | +#define J_ASSERT(expr) do {} while (0) | |
23516 | +#define J_ASSERT_BH(bh, expr) do {} while (0) | |
23517 | +#define buffer_jbd(bh) 0 | |
23518 | +#define buffer_jlist_eq(bh, val) 0 | |
23519 | +#define journal_buffer_journal_lru(bh) 0 | |
23520 | + | |
23521 | +#endif /* defined(__KERNEL__) && !defined(CONFIG_JBD) */ | |
23522 | +#endif /* _LINUX_JBD_H */ | |
23523 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/kernel-list.h busybox/e2fsprogs/ext2fs/kernel-list.h | |
23524 | --- busybox-1.00/e2fsprogs/ext2fs/kernel-list.h 1970-01-01 01:00:00.000000000 +0100 | |
23525 | +++ busybox/e2fsprogs/ext2fs/kernel-list.h 2005-06-04 08:20:16.000000000 +0200 | |
23526 | @@ -0,0 +1,112 @@ | |
23527 | +#ifndef _LINUX_LIST_H | |
23528 | +#define _LINUX_LIST_H | |
23529 | + | |
23530 | +/* | |
23531 | + * Simple doubly linked list implementation. | |
23532 | + * | |
23533 | + * Some of the internal functions ("__xxx") are useful when | |
23534 | + * manipulating whole lists rather than single entries, as | |
23535 | + * sometimes we already know the next/prev entries and we can | |
23536 | + * generate better code by using them directly rather than | |
23537 | + * using the generic single-entry routines. | |
23538 | + */ | |
23539 | + | |
23540 | +struct list_head { | |
23541 | + struct list_head *next, *prev; | |
23542 | +}; | |
23543 | + | |
23544 | +#define LIST_HEAD_INIT(name) { &(name), &(name) } | |
23545 | + | |
23546 | +#define LIST_HEAD(name) \ | |
23547 | + struct list_head name = { &name, &name } | |
23548 | + | |
23549 | +#define INIT_LIST_HEAD(ptr) do { \ | |
23550 | + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ | |
23551 | +} while (0) | |
23552 | + | |
23553 | +#if (!defined(__GNUC__) && !defined(__WATCOMC__)) | |
23554 | +#define __inline__ | |
23555 | +#endif | |
23556 | + | |
23557 | +/* | |
23558 | + * Insert a new entry between two known consecutive entries. | |
23559 | + * | |
23560 | + * This is only for internal list manipulation where we know | |
23561 | + * the prev/next entries already! | |
23562 | + */ | |
23563 | +static __inline__ void __list_add(struct list_head * new, | |
23564 | + struct list_head * prev, | |
23565 | + struct list_head * next) | |
23566 | +{ | |
23567 | + next->prev = new; | |
23568 | + new->next = next; | |
23569 | + new->prev = prev; | |
23570 | + prev->next = new; | |
23571 | +} | |
23572 | + | |
23573 | +/* | |
23574 | + * Insert a new entry after the specified head.. | |
23575 | + */ | |
23576 | +static __inline__ void list_add(struct list_head *new, struct list_head *head) | |
23577 | +{ | |
23578 | + __list_add(new, head, head->next); | |
23579 | +} | |
23580 | + | |
23581 | +/* | |
23582 | + * Insert a new entry at the tail | |
23583 | + */ | |
23584 | +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) | |
23585 | +{ | |
23586 | + __list_add(new, head->prev, head); | |
23587 | +} | |
23588 | + | |
23589 | +/* | |
23590 | + * Delete a list entry by making the prev/next entries | |
23591 | + * point to each other. | |
23592 | + * | |
23593 | + * This is only for internal list manipulation where we know | |
23594 | + * the prev/next entries already! | |
23595 | + */ | |
23596 | +static __inline__ void __list_del(struct list_head * prev, | |
23597 | + struct list_head * next) | |
23598 | +{ | |
23599 | + next->prev = prev; | |
23600 | + prev->next = next; | |
23601 | +} | |
23602 | + | |
23603 | +static __inline__ void list_del(struct list_head *entry) | |
23604 | +{ | |
23605 | + __list_del(entry->prev, entry->next); | |
23606 | +} | |
23607 | + | |
23608 | +static __inline__ int list_empty(struct list_head *head) | |
23609 | +{ | |
23610 | + return head->next == head; | |
23611 | +} | |
23612 | + | |
23613 | +/* | |
23614 | + * Splice in "list" into "head" | |
23615 | + */ | |
23616 | +static __inline__ void list_splice(struct list_head *list, struct list_head *head) | |
23617 | +{ | |
23618 | + struct list_head *first = list->next; | |
23619 | + | |
23620 | + if (first != list) { | |
23621 | + struct list_head *last = list->prev; | |
23622 | + struct list_head *at = head->next; | |
23623 | + | |
23624 | + first->prev = head; | |
23625 | + head->next = first; | |
23626 | + | |
23627 | + last->next = at; | |
23628 | + at->prev = last; | |
23629 | + } | |
23630 | +} | |
23631 | + | |
23632 | +#define list_entry(ptr, type, member) \ | |
23633 | + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) | |
23634 | + | |
23635 | +#define list_for_each(pos, head) \ | |
23636 | + for (pos = (head)->next; pos != (head); pos = pos->next) | |
23637 | + | |
23638 | +#endif | |
23639 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/link.c busybox/e2fsprogs/ext2fs/link.c | |
23640 | --- busybox-1.00/e2fsprogs/ext2fs/link.c 1970-01-01 01:00:00.000000000 +0100 | |
23641 | +++ busybox/e2fsprogs/ext2fs/link.c 2005-06-04 08:20:16.000000000 +0200 | |
23642 | @@ -0,0 +1,134 @@ | |
23643 | +/* | |
23644 | + * link.c --- create links in a ext2fs directory | |
23645 | + * | |
23646 | + * Copyright (C) 1993, 1994 Theodore Ts'o. | |
23647 | + * | |
23648 | + * %Begin-Header% | |
23649 | + * This file may be redistributed under the terms of the GNU Public | |
23650 | + * License. | |
23651 | + * %End-Header% | |
23652 | + */ | |
23653 | + | |
23654 | +#include <stdio.h> | |
23655 | +#include <string.h> | |
23656 | +#if HAVE_UNISTD_H | |
23657 | +#include <unistd.h> | |
23658 | +#endif | |
23659 | + | |
23660 | +#include "ext2_fs.h" | |
23661 | +#include "ext2fs.h" | |
23662 | + | |
23663 | +struct link_struct { | |
23664 | + const char *name; | |
23665 | + int namelen; | |
23666 | + ext2_ino_t inode; | |
23667 | + int flags; | |
23668 | + int done; | |
23669 | + struct ext2_super_block *sb; | |
23670 | +}; | |
23671 | + | |
23672 | +static int link_proc(struct ext2_dir_entry *dirent, | |
23673 | + int offset, | |
23674 | + int blocksize, | |
23675 | + char *buf, | |
23676 | + void *priv_data) | |
23677 | +{ | |
23678 | + struct link_struct *ls = (struct link_struct *) priv_data; | |
23679 | + struct ext2_dir_entry *next; | |
23680 | + int rec_len, min_rec_len; | |
23681 | + int ret = 0; | |
23682 | + | |
23683 | + rec_len = EXT2_DIR_REC_LEN(ls->namelen); | |
23684 | + | |
23685 | + /* | |
23686 | + * See if the following directory entry (if any) is unused; | |
23687 | + * if so, absorb it into this one. | |
23688 | + */ | |
23689 | + next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len); | |
23690 | + if ((offset + dirent->rec_len < blocksize - 8) && | |
23691 | + (next->inode == 0) && | |
23692 | + (offset + dirent->rec_len + next->rec_len <= blocksize)) { | |
23693 | + dirent->rec_len += next->rec_len; | |
23694 | + ret = DIRENT_CHANGED; | |
23695 | + } | |
23696 | + | |
23697 | + /* | |
23698 | + * If the directory entry is used, see if we can split the | |
23699 | + * directory entry to make room for the new name. If so, | |
23700 | + * truncate it and return. | |
23701 | + */ | |
23702 | + if (dirent->inode) { | |
23703 | + min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); | |
23704 | + if (dirent->rec_len < (min_rec_len + rec_len)) | |
23705 | + return ret; | |
23706 | + rec_len = dirent->rec_len - min_rec_len; | |
23707 | + dirent->rec_len = min_rec_len; | |
23708 | + next = (struct ext2_dir_entry *) (buf + offset + | |
23709 | + dirent->rec_len); | |
23710 | + next->inode = 0; | |
23711 | + next->name_len = 0; | |
23712 | + next->rec_len = rec_len; | |
23713 | + return DIRENT_CHANGED; | |
23714 | + } | |
23715 | + | |
23716 | + /* | |
23717 | + * If we get this far, then the directory entry is not used. | |
23718 | + * See if we can fit the request entry in. If so, do it. | |
23719 | + */ | |
23720 | + if (dirent->rec_len < rec_len) | |
23721 | + return ret; | |
23722 | + dirent->inode = ls->inode; | |
23723 | + dirent->name_len = ls->namelen; | |
23724 | + strncpy(dirent->name, ls->name, ls->namelen); | |
23725 | + if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) | |
23726 | + dirent->name_len |= (ls->flags & 0x7) << 8; | |
23727 | + | |
23728 | + ls->done++; | |
23729 | + return DIRENT_ABORT|DIRENT_CHANGED; | |
23730 | +} | |
23731 | + | |
23732 | +/* | |
23733 | + * Note: the low 3 bits of the flags field are used as the directory | |
23734 | + * entry filetype. | |
23735 | + */ | |
23736 | +#ifdef __TURBOC__ | |
23737 | + #pragma argsused | |
23738 | +#endif | |
23739 | +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, | |
23740 | + ext2_ino_t ino, int flags) | |
23741 | +{ | |
23742 | + errcode_t retval; | |
23743 | + struct link_struct ls; | |
23744 | + struct ext2_inode inode; | |
23745 | + | |
23746 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
23747 | + | |
23748 | + if (!(fs->flags & EXT2_FLAG_RW)) | |
23749 | + return EXT2_ET_RO_FILSYS; | |
23750 | + | |
23751 | + ls.name = name; | |
23752 | + ls.namelen = name ? strlen(name) : 0; | |
23753 | + ls.inode = ino; | |
23754 | + ls.flags = flags; | |
23755 | + ls.done = 0; | |
23756 | + ls.sb = fs->super; | |
23757 | + | |
23758 | + retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, | |
23759 | + 0, link_proc, &ls); | |
23760 | + if (retval) | |
23761 | + return retval; | |
23762 | + | |
23763 | + if (!ls.done) | |
23764 | + return EXT2_ET_DIR_NO_SPACE; | |
23765 | + | |
23766 | + if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) | |
23767 | + return retval; | |
23768 | + | |
23769 | + if (inode.i_flags & EXT2_INDEX_FL) { | |
23770 | + inode.i_flags &= ~EXT2_INDEX_FL; | |
23771 | + if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0) | |
23772 | + return retval; | |
23773 | + } | |
23774 | + | |
23775 | + return 0; | |
23776 | +} | |
23777 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/llseek.c busybox/e2fsprogs/ext2fs/llseek.c | |
23778 | --- busybox-1.00/e2fsprogs/ext2fs/llseek.c 1970-01-01 01:00:00.000000000 +0100 | |
23779 | +++ busybox/e2fsprogs/ext2fs/llseek.c 2005-06-04 08:20:16.000000000 +0200 | |
23780 | @@ -0,0 +1,135 @@ | |
23781 | +/* | |
23782 | + * llseek.c -- stub calling the llseek system call | |
23783 | + * | |
23784 | + * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o. | |
23785 | + * | |
23786 | + * %Begin-Header% | |
23787 | + * This file may be redistributed under the terms of the GNU Public | |
23788 | + * License. | |
23789 | + * %End-Header% | |
23790 | + */ | |
23791 | + | |
23792 | +#if HAVE_SYS_TYPES_H | |
23793 | +#include <sys/types.h> | |
23794 | +#endif | |
23795 | + | |
23796 | +#if HAVE_ERRNO_H | |
23797 | +#include <errno.h> | |
23798 | +#endif | |
23799 | +#if HAVE_UNISTD_H | |
23800 | +#include <unistd.h> | |
23801 | +#endif | |
23802 | +#ifdef __MSDOS__ | |
23803 | +#include <io.h> | |
23804 | +#endif | |
23805 | +#include "et/com_err.h" | |
23806 | +#include "ext2fs/ext2_io.h" | |
23807 | + | |
23808 | +#ifdef __linux__ | |
23809 | + | |
23810 | +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) | |
23811 | + | |
23812 | +#define my_llseek lseek64 | |
23813 | + | |
23814 | +#else | |
23815 | +#if defined(HAVE_LLSEEK) | |
23816 | +#include <syscall.h> | |
23817 | + | |
23818 | +#ifndef HAVE_LLSEEK_PROTOTYPE | |
23819 | +extern long long llseek (int fd, long long offset, int origin); | |
23820 | +#endif | |
23821 | + | |
23822 | +#define my_llseek llseek | |
23823 | + | |
23824 | +#else /* ! HAVE_LLSEEK */ | |
23825 | + | |
23826 | +#if defined(__alpha__) || defined (__ia64__) | |
23827 | + | |
23828 | +#define llseek lseek | |
23829 | + | |
23830 | +#else /* !__alpha__ && !__ia64__*/ | |
23831 | + | |
23832 | +#include <linux/unistd.h> | |
23833 | + | |
23834 | +#ifndef __NR__llseek | |
23835 | +#define __NR__llseek 140 | |
23836 | +#endif | |
23837 | + | |
23838 | +#ifndef __i386__ | |
23839 | +static int _llseek (unsigned int, unsigned long, | |
23840 | + unsigned long, ext2_loff_t *, unsigned int); | |
23841 | + | |
23842 | +static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high, | |
23843 | + unsigned long, offset_low,ext2_loff_t *,result, | |
23844 | + unsigned int, origin) | |
23845 | +#endif | |
23846 | + | |
23847 | +static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin) | |
23848 | +{ | |
23849 | + ext2_loff_t result; | |
23850 | + int retval; | |
23851 | + | |
23852 | +#ifndef __i386__ | |
23853 | + retval = _llseek(fd, ((unsigned long long) offset) >> 32, | |
23854 | +#else | |
23855 | + retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32), | |
23856 | +#endif | |
23857 | + ((unsigned long long) offset) & 0xffffffff, | |
23858 | + &result, origin); | |
23859 | + return (retval == -1 ? (ext2_loff_t) retval : result); | |
23860 | +} | |
23861 | + | |
23862 | +#endif /* __alpha__ || __ia64__ */ | |
23863 | + | |
23864 | +#endif /* HAVE_LLSEEK */ | |
23865 | +#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */ | |
23866 | + | |
23867 | +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) | |
23868 | +{ | |
23869 | + ext2_loff_t result; | |
23870 | + static int do_compat = 0; | |
23871 | + | |
23872 | + if ((sizeof(off_t) >= sizeof(ext2_loff_t)) || | |
23873 | + (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) | |
23874 | + return lseek(fd, (off_t) offset, origin); | |
23875 | + | |
23876 | + if (do_compat) { | |
23877 | + errno = EINVAL; | |
23878 | + return -1; | |
23879 | + } | |
23880 | + | |
23881 | + result = my_llseek (fd, offset, origin); | |
23882 | + if (result == -1 && errno == ENOSYS) { | |
23883 | + /* | |
23884 | + * Just in case this code runs on top of an old kernel | |
23885 | + * which does not support the llseek system call | |
23886 | + */ | |
23887 | + do_compat++; | |
23888 | + errno = EINVAL; | |
23889 | + } | |
23890 | + return result; | |
23891 | +} | |
23892 | + | |
23893 | +#else /* !linux */ | |
23894 | + | |
23895 | +#ifndef EINVAL | |
23896 | +#define EINVAL EXT2_ET_INVALID_ARGUMENT | |
23897 | +#endif | |
23898 | + | |
23899 | +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) | |
23900 | +{ | |
23901 | +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) | |
23902 | + return lseek64 (fd, offset, origin); | |
23903 | +#else | |
23904 | + if ((sizeof(off_t) < sizeof(ext2_loff_t)) && | |
23905 | + (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) { | |
23906 | + errno = EINVAL; | |
23907 | + return -1; | |
23908 | + } | |
23909 | + return lseek (fd, (off_t) offset, origin); | |
23910 | +#endif | |
23911 | +} | |
23912 | + | |
23913 | +#endif /* linux */ | |
23914 | + | |
23915 | + | |
23916 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/lookup.c busybox/e2fsprogs/ext2fs/lookup.c | |
23917 | --- busybox-1.00/e2fsprogs/ext2fs/lookup.c 1970-01-01 01:00:00.000000000 +0100 | |
23918 | +++ busybox/e2fsprogs/ext2fs/lookup.c 2005-06-04 08:20:16.000000000 +0200 | |
23919 | @@ -0,0 +1,69 @@ | |
23920 | +/* | |
23921 | + * lookup.c --- ext2fs directory lookup operations | |
23922 | + * | |
23923 | + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. | |
23924 | + * | |
23925 | + * %Begin-Header% | |
23926 | + * This file may be redistributed under the terms of the GNU Public | |
23927 | + * License. | |
23928 | + * %End-Header% | |
23929 | + */ | |
23930 | + | |
23931 | +#include <stdio.h> | |
23932 | +#include <string.h> | |
23933 | +#if HAVE_UNISTD_H | |
23934 | +#include <unistd.h> | |
23935 | +#endif | |
23936 | + | |
23937 | +#include "ext2_fs.h" | |
23938 | +#include "ext2fs.h" | |
23939 | + | |
23940 | +struct lookup_struct { | |
23941 | + const char *name; | |
23942 | + int len; | |
23943 | + ext2_ino_t *inode; | |
23944 | + int found; | |
23945 | +}; | |
23946 | + | |
23947 | +#ifdef __TURBOC__ | |
23948 | + #pragma argsused | |
23949 | +#endif | |
23950 | +static int lookup_proc(struct ext2_dir_entry *dirent, | |
23951 | + int offset EXT2FS_ATTR((unused)), | |
23952 | + int blocksize EXT2FS_ATTR((unused)), | |
23953 | + char *buf EXT2FS_ATTR((unused)), | |
23954 | + void *priv_data) | |
23955 | +{ | |
23956 | + struct lookup_struct *ls = (struct lookup_struct *) priv_data; | |
23957 | + | |
23958 | + if (ls->len != (dirent->name_len & 0xFF)) | |
23959 | + return 0; | |
23960 | + if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF))) | |
23961 | + return 0; | |
23962 | + *ls->inode = dirent->inode; | |
23963 | + ls->found++; | |
23964 | + return DIRENT_ABORT; | |
23965 | +} | |
23966 | + | |
23967 | + | |
23968 | +errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, | |
23969 | + int namelen, char *buf, ext2_ino_t *inode) | |
23970 | +{ | |
23971 | + errcode_t retval; | |
23972 | + struct lookup_struct ls; | |
23973 | + | |
23974 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
23975 | + | |
23976 | + ls.name = name; | |
23977 | + ls.len = namelen; | |
23978 | + ls.inode = inode; | |
23979 | + ls.found = 0; | |
23980 | + | |
23981 | + retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls); | |
23982 | + if (retval) | |
23983 | + return retval; | |
23984 | + | |
23985 | + return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND; | |
23986 | +} | |
23987 | + | |
23988 | + | |
23989 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/mkdir.c busybox/e2fsprogs/ext2fs/mkdir.c | |
23990 | --- busybox-1.00/e2fsprogs/ext2fs/mkdir.c 1970-01-01 01:00:00.000000000 +0100 | |
23991 | +++ busybox/e2fsprogs/ext2fs/mkdir.c 2005-06-04 08:20:16.000000000 +0200 | |
23992 | @@ -0,0 +1,142 @@ | |
23993 | +/* | |
23994 | + * mkdir.c --- make a directory in the filesystem | |
23995 | + * | |
23996 | + * Copyright (C) 1994, 1995 Theodore Ts'o. | |
23997 | + * | |
23998 | + * %Begin-Header% | |
23999 | + * This file may be redistributed under the terms of the GNU Public | |
24000 | + * License. | |
24001 | + * %End-Header% | |
24002 | + */ | |
24003 | + | |
24004 | +#include <stdio.h> | |
24005 | +#include <string.h> | |
24006 | +#if HAVE_UNISTD_H | |
24007 | +#include <unistd.h> | |
24008 | +#endif | |
24009 | +#include <fcntl.h> | |
24010 | +#include <time.h> | |
24011 | +#if HAVE_SYS_STAT_H | |
24012 | +#include <sys/stat.h> | |
24013 | +#endif | |
24014 | +#if HAVE_SYS_TYPES_H | |
24015 | +#include <sys/types.h> | |
24016 | +#endif | |
24017 | + | |
24018 | +#include "ext2_fs.h" | |
24019 | +#include "ext2fs.h" | |
24020 | + | |
24021 | +#ifndef EXT2_FT_DIR | |
24022 | +#define EXT2_FT_DIR 2 | |
24023 | +#endif | |
24024 | + | |
24025 | +errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | |
24026 | + const char *name) | |
24027 | +{ | |
24028 | + errcode_t retval; | |
24029 | + struct ext2_inode parent_inode, inode; | |
24030 | + ext2_ino_t ino = inum; | |
24031 | + ext2_ino_t scratch_ino; | |
24032 | + blk_t blk; | |
24033 | + char *block = 0; | |
24034 | + | |
24035 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
24036 | + | |
24037 | + /* | |
24038 | + * Allocate an inode, if necessary | |
24039 | + */ | |
24040 | + if (!ino) { | |
24041 | + retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, | |
24042 | + 0, &ino); | |
24043 | + if (retval) | |
24044 | + goto cleanup; | |
24045 | + } | |
24046 | + | |
24047 | + /* | |
24048 | + * Allocate a data block for the directory | |
24049 | + */ | |
24050 | + retval = ext2fs_new_block(fs, 0, 0, &blk); | |
24051 | + if (retval) | |
24052 | + goto cleanup; | |
24053 | + | |
24054 | + /* | |
24055 | + * Create a scratch template for the directory | |
24056 | + */ | |
24057 | + retval = ext2fs_new_dir_block(fs, ino, parent, &block); | |
24058 | + if (retval) | |
24059 | + goto cleanup; | |
24060 | + | |
24061 | + /* | |
24062 | + * Get the parent's inode, if necessary | |
24063 | + */ | |
24064 | + if (parent != ino) { | |
24065 | + retval = ext2fs_read_inode(fs, parent, &parent_inode); | |
24066 | + if (retval) | |
24067 | + goto cleanup; | |
24068 | + } else | |
24069 | + memset(&parent_inode, 0, sizeof(parent_inode)); | |
24070 | + | |
24071 | + /* | |
24072 | + * Create the inode structure.... | |
24073 | + */ | |
24074 | + memset(&inode, 0, sizeof(struct ext2_inode)); | |
24075 | + inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); | |
24076 | + inode.i_uid = inode.i_gid = 0; | |
24077 | + inode.i_blocks = fs->blocksize / 512; | |
24078 | + inode.i_block[0] = blk; | |
24079 | + inode.i_links_count = 2; | |
24080 | + inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL); | |
24081 | + inode.i_size = fs->blocksize; | |
24082 | + | |
24083 | + /* | |
24084 | + * Write out the inode and inode data block | |
24085 | + */ | |
24086 | + retval = ext2fs_write_dir_block(fs, blk, block); | |
24087 | + if (retval) | |
24088 | + goto cleanup; | |
24089 | + retval = ext2fs_write_new_inode(fs, ino, &inode); | |
24090 | + if (retval) | |
24091 | + goto cleanup; | |
24092 | + | |
24093 | + /* | |
24094 | + * Link the directory into the filesystem hierarchy | |
24095 | + */ | |
24096 | + if (name) { | |
24097 | + retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, | |
24098 | + &scratch_ino); | |
24099 | + if (!retval) { | |
24100 | + retval = EXT2_ET_DIR_EXISTS; | |
24101 | + name = 0; | |
24102 | + goto cleanup; | |
24103 | + } | |
24104 | + if (retval != EXT2_ET_FILE_NOT_FOUND) | |
24105 | + goto cleanup; | |
24106 | + retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); | |
24107 | + if (retval) | |
24108 | + goto cleanup; | |
24109 | + } | |
24110 | + | |
24111 | + /* | |
24112 | + * Update parent inode's counts | |
24113 | + */ | |
24114 | + if (parent != ino) { | |
24115 | + parent_inode.i_links_count++; | |
24116 | + retval = ext2fs_write_inode(fs, parent, &parent_inode); | |
24117 | + if (retval) | |
24118 | + goto cleanup; | |
24119 | + } | |
24120 | + | |
24121 | + /* | |
24122 | + * Update accounting.... | |
24123 | + */ | |
24124 | + ext2fs_block_alloc_stats(fs, blk, +1); | |
24125 | + ext2fs_inode_alloc_stats2(fs, ino, +1, 1); | |
24126 | + | |
24127 | +cleanup: | |
24128 | + if (block) | |
24129 | + ext2fs_free_mem(&block); | |
24130 | + return retval; | |
24131 | + | |
24132 | +} | |
24133 | + | |
24134 | + | |
24135 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/mkjournal.c busybox/e2fsprogs/ext2fs/mkjournal.c | |
24136 | --- busybox-1.00/e2fsprogs/ext2fs/mkjournal.c 1970-01-01 01:00:00.000000000 +0100 | |
24137 | +++ busybox/e2fsprogs/ext2fs/mkjournal.c 2005-06-04 08:20:16.000000000 +0200 | |
24138 | @@ -0,0 +1,425 @@ | |
24139 | +/* | |
24140 | + * mkjournal.c --- make a journal for a filesystem | |
24141 | + * | |
24142 | + * Copyright (C) 2000 Theodore Ts'o. | |
24143 | + * | |
24144 | + * %Begin-Header% | |
24145 | + * This file may be redistributed under the terms of the GNU Public | |
24146 | + * License. | |
24147 | + * %End-Header% | |
24148 | + */ | |
24149 | + | |
24150 | +#include <stdio.h> | |
24151 | +#include <string.h> | |
24152 | +#if HAVE_UNISTD_H | |
24153 | +#include <unistd.h> | |
24154 | +#endif | |
24155 | +#if HAVE_ERRNO_H | |
24156 | +#include <errno.h> | |
24157 | +#endif | |
24158 | +#include <fcntl.h> | |
24159 | +#include <time.h> | |
24160 | +#if HAVE_SYS_STAT_H | |
24161 | +#include <sys/stat.h> | |
24162 | +#endif | |
24163 | +#if HAVE_SYS_TYPES_H | |
24164 | +#include <sys/types.h> | |
24165 | +#endif | |
24166 | +#if HAVE_SYS_IOCTL_H | |
24167 | +#include <sys/ioctl.h> | |
24168 | +#endif | |
24169 | +#if HAVE_NETINET_IN_H | |
24170 | +#include <netinet/in.h> | |
24171 | +#endif | |
24172 | + | |
24173 | +#include "ext2_fs.h" | |
24174 | +#include "e2p/e2p.h" | |
24175 | +#include "ext2fs.h" | |
24176 | +#include "jfs_user.h" | |
24177 | + | |
24178 | +/* | |
24179 | + * This function automatically sets up the journal superblock and | |
24180 | + * returns it as an allocated block. | |
24181 | + */ | |
24182 | +errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, | |
24183 | + __u32 size, int flags, | |
24184 | + char **ret_jsb) | |
24185 | +{ | |
24186 | + errcode_t retval; | |
24187 | + journal_superblock_t *jsb; | |
24188 | + | |
24189 | + if (size < 1024) | |
24190 | + return EXT2_ET_JOURNAL_TOO_SMALL; | |
24191 | + | |
24192 | + if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) | |
24193 | + return retval; | |
24194 | + | |
24195 | + memset (jsb, 0, fs->blocksize); | |
24196 | + | |
24197 | + jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); | |
24198 | + if (flags & EXT2_MKJOURNAL_V1_SUPER) | |
24199 | + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1); | |
24200 | + else | |
24201 | + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); | |
24202 | + jsb->s_blocksize = htonl(fs->blocksize); | |
24203 | + jsb->s_maxlen = htonl(size); | |
24204 | + jsb->s_nr_users = htonl(1); | |
24205 | + jsb->s_first = htonl(1); | |
24206 | + jsb->s_sequence = htonl(1); | |
24207 | + memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid)); | |
24208 | + /* | |
24209 | + * If we're creating an external journal device, we need to | |
24210 | + * adjust these fields. | |
24211 | + */ | |
24212 | + if (fs->super->s_feature_incompat & | |
24213 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { | |
24214 | + jsb->s_nr_users = 0; | |
24215 | + if (fs->blocksize == 1024) | |
24216 | + jsb->s_first = htonl(3); | |
24217 | + else | |
24218 | + jsb->s_first = htonl(2); | |
24219 | + } | |
24220 | + | |
24221 | + *ret_jsb = (char *) jsb; | |
24222 | + return 0; | |
24223 | +} | |
24224 | + | |
24225 | +/* | |
24226 | + * This function writes a journal using POSIX routines. It is used | |
24227 | + * for creating external journals and creating journals on live | |
24228 | + * filesystems. | |
24229 | + */ | |
24230 | +static errcode_t write_journal_file(ext2_filsys fs, char *filename, | |
24231 | + blk_t size, int flags) | |
24232 | +{ | |
24233 | + errcode_t retval; | |
24234 | + char *buf = 0; | |
24235 | + int fd, ret_size; | |
24236 | + blk_t i; | |
24237 | + | |
24238 | + if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) | |
24239 | + return retval; | |
24240 | + | |
24241 | + /* Open the device or journal file */ | |
24242 | + if ((fd = open(filename, O_WRONLY)) < 0) { | |
24243 | + retval = errno; | |
24244 | + goto errout; | |
24245 | + } | |
24246 | + | |
24247 | + /* Write the superblock out */ | |
24248 | + retval = EXT2_ET_SHORT_WRITE; | |
24249 | + ret_size = write(fd, buf, fs->blocksize); | |
24250 | + if (ret_size < 0) { | |
24251 | + retval = errno; | |
24252 | + goto errout; | |
24253 | + } | |
24254 | + if (ret_size != (int) fs->blocksize) | |
24255 | + goto errout; | |
24256 | + memset(buf, 0, fs->blocksize); | |
24257 | + | |
24258 | + for (i = 1; i < size; i++) { | |
24259 | + ret_size = write(fd, buf, fs->blocksize); | |
24260 | + if (ret_size < 0) { | |
24261 | + retval = errno; | |
24262 | + goto errout; | |
24263 | + } | |
24264 | + if (ret_size != (int) fs->blocksize) | |
24265 | + goto errout; | |
24266 | + } | |
24267 | + close(fd); | |
24268 | + | |
24269 | + retval = 0; | |
24270 | +errout: | |
24271 | + ext2fs_free_mem(&buf); | |
24272 | + return retval; | |
24273 | +} | |
24274 | + | |
24275 | +/* | |
24276 | + * Helper function for creating the journal using direct I/O routines | |
24277 | + */ | |
24278 | +struct mkjournal_struct { | |
24279 | + int num_blocks; | |
24280 | + int newblocks; | |
24281 | + char *buf; | |
24282 | + errcode_t err; | |
24283 | +}; | |
24284 | + | |
24285 | +static int mkjournal_proc(ext2_filsys fs, | |
24286 | + blk_t *blocknr, | |
24287 | + e2_blkcnt_t blockcnt, | |
24288 | + blk_t ref_block EXT2FS_ATTR((unused)), | |
24289 | + int ref_offset EXT2FS_ATTR((unused)), | |
24290 | + void *priv_data) | |
24291 | +{ | |
24292 | + struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data; | |
24293 | + blk_t new_blk; | |
24294 | + static blk_t last_blk = 0; | |
24295 | + errcode_t retval; | |
24296 | + | |
24297 | + if (*blocknr) { | |
24298 | + last_blk = *blocknr; | |
24299 | + return 0; | |
24300 | + } | |
24301 | + retval = ext2fs_new_block(fs, last_blk, 0, &new_blk); | |
24302 | + if (retval) { | |
24303 | + es->err = retval; | |
24304 | + return BLOCK_ABORT; | |
24305 | + } | |
24306 | + if (blockcnt > 0) | |
24307 | + es->num_blocks--; | |
24308 | + | |
24309 | + es->newblocks++; | |
24310 | + retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf); | |
24311 | + | |
24312 | + if (blockcnt == 0) | |
24313 | + memset(es->buf, 0, fs->blocksize); | |
24314 | + | |
24315 | + if (retval) { | |
24316 | + es->err = retval; | |
24317 | + return BLOCK_ABORT; | |
24318 | + } | |
24319 | + *blocknr = new_blk; | |
24320 | + last_blk = new_blk; | |
24321 | + ext2fs_block_alloc_stats(fs, new_blk, +1); | |
24322 | + | |
24323 | + if (es->num_blocks == 0) | |
24324 | + return (BLOCK_CHANGED | BLOCK_ABORT); | |
24325 | + else | |
24326 | + return BLOCK_CHANGED; | |
24327 | + | |
24328 | +} | |
24329 | + | |
24330 | +/* | |
24331 | + * This function creates a journal using direct I/O routines. | |
24332 | + */ | |
24333 | +static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, | |
24334 | + blk_t size, int flags) | |
24335 | +{ | |
24336 | + char *buf; | |
24337 | + errcode_t retval; | |
24338 | + struct ext2_inode inode; | |
24339 | + struct mkjournal_struct es; | |
24340 | + | |
24341 | + if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) | |
24342 | + return retval; | |
24343 | + | |
24344 | + if ((retval = ext2fs_read_bitmaps(fs))) | |
24345 | + return retval; | |
24346 | + | |
24347 | + if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) | |
24348 | + return retval; | |
24349 | + | |
24350 | + if (inode.i_blocks > 0) | |
24351 | + return EEXIST; | |
24352 | + | |
24353 | + es.num_blocks = size; | |
24354 | + es.newblocks = 0; | |
24355 | + es.buf = buf; | |
24356 | + es.err = 0; | |
24357 | + | |
24358 | + retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND, | |
24359 | + 0, mkjournal_proc, &es); | |
24360 | + if (es.err) { | |
24361 | + retval = es.err; | |
24362 | + goto errout; | |
24363 | + } | |
24364 | + | |
24365 | + if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) | |
24366 | + goto errout; | |
24367 | + | |
24368 | + inode.i_size += fs->blocksize * size; | |
24369 | + inode.i_blocks += (fs->blocksize / 512) * es.newblocks; | |
24370 | + inode.i_mtime = inode.i_ctime = time(0); | |
24371 | + inode.i_links_count = 1; | |
24372 | + inode.i_mode = LINUX_S_IFREG | 0600; | |
24373 | + | |
24374 | + if ((retval = ext2fs_write_inode(fs, journal_ino, &inode))) | |
24375 | + goto errout; | |
24376 | + retval = 0; | |
24377 | + | |
24378 | + memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); | |
24379 | + fs->super->s_jnl_blocks[16] = inode.i_size; | |
24380 | + fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; | |
24381 | + ext2fs_mark_super_dirty(fs); | |
24382 | + | |
24383 | +errout: | |
24384 | + ext2fs_free_mem(&buf); | |
24385 | + return retval; | |
24386 | +} | |
24387 | + | |
24388 | +/* | |
24389 | + * This function adds a journal device to a filesystem | |
24390 | + */ | |
24391 | +errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) | |
24392 | +{ | |
24393 | + struct stat st; | |
24394 | + errcode_t retval; | |
24395 | + char buf[1024]; | |
24396 | + journal_superblock_t *jsb; | |
24397 | + int start; | |
24398 | + __u32 i, nr_users; | |
24399 | + | |
24400 | + /* Make sure the device exists and is a block device */ | |
24401 | + if (stat(journal_dev->device_name, &st) < 0) | |
24402 | + return errno; | |
24403 | + | |
24404 | + if (!S_ISBLK(st.st_mode)) | |
24405 | + return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */ | |
24406 | + | |
24407 | + /* Get the journal superblock */ | |
24408 | + start = 1; | |
24409 | + if (journal_dev->blocksize == 1024) | |
24410 | + start++; | |
24411 | + if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf))) | |
24412 | + return retval; | |
24413 | + | |
24414 | + jsb = (journal_superblock_t *) buf; | |
24415 | + if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || | |
24416 | + (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) | |
24417 | + return EXT2_ET_NO_JOURNAL_SB; | |
24418 | + | |
24419 | + if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize) | |
24420 | + return EXT2_ET_UNEXPECTED_BLOCK_SIZE; | |
24421 | + | |
24422 | + /* Check and see if this filesystem has already been added */ | |
24423 | + nr_users = ntohl(jsb->s_nr_users); | |
24424 | + for (i=0; i < nr_users; i++) { | |
24425 | + if (memcmp(fs->super->s_uuid, | |
24426 | + &jsb->s_users[i*16], 16) == 0) | |
24427 | + break; | |
24428 | + } | |
24429 | + if (i >= nr_users) { | |
24430 | + memcpy(&jsb->s_users[nr_users*16], | |
24431 | + fs->super->s_uuid, 16); | |
24432 | + jsb->s_nr_users = htonl(nr_users+1); | |
24433 | + } | |
24434 | + | |
24435 | + /* Writeback the journal superblock */ | |
24436 | + if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf))) | |
24437 | + return retval; | |
24438 | + | |
24439 | + fs->super->s_journal_inum = 0; | |
24440 | + fs->super->s_journal_dev = st.st_rdev; | |
24441 | + memcpy(fs->super->s_journal_uuid, jsb->s_uuid, | |
24442 | + sizeof(fs->super->s_journal_uuid)); | |
24443 | + fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; | |
24444 | + ext2fs_mark_super_dirty(fs); | |
24445 | + return 0; | |
24446 | +} | |
24447 | + | |
24448 | +/* | |
24449 | + * This function adds a journal inode to a filesystem, using either | |
24450 | + * POSIX routines if the filesystem is mounted, or using direct I/O | |
24451 | + * functions if it is not. | |
24452 | + */ | |
24453 | +errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) | |
24454 | +{ | |
24455 | + errcode_t retval; | |
24456 | + ext2_ino_t journal_ino; | |
24457 | + struct stat st; | |
24458 | + char jfile[1024]; | |
24459 | + int fd, mount_flags, f; | |
24460 | + | |
24461 | + if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags, | |
24462 | + jfile, sizeof(jfile)-10))) | |
24463 | + return retval; | |
24464 | + | |
24465 | + if (mount_flags & EXT2_MF_MOUNTED) { | |
24466 | + strcat(jfile, "/.journal"); | |
24467 | + | |
24468 | + /* | |
24469 | + * If .../.journal already exists, make sure any | |
24470 | + * immutable or append-only flags are cleared. | |
24471 | + */ | |
24472 | +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) | |
24473 | + (void) chflags (jfile, 0); | |
24474 | +#else | |
24475 | +#if HAVE_EXT2_IOCTLS | |
24476 | + fd = open(jfile, O_RDONLY); | |
24477 | + if (fd >= 0) { | |
24478 | + f = 0; | |
24479 | + ioctl(fd, EXT2_IOC_SETFLAGS, &f); | |
24480 | + close(fd); | |
24481 | + } | |
24482 | +#endif | |
24483 | +#endif | |
24484 | + | |
24485 | + /* Create the journal file */ | |
24486 | + if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) | |
24487 | + return errno; | |
24488 | + | |
24489 | + if ((retval = write_journal_file(fs, jfile, size, flags))) | |
24490 | + goto errout; | |
24491 | + | |
24492 | + /* Get inode number of the journal file */ | |
24493 | + if (fstat(fd, &st) < 0) | |
24494 | + goto errout; | |
24495 | + | |
24496 | +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) | |
24497 | + retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); | |
24498 | +#else | |
24499 | +#if HAVE_EXT2_IOCTLS | |
24500 | + f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL; | |
24501 | + retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); | |
24502 | +#endif | |
24503 | +#endif | |
24504 | + if (retval) | |
24505 | + goto errout; | |
24506 | + | |
24507 | + close(fd); | |
24508 | + journal_ino = st.st_ino; | |
24509 | + } else { | |
24510 | + journal_ino = EXT2_JOURNAL_INO; | |
24511 | + if ((retval = write_journal_inode(fs, journal_ino, | |
24512 | + size, flags))) | |
24513 | + return retval; | |
24514 | + } | |
24515 | + | |
24516 | + fs->super->s_journal_inum = journal_ino; | |
24517 | + fs->super->s_journal_dev = 0; | |
24518 | + memset(fs->super->s_journal_uuid, 0, | |
24519 | + sizeof(fs->super->s_journal_uuid)); | |
24520 | + fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; | |
24521 | + | |
24522 | + ext2fs_mark_super_dirty(fs); | |
24523 | + return 0; | |
24524 | +errout: | |
24525 | + close(fd); | |
24526 | + return retval; | |
24527 | +} | |
24528 | + | |
24529 | +#ifdef DEBUG | |
24530 | +main(int argc, char **argv) | |
24531 | +{ | |
24532 | + errcode_t retval; | |
24533 | + char *device_name; | |
24534 | + ext2_filsys fs; | |
24535 | + | |
24536 | + if (argc < 2) { | |
24537 | + fprintf(stderr, "Usage: %s filesystem\n", argv[0]); | |
24538 | + exit(1); | |
24539 | + } | |
24540 | + device_name = argv[1]; | |
24541 | + | |
24542 | + retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, | |
24543 | + unix_io_manager, &fs); | |
24544 | + if (retval) { | |
24545 | + com_err(argv[0], retval, "while opening %s", device_name); | |
24546 | + exit(1); | |
24547 | + } | |
24548 | + | |
24549 | + retval = ext2fs_add_journal_inode(fs, 1024); | |
24550 | + if (retval) { | |
24551 | + com_err(argv[0], retval, "while adding journal to %s", | |
24552 | + device_name); | |
24553 | + exit(1); | |
24554 | + } | |
24555 | + retval = ext2fs_flush(fs); | |
24556 | + if (retval) { | |
24557 | + printf("Warning, had trouble writing out superblocks.\n"); | |
24558 | + } | |
24559 | + ext2fs_close(fs); | |
24560 | + exit(0); | |
24561 | + | |
24562 | +} | |
24563 | +#endif | |
24564 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/namei.c busybox/e2fsprogs/ext2fs/namei.c | |
24565 | --- busybox-1.00/e2fsprogs/ext2fs/namei.c 1970-01-01 01:00:00.000000000 +0100 | |
24566 | +++ busybox/e2fsprogs/ext2fs/namei.c 2005-06-04 08:20:16.000000000 +0200 | |
24567 | @@ -0,0 +1,205 @@ | |
24568 | +/* | |
24569 | + * namei.c --- ext2fs directory lookup operations | |
24570 | + * | |
24571 | + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. | |
24572 | + * | |
24573 | + * %Begin-Header% | |
24574 | + * This file may be redistributed under the terms of the GNU Public | |
24575 | + * License. | |
24576 | + * %End-Header% | |
24577 | + */ | |
24578 | + | |
24579 | +#include <stdio.h> | |
24580 | +#include <string.h> | |
24581 | +#if HAVE_UNISTD_H | |
24582 | +#include <unistd.h> | |
24583 | +#endif | |
24584 | + | |
24585 | +/* #define NAMEI_DEBUG */ | |
24586 | + | |
24587 | +#include "ext2_fs.h" | |
24588 | +#include "ext2fs.h" | |
24589 | + | |
24590 | +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, | |
24591 | + const char *pathname, size_t pathlen, int follow, | |
24592 | + int link_count, char *buf, ext2_ino_t *res_inode); | |
24593 | + | |
24594 | +static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, | |
24595 | + ext2_ino_t inode, int link_count, | |
24596 | + char *buf, ext2_ino_t *res_inode) | |
24597 | +{ | |
24598 | + char *pathname; | |
24599 | + char *buffer = 0; | |
24600 | + errcode_t retval; | |
24601 | + struct ext2_inode ei; | |
24602 | + | |
24603 | +#ifdef NAMEI_DEBUG | |
24604 | + printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", | |
24605 | + root, dir, inode, link_count); | |
24606 | + | |
24607 | +#endif | |
24608 | + retval = ext2fs_read_inode (fs, inode, &ei); | |
24609 | + if (retval) return retval; | |
24610 | + if (!LINUX_S_ISLNK (ei.i_mode)) { | |
24611 | + *res_inode = inode; | |
24612 | + return 0; | |
24613 | + } | |
24614 | + if (link_count++ > 5) { | |
24615 | + return EXT2_ET_SYMLINK_LOOP; | |
24616 | + } | |
24617 | + if (ext2fs_inode_data_blocks(fs,&ei)) { | |
24618 | + retval = ext2fs_get_mem(fs->blocksize, &buffer); | |
24619 | + if (retval) | |
24620 | + return retval; | |
24621 | + retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer); | |
24622 | + if (retval) { | |
24623 | + ext2fs_free_mem(&buffer); | |
24624 | + return retval; | |
24625 | + } | |
24626 | + pathname = buffer; | |
24627 | + } else | |
24628 | + pathname = (char *)&(ei.i_block[0]); | |
24629 | + retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, | |
24630 | + link_count, buf, res_inode); | |
24631 | + if (buffer) | |
24632 | + ext2fs_free_mem(&buffer); | |
24633 | + return retval; | |
24634 | +} | |
24635 | + | |
24636 | +/* | |
24637 | + * This routine interprets a pathname in the context of the current | |
24638 | + * directory and the root directory, and returns the inode of the | |
24639 | + * containing directory, and a pointer to the filename of the file | |
24640 | + * (pointing into the pathname) and the length of the filename. | |
24641 | + */ | |
24642 | +static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, | |
24643 | + const char *pathname, int pathlen, | |
24644 | + int link_count, char *buf, | |
24645 | + const char **name, int *namelen, | |
24646 | + ext2_ino_t *res_inode) | |
24647 | +{ | |
24648 | + char c; | |
24649 | + const char *thisname; | |
24650 | + int len; | |
24651 | + ext2_ino_t inode; | |
24652 | + errcode_t retval; | |
24653 | + | |
24654 | + if ((c = *pathname) == '/') { | |
24655 | + dir = root; | |
24656 | + pathname++; | |
24657 | + pathlen--; | |
24658 | + } | |
24659 | + while (1) { | |
24660 | + thisname = pathname; | |
24661 | + for (len=0; --pathlen >= 0;len++) { | |
24662 | + c = *(pathname++); | |
24663 | + if (c == '/') | |
24664 | + break; | |
24665 | + } | |
24666 | + if (pathlen < 0) | |
24667 | + break; | |
24668 | + retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode); | |
24669 | + if (retval) return retval; | |
24670 | + retval = follow_link (fs, root, dir, inode, | |
24671 | + link_count, buf, &dir); | |
24672 | + if (retval) return retval; | |
24673 | + } | |
24674 | + *name = thisname; | |
24675 | + *namelen = len; | |
24676 | + *res_inode = dir; | |
24677 | + return 0; | |
24678 | +} | |
24679 | + | |
24680 | +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, | |
24681 | + const char *pathname, size_t pathlen, int follow, | |
24682 | + int link_count, char *buf, ext2_ino_t *res_inode) | |
24683 | +{ | |
24684 | + const char *basename; | |
24685 | + int namelen; | |
24686 | + ext2_ino_t dir, inode; | |
24687 | + errcode_t retval; | |
24688 | + | |
24689 | +#ifdef NAMEI_DEBUG | |
24690 | + printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n", | |
24691 | + root, base, pathlen, pathname, link_count); | |
24692 | +#endif | |
24693 | + retval = dir_namei(fs, root, base, pathname, pathlen, | |
24694 | + link_count, buf, &basename, &namelen, &dir); | |
24695 | + if (retval) return retval; | |
24696 | + if (!namelen) { /* special case: '/usr/' etc */ | |
24697 | + *res_inode=dir; | |
24698 | + return 0; | |
24699 | + } | |
24700 | + retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode); | |
24701 | + if (retval) | |
24702 | + return retval; | |
24703 | + if (follow) { | |
24704 | + retval = follow_link(fs, root, dir, inode, link_count, | |
24705 | + buf, &inode); | |
24706 | + if (retval) | |
24707 | + return retval; | |
24708 | + } | |
24709 | +#ifdef NAMEI_DEBUG | |
24710 | + printf("open_namei: (link_count=%d) returns %lu\n", | |
24711 | + link_count, inode); | |
24712 | +#endif | |
24713 | + *res_inode = inode; | |
24714 | + return 0; | |
24715 | +} | |
24716 | + | |
24717 | +errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, | |
24718 | + const char *name, ext2_ino_t *inode) | |
24719 | +{ | |
24720 | + char *buf; | |
24721 | + errcode_t retval; | |
24722 | + | |
24723 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
24724 | + | |
24725 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
24726 | + if (retval) | |
24727 | + return retval; | |
24728 | + | |
24729 | + retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0, | |
24730 | + buf, inode); | |
24731 | + | |
24732 | + ext2fs_free_mem(&buf); | |
24733 | + return retval; | |
24734 | +} | |
24735 | + | |
24736 | +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, | |
24737 | + const char *name, ext2_ino_t *inode) | |
24738 | +{ | |
24739 | + char *buf; | |
24740 | + errcode_t retval; | |
24741 | + | |
24742 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
24743 | + | |
24744 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
24745 | + if (retval) | |
24746 | + return retval; | |
24747 | + | |
24748 | + retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0, | |
24749 | + buf, inode); | |
24750 | + | |
24751 | + ext2fs_free_mem(&buf); | |
24752 | + return retval; | |
24753 | +} | |
24754 | + | |
24755 | +errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, | |
24756 | + ext2_ino_t inode, ext2_ino_t *res_inode) | |
24757 | +{ | |
24758 | + char *buf; | |
24759 | + errcode_t retval; | |
24760 | + | |
24761 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
24762 | + | |
24763 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
24764 | + if (retval) | |
24765 | + return retval; | |
24766 | + | |
24767 | + retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode); | |
24768 | + | |
24769 | + ext2fs_free_mem(&buf); | |
24770 | + return retval; | |
24771 | +} | |
24772 | + | |
24773 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/native.c busybox/e2fsprogs/ext2fs/native.c | |
24774 | --- busybox-1.00/e2fsprogs/ext2fs/native.c 1970-01-01 01:00:00.000000000 +0100 | |
24775 | +++ busybox/e2fsprogs/ext2fs/native.c 2005-06-04 08:20:16.000000000 +0200 | |
24776 | @@ -0,0 +1,27 @@ | |
24777 | +/* | |
24778 | + * native.c --- returns the ext2_flag for a native byte order | |
24779 | + * | |
24780 | + * Copyright (C) 1996 Theodore Ts'o. | |
24781 | + * | |
24782 | + * %Begin-Header% | |
24783 | + * This file may be redistributed under the terms of the GNU Public | |
24784 | + * License. | |
24785 | + * %End-Header% | |
24786 | + */ | |
24787 | + | |
24788 | +#include <stdio.h> | |
24789 | + | |
24790 | +#include "ext2_fs.h" | |
24791 | +#include "ext2fs.h" | |
24792 | + | |
24793 | +int ext2fs_native_flag(void) | |
24794 | +{ | |
24795 | +#ifdef WORDS_BIGENDIAN | |
24796 | + return EXT2_FLAG_SWAP_BYTES; | |
24797 | +#else | |
24798 | + return 0; | |
24799 | +#endif | |
24800 | +} | |
24801 | + | |
24802 | + | |
24803 | + | |
24804 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/newdir.c busybox/e2fsprogs/ext2fs/newdir.c | |
24805 | --- busybox-1.00/e2fsprogs/ext2fs/newdir.c 1970-01-01 01:00:00.000000000 +0100 | |
24806 | +++ busybox/e2fsprogs/ext2fs/newdir.c 2005-06-04 08:20:16.000000000 +0200 | |
24807 | @@ -0,0 +1,72 @@ | |
24808 | +/* | |
24809 | + * newdir.c --- create a new directory block | |
24810 | + * | |
24811 | + * Copyright (C) 1994, 1995 Theodore Ts'o. | |
24812 | + * | |
24813 | + * %Begin-Header% | |
24814 | + * This file may be redistributed under the terms of the GNU Public | |
24815 | + * License. | |
24816 | + * %End-Header% | |
24817 | + */ | |
24818 | + | |
24819 | +#include <stdio.h> | |
24820 | +#include <string.h> | |
24821 | +#if HAVE_UNISTD_H | |
24822 | +#include <unistd.h> | |
24823 | +#endif | |
24824 | + | |
24825 | +#include "ext2_fs.h" | |
24826 | +#include "ext2fs.h" | |
24827 | + | |
24828 | +#ifndef EXT2_FT_DIR | |
24829 | +#define EXT2_FT_DIR 2 | |
24830 | +#endif | |
24831 | + | |
24832 | +/* | |
24833 | + * Create new directory block | |
24834 | + */ | |
24835 | +errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, | |
24836 | + ext2_ino_t parent_ino, char **block) | |
24837 | +{ | |
24838 | + struct ext2_dir_entry *dir = NULL; | |
24839 | + errcode_t retval; | |
24840 | + char *buf; | |
24841 | + int rec_len; | |
24842 | + int filetype = 0; | |
24843 | + | |
24844 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
24845 | + | |
24846 | + retval = ext2fs_get_mem(fs->blocksize, &buf); | |
24847 | + if (retval) | |
24848 | + return retval; | |
24849 | + memset(buf, 0, fs->blocksize); | |
24850 | + dir = (struct ext2_dir_entry *) buf; | |
24851 | + dir->rec_len = fs->blocksize; | |
24852 | + | |
24853 | + if (dir_ino) { | |
24854 | + if (fs->super->s_feature_incompat & | |
24855 | + EXT2_FEATURE_INCOMPAT_FILETYPE) | |
24856 | + filetype = EXT2_FT_DIR << 8; | |
24857 | + /* | |
24858 | + * Set up entry for '.' | |
24859 | + */ | |
24860 | + dir->inode = dir_ino; | |
24861 | + dir->name_len = 1 | filetype; | |
24862 | + dir->name[0] = '.'; | |
24863 | + rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1); | |
24864 | + dir->rec_len = EXT2_DIR_REC_LEN(1); | |
24865 | + | |
24866 | + /* | |
24867 | + * Set up entry for '..' | |
24868 | + */ | |
24869 | + dir = (struct ext2_dir_entry *) (buf + dir->rec_len); | |
24870 | + dir->rec_len = rec_len; | |
24871 | + dir->inode = parent_ino; | |
24872 | + dir->name_len = 2 | filetype; | |
24873 | + dir->name[0] = '.'; | |
24874 | + dir->name[1] = '.'; | |
24875 | + | |
24876 | + } | |
24877 | + *block = buf; | |
24878 | + return 0; | |
24879 | +} | |
24880 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/openfs.c busybox/e2fsprogs/ext2fs/openfs.c | |
24881 | --- busybox-1.00/e2fsprogs/ext2fs/openfs.c 1970-01-01 01:00:00.000000000 +0100 | |
24882 | +++ busybox/e2fsprogs/ext2fs/openfs.c 2005-06-04 08:20:16.000000000 +0200 | |
24883 | @@ -0,0 +1,326 @@ | |
24884 | +/* | |
24885 | + * openfs.c --- open an ext2 filesystem | |
24886 | + * | |
24887 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
24888 | + * | |
24889 | + * %Begin-Header% | |
24890 | + * This file may be redistributed under the terms of the GNU Public | |
24891 | + * License. | |
24892 | + * %End-Header% | |
24893 | + */ | |
24894 | + | |
24895 | +#include <stdio.h> | |
24896 | +#include <string.h> | |
24897 | +#if HAVE_UNISTD_H | |
24898 | +#include <unistd.h> | |
24899 | +#endif | |
24900 | +#include <fcntl.h> | |
24901 | +#include <time.h> | |
24902 | +#if HAVE_SYS_STAT_H | |
24903 | +#include <sys/stat.h> | |
24904 | +#endif | |
24905 | +#if HAVE_SYS_TYPES_H | |
24906 | +#include <sys/types.h> | |
24907 | +#endif | |
24908 | + | |
24909 | +#include "ext2_fs.h" | |
24910 | + | |
24911 | + | |
24912 | +#include "ext2fs.h" | |
24913 | +#include "e2image.h" | |
24914 | + | |
24915 | +blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i) | |
24916 | +{ | |
24917 | + int bg; | |
24918 | + int has_super = 0; | |
24919 | + int ret_blk; | |
24920 | + | |
24921 | + if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || | |
24922 | + (i < fs->super->s_first_meta_bg)) | |
24923 | + return (group_block + i + 1); | |
24924 | + | |
24925 | + bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i; | |
24926 | + if (ext2fs_bg_has_super(fs, bg)) | |
24927 | + has_super = 1; | |
24928 | + ret_blk = (fs->super->s_first_data_block + has_super + | |
24929 | + (bg * fs->super->s_blocks_per_group)); | |
24930 | + /* | |
24931 | + * If group_block is not the normal value, we're trying to use | |
24932 | + * the backup group descriptors and superblock --- so use the | |
24933 | + * alternate location of the second block group in the | |
24934 | + * metablock group. Ideally we should be testing each bg | |
24935 | + * descriptor block individually for correctness, but we don't | |
24936 | + * have the infrastructure in place to do that. | |
24937 | + */ | |
24938 | + if (group_block != fs->super->s_first_data_block && | |
24939 | + ((ret_blk + fs->super->s_blocks_per_group) < | |
24940 | + fs->super->s_blocks_count)) | |
24941 | + ret_blk += fs->super->s_blocks_per_group; | |
24942 | + return ret_blk; | |
24943 | +} | |
24944 | + | |
24945 | +errcode_t ext2fs_open(const char *name, int flags, int superblock, | |
24946 | + unsigned int block_size, io_manager manager, | |
24947 | + ext2_filsys *ret_fs) | |
24948 | +{ | |
24949 | + return ext2fs_open2(name, 0, flags, superblock, block_size, | |
24950 | + manager, ret_fs); | |
24951 | +} | |
24952 | + | |
24953 | +/* | |
24954 | + * Note: if superblock is non-zero, block-size must also be non-zero. | |
24955 | + * Superblock and block_size can be zero to use the default size. | |
24956 | + * | |
24957 | + * Valid flags for ext2fs_open() | |
24958 | + * | |
24959 | + * EXT2_FLAG_RW - Open the filesystem for read/write. | |
24960 | + * EXT2_FLAG_FORCE - Open the filesystem even if some of the | |
24961 | + * features aren't supported. | |
24962 | + * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device | |
24963 | + */ | |
24964 | +errcode_t ext2fs_open2(const char *name, const char *io_options, | |
24965 | + int flags, int superblock, | |
24966 | + unsigned int block_size, io_manager manager, | |
24967 | + ext2_filsys *ret_fs) | |
24968 | +{ | |
24969 | + ext2_filsys fs; | |
24970 | + errcode_t retval; | |
24971 | + unsigned long i; | |
24972 | + int j, groups_per_block, blocks_per_group; | |
24973 | + blk_t group_block, blk; | |
24974 | + char *dest, *cp; | |
24975 | + struct ext2_group_desc *gdp; | |
24976 | + | |
24977 | + EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); | |
24978 | + | |
24979 | + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); | |
24980 | + if (retval) | |
24981 | + return retval; | |
24982 | + | |
24983 | + memset(fs, 0, sizeof(struct struct_ext2_filsys)); | |
24984 | + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; | |
24985 | + fs->flags = flags; | |
24986 | + fs->umask = 022; | |
24987 | + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); | |
24988 | + if (retval) | |
24989 | + goto cleanup; | |
24990 | + strcpy(fs->device_name, name); | |
24991 | + cp = strchr(fs->device_name, '?'); | |
24992 | + if (!io_options && cp) { | |
24993 | + *cp++ = 0; | |
24994 | + io_options = cp; | |
24995 | + } | |
24996 | + | |
24997 | + retval = manager->open(fs->device_name, | |
24998 | + (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0, | |
24999 | + &fs->io); | |
25000 | + if (retval) | |
25001 | + goto cleanup; | |
25002 | + if (io_options && | |
25003 | + (retval = io_channel_set_options(fs->io, io_options))) | |
25004 | + goto cleanup; | |
25005 | + fs->image_io = fs->io; | |
25006 | + fs->io->app_data = fs; | |
25007 | + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super); | |
25008 | + if (retval) | |
25009 | + goto cleanup; | |
25010 | + if (flags & EXT2_FLAG_IMAGE_FILE) { | |
25011 | + retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr), | |
25012 | + &fs->image_header); | |
25013 | + if (retval) | |
25014 | + goto cleanup; | |
25015 | + retval = io_channel_read_blk(fs->io, 0, | |
25016 | + -(int)sizeof(struct ext2_image_hdr), | |
25017 | + fs->image_header); | |
25018 | + if (retval) | |
25019 | + goto cleanup; | |
25020 | + if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE) | |
25021 | + return EXT2_ET_MAGIC_E2IMAGE; | |
25022 | + superblock = 1; | |
25023 | + block_size = fs->image_header->fs_blocksize; | |
25024 | + } | |
25025 | + | |
25026 | + /* | |
25027 | + * If the user specifies a specific block # for the | |
25028 | + * superblock, then he/she must also specify the block size! | |
25029 | + * Otherwise, read the master superblock located at offset | |
25030 | + * SUPERBLOCK_OFFSET from the start of the partition. | |
25031 | + * | |
25032 | + * Note: we only save a backup copy of the superblock if we | |
25033 | + * are reading the superblock from the primary superblock location. | |
25034 | + */ | |
25035 | + if (superblock) { | |
25036 | + if (!block_size) { | |
25037 | + retval = EXT2_ET_INVALID_ARGUMENT; | |
25038 | + goto cleanup; | |
25039 | + } | |
25040 | + io_channel_set_blksize(fs->io, block_size); | |
25041 | + group_block = superblock; | |
25042 | + fs->orig_super = 0; | |
25043 | + } else { | |
25044 | + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); | |
25045 | + superblock = 1; | |
25046 | + group_block = 0; | |
25047 | + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); | |
25048 | + if (retval) | |
25049 | + goto cleanup; | |
25050 | + } | |
25051 | + retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, | |
25052 | + fs->super); | |
25053 | + if (retval) | |
25054 | + goto cleanup; | |
25055 | + if (fs->orig_super) | |
25056 | + memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE); | |
25057 | + | |
25058 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
25059 | + if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) || | |
25060 | + (fs->flags & EXT2_FLAG_SWAP_BYTES)) { | |
25061 | + fs->flags |= EXT2_FLAG_SWAP_BYTES; | |
25062 | + | |
25063 | + ext2fs_swap_super(fs->super); | |
25064 | + } | |
25065 | +#endif | |
25066 | + | |
25067 | + if (fs->super->s_magic != EXT2_SUPER_MAGIC) { | |
25068 | + retval = EXT2_ET_BAD_MAGIC; | |
25069 | + goto cleanup; | |
25070 | + } | |
25071 | + if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) { | |
25072 | + retval = EXT2_ET_REV_TOO_HIGH; | |
25073 | + goto cleanup; | |
25074 | + } | |
25075 | + | |
25076 | + /* | |
25077 | + * Check for feature set incompatibility | |
25078 | + */ | |
25079 | + if (!(flags & EXT2_FLAG_FORCE)) { | |
25080 | + if (fs->super->s_feature_incompat & | |
25081 | + ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { | |
25082 | + retval = EXT2_ET_UNSUPP_FEATURE; | |
25083 | + goto cleanup; | |
25084 | + } | |
25085 | + if ((flags & EXT2_FLAG_RW) && | |
25086 | + (fs->super->s_feature_ro_compat & | |
25087 | + ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { | |
25088 | + retval = EXT2_ET_RO_UNSUPP_FEATURE; | |
25089 | + goto cleanup; | |
25090 | + } | |
25091 | + if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) && | |
25092 | + (fs->super->s_feature_incompat & | |
25093 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { | |
25094 | + retval = EXT2_ET_UNSUPP_FEATURE; | |
25095 | + goto cleanup; | |
25096 | + } | |
25097 | + } | |
25098 | + | |
25099 | + fs->blocksize = EXT2_BLOCK_SIZE(fs->super); | |
25100 | + if (fs->blocksize == 0) { | |
25101 | + retval = EXT2_ET_CORRUPT_SUPERBLOCK; | |
25102 | + goto cleanup; | |
25103 | + } | |
25104 | + fs->fragsize = EXT2_FRAG_SIZE(fs->super); | |
25105 | + fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group * | |
25106 | + EXT2_INODE_SIZE(fs->super) + | |
25107 | + EXT2_BLOCK_SIZE(fs->super) - 1) / | |
25108 | + EXT2_BLOCK_SIZE(fs->super)); | |
25109 | + if (block_size) { | |
25110 | + if (block_size != fs->blocksize) { | |
25111 | + retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE; | |
25112 | + goto cleanup; | |
25113 | + } | |
25114 | + } | |
25115 | + /* | |
25116 | + * Set the blocksize to the filesystem's blocksize. | |
25117 | + */ | |
25118 | + io_channel_set_blksize(fs->io, fs->blocksize); | |
25119 | + | |
25120 | + /* | |
25121 | + * If this is an external journal device, don't try to read | |
25122 | + * the group descriptors, because they're not there. | |
25123 | + */ | |
25124 | + if (fs->super->s_feature_incompat & | |
25125 | + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { | |
25126 | + fs->group_desc_count = 0; | |
25127 | + *ret_fs = fs; | |
25128 | + return 0; | |
25129 | + } | |
25130 | + | |
25131 | + /* | |
25132 | + * Read group descriptors | |
25133 | + */ | |
25134 | + blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super); | |
25135 | + if (blocks_per_group == 0 || | |
25136 | + blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) || | |
25137 | + fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) { | |
25138 | + retval = EXT2_ET_CORRUPT_SUPERBLOCK; | |
25139 | + goto cleanup; | |
25140 | + } | |
25141 | + fs->group_desc_count = (fs->super->s_blocks_count - | |
25142 | + fs->super->s_first_data_block + | |
25143 | + blocks_per_group - 1) / blocks_per_group; | |
25144 | + fs->desc_blocks = (fs->group_desc_count + | |
25145 | + EXT2_DESC_PER_BLOCK(fs->super) - 1) | |
25146 | + / EXT2_DESC_PER_BLOCK(fs->super); | |
25147 | + retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize, | |
25148 | + &fs->group_desc); | |
25149 | + if (retval) | |
25150 | + goto cleanup; | |
25151 | + if (!group_block) | |
25152 | + group_block = fs->super->s_first_data_block; | |
25153 | + dest = (char *) fs->group_desc; | |
25154 | + groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc); | |
25155 | + for (i=0 ; i < fs->desc_blocks; i++) { | |
25156 | + blk = ext2fs_descriptor_block_loc(fs, group_block, i); | |
25157 | + retval = io_channel_read_blk(fs->io, blk, 1, dest); | |
25158 | + if (retval) | |
25159 | + goto cleanup; | |
25160 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
25161 | + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | |
25162 | + gdp = (struct ext2_group_desc *) dest; | |
25163 | + for (j=0; j < groups_per_block; j++) | |
25164 | + ext2fs_swap_group_desc(gdp++); | |
25165 | + } | |
25166 | +#endif | |
25167 | + dest += fs->blocksize; | |
25168 | + } | |
25169 | + | |
25170 | + *ret_fs = fs; | |
25171 | + return 0; | |
25172 | +cleanup: | |
25173 | + ext2fs_free(fs); | |
25174 | + return retval; | |
25175 | +} | |
25176 | + | |
25177 | +/* | |
25178 | + * Set/get the filesystem data I/O channel. | |
25179 | + * | |
25180 | + * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true. | |
25181 | + */ | |
25182 | +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io) | |
25183 | +{ | |
25184 | + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) | |
25185 | + return EXT2_ET_NOT_IMAGE_FILE; | |
25186 | + if (old_io) { | |
25187 | + *old_io = (fs->image_io == fs->io) ? 0 : fs->io; | |
25188 | + } | |
25189 | + return 0; | |
25190 | +} | |
25191 | + | |
25192 | +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io) | |
25193 | +{ | |
25194 | + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) | |
25195 | + return EXT2_ET_NOT_IMAGE_FILE; | |
25196 | + fs->io = new_io ? new_io : fs->image_io; | |
25197 | + return 0; | |
25198 | +} | |
25199 | + | |
25200 | +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io) | |
25201 | +{ | |
25202 | + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) | |
25203 | + return EXT2_ET_NOT_IMAGE_FILE; | |
25204 | + fs->io = fs->image_io = new_io; | |
25205 | + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW | | |
25206 | + EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY; | |
25207 | + fs->flags &= ~EXT2_FLAG_IMAGE_FILE; | |
25208 | + return 0; | |
25209 | +} | |
25210 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/read_bb.c busybox/e2fsprogs/ext2fs/read_bb.c | |
25211 | --- busybox-1.00/e2fsprogs/ext2fs/read_bb.c 1970-01-01 01:00:00.000000000 +0100 | |
25212 | +++ busybox/e2fsprogs/ext2fs/read_bb.c 2005-06-04 08:20:16.000000000 +0200 | |
25213 | @@ -0,0 +1,97 @@ | |
25214 | +/* | |
25215 | + * read_bb --- read the bad blocks inode | |
25216 | + * | |
25217 | + * Copyright (C) 1994 Theodore Ts'o. | |
25218 | + * | |
25219 | + * %Begin-Header% | |
25220 | + * This file may be redistributed under the terms of the GNU Public | |
25221 | + * License. | |
25222 | + * %End-Header% | |
25223 | + */ | |
25224 | + | |
25225 | +#include <stdio.h> | |
25226 | +#include <string.h> | |
25227 | +#if HAVE_UNISTD_H | |
25228 | +#include <unistd.h> | |
25229 | +#endif | |
25230 | +#include <fcntl.h> | |
25231 | +#include <time.h> | |
25232 | +#if HAVE_SYS_STAT_H | |
25233 | +#include <sys/stat.h> | |
25234 | +#endif | |
25235 | +#if HAVE_SYS_TYPES_H | |
25236 | +#include <sys/types.h> | |
25237 | +#endif | |
25238 | + | |
25239 | +#include "ext2_fs.h" | |
25240 | +#include "ext2fs.h" | |
25241 | + | |
25242 | +struct read_bb_record { | |
25243 | + ext2_badblocks_list bb_list; | |
25244 | + errcode_t err; | |
25245 | +}; | |
25246 | + | |
25247 | +/* | |
25248 | + * Helper function for ext2fs_read_bb_inode() | |
25249 | + */ | |
25250 | +#ifdef __TURBOC__ | |
25251 | + #pragma argsused | |
25252 | +#endif | |
25253 | +static int mark_bad_block(ext2_filsys fs, blk_t *block_nr, | |
25254 | + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), | |
25255 | + blk_t ref_block EXT2FS_ATTR((unused)), | |
25256 | + int ref_offset EXT2FS_ATTR((unused)), | |
25257 | + void *priv_data) | |
25258 | +{ | |
25259 | + struct read_bb_record *rb = (struct read_bb_record *) priv_data; | |
25260 | + | |
25261 | + if (blockcnt < 0) | |
25262 | + return 0; | |
25263 | + | |
25264 | + if ((*block_nr < fs->super->s_first_data_block) || | |
25265 | + (*block_nr >= fs->super->s_blocks_count)) | |
25266 | + return 0; /* Ignore illegal blocks */ | |
25267 | + | |
25268 | + rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr); | |
25269 | + if (rb->err) | |
25270 | + return BLOCK_ABORT; | |
25271 | + return 0; | |
25272 | +} | |
25273 | + | |
25274 | +/* | |
25275 | + * Reads the current bad blocks from the bad blocks inode. | |
25276 | + */ | |
25277 | +errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list) | |
25278 | +{ | |
25279 | + errcode_t retval; | |
25280 | + struct read_bb_record rb; | |
25281 | + struct ext2_inode inode; | |
25282 | + blk_t numblocks; | |
25283 | + | |
25284 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
25285 | + | |
25286 | + if (!*bb_list) { | |
25287 | + retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); | |
25288 | + if (retval) | |
25289 | + return retval; | |
25290 | + if (inode.i_blocks < 500) | |
25291 | + numblocks = (inode.i_blocks / | |
25292 | + (fs->blocksize / 512)) + 20; | |
25293 | + else | |
25294 | + numblocks = 500; | |
25295 | + retval = ext2fs_badblocks_list_create(bb_list, numblocks); | |
25296 | + if (retval) | |
25297 | + return retval; | |
25298 | + } | |
25299 | + | |
25300 | + rb.bb_list = *bb_list; | |
25301 | + rb.err = 0; | |
25302 | + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0, | |
25303 | + mark_bad_block, &rb); | |
25304 | + if (retval) | |
25305 | + return retval; | |
25306 | + | |
25307 | + return rb.err; | |
25308 | +} | |
25309 | + | |
25310 | + | |
25311 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/read_bb_file.c busybox/e2fsprogs/ext2fs/read_bb_file.c | |
25312 | --- busybox-1.00/e2fsprogs/ext2fs/read_bb_file.c 1970-01-01 01:00:00.000000000 +0100 | |
25313 | +++ busybox/e2fsprogs/ext2fs/read_bb_file.c 2005-06-04 08:20:16.000000000 +0200 | |
25314 | @@ -0,0 +1,97 @@ | |
25315 | +/* | |
25316 | + * read_bb_file.c --- read a list of bad blocks from a FILE * | |
25317 | + * | |
25318 | + * Copyright (C) 1994, 1995, 2000 Theodore Ts'o. | |
25319 | + * | |
25320 | + * %Begin-Header% | |
25321 | + * This file may be redistributed under the terms of the GNU Public | |
25322 | + * License. | |
25323 | + * %End-Header% | |
25324 | + */ | |
25325 | + | |
25326 | +#include <stdio.h> | |
25327 | +#include <string.h> | |
25328 | +#if HAVE_UNISTD_H | |
25329 | +#include <unistd.h> | |
25330 | +#endif | |
25331 | +#include <fcntl.h> | |
25332 | +#include <time.h> | |
25333 | +#if HAVE_SYS_STAT_H | |
25334 | +#include <sys/stat.h> | |
25335 | +#endif | |
25336 | +#if HAVE_SYS_TYPES_H | |
25337 | +#include <sys/types.h> | |
25338 | +#endif | |
25339 | + | |
25340 | +#include "ext2_fs.h" | |
25341 | +#include "ext2fs.h" | |
25342 | + | |
25343 | +/* | |
25344 | + * Reads a list of bad blocks from a FILE * | |
25345 | + */ | |
25346 | +errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, | |
25347 | + ext2_badblocks_list *bb_list, | |
25348 | + void *priv_data, | |
25349 | + void (*invalid)(ext2_filsys fs, | |
25350 | + blk_t blk, | |
25351 | + char *badstr, | |
25352 | + void *priv_data)) | |
25353 | +{ | |
25354 | + errcode_t retval; | |
25355 | + blk_t blockno; | |
25356 | + int count; | |
25357 | + char buf[128]; | |
25358 | + | |
25359 | + if (fs) | |
25360 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
25361 | + | |
25362 | + if (!*bb_list) { | |
25363 | + retval = ext2fs_badblocks_list_create(bb_list, 10); | |
25364 | + if (retval) | |
25365 | + return retval; | |
25366 | + } | |
25367 | + | |
25368 | + while (!feof (f)) { | |
25369 | + if (fgets(buf, sizeof(buf), f) == NULL) | |
25370 | + break; | |
25371 | + count = sscanf(buf, "%u", &blockno); | |
25372 | + if (count <= 0) | |
25373 | + continue; | |
25374 | + if (fs && | |
25375 | + ((blockno < fs->super->s_first_data_block) || | |
25376 | + (blockno >= fs->super->s_blocks_count))) { | |
25377 | + if (invalid) | |
25378 | + (invalid)(fs, blockno, buf, priv_data); | |
25379 | + continue; | |
25380 | + } | |
25381 | + retval = ext2fs_badblocks_list_add(*bb_list, blockno); | |
25382 | + if (retval) | |
25383 | + return retval; | |
25384 | + } | |
25385 | + return 0; | |
25386 | +} | |
25387 | + | |
25388 | +static void call_compat_invalid(ext2_filsys fs, blk_t blk, | |
25389 | + char *badstr EXT2FS_ATTR((unused)), | |
25390 | + void *priv_data) | |
25391 | +{ | |
25392 | + void (*invalid)(ext2_filsys, blk_t); | |
25393 | + | |
25394 | + invalid = (void (*)(ext2_filsys, blk_t)) priv_data; | |
25395 | + if (invalid) | |
25396 | + invalid(fs, blk); | |
25397 | +} | |
25398 | + | |
25399 | + | |
25400 | +/* | |
25401 | + * Reads a list of bad blocks from a FILE * | |
25402 | + */ | |
25403 | +errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, | |
25404 | + ext2_badblocks_list *bb_list, | |
25405 | + void (*invalid)(ext2_filsys fs, blk_t blk)) | |
25406 | +{ | |
25407 | + return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid, | |
25408 | + call_compat_invalid); | |
25409 | +} | |
25410 | + | |
25411 | + | |
25412 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/res_gdt.c busybox/e2fsprogs/ext2fs/res_gdt.c | |
25413 | --- busybox-1.00/e2fsprogs/ext2fs/res_gdt.c 1970-01-01 01:00:00.000000000 +0100 | |
25414 | +++ busybox/e2fsprogs/ext2fs/res_gdt.c 2005-06-04 08:20:16.000000000 +0200 | |
25415 | @@ -0,0 +1,220 @@ | |
25416 | +/* | |
25417 | + * res_gdt.c --- reserve blocks for growing the group descriptor table | |
25418 | + * during online resizing. | |
25419 | + * | |
25420 | + * Copyright (C) 2002 Andreas Dilger | |
25421 | + * | |
25422 | + * %Begin-Header% | |
25423 | + * This file may be redistributed under the terms of the GNU Public | |
25424 | + * License. | |
25425 | + * %End-Header% | |
25426 | + */ | |
25427 | + | |
25428 | +#include <stdio.h> | |
25429 | +#include <string.h> | |
25430 | +#include <time.h> | |
25431 | +#include "ext2_fs.h" | |
25432 | +#include "ext2fs.h" | |
25433 | + | |
25434 | +/* | |
25435 | + * Iterate through the groups which hold BACKUP superblock/GDT copies in an | |
25436 | + * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before | |
25437 | + * calling this for the first time. In a sparse filesystem it will be the | |
25438 | + * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... | |
25439 | + * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... | |
25440 | + */ | |
25441 | +static unsigned int list_backups(ext2_filsys fs, unsigned int *three, | |
25442 | + unsigned int *five, unsigned int *seven) | |
25443 | +{ | |
25444 | + unsigned int *min = three; | |
25445 | + int mult = 3; | |
25446 | + unsigned int ret; | |
25447 | + | |
25448 | + if (!(fs->super->s_feature_ro_compat & | |
25449 | + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { | |
25450 | + ret = *min; | |
25451 | + *min += 1; | |
25452 | + return ret; | |
25453 | + } | |
25454 | + | |
25455 | + if (*five < *min) { | |
25456 | + min = five; | |
25457 | + mult = 5; | |
25458 | + } | |
25459 | + if (*seven < *min) { | |
25460 | + min = seven; | |
25461 | + mult = 7; | |
25462 | + } | |
25463 | + | |
25464 | + ret = *min; | |
25465 | + *min *= mult; | |
25466 | + | |
25467 | + return ret; | |
25468 | +} | |
25469 | + | |
25470 | +/* | |
25471 | + * This code assumes that the reserved blocks have already been marked in-use | |
25472 | + * during ext2fs_initialize(), so that they are not allocated for other | |
25473 | + * uses before we can add them to the resize inode (which has to come | |
25474 | + * after the creation of the inode table). | |
25475 | + */ | |
25476 | +errcode_t ext2fs_create_resize_inode(ext2_filsys fs) | |
25477 | +{ | |
25478 | + errcode_t retval, retval2; | |
25479 | + struct ext2_super_block *sb; | |
25480 | + struct ext2_inode inode; | |
25481 | + __u32 *dindir_buf, *gdt_buf; | |
25482 | + int rsv_add; | |
25483 | + unsigned long long apb, inode_size; | |
25484 | + blk_t dindir_blk, rsv_off, gdt_off, gdt_blk; | |
25485 | + int dindir_dirty = 0, inode_dirty = 0; | |
25486 | + | |
25487 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
25488 | + | |
25489 | + sb = fs->super; | |
25490 | + | |
25491 | + retval = ext2fs_get_mem(2 * fs->blocksize, (void **)&dindir_buf); | |
25492 | + if (retval) | |
25493 | + goto out_free; | |
25494 | + gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize); | |
25495 | + | |
25496 | + retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); | |
25497 | + if (retval) | |
25498 | + goto out_free; | |
25499 | + | |
25500 | + /* Maximum possible file size (we donly use the dindirect blocks) */ | |
25501 | + apb = EXT2_ADDR_PER_BLOCK(sb); | |
25502 | + rsv_add = fs->blocksize / 512; | |
25503 | + if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) { | |
25504 | +#ifdef RES_GDT_DEBUG | |
25505 | + printf("reading GDT dindir %u\n", dindir_blk); | |
25506 | +#endif | |
25507 | + retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf); | |
25508 | + if (retval) | |
25509 | + goto out_inode; | |
25510 | + } else { | |
25511 | + blk_t goal = 3 + sb->s_reserved_gdt_blocks + | |
25512 | + fs->desc_blocks + fs->inode_blocks_per_group; | |
25513 | + | |
25514 | + retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk); | |
25515 | + if (retval) | |
25516 | + goto out_free; | |
25517 | + inode.i_mode = LINUX_S_IFREG | 0600; | |
25518 | + inode.i_links_count = 1; | |
25519 | + inode.i_block[EXT2_DIND_BLOCK] = dindir_blk; | |
25520 | + inode.i_blocks = rsv_add; | |
25521 | + memset(dindir_buf, 0, fs->blocksize); | |
25522 | +#ifdef RES_GDT_DEBUG | |
25523 | + printf("allocated GDT dindir %u\n", dindir_blk); | |
25524 | +#endif | |
25525 | + dindir_dirty = inode_dirty = 1; | |
25526 | + inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS; | |
25527 | + inode_size *= fs->blocksize; | |
25528 | + inode.i_size = inode_size & 0xFFFFFFFF; | |
25529 | + inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF; | |
25530 | + if(inode.i_size_high) { | |
25531 | + sb->s_feature_ro_compat |= | |
25532 | + EXT2_FEATURE_RO_COMPAT_LARGE_FILE; | |
25533 | + } | |
25534 | + inode.i_ctime = time(0); | |
25535 | + } | |
25536 | + | |
25537 | + for (rsv_off = 0, gdt_off = fs->desc_blocks, | |
25538 | + gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks; | |
25539 | + rsv_off < sb->s_reserved_gdt_blocks; | |
25540 | + rsv_off++, gdt_off++, gdt_blk++) { | |
25541 | + unsigned int three = 1, five = 5, seven = 7; | |
25542 | + unsigned int grp, last = 0; | |
25543 | + int gdt_dirty = 0; | |
25544 | + | |
25545 | + gdt_off %= apb; | |
25546 | + if (!dindir_buf[gdt_off]) { | |
25547 | + /* FIXME XXX XXX | |
25548 | + blk_t new_blk; | |
25549 | + | |
25550 | + retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk); | |
25551 | + if (retval) | |
25552 | + goto out_free; | |
25553 | + if (new_blk != gdt_blk) { | |
25554 | + // XXX free block | |
25555 | + retval = -1; // XXX | |
25556 | + } | |
25557 | + */ | |
25558 | + gdt_dirty = dindir_dirty = inode_dirty = 1; | |
25559 | + memset(gdt_buf, 0, fs->blocksize); | |
25560 | + dindir_buf[gdt_off] = gdt_blk; | |
25561 | + inode.i_blocks += rsv_add; | |
25562 | +#ifdef RES_GDT_DEBUG | |
25563 | + printf("added primary GDT block %u at %u[%u]\n", | |
25564 | + gdt_blk, dindir_blk, gdt_off); | |
25565 | +#endif | |
25566 | + } else if (dindir_buf[gdt_off] == gdt_blk) { | |
25567 | +#ifdef RES_GDT_DEBUG | |
25568 | + printf("reading primary GDT block %u\n", gdt_blk); | |
25569 | +#endif | |
25570 | + retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf); | |
25571 | + if (retval) | |
25572 | + goto out_dindir; | |
25573 | + } else { | |
25574 | +#ifdef RES_GDT_DEBUG | |
25575 | + printf("bad primary GDT %u != %u at %u[%u]\n", | |
25576 | + dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off); | |
25577 | +#endif | |
25578 | + retval = EXT2_ET_RESIZE_INODE_CORRUPT; | |
25579 | + goto out_dindir; | |
25580 | + } | |
25581 | + | |
25582 | + while ((grp = list_backups(fs, &three, &five, &seven)) < | |
25583 | + fs->group_desc_count) { | |
25584 | + blk_t expect = gdt_blk + grp * sb->s_blocks_per_group; | |
25585 | + | |
25586 | + if (!gdt_buf[last]) { | |
25587 | +#ifdef RES_GDT_DEBUG | |
25588 | + printf("added backup GDT %u grp %u@%u[%u]\n", | |
25589 | + expect, grp, gdt_blk, last); | |
25590 | +#endif | |
25591 | + gdt_buf[last] = expect; | |
25592 | + inode.i_blocks += rsv_add; | |
25593 | + gdt_dirty = inode_dirty = 1; | |
25594 | + } else if (gdt_buf[last] != expect) { | |
25595 | +#ifdef RES_GDT_DEBUG | |
25596 | + printf("bad backup GDT %u != %u at %u[%u]\n", | |
25597 | + gdt_buf[last], expect, gdt_blk, last); | |
25598 | +#endif | |
25599 | + retval = EXT2_ET_RESIZE_INODE_CORRUPT; | |
25600 | + goto out_dindir; | |
25601 | + } | |
25602 | + last++; | |
25603 | + } | |
25604 | + if (gdt_dirty) { | |
25605 | +#ifdef RES_GDT_DEBUG | |
25606 | + printf("writing primary GDT block %u\n", gdt_blk); | |
25607 | +#endif | |
25608 | + retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf); | |
25609 | + if (retval) | |
25610 | + goto out_dindir; | |
25611 | + } | |
25612 | + } | |
25613 | + | |
25614 | +out_dindir: | |
25615 | + if (dindir_dirty) { | |
25616 | + retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf); | |
25617 | + if (!retval) | |
25618 | + retval = retval2; | |
25619 | + } | |
25620 | +out_inode: | |
25621 | +#ifdef RES_GDT_DEBUG | |
25622 | + printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks, | |
25623 | + inode.i_size); | |
25624 | +#endif | |
25625 | + if (inode_dirty) { | |
25626 | + inode.i_atime = inode.i_mtime = time(0); | |
25627 | + retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode); | |
25628 | + if (!retval) | |
25629 | + retval = retval2; | |
25630 | + } | |
25631 | +out_free: | |
25632 | + ext2fs_free_mem((void **)&dindir_buf); | |
25633 | + return retval; | |
25634 | +} | |
25635 | + | |
25636 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/rs_bitmap.c busybox/e2fsprogs/ext2fs/rs_bitmap.c | |
25637 | --- busybox-1.00/e2fsprogs/ext2fs/rs_bitmap.c 1970-01-01 01:00:00.000000000 +0100 | |
25638 | +++ busybox/e2fsprogs/ext2fs/rs_bitmap.c 2005-06-04 08:20:16.000000000 +0200 | |
25639 | @@ -0,0 +1,106 @@ | |
25640 | +/* | |
25641 | + * rs_bitmap.c --- routine for changing the size of a bitmap | |
25642 | + * | |
25643 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
25644 | + * | |
25645 | + * %Begin-Header% | |
25646 | + * This file may be redistributed under the terms of the GNU Public | |
25647 | + * License. | |
25648 | + * %End-Header% | |
25649 | + */ | |
25650 | + | |
25651 | +#include <stdio.h> | |
25652 | +#include <string.h> | |
25653 | +#if HAVE_UNISTD_H | |
25654 | +#include <unistd.h> | |
25655 | +#endif | |
25656 | +#include <fcntl.h> | |
25657 | +#include <time.h> | |
25658 | +#ifdef HAVE_SYS_STAT_H | |
25659 | +#include <sys/stat.h> | |
25660 | +#endif | |
25661 | +#ifdef HAVE_SYS_TYPES_H | |
25662 | +#include <sys/types.h> | |
25663 | +#endif | |
25664 | + | |
25665 | +#include "ext2_fs.h" | |
25666 | +#include "ext2fs.h" | |
25667 | + | |
25668 | +errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end, | |
25669 | + ext2fs_generic_bitmap bmap) | |
25670 | +{ | |
25671 | + errcode_t retval; | |
25672 | + size_t size, new_size; | |
25673 | + __u32 bitno; | |
25674 | + | |
25675 | + if (!bmap) | |
25676 | + return EXT2_ET_INVALID_ARGUMENT; | |
25677 | + | |
25678 | + EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP); | |
25679 | + | |
25680 | + /* | |
25681 | + * If we're expanding the bitmap, make sure all of the new | |
25682 | + * parts of the bitmap are zero. | |
25683 | + */ | |
25684 | + if (new_end > bmap->end) { | |
25685 | + bitno = bmap->real_end; | |
25686 | + if (bitno > new_end) | |
25687 | + bitno = new_end; | |
25688 | + for (; bitno > bmap->end; bitno--) | |
25689 | + ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap); | |
25690 | + } | |
25691 | + if (new_real_end == bmap->real_end) { | |
25692 | + bmap->end = new_end; | |
25693 | + return 0; | |
25694 | + } | |
25695 | + | |
25696 | + size = ((bmap->real_end - bmap->start) / 8) + 1; | |
25697 | + new_size = ((new_real_end - bmap->start) / 8) + 1; | |
25698 | + | |
25699 | + if (size != new_size) { | |
25700 | + retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap); | |
25701 | + if (retval) | |
25702 | + return retval; | |
25703 | + } | |
25704 | + if (new_size > size) | |
25705 | + memset(bmap->bitmap + size, 0, new_size - size); | |
25706 | + | |
25707 | + bmap->end = new_end; | |
25708 | + bmap->real_end = new_real_end; | |
25709 | + return 0; | |
25710 | +} | |
25711 | + | |
25712 | +errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, | |
25713 | + ext2fs_inode_bitmap bmap) | |
25714 | +{ | |
25715 | + errcode_t retval; | |
25716 | + | |
25717 | + if (!bmap) | |
25718 | + return EXT2_ET_INVALID_ARGUMENT; | |
25719 | + | |
25720 | + EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP); | |
25721 | + | |
25722 | + bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; | |
25723 | + retval = ext2fs_resize_generic_bitmap(new_end, new_real_end, | |
25724 | + bmap); | |
25725 | + bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP; | |
25726 | + return retval; | |
25727 | +} | |
25728 | + | |
25729 | +errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, | |
25730 | + ext2fs_block_bitmap bmap) | |
25731 | +{ | |
25732 | + errcode_t retval; | |
25733 | + | |
25734 | + if (!bmap) | |
25735 | + return EXT2_ET_INVALID_ARGUMENT; | |
25736 | + | |
25737 | + EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP); | |
25738 | + | |
25739 | + bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; | |
25740 | + retval = ext2fs_resize_generic_bitmap(new_end, new_real_end, | |
25741 | + bmap); | |
25742 | + bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP; | |
25743 | + return retval; | |
25744 | +} | |
25745 | + | |
25746 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/rw_bitmaps.c busybox/e2fsprogs/ext2fs/rw_bitmaps.c | |
25747 | --- busybox-1.00/e2fsprogs/ext2fs/rw_bitmaps.c 1970-01-01 01:00:00.000000000 +0100 | |
25748 | +++ busybox/e2fsprogs/ext2fs/rw_bitmaps.c 2005-06-04 08:20:16.000000000 +0200 | |
25749 | @@ -0,0 +1,300 @@ | |
25750 | +/* | |
25751 | + * rw_bitmaps.c --- routines to read and write the inode and block bitmaps. | |
25752 | + * | |
25753 | + * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o. | |
25754 | + * | |
25755 | + * %Begin-Header% | |
25756 | + * This file may be redistributed under the terms of the GNU Public | |
25757 | + * License. | |
25758 | + * %End-Header% | |
25759 | + */ | |
25760 | + | |
25761 | +#include <stdio.h> | |
25762 | +#include <string.h> | |
25763 | +#if HAVE_UNISTD_H | |
25764 | +#include <unistd.h> | |
25765 | +#endif | |
25766 | +#include <fcntl.h> | |
25767 | +#include <time.h> | |
25768 | +#ifdef HAVE_SYS_STAT_H | |
25769 | +#include <sys/stat.h> | |
25770 | +#endif | |
25771 | +#ifdef HAVE_SYS_TYPES_H | |
25772 | +#include <sys/types.h> | |
25773 | +#endif | |
25774 | + | |
25775 | +#include "ext2_fs.h" | |
25776 | +#include "ext2fs.h" | |
25777 | +#include "e2image.h" | |
25778 | + | |
25779 | +#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS) | |
25780 | +/* | |
25781 | + * On the PowerPC, the big-endian variant of the ext2 filesystem | |
25782 | + * has its bitmaps stored as 32-bit words with bit 0 as the LSB | |
25783 | + * of each word. Thus a bitmap with only bit 0 set would be, as | |
25784 | + * a string of bytes, 00 00 00 01 00 ... | |
25785 | + * To cope with this, we byte-reverse each word of a bitmap if | |
25786 | + * we have a big-endian filesystem, that is, if we are *not* | |
25787 | + * byte-swapping other word-sized numbers. | |
25788 | + */ | |
25789 | +#define EXT2_BIG_ENDIAN_BITMAPS | |
25790 | +#endif | |
25791 | + | |
25792 | +#ifdef EXT2_BIG_ENDIAN_BITMAPS | |
25793 | +static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes) | |
25794 | +{ | |
25795 | + __u32 *p = (__u32 *) bitmap; | |
25796 | + int n; | |
25797 | + | |
25798 | + for (n = nbytes / sizeof(__u32); n > 0; --n, ++p) | |
25799 | + *p = ext2fs_swab32(*p); | |
25800 | +} | |
25801 | +#endif | |
25802 | + | |
25803 | +errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) | |
25804 | +{ | |
25805 | + dgrp_t i; | |
25806 | + size_t nbytes; | |
25807 | + errcode_t retval; | |
25808 | + char * inode_bitmap = fs->inode_map->bitmap; | |
25809 | + char * bitmap_block = NULL; | |
25810 | + blk_t blk; | |
25811 | + | |
25812 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
25813 | + | |
25814 | + if (!(fs->flags & EXT2_FLAG_RW)) | |
25815 | + return EXT2_ET_RO_FILSYS; | |
25816 | + if (!inode_bitmap) | |
25817 | + return 0; | |
25818 | + nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); | |
25819 | + | |
25820 | + retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); | |
25821 | + if (retval) | |
25822 | + return retval; | |
25823 | + memset(bitmap_block, 0xff, fs->blocksize); | |
25824 | + for (i = 0; i < fs->group_desc_count; i++) { | |
25825 | + memcpy(bitmap_block, inode_bitmap, nbytes); | |
25826 | + blk = fs->group_desc[i].bg_inode_bitmap; | |
25827 | + if (blk) { | |
25828 | +#ifdef EXT2_BIG_ENDIAN_BITMAPS | |
25829 | + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
25830 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) | |
25831 | + ext2fs_swap_bitmap(fs, bitmap_block, nbytes); | |
25832 | +#endif | |
25833 | + retval = io_channel_write_blk(fs->io, blk, 1, | |
25834 | + bitmap_block); | |
25835 | + if (retval) | |
25836 | + return EXT2_ET_INODE_BITMAP_WRITE; | |
25837 | + } | |
25838 | + inode_bitmap += nbytes; | |
25839 | + } | |
25840 | + fs->flags &= ~EXT2_FLAG_IB_DIRTY; | |
25841 | + ext2fs_free_mem(&bitmap_block); | |
25842 | + return 0; | |
25843 | +} | |
25844 | + | |
25845 | +errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) | |
25846 | +{ | |
25847 | + dgrp_t i; | |
25848 | + unsigned int j; | |
25849 | + int nbytes; | |
25850 | + unsigned int nbits; | |
25851 | + errcode_t retval; | |
25852 | + char * block_bitmap = fs->block_map->bitmap; | |
25853 | + char * bitmap_block = NULL; | |
25854 | + blk_t blk; | |
25855 | + | |
25856 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
25857 | + | |
25858 | + if (!(fs->flags & EXT2_FLAG_RW)) | |
25859 | + return EXT2_ET_RO_FILSYS; | |
25860 | + if (!block_bitmap) | |
25861 | + return 0; | |
25862 | + nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; | |
25863 | + retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); | |
25864 | + if (retval) | |
25865 | + return retval; | |
25866 | + memset(bitmap_block, 0xff, fs->blocksize); | |
25867 | + for (i = 0; i < fs->group_desc_count; i++) { | |
25868 | + memcpy(bitmap_block, block_bitmap, nbytes); | |
25869 | + if (i == fs->group_desc_count - 1) { | |
25870 | + /* Force bitmap padding for the last group */ | |
25871 | + nbits = ((fs->super->s_blocks_count | |
25872 | + - fs->super->s_first_data_block) | |
25873 | + % EXT2_BLOCKS_PER_GROUP(fs->super)); | |
25874 | + if (nbits) | |
25875 | + for (j = nbits; j < fs->blocksize * 8; j++) | |
25876 | + ext2fs_set_bit(j, bitmap_block); | |
25877 | + } | |
25878 | + blk = fs->group_desc[i].bg_block_bitmap; | |
25879 | + if (blk) { | |
25880 | +#ifdef EXT2_BIG_ENDIAN_BITMAPS | |
25881 | + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
25882 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) | |
25883 | + ext2fs_swap_bitmap(fs, bitmap_block, nbytes); | |
25884 | +#endif | |
25885 | + retval = io_channel_write_blk(fs->io, blk, 1, | |
25886 | + bitmap_block); | |
25887 | + if (retval) | |
25888 | + return EXT2_ET_BLOCK_BITMAP_WRITE; | |
25889 | + } | |
25890 | + block_bitmap += nbytes; | |
25891 | + } | |
25892 | + fs->flags &= ~EXT2_FLAG_BB_DIRTY; | |
25893 | + ext2fs_free_mem(&bitmap_block); | |
25894 | + return 0; | |
25895 | +} | |
25896 | + | |
25897 | +static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | |
25898 | +{ | |
25899 | + dgrp_t i; | |
25900 | + char *block_bitmap = 0, *inode_bitmap = 0; | |
25901 | + char *buf; | |
25902 | + errcode_t retval; | |
25903 | + int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8; | |
25904 | + int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8; | |
25905 | + blk_t blk; | |
25906 | + | |
25907 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
25908 | + | |
25909 | + fs->write_bitmaps = ext2fs_write_bitmaps; | |
25910 | + | |
25911 | + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); | |
25912 | + if (retval) | |
25913 | + return retval; | |
25914 | + if (do_block) { | |
25915 | + if (fs->block_map) | |
25916 | + ext2fs_free_block_bitmap(fs->block_map); | |
25917 | + sprintf(buf, "block bitmap for %s", fs->device_name); | |
25918 | + retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); | |
25919 | + if (retval) | |
25920 | + goto cleanup; | |
25921 | + block_bitmap = fs->block_map->bitmap; | |
25922 | + } | |
25923 | + if (do_inode) { | |
25924 | + if (fs->inode_map) | |
25925 | + ext2fs_free_inode_bitmap(fs->inode_map); | |
25926 | + sprintf(buf, "inode bitmap for %s", fs->device_name); | |
25927 | + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); | |
25928 | + if (retval) | |
25929 | + goto cleanup; | |
25930 | + inode_bitmap = fs->inode_map->bitmap; | |
25931 | + } | |
25932 | + ext2fs_free_mem(&buf); | |
25933 | + | |
25934 | + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { | |
25935 | + if (inode_bitmap) { | |
25936 | + blk = (fs->image_header->offset_inodemap / | |
25937 | + fs->blocksize); | |
25938 | + retval = io_channel_read_blk(fs->image_io, blk, | |
25939 | + -(inode_nbytes * fs->group_desc_count), | |
25940 | + inode_bitmap); | |
25941 | + if (retval) | |
25942 | + goto cleanup; | |
25943 | + } | |
25944 | + if (block_bitmap) { | |
25945 | + blk = (fs->image_header->offset_blockmap / | |
25946 | + fs->blocksize); | |
25947 | + retval = io_channel_read_blk(fs->image_io, blk, | |
25948 | + -(block_nbytes * fs->group_desc_count), | |
25949 | + block_bitmap); | |
25950 | + if (retval) | |
25951 | + goto cleanup; | |
25952 | + } | |
25953 | + return 0; | |
25954 | + } | |
25955 | + | |
25956 | + for (i = 0; i < fs->group_desc_count; i++) { | |
25957 | + if (block_bitmap) { | |
25958 | + blk = fs->group_desc[i].bg_block_bitmap; | |
25959 | + if (blk) { | |
25960 | + retval = io_channel_read_blk(fs->io, blk, | |
25961 | + -block_nbytes, block_bitmap); | |
25962 | + if (retval) { | |
25963 | + retval = EXT2_ET_BLOCK_BITMAP_READ; | |
25964 | + goto cleanup; | |
25965 | + } | |
25966 | +#ifdef EXT2_BIG_ENDIAN_BITMAPS | |
25967 | + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
25968 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) | |
25969 | + ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes); | |
25970 | +#endif | |
25971 | + } else | |
25972 | + memset(block_bitmap, 0, block_nbytes); | |
25973 | + block_bitmap += block_nbytes; | |
25974 | + } | |
25975 | + if (inode_bitmap) { | |
25976 | + blk = fs->group_desc[i].bg_inode_bitmap; | |
25977 | + if (blk) { | |
25978 | + retval = io_channel_read_blk(fs->io, blk, | |
25979 | + -inode_nbytes, inode_bitmap); | |
25980 | + if (retval) { | |
25981 | + retval = EXT2_ET_INODE_BITMAP_READ; | |
25982 | + goto cleanup; | |
25983 | + } | |
25984 | +#ifdef EXT2_BIG_ENDIAN_BITMAPS | |
25985 | + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || | |
25986 | + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) | |
25987 | + ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes); | |
25988 | +#endif | |
25989 | + } else | |
25990 | + memset(inode_bitmap, 0, inode_nbytes); | |
25991 | + inode_bitmap += inode_nbytes; | |
25992 | + } | |
25993 | + } | |
25994 | + return 0; | |
25995 | + | |
25996 | +cleanup: | |
25997 | + if (do_block) { | |
25998 | + ext2fs_free_mem(&fs->block_map); | |
25999 | + fs->block_map = 0; | |
26000 | + } | |
26001 | + if (do_inode) { | |
26002 | + ext2fs_free_mem(&fs->inode_map); | |
26003 | + fs->inode_map = 0; | |
26004 | + } | |
26005 | + if (buf) | |
26006 | + ext2fs_free_mem(&buf); | |
26007 | + return retval; | |
26008 | +} | |
26009 | + | |
26010 | +errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs) | |
26011 | +{ | |
26012 | + return read_bitmaps(fs, 1, 0); | |
26013 | +} | |
26014 | + | |
26015 | +errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) | |
26016 | +{ | |
26017 | + return read_bitmaps(fs, 0, 1); | |
26018 | +} | |
26019 | + | |
26020 | +errcode_t ext2fs_read_bitmaps(ext2_filsys fs) | |
26021 | +{ | |
26022 | + | |
26023 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
26024 | + | |
26025 | + if (fs->inode_map && fs->block_map) | |
26026 | + return 0; | |
26027 | + | |
26028 | + return read_bitmaps(fs, !fs->inode_map, !fs->block_map); | |
26029 | +} | |
26030 | + | |
26031 | +errcode_t ext2fs_write_bitmaps(ext2_filsys fs) | |
26032 | +{ | |
26033 | + errcode_t retval; | |
26034 | + | |
26035 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
26036 | + | |
26037 | + if (fs->block_map && ext2fs_test_bb_dirty(fs)) { | |
26038 | + retval = ext2fs_write_block_bitmap(fs); | |
26039 | + if (retval) | |
26040 | + return retval; | |
26041 | + } | |
26042 | + if (fs->inode_map && ext2fs_test_ib_dirty(fs)) { | |
26043 | + retval = ext2fs_write_inode_bitmap(fs); | |
26044 | + if (retval) | |
26045 | + return retval; | |
26046 | + } | |
26047 | + return 0; | |
26048 | +} | |
26049 | + | |
26050 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/sparse.c busybox/e2fsprogs/ext2fs/sparse.c | |
26051 | --- busybox-1.00/e2fsprogs/ext2fs/sparse.c 1970-01-01 01:00:00.000000000 +0100 | |
26052 | +++ busybox/e2fsprogs/ext2fs/sparse.c 2005-06-04 08:20:16.000000000 +0200 | |
26053 | @@ -0,0 +1,78 @@ | |
26054 | +/* | |
26055 | + * sparse.c --- find the groups in an ext2 filesystem with metadata backups | |
26056 | + * | |
26057 | + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | |
26058 | + * Copyright (C) 2002 Andreas Dilger. | |
26059 | + * | |
26060 | + * %Begin-Header% | |
26061 | + * This file may be redistributed under the terms of the GNU Public | |
26062 | + * License. | |
26063 | + * %End-Header% | |
26064 | + */ | |
26065 | + | |
26066 | +#include <stdio.h> | |
26067 | + | |
26068 | +#include "ext2_fs.h" | |
26069 | +#include "ext2fsP.h" | |
26070 | + | |
26071 | +static int test_root(int a, int b) | |
26072 | +{ | |
26073 | + if (a == 0) | |
26074 | + return 1; | |
26075 | + while (1) { | |
26076 | + if (a == 1) | |
26077 | + return 1; | |
26078 | + if (a % b) | |
26079 | + return 0; | |
26080 | + a = a / b; | |
26081 | + } | |
26082 | +} | |
26083 | + | |
26084 | +int ext2fs_bg_has_super(ext2_filsys fs, int group_block) | |
26085 | +{ | |
26086 | + if (!(fs->super->s_feature_ro_compat & | |
26087 | + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) | |
26088 | + return 1; | |
26089 | + | |
26090 | + if (test_root(group_block, 3) || (test_root(group_block, 5)) || | |
26091 | + test_root(group_block, 7)) | |
26092 | + return 1; | |
26093 | + | |
26094 | + return 0; | |
26095 | +} | |
26096 | + | |
26097 | +/* | |
26098 | + * Iterate through the groups which hold BACKUP superblock/GDT copies in an | |
26099 | + * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before | |
26100 | + * calling this for the first time. In a sparse filesystem it will be the | |
26101 | + * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... | |
26102 | + * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... | |
26103 | + */ | |
26104 | +unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three, | |
26105 | + unsigned int *five, unsigned int *seven) | |
26106 | +{ | |
26107 | + unsigned int *min = three; | |
26108 | + int mult = 3; | |
26109 | + unsigned int ret; | |
26110 | + | |
26111 | + if (!(fs->super->s_feature_ro_compat & | |
26112 | + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { | |
26113 | + ret = *min; | |
26114 | + *min += 1; | |
26115 | + return ret; | |
26116 | + } | |
26117 | + | |
26118 | + if (*five < *min) { | |
26119 | + min = five; | |
26120 | + mult = 5; | |
26121 | + } | |
26122 | + if (*seven < *min) { | |
26123 | + min = seven; | |
26124 | + mult = 7; | |
26125 | + } | |
26126 | + | |
26127 | + ret = *min; | |
26128 | + *min *= mult; | |
26129 | + | |
26130 | + return ret; | |
26131 | +} | |
26132 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/swapfs.c busybox/e2fsprogs/ext2fs/swapfs.c | |
26133 | --- busybox-1.00/e2fsprogs/ext2fs/swapfs.c 1970-01-01 01:00:00.000000000 +0100 | |
26134 | +++ busybox/e2fsprogs/ext2fs/swapfs.c 2005-06-04 08:20:16.000000000 +0200 | |
26135 | @@ -0,0 +1,237 @@ | |
26136 | +/* | |
26137 | + * swapfs.c --- swap ext2 filesystem data structures | |
26138 | + * | |
26139 | + * Copyright (C) 1995, 1996, 2002 Theodore Ts'o. | |
26140 | + * | |
26141 | + * %Begin-Header% | |
26142 | + * This file may be redistributed under the terms of the GNU Public | |
26143 | + * License. | |
26144 | + * %End-Header% | |
26145 | + */ | |
26146 | + | |
26147 | +#include <stdio.h> | |
26148 | +#if HAVE_UNISTD_H | |
26149 | +#include <unistd.h> | |
26150 | +#endif | |
26151 | +#include <string.h> | |
26152 | +#include <time.h> | |
26153 | + | |
26154 | +#include "ext2_fs.h" | |
26155 | +#include "ext2fs.h" | |
26156 | +#include <ext2fs/ext2_ext_attr.h> | |
26157 | + | |
26158 | +#ifdef EXT2FS_ENABLE_SWAPFS | |
26159 | +void ext2fs_swap_super(struct ext2_super_block * sb) | |
26160 | +{ | |
26161 | + int i; | |
26162 | + sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count); | |
26163 | + sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count); | |
26164 | + sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count); | |
26165 | + sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count); | |
26166 | + sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count); | |
26167 | + sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block); | |
26168 | + sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size); | |
26169 | + sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size); | |
26170 | + sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group); | |
26171 | + sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group); | |
26172 | + sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group); | |
26173 | + sb->s_mtime = ext2fs_swab32(sb->s_mtime); | |
26174 | + sb->s_wtime = ext2fs_swab32(sb->s_wtime); | |
26175 | + sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count); | |
26176 | + sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count); | |
26177 | + sb->s_magic = ext2fs_swab16(sb->s_magic); | |
26178 | + sb->s_state = ext2fs_swab16(sb->s_state); | |
26179 | + sb->s_errors = ext2fs_swab16(sb->s_errors); | |
26180 | + sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level); | |
26181 | + sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck); | |
26182 | + sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval); | |
26183 | + sb->s_creator_os = ext2fs_swab32(sb->s_creator_os); | |
26184 | + sb->s_rev_level = ext2fs_swab32(sb->s_rev_level); | |
26185 | + sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid); | |
26186 | + sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid); | |
26187 | + sb->s_first_ino = ext2fs_swab32(sb->s_first_ino); | |
26188 | + sb->s_inode_size = ext2fs_swab16(sb->s_inode_size); | |
26189 | + sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr); | |
26190 | + sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat); | |
26191 | + sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat); | |
26192 | + sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat); | |
26193 | + sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap); | |
26194 | + sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks); | |
26195 | + sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum); | |
26196 | + sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev); | |
26197 | + sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan); | |
26198 | + sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts); | |
26199 | + sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg); | |
26200 | + sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time); | |
26201 | + for (i=0; i < 4; i++) | |
26202 | + sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); | |
26203 | + for (i=0; i < 17; i++) | |
26204 | + sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]); | |
26205 | + | |
26206 | +} | |
26207 | + | |
26208 | +void ext2fs_swap_group_desc(struct ext2_group_desc *gdp) | |
26209 | +{ | |
26210 | + gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap); | |
26211 | + gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap); | |
26212 | + gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table); | |
26213 | + gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count); | |
26214 | + gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count); | |
26215 | + gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count); | |
26216 | +} | |
26217 | + | |
26218 | +void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header) | |
26219 | +{ | |
26220 | + struct ext2_ext_attr_header *from_header = | |
26221 | + (struct ext2_ext_attr_header *)from; | |
26222 | + struct ext2_ext_attr_header *to_header = | |
26223 | + (struct ext2_ext_attr_header *)to; | |
26224 | + struct ext2_ext_attr_entry *from_entry, *to_entry; | |
26225 | + char *from_end = (char *)from_header + bufsize; | |
26226 | + int n; | |
26227 | + | |
26228 | + if (to_header != from_header) | |
26229 | + memcpy(to_header, from_header, bufsize); | |
26230 | + | |
26231 | + from_entry = (struct ext2_ext_attr_entry *)from_header; | |
26232 | + to_entry = (struct ext2_ext_attr_entry *)to_header; | |
26233 | + | |
26234 | + if (has_header) { | |
26235 | + to_header->h_magic = ext2fs_swab32(from_header->h_magic); | |
26236 | + to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); | |
26237 | + to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); | |
26238 | + for (n=0; n<4; n++) | |
26239 | + to_header->h_reserved[n] = | |
26240 | + ext2fs_swab32(from_header->h_reserved[n]); | |
26241 | + from_entry = (struct ext2_ext_attr_entry *)(from_header+1); | |
26242 | + to_entry = (struct ext2_ext_attr_entry *)(to_header+1); | |
26243 | + } | |
26244 | + | |
26245 | + while ((char *)from_entry < from_end && *(__u32 *)from_entry) { | |
26246 | + to_entry->e_value_offs = | |
26247 | + ext2fs_swab16(from_entry->e_value_offs); | |
26248 | + to_entry->e_value_block = | |
26249 | + ext2fs_swab32(from_entry->e_value_block); | |
26250 | + to_entry->e_value_size = | |
26251 | + ext2fs_swab32(from_entry->e_value_size); | |
26252 | + from_entry = EXT2_EXT_ATTR_NEXT(from_entry); | |
26253 | + to_entry = EXT2_EXT_ATTR_NEXT(to_entry); | |
26254 | + } | |
26255 | +} | |
26256 | + | |
26257 | +void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, | |
26258 | + struct ext2_inode_large *f, int hostorder, | |
26259 | + int bufsize) | |
26260 | +{ | |
26261 | + unsigned i; | |
26262 | + int islnk = 0; | |
26263 | + __u32 *eaf, *eat; | |
26264 | + | |
26265 | + if (hostorder && LINUX_S_ISLNK(f->i_mode)) | |
26266 | + islnk = 1; | |
26267 | + t->i_mode = ext2fs_swab16(f->i_mode); | |
26268 | + if (!hostorder && LINUX_S_ISLNK(t->i_mode)) | |
26269 | + islnk = 1; | |
26270 | + t->i_uid = ext2fs_swab16(f->i_uid); | |
26271 | + t->i_size = ext2fs_swab32(f->i_size); | |
26272 | + t->i_atime = ext2fs_swab32(f->i_atime); | |
26273 | + t->i_ctime = ext2fs_swab32(f->i_ctime); | |
26274 | + t->i_mtime = ext2fs_swab32(f->i_mtime); | |
26275 | + t->i_dtime = ext2fs_swab32(f->i_dtime); | |
26276 | + t->i_gid = ext2fs_swab16(f->i_gid); | |
26277 | + t->i_links_count = ext2fs_swab16(f->i_links_count); | |
26278 | + t->i_blocks = ext2fs_swab32(f->i_blocks); | |
26279 | + t->i_flags = ext2fs_swab32(f->i_flags); | |
26280 | + t->i_file_acl = ext2fs_swab32(f->i_file_acl); | |
26281 | + t->i_dir_acl = ext2fs_swab32(f->i_dir_acl); | |
26282 | + if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) { | |
26283 | + for (i = 0; i < EXT2_N_BLOCKS; i++) | |
26284 | + t->i_block[i] = ext2fs_swab32(f->i_block[i]); | |
26285 | + } else if (t != f) { | |
26286 | + for (i = 0; i < EXT2_N_BLOCKS; i++) | |
26287 | + t->i_block[i] = f->i_block[i]; | |
26288 | + } | |
26289 | + t->i_generation = ext2fs_swab32(f->i_generation); | |
26290 | + t->i_faddr = ext2fs_swab32(f->i_faddr); | |
26291 | + | |
26292 | + switch (fs->super->s_creator_os) { | |
26293 | + case EXT2_OS_LINUX: | |
26294 | + t->osd1.linux1.l_i_reserved1 = | |
26295 | + ext2fs_swab32(f->osd1.linux1.l_i_reserved1); | |
26296 | + t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag; | |
26297 | + t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize; | |
26298 | + t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1); | |
26299 | + t->osd2.linux2.l_i_uid_high = | |
26300 | + ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); | |
26301 | + t->osd2.linux2.l_i_gid_high = | |
26302 | + ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); | |
26303 | + t->osd2.linux2.l_i_reserved2 = | |
26304 | + ext2fs_swab32(f->osd2.linux2.l_i_reserved2); | |
26305 | + break; | |
26306 | + case EXT2_OS_HURD: | |
26307 | + t->osd1.hurd1.h_i_translator = | |
26308 | + ext2fs_swab32 (f->osd1.hurd1.h_i_translator); | |
26309 | + t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; | |
26310 | + t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; | |
26311 | + t->osd2.hurd2.h_i_mode_high = | |
26312 | + ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); | |
26313 | + t->osd2.hurd2.h_i_uid_high = | |
26314 | + ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); | |
26315 | + t->osd2.hurd2.h_i_gid_high = | |
26316 | + ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); | |
26317 | + t->osd2.hurd2.h_i_author = | |
26318 | + ext2fs_swab32 (f->osd2.hurd2.h_i_author); | |
26319 | + break; | |
26320 | + case EXT2_OS_MASIX: | |
26321 | + t->osd1.masix1.m_i_reserved1 = | |
26322 | + ext2fs_swab32(f->osd1.masix1.m_i_reserved1); | |
26323 | + t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag; | |
26324 | + t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize; | |
26325 | + t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1); | |
26326 | + t->osd2.masix2.m_i_reserved2[0] = | |
26327 | + ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]); | |
26328 | + t->osd2.masix2.m_i_reserved2[1] = | |
26329 | + ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]); | |
26330 | + break; | |
26331 | + } | |
26332 | + | |
26333 | + if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) | |
26334 | + return; /* no i_extra_isize field */ | |
26335 | + | |
26336 | + t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); | |
26337 | + if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) - | |
26338 | + sizeof(struct ext2_inode)) { | |
26339 | + /* this is error case: i_extra_size is too large */ | |
26340 | + return; | |
26341 | + } | |
26342 | + | |
26343 | + i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32); | |
26344 | + if (bufsize < (int) i) | |
26345 | + return; /* no space for EA magic */ | |
26346 | + | |
26347 | + eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + | |
26348 | + f->i_extra_isize); | |
26349 | + | |
26350 | + if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC) | |
26351 | + return; /* it seems no magic here */ | |
26352 | + | |
26353 | + eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + | |
26354 | + f->i_extra_isize); | |
26355 | + *eat = ext2fs_swab32(*eaf); | |
26356 | + | |
26357 | + /* convert EA(s) */ | |
26358 | + ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), | |
26359 | + bufsize - sizeof(struct ext2_inode) - | |
26360 | + t->i_extra_isize - sizeof(__u32), 0); | |
26361 | + | |
26362 | +} | |
26363 | + | |
26364 | +void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, | |
26365 | + struct ext2_inode *f, int hostorder) | |
26366 | +{ | |
26367 | + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t, | |
26368 | + (struct ext2_inode_large *) f, hostorder, | |
26369 | + sizeof(struct ext2_inode)); | |
26370 | +} | |
26371 | + | |
26372 | +#endif | |
26373 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/test_io.c busybox/e2fsprogs/ext2fs/test_io.c | |
26374 | --- busybox-1.00/e2fsprogs/ext2fs/test_io.c 1970-01-01 01:00:00.000000000 +0100 | |
26375 | +++ busybox/e2fsprogs/ext2fs/test_io.c 2005-06-04 08:20:16.000000000 +0200 | |
26376 | @@ -0,0 +1,382 @@ | |
26377 | +/* | |
26378 | + * test_io.c --- This is the Test I/O interface. | |
26379 | + * | |
26380 | + * Copyright (C) 1996 Theodore Ts'o. | |
26381 | + * | |
26382 | + * %Begin-Header% | |
26383 | + * This file may be redistributed under the terms of the GNU Public | |
26384 | + * License. | |
26385 | + * %End-Header% | |
26386 | + */ | |
26387 | + | |
26388 | +#include <stdio.h> | |
26389 | +#include <string.h> | |
26390 | +#if HAVE_UNISTD_H | |
26391 | +#include <unistd.h> | |
26392 | +#endif | |
26393 | +#include <fcntl.h> | |
26394 | +#include <time.h> | |
26395 | +#if HAVE_SYS_STAT_H | |
26396 | +#include <sys/stat.h> | |
26397 | +#endif | |
26398 | +#if HAVE_SYS_TYPES_H | |
26399 | +#include <sys/types.h> | |
26400 | +#endif | |
26401 | + | |
26402 | +#include "ext2_fs.h" | |
26403 | +#include "ext2fs.h" | |
26404 | + | |
26405 | +/* | |
26406 | + * For checking structure magic numbers... | |
26407 | + */ | |
26408 | + | |
26409 | +#define EXT2_CHECK_MAGIC(struct, code) \ | |
26410 | + if ((struct)->magic != (code)) return (code) | |
26411 | + | |
26412 | +struct test_private_data { | |
26413 | + int magic; | |
26414 | + io_channel real; | |
26415 | + int flags; | |
26416 | + FILE *outfile; | |
26417 | + unsigned long block; | |
26418 | + int read_abort_count, write_abort_count; | |
26419 | + void (*read_blk)(unsigned long block, int count, errcode_t err); | |
26420 | + void (*write_blk)(unsigned long block, int count, errcode_t err); | |
26421 | + void (*set_blksize)(int blksize, errcode_t err); | |
26422 | + void (*write_byte)(unsigned long block, int count, errcode_t err); | |
26423 | +}; | |
26424 | + | |
26425 | +static errcode_t test_open(const char *name, int flags, io_channel *channel); | |
26426 | +static errcode_t test_close(io_channel channel); | |
26427 | +static errcode_t test_set_blksize(io_channel channel, int blksize); | |
26428 | +static errcode_t test_read_blk(io_channel channel, unsigned long block, | |
26429 | + int count, void *data); | |
26430 | +static errcode_t test_write_blk(io_channel channel, unsigned long block, | |
26431 | + int count, const void *data); | |
26432 | +static errcode_t test_flush(io_channel channel); | |
26433 | +static errcode_t test_write_byte(io_channel channel, unsigned long offset, | |
26434 | + int count, const void *buf); | |
26435 | +static errcode_t test_set_option(io_channel channel, const char *option, | |
26436 | + const char *arg); | |
26437 | + | |
26438 | +static struct struct_io_manager struct_test_manager = { | |
26439 | + EXT2_ET_MAGIC_IO_MANAGER, | |
26440 | + "Test I/O Manager", | |
26441 | + test_open, | |
26442 | + test_close, | |
26443 | + test_set_blksize, | |
26444 | + test_read_blk, | |
26445 | + test_write_blk, | |
26446 | + test_flush, | |
26447 | + test_write_byte, | |
26448 | + test_set_option | |
26449 | +}; | |
26450 | + | |
26451 | +io_manager test_io_manager = &struct_test_manager; | |
26452 | + | |
26453 | +/* | |
26454 | + * These global variable can be set by the test program as | |
26455 | + * necessary *before* calling test_open | |
26456 | + */ | |
26457 | +io_manager test_io_backing_manager = 0; | |
26458 | +void (*test_io_cb_read_blk) | |
26459 | + (unsigned long block, int count, errcode_t err) = 0; | |
26460 | +void (*test_io_cb_write_blk) | |
26461 | + (unsigned long block, int count, errcode_t err) = 0; | |
26462 | +void (*test_io_cb_set_blksize) | |
26463 | + (int blksize, errcode_t err) = 0; | |
26464 | +void (*test_io_cb_write_byte) | |
26465 | + (unsigned long block, int count, errcode_t err) = 0; | |
26466 | + | |
26467 | +/* | |
26468 | + * Test flags | |
26469 | + */ | |
26470 | +#define TEST_FLAG_READ 0x01 | |
26471 | +#define TEST_FLAG_WRITE 0x02 | |
26472 | +#define TEST_FLAG_SET_BLKSIZE 0x04 | |
26473 | +#define TEST_FLAG_FLUSH 0x08 | |
26474 | +#define TEST_FLAG_DUMP 0x10 | |
26475 | +#define TEST_FLAG_SET_OPTION 0x20 | |
26476 | + | |
26477 | +static void test_dump_block(io_channel channel, | |
26478 | + struct test_private_data *data, | |
26479 | + unsigned long block, const void *buf) | |
26480 | +{ | |
26481 | + const unsigned char *cp; | |
26482 | + FILE *f = data->outfile; | |
26483 | + int i; | |
26484 | + unsigned long cksum = 0; | |
26485 | + | |
26486 | + for (i=0, cp = buf; i < channel->block_size; i++, cp++) { | |
26487 | + cksum += *cp; | |
26488 | + } | |
26489 | + fprintf(f, "Contents of block %lu, checksum %08lu: \n", block, cksum); | |
26490 | + for (i=0, cp = buf; i < channel->block_size; i++, cp++) { | |
26491 | + if ((i % 16) == 0) | |
26492 | + fprintf(f, "%04x: ", i); | |
26493 | + fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' '); | |
26494 | + } | |
26495 | +} | |
26496 | + | |
26497 | +static void test_abort(io_channel channel, unsigned long block) | |
26498 | +{ | |
26499 | + struct test_private_data *data; | |
26500 | + FILE *f; | |
26501 | + | |
26502 | + data = (struct test_private_data *) channel->private_data; | |
26503 | + f = data->outfile; | |
26504 | + test_flush(channel); | |
26505 | + | |
26506 | + fprintf(f, "Aborting due to I/O to block %lu\n", block); | |
26507 | + fflush(f); | |
26508 | + abort(); | |
26509 | +} | |
26510 | + | |
26511 | +static errcode_t test_open(const char *name, int flags, io_channel *channel) | |
26512 | +{ | |
26513 | + io_channel io = NULL; | |
26514 | + struct test_private_data *data = NULL; | |
26515 | + errcode_t retval; | |
26516 | + char *value; | |
26517 | + | |
26518 | + if (name == 0) | |
26519 | + return EXT2_ET_BAD_DEVICE_NAME; | |
26520 | + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); | |
26521 | + if (retval) | |
26522 | + return retval; | |
26523 | + memset(io, 0, sizeof(struct struct_io_channel)); | |
26524 | + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; | |
26525 | + retval = ext2fs_get_mem(sizeof(struct test_private_data), &data); | |
26526 | + if (retval) { | |
26527 | + retval = EXT2_ET_NO_MEMORY; | |
26528 | + goto cleanup; | |
26529 | + } | |
26530 | + io->manager = test_io_manager; | |
26531 | + retval = ext2fs_get_mem(strlen(name)+1, &io->name); | |
26532 | + if (retval) | |
26533 | + goto cleanup; | |
26534 | + | |
26535 | + strcpy(io->name, name); | |
26536 | + io->private_data = data; | |
26537 | + io->block_size = 1024; | |
26538 | + io->read_error = 0; | |
26539 | + io->write_error = 0; | |
26540 | + io->refcount = 1; | |
26541 | + | |
26542 | + memset(data, 0, sizeof(struct test_private_data)); | |
26543 | + data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL; | |
26544 | + if (test_io_backing_manager) { | |
26545 | + retval = test_io_backing_manager->open(name, flags, | |
26546 | + &data->real); | |
26547 | + if (retval) | |
26548 | + goto cleanup; | |
26549 | + } else | |
26550 | + data->real = 0; | |
26551 | + data->read_blk = test_io_cb_read_blk; | |
26552 | + data->write_blk = test_io_cb_write_blk; | |
26553 | + data->set_blksize = test_io_cb_set_blksize; | |
26554 | + data->write_byte = test_io_cb_write_byte; | |
26555 | + | |
26556 | + data->outfile = NULL; | |
26557 | + if ((value = getenv("TEST_IO_LOGFILE")) != NULL) | |
26558 | + data->outfile = fopen(value, "w"); | |
26559 | + if (!data->outfile) | |
26560 | + data->outfile = stderr; | |
26561 | + | |
26562 | + data->flags = 0; | |
26563 | + if ((value = getenv("TEST_IO_FLAGS")) != NULL) | |
26564 | + data->flags = strtoul(value, NULL, 0); | |
26565 | + | |
26566 | + data->block = 0; | |
26567 | + if ((value = getenv("TEST_IO_BLOCK")) != NULL) | |
26568 | + data->block = strtoul(value, NULL, 0); | |
26569 | + | |
26570 | + data->read_abort_count = 0; | |
26571 | + if ((value = getenv("TEST_IO_READ_ABORT")) != NULL) | |
26572 | + data->read_abort_count = strtoul(value, NULL, 0); | |
26573 | + | |
26574 | + data->write_abort_count = 0; | |
26575 | + if ((value = getenv("TEST_IO_WRITE_ABORT")) != NULL) | |
26576 | + data->write_abort_count = strtoul(value, NULL, 0); | |
26577 | + | |
26578 | + *channel = io; | |
26579 | + return 0; | |
26580 | + | |
26581 | +cleanup: | |
26582 | + if (io) | |
26583 | + ext2fs_free_mem(&io); | |
26584 | + if (data) | |
26585 | + ext2fs_free_mem(&data); | |
26586 | + return retval; | |
26587 | +} | |
26588 | + | |
26589 | +static errcode_t test_close(io_channel channel) | |
26590 | +{ | |
26591 | + struct test_private_data *data; | |
26592 | + errcode_t retval = 0; | |
26593 | + | |
26594 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
26595 | + data = (struct test_private_data *) channel->private_data; | |
26596 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); | |
26597 | + | |
26598 | + if (--channel->refcount > 0) | |
26599 | + return 0; | |
26600 | + | |
26601 | + if (data->real) | |
26602 | + retval = io_channel_close(data->real); | |
26603 | + | |
26604 | + if (data->outfile && data->outfile != stderr) | |
26605 | + fclose(data->outfile); | |
26606 | + | |
26607 | + ext2fs_free_mem(&channel->private_data); | |
26608 | + if (channel->name) | |
26609 | + ext2fs_free_mem(&channel->name); | |
26610 | + ext2fs_free_mem(&channel); | |
26611 | + return retval; | |
26612 | +} | |
26613 | + | |
26614 | +static errcode_t test_set_blksize(io_channel channel, int blksize) | |
26615 | +{ | |
26616 | + struct test_private_data *data; | |
26617 | + errcode_t retval = 0; | |
26618 | + | |
26619 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
26620 | + data = (struct test_private_data *) channel->private_data; | |
26621 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); | |
26622 | + | |
26623 | + if (data->real) | |
26624 | + retval = io_channel_set_blksize(data->real, blksize); | |
26625 | + if (data->set_blksize) | |
26626 | + data->set_blksize(blksize, retval); | |
26627 | + if (data->flags & TEST_FLAG_SET_BLKSIZE) | |
26628 | + fprintf(data->outfile, | |
26629 | + "Test_io: set_blksize(%d) returned %s\n", | |
26630 | + blksize, retval ? error_message(retval) : "OK"); | |
26631 | + channel->block_size = blksize; | |
26632 | + return retval; | |
26633 | +} | |
26634 | + | |
26635 | + | |
26636 | +static errcode_t test_read_blk(io_channel channel, unsigned long block, | |
26637 | + int count, void *buf) | |
26638 | +{ | |
26639 | + struct test_private_data *data; | |
26640 | + errcode_t retval = 0; | |
26641 | + | |
26642 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
26643 | + data = (struct test_private_data *) channel->private_data; | |
26644 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); | |
26645 | + | |
26646 | + if (data->real) | |
26647 | + retval = io_channel_read_blk(data->real, block, count, buf); | |
26648 | + if (data->read_blk) | |
26649 | + data->read_blk(block, count, retval); | |
26650 | + if (data->flags & TEST_FLAG_READ) | |
26651 | + fprintf(data->outfile, | |
26652 | + "Test_io: read_blk(%lu, %d) returned %s\n", | |
26653 | + block, count, retval ? error_message(retval) : "OK"); | |
26654 | + if (data->block && data->block == block) { | |
26655 | + if (data->flags & TEST_FLAG_DUMP) | |
26656 | + test_dump_block(channel, data, block, buf); | |
26657 | + if (--data->read_abort_count == 0) | |
26658 | + test_abort(channel, block); | |
26659 | + } | |
26660 | + return retval; | |
26661 | +} | |
26662 | + | |
26663 | +static errcode_t test_write_blk(io_channel channel, unsigned long block, | |
26664 | + int count, const void *buf) | |
26665 | +{ | |
26666 | + struct test_private_data *data; | |
26667 | + errcode_t retval = 0; | |
26668 | + | |
26669 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
26670 | + data = (struct test_private_data *) channel->private_data; | |
26671 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); | |
26672 | + | |
26673 | + if (data->real) | |
26674 | + retval = io_channel_write_blk(data->real, block, count, buf); | |
26675 | + if (data->write_blk) | |
26676 | + data->write_blk(block, count, retval); | |
26677 | + if (data->flags & TEST_FLAG_WRITE) | |
26678 | + fprintf(data->outfile, | |
26679 | + "Test_io: write_blk(%lu, %d) returned %s\n", | |
26680 | + block, count, retval ? error_message(retval) : "OK"); | |
26681 | + if (data->block && data->block == block) { | |
26682 | + if (data->flags & TEST_FLAG_DUMP) | |
26683 | + test_dump_block(channel, data, block, buf); | |
26684 | + if (--data->write_abort_count == 0) | |
26685 | + test_abort(channel, block); | |
26686 | + } | |
26687 | + return retval; | |
26688 | +} | |
26689 | + | |
26690 | +static errcode_t test_write_byte(io_channel channel, unsigned long offset, | |
26691 | + int count, const void *buf) | |
26692 | +{ | |
26693 | + struct test_private_data *data; | |
26694 | + errcode_t retval = 0; | |
26695 | + | |
26696 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
26697 | + data = (struct test_private_data *) channel->private_data; | |
26698 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); | |
26699 | + | |
26700 | + if (data->real && data->real->manager->write_byte) | |
26701 | + retval = io_channel_write_byte(data->real, offset, count, buf); | |
26702 | + if (data->write_byte) | |
26703 | + data->write_byte(offset, count, retval); | |
26704 | + if (data->flags & TEST_FLAG_WRITE) | |
26705 | + fprintf(data->outfile, | |
26706 | + "Test_io: write_byte(%lu, %d) returned %s\n", | |
26707 | + offset, count, retval ? error_message(retval) : "OK"); | |
26708 | + return retval; | |
26709 | +} | |
26710 | + | |
26711 | +/* | |
26712 | + * Flush data buffers to disk. | |
26713 | + */ | |
26714 | +static errcode_t test_flush(io_channel channel) | |
26715 | +{ | |
26716 | + struct test_private_data *data; | |
26717 | + errcode_t retval = 0; | |
26718 | + | |
26719 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
26720 | + data = (struct test_private_data *) channel->private_data; | |
26721 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); | |
26722 | + | |
26723 | + if (data->real) | |
26724 | + retval = io_channel_flush(data->real); | |
26725 | + | |
26726 | + if (data->flags & TEST_FLAG_FLUSH) | |
26727 | + fprintf(data->outfile, "Test_io: flush() returned %s\n", | |
26728 | + retval ? error_message(retval) : "OK"); | |
26729 | + | |
26730 | + return retval; | |
26731 | +} | |
26732 | + | |
26733 | +static errcode_t test_set_option(io_channel channel, const char *option, | |
26734 | + const char *arg) | |
26735 | +{ | |
26736 | + struct test_private_data *data; | |
26737 | + errcode_t retval = 0; | |
26738 | + | |
26739 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
26740 | + data = (struct test_private_data *) channel->private_data; | |
26741 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); | |
26742 | + | |
26743 | + | |
26744 | + if (data->flags & TEST_FLAG_SET_OPTION) | |
26745 | + fprintf(data->outfile, "Test_io: set_option(%s, %s) ", | |
26746 | + option, arg); | |
26747 | + if (data->real && data->real->manager->set_option) { | |
26748 | + retval = (data->real->manager->set_option)(data->real, | |
26749 | + option, arg); | |
26750 | + if (data->flags & TEST_FLAG_SET_OPTION) | |
26751 | + fprintf(data->outfile, "returned %s\n", | |
26752 | + retval ? error_message(retval) : "OK"); | |
26753 | + } else { | |
26754 | + if (data->flags & TEST_FLAG_SET_OPTION) | |
26755 | + fprintf(data->outfile, "not implemented\n"); | |
26756 | + } | |
26757 | + return retval; | |
26758 | +} | |
26759 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/unix_io.c busybox/e2fsprogs/ext2fs/unix_io.c | |
26760 | --- busybox-1.00/e2fsprogs/ext2fs/unix_io.c 1970-01-01 01:00:00.000000000 +0100 | |
26761 | +++ busybox/e2fsprogs/ext2fs/unix_io.c 2005-06-04 08:20:16.000000000 +0200 | |
26762 | @@ -0,0 +1,707 @@ | |
26763 | +/* | |
26764 | + * unix_io.c --- This is the Unix (well, really POSIX) implementation | |
26765 | + * of the I/O manager. | |
26766 | + * | |
26767 | + * Implements a one-block write-through cache. | |
26768 | + * | |
26769 | + * Includes support for Windows NT support under Cygwin. | |
26770 | + * | |
26771 | + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, | |
26772 | + * 2002 by Theodore Ts'o. | |
26773 | + * | |
26774 | + * %Begin-Header% | |
26775 | + * This file may be redistributed under the terms of the GNU Public | |
26776 | + * License. | |
26777 | + * %End-Header% | |
26778 | + */ | |
26779 | + | |
26780 | +#include <stdio.h> | |
26781 | +#include <string.h> | |
26782 | +#if HAVE_UNISTD_H | |
26783 | +#include <unistd.h> | |
26784 | +#endif | |
26785 | +#if HAVE_ERRNO_H | |
26786 | +#include <errno.h> | |
26787 | +#endif | |
26788 | +#include <fcntl.h> | |
26789 | +#include <time.h> | |
26790 | +#ifdef __linux__ | |
26791 | +#include <sys/utsname.h> | |
26792 | +#endif | |
26793 | +#if HAVE_SYS_STAT_H | |
26794 | +#include <sys/stat.h> | |
26795 | +#endif | |
26796 | +#if HAVE_SYS_TYPES_H | |
26797 | +#include <sys/types.h> | |
26798 | +#endif | |
26799 | +#if HAVE_SYS_RESOURCE_H | |
26800 | +#include <sys/resource.h> | |
26801 | +#endif | |
26802 | + | |
26803 | +#include "ext2_fs.h" | |
26804 | +#include "ext2fs.h" | |
26805 | + | |
26806 | +/* | |
26807 | + * For checking structure magic numbers... | |
26808 | + */ | |
26809 | + | |
26810 | +#define EXT2_CHECK_MAGIC(struct, code) \ | |
26811 | + if ((struct)->magic != (code)) return (code) | |
26812 | + | |
26813 | +struct unix_cache { | |
26814 | + char *buf; | |
26815 | + unsigned long block; | |
26816 | + int access_time; | |
26817 | + unsigned dirty:1; | |
26818 | + unsigned in_use:1; | |
26819 | +}; | |
26820 | + | |
26821 | +#define CACHE_SIZE 8 | |
26822 | +#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */ | |
26823 | +#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */ | |
26824 | + | |
26825 | +struct unix_private_data { | |
26826 | + int magic; | |
26827 | + int dev; | |
26828 | + int flags; | |
26829 | + int access_time; | |
26830 | + ext2_loff_t offset; | |
26831 | + struct unix_cache cache[CACHE_SIZE]; | |
26832 | +}; | |
26833 | + | |
26834 | +static errcode_t unix_open(const char *name, int flags, io_channel *channel); | |
26835 | +static errcode_t unix_close(io_channel channel); | |
26836 | +static errcode_t unix_set_blksize(io_channel channel, int blksize); | |
26837 | +static errcode_t unix_read_blk(io_channel channel, unsigned long block, | |
26838 | + int count, void *data); | |
26839 | +static errcode_t unix_write_blk(io_channel channel, unsigned long block, | |
26840 | + int count, const void *data); | |
26841 | +static errcode_t unix_flush(io_channel channel); | |
26842 | +static errcode_t unix_write_byte(io_channel channel, unsigned long offset, | |
26843 | + int size, const void *data); | |
26844 | +static errcode_t unix_set_option(io_channel channel, const char *option, | |
26845 | + const char *arg); | |
26846 | + | |
26847 | +static void reuse_cache(io_channel channel, struct unix_private_data *data, | |
26848 | + struct unix_cache *cache, unsigned long block); | |
26849 | + | |
26850 | +/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel | |
26851 | + * does not know buffered block devices - everything is raw. */ | |
26852 | +#if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | |
26853 | +#define NEED_BOUNCE_BUFFER | |
26854 | +#else | |
26855 | +#undef NEED_BOUNCE_BUFFER | |
26856 | +#endif | |
26857 | + | |
26858 | +static struct struct_io_manager struct_unix_manager = { | |
26859 | + EXT2_ET_MAGIC_IO_MANAGER, | |
26860 | + "Unix I/O Manager", | |
26861 | + unix_open, | |
26862 | + unix_close, | |
26863 | + unix_set_blksize, | |
26864 | + unix_read_blk, | |
26865 | + unix_write_blk, | |
26866 | + unix_flush, | |
26867 | +#ifdef NEED_BOUNCE_BUFFER | |
26868 | + 0, | |
26869 | +#else | |
26870 | + unix_write_byte, | |
26871 | +#endif | |
26872 | + unix_set_option | |
26873 | +}; | |
26874 | + | |
26875 | +io_manager unix_io_manager = &struct_unix_manager; | |
26876 | + | |
26877 | +/* | |
26878 | + * Here are the raw I/O functions | |
26879 | + */ | |
26880 | +#ifndef NEED_BOUNCE_BUFFER | |
26881 | +static errcode_t raw_read_blk(io_channel channel, | |
26882 | + struct unix_private_data *data, | |
26883 | + unsigned long block, | |
26884 | + int count, void *buf) | |
26885 | +{ | |
26886 | + errcode_t retval; | |
26887 | + ssize_t size; | |
26888 | + ext2_loff_t location; | |
26889 | + int actual = 0; | |
26890 | + | |
26891 | + size = (count < 0) ? -count : count * channel->block_size; | |
26892 | + location = ((ext2_loff_t) block * channel->block_size) + data->offset; | |
26893 | + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { | |
26894 | + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; | |
26895 | + goto error_out; | |
26896 | + } | |
26897 | + actual = read(data->dev, buf, size); | |
26898 | + if (actual != size) { | |
26899 | + if (actual < 0) | |
26900 | + actual = 0; | |
26901 | + retval = EXT2_ET_SHORT_READ; | |
26902 | + goto error_out; | |
26903 | + } | |
26904 | + return 0; | |
26905 | + | |
26906 | +error_out: | |
26907 | + memset((char *) buf+actual, 0, size-actual); | |
26908 | + if (channel->read_error) | |
26909 | + retval = (channel->read_error)(channel, block, count, buf, | |
26910 | + size, actual, retval); | |
26911 | + return retval; | |
26912 | +} | |
26913 | +#else /* NEED_BOUNCE_BUFFER */ | |
26914 | +/* | |
26915 | + * Windows and FreeBSD block devices only allow sector alignment IO in offset and size | |
26916 | + */ | |
26917 | +static errcode_t raw_read_blk(io_channel channel, | |
26918 | + struct unix_private_data *data, | |
26919 | + unsigned long block, | |
26920 | + int count, void *buf) | |
26921 | +{ | |
26922 | + errcode_t retval; | |
26923 | + size_t size, alignsize, fragment; | |
26924 | + ext2_loff_t location; | |
26925 | + int total = 0, actual; | |
26926 | +#define BLOCKALIGN 512 | |
26927 | + char sector[BLOCKALIGN]; | |
26928 | + | |
26929 | + size = (count < 0) ? -count : count * channel->block_size; | |
26930 | + location = ((ext2_loff_t) block * channel->block_size) + data->offset; | |
26931 | +#ifdef DEBUG | |
26932 | + printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n", | |
26933 | + count, size, block, channel->block_size, location); | |
26934 | +#endif | |
26935 | + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { | |
26936 | + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; | |
26937 | + goto error_out; | |
26938 | + } | |
26939 | + fragment = size % BLOCKALIGN; | |
26940 | + alignsize = size - fragment; | |
26941 | + if (alignsize) { | |
26942 | + actual = read(data->dev, buf, alignsize); | |
26943 | + if (actual != alignsize) | |
26944 | + goto short_read; | |
26945 | + } | |
26946 | + if (fragment) { | |
26947 | + actual = read(data->dev, sector, BLOCKALIGN); | |
26948 | + if (actual != BLOCKALIGN) | |
26949 | + goto short_read; | |
26950 | + memcpy(buf+alignsize, sector, fragment); | |
26951 | + } | |
26952 | + return 0; | |
26953 | + | |
26954 | +short_read: | |
26955 | + if (actual>0) | |
26956 | + total += actual; | |
26957 | + retval = EXT2_ET_SHORT_READ; | |
26958 | + | |
26959 | +error_out: | |
26960 | + memset((char *) buf+total, 0, size-actual); | |
26961 | + if (channel->read_error) | |
26962 | + retval = (channel->read_error)(channel, block, count, buf, | |
26963 | + size, actual, retval); | |
26964 | + return retval; | |
26965 | +} | |
26966 | +#endif | |
26967 | + | |
26968 | +static errcode_t raw_write_blk(io_channel channel, | |
26969 | + struct unix_private_data *data, | |
26970 | + unsigned long block, | |
26971 | + int count, const void *buf) | |
26972 | +{ | |
26973 | + ssize_t size; | |
26974 | + ext2_loff_t location; | |
26975 | + int actual = 0; | |
26976 | + errcode_t retval; | |
26977 | + | |
26978 | + if (count == 1) | |
26979 | + size = channel->block_size; | |
26980 | + else { | |
26981 | + if (count < 0) | |
26982 | + size = -count; | |
26983 | + else | |
26984 | + size = count * channel->block_size; | |
26985 | + } | |
26986 | + | |
26987 | + location = ((ext2_loff_t) block * channel->block_size) + data->offset; | |
26988 | + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { | |
26989 | + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; | |
26990 | + goto error_out; | |
26991 | + } | |
26992 | + | |
26993 | + actual = write(data->dev, buf, size); | |
26994 | + if (actual != size) { | |
26995 | + retval = EXT2_ET_SHORT_WRITE; | |
26996 | + goto error_out; | |
26997 | + } | |
26998 | + return 0; | |
26999 | + | |
27000 | +error_out: | |
27001 | + if (channel->write_error) | |
27002 | + retval = (channel->write_error)(channel, block, count, buf, | |
27003 | + size, actual, retval); | |
27004 | + return retval; | |
27005 | +} | |
27006 | + | |
27007 | + | |
27008 | +/* | |
27009 | + * Here we implement the cache functions | |
27010 | + */ | |
27011 | + | |
27012 | +/* Allocate the cache buffers */ | |
27013 | +static errcode_t alloc_cache(io_channel channel, | |
27014 | + struct unix_private_data *data) | |
27015 | +{ | |
27016 | + errcode_t retval; | |
27017 | + struct unix_cache *cache; | |
27018 | + int i; | |
27019 | + | |
27020 | + data->access_time = 0; | |
27021 | + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { | |
27022 | + cache->block = 0; | |
27023 | + cache->access_time = 0; | |
27024 | + cache->dirty = 0; | |
27025 | + cache->in_use = 0; | |
27026 | + if ((retval = ext2fs_get_mem(channel->block_size, | |
27027 | + &cache->buf))) | |
27028 | + return retval; | |
27029 | + } | |
27030 | + return 0; | |
27031 | +} | |
27032 | + | |
27033 | +/* Free the cache buffers */ | |
27034 | +static void free_cache(struct unix_private_data *data) | |
27035 | +{ | |
27036 | + struct unix_cache *cache; | |
27037 | + int i; | |
27038 | + | |
27039 | + data->access_time = 0; | |
27040 | + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { | |
27041 | + cache->block = 0; | |
27042 | + cache->access_time = 0; | |
27043 | + cache->dirty = 0; | |
27044 | + cache->in_use = 0; | |
27045 | + if (cache->buf) | |
27046 | + ext2fs_free_mem(&cache->buf); | |
27047 | + cache->buf = 0; | |
27048 | + } | |
27049 | +} | |
27050 | + | |
27051 | +#ifndef NO_IO_CACHE | |
27052 | +/* | |
27053 | + * Try to find a block in the cache. If the block is not found, and | |
27054 | + * eldest is a non-zero pointer, then fill in eldest with the cache | |
27055 | + * entry to that should be reused. | |
27056 | + */ | |
27057 | +static struct unix_cache *find_cached_block(struct unix_private_data *data, | |
27058 | + unsigned long block, | |
27059 | + struct unix_cache **eldest) | |
27060 | +{ | |
27061 | + struct unix_cache *cache, *unused_cache, *oldest_cache; | |
27062 | + int i; | |
27063 | + | |
27064 | + unused_cache = oldest_cache = 0; | |
27065 | + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { | |
27066 | + if (!cache->in_use) { | |
27067 | + if (!unused_cache) | |
27068 | + unused_cache = cache; | |
27069 | + continue; | |
27070 | + } | |
27071 | + if (cache->block == block) { | |
27072 | + cache->access_time = ++data->access_time; | |
27073 | + return cache; | |
27074 | + } | |
27075 | + if (!oldest_cache || | |
27076 | + (cache->access_time < oldest_cache->access_time)) | |
27077 | + oldest_cache = cache; | |
27078 | + } | |
27079 | + if (eldest) | |
27080 | + *eldest = (unused_cache) ? unused_cache : oldest_cache; | |
27081 | + return 0; | |
27082 | +} | |
27083 | + | |
27084 | +/* | |
27085 | + * Reuse a particular cache entry for another block. | |
27086 | + */ | |
27087 | +static void reuse_cache(io_channel channel, struct unix_private_data *data, | |
27088 | + struct unix_cache *cache, unsigned long block) | |
27089 | +{ | |
27090 | + if (cache->dirty && cache->in_use) | |
27091 | + raw_write_blk(channel, data, cache->block, 1, cache->buf); | |
27092 | + | |
27093 | + cache->in_use = 1; | |
27094 | + cache->dirty = 0; | |
27095 | + cache->block = block; | |
27096 | + cache->access_time = ++data->access_time; | |
27097 | +} | |
27098 | + | |
27099 | +/* | |
27100 | + * Flush all of the blocks in the cache | |
27101 | + */ | |
27102 | +static errcode_t flush_cached_blocks(io_channel channel, | |
27103 | + struct unix_private_data *data, | |
27104 | + int invalidate) | |
27105 | + | |
27106 | +{ | |
27107 | + struct unix_cache *cache; | |
27108 | + errcode_t retval, retval2; | |
27109 | + int i; | |
27110 | + | |
27111 | + retval2 = 0; | |
27112 | + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { | |
27113 | + if (!cache->in_use) | |
27114 | + continue; | |
27115 | + | |
27116 | + if (invalidate) | |
27117 | + cache->in_use = 0; | |
27118 | + | |
27119 | + if (!cache->dirty) | |
27120 | + continue; | |
27121 | + | |
27122 | + retval = raw_write_blk(channel, data, | |
27123 | + cache->block, 1, cache->buf); | |
27124 | + if (retval) | |
27125 | + retval2 = retval; | |
27126 | + else | |
27127 | + cache->dirty = 0; | |
27128 | + } | |
27129 | + return retval2; | |
27130 | +} | |
27131 | +#endif /* NO_IO_CACHE */ | |
27132 | + | |
27133 | +static errcode_t unix_open(const char *name, int flags, io_channel *channel) | |
27134 | +{ | |
27135 | + io_channel io = NULL; | |
27136 | + struct unix_private_data *data = NULL; | |
27137 | + errcode_t retval; | |
27138 | + int open_flags; | |
27139 | + struct stat st; | |
27140 | +#ifdef __linux__ | |
27141 | + struct utsname ut; | |
27142 | +#endif | |
27143 | + | |
27144 | + if (name == 0) | |
27145 | + return EXT2_ET_BAD_DEVICE_NAME; | |
27146 | + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); | |
27147 | + if (retval) | |
27148 | + return retval; | |
27149 | + memset(io, 0, sizeof(struct struct_io_channel)); | |
27150 | + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; | |
27151 | + retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data); | |
27152 | + if (retval) | |
27153 | + goto cleanup; | |
27154 | + | |
27155 | + io->manager = unix_io_manager; | |
27156 | + retval = ext2fs_get_mem(strlen(name)+1, &io->name); | |
27157 | + if (retval) | |
27158 | + goto cleanup; | |
27159 | + | |
27160 | + strcpy(io->name, name); | |
27161 | + io->private_data = data; | |
27162 | + io->block_size = 1024; | |
27163 | + io->read_error = 0; | |
27164 | + io->write_error = 0; | |
27165 | + io->refcount = 1; | |
27166 | + | |
27167 | + memset(data, 0, sizeof(struct unix_private_data)); | |
27168 | + data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; | |
27169 | + | |
27170 | + if ((retval = alloc_cache(io, data))) | |
27171 | + goto cleanup; | |
27172 | + | |
27173 | + open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; | |
27174 | +#ifdef CONFIG_LFS | |
27175 | + data->dev = open64(io->name, open_flags); | |
27176 | +#else | |
27177 | + data->dev = open(io->name, open_flags); | |
27178 | +#endif | |
27179 | + if (data->dev < 0) { | |
27180 | + retval = errno; | |
27181 | + goto cleanup; | |
27182 | + } | |
27183 | + | |
27184 | +#ifdef __linux__ | |
27185 | +#undef RLIM_INFINITY | |
27186 | +#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4))) | |
27187 | +#define RLIM_INFINITY ((unsigned long)(~0UL>>1)) | |
27188 | +#else | |
27189 | +#define RLIM_INFINITY (~0UL) | |
27190 | +#endif | |
27191 | + /* | |
27192 | + * Work around a bug in 2.4.10-2.4.18 kernels where writes to | |
27193 | + * block devices are wrongly getting hit by the filesize | |
27194 | + * limit. This workaround isn't perfect, since it won't work | |
27195 | + * if glibc wasn't built against 2.2 header files. (Sigh.) | |
27196 | + * | |
27197 | + */ | |
27198 | + if ((flags & IO_FLAG_RW) && | |
27199 | + (uname(&ut) == 0) && | |
27200 | + ((ut.release[0] == '2') && (ut.release[1] == '.') && | |
27201 | + (ut.release[2] == '4') && (ut.release[3] == '.') && | |
27202 | + (ut.release[4] == '1') && (ut.release[5] >= '0') && | |
27203 | + (ut.release[5] < '8')) && | |
27204 | + (fstat(data->dev, &st) == 0) && | |
27205 | + (S_ISBLK(st.st_mode))) { | |
27206 | + struct rlimit rlim; | |
27207 | + | |
27208 | + rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY; | |
27209 | + setrlimit(RLIMIT_FSIZE, &rlim); | |
27210 | + getrlimit(RLIMIT_FSIZE, &rlim); | |
27211 | + if (((unsigned long) rlim.rlim_cur) < | |
27212 | + ((unsigned long) rlim.rlim_max)) { | |
27213 | + rlim.rlim_cur = rlim.rlim_max; | |
27214 | + setrlimit(RLIMIT_FSIZE, &rlim); | |
27215 | + } | |
27216 | + } | |
27217 | +#endif | |
27218 | + *channel = io; | |
27219 | + return 0; | |
27220 | + | |
27221 | +cleanup: | |
27222 | + if (data) { | |
27223 | + free_cache(data); | |
27224 | + ext2fs_free_mem(&data); | |
27225 | + } | |
27226 | + if (io) | |
27227 | + ext2fs_free_mem(&io); | |
27228 | + return retval; | |
27229 | +} | |
27230 | + | |
27231 | +static errcode_t unix_close(io_channel channel) | |
27232 | +{ | |
27233 | + struct unix_private_data *data; | |
27234 | + errcode_t retval = 0; | |
27235 | + | |
27236 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
27237 | + data = (struct unix_private_data *) channel->private_data; | |
27238 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); | |
27239 | + | |
27240 | + if (--channel->refcount > 0) | |
27241 | + return 0; | |
27242 | + | |
27243 | +#ifndef NO_IO_CACHE | |
27244 | + retval = flush_cached_blocks(channel, data, 0); | |
27245 | +#endif | |
27246 | + | |
27247 | + if (close(data->dev) < 0) | |
27248 | + retval = errno; | |
27249 | + free_cache(data); | |
27250 | + | |
27251 | + ext2fs_free_mem(&channel->private_data); | |
27252 | + if (channel->name) | |
27253 | + ext2fs_free_mem(&channel->name); | |
27254 | + ext2fs_free_mem(&channel); | |
27255 | + return retval; | |
27256 | +} | |
27257 | + | |
27258 | +static errcode_t unix_set_blksize(io_channel channel, int blksize) | |
27259 | +{ | |
27260 | + struct unix_private_data *data; | |
27261 | + errcode_t retval; | |
27262 | + | |
27263 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
27264 | + data = (struct unix_private_data *) channel->private_data; | |
27265 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); | |
27266 | + | |
27267 | + if (channel->block_size != blksize) { | |
27268 | +#ifndef NO_IO_CACHE | |
27269 | + if ((retval = flush_cached_blocks(channel, data, 0))) | |
27270 | + return retval; | |
27271 | +#endif | |
27272 | + | |
27273 | + channel->block_size = blksize; | |
27274 | + free_cache(data); | |
27275 | + if ((retval = alloc_cache(channel, data))) | |
27276 | + return retval; | |
27277 | + } | |
27278 | + return 0; | |
27279 | +} | |
27280 | + | |
27281 | + | |
27282 | +static errcode_t unix_read_blk(io_channel channel, unsigned long block, | |
27283 | + int count, void *buf) | |
27284 | +{ | |
27285 | + struct unix_private_data *data; | |
27286 | + struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; | |
27287 | + errcode_t retval; | |
27288 | + char *cp; | |
27289 | + int i, j; | |
27290 | + | |
27291 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
27292 | + data = (struct unix_private_data *) channel->private_data; | |
27293 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); | |
27294 | + | |
27295 | +#ifdef NO_IO_CACHE | |
27296 | + return raw_read_blk(channel, data, block, count, buf); | |
27297 | +#else | |
27298 | + /* | |
27299 | + * If we're doing an odd-sized read or a very large read, | |
27300 | + * flush out the cache and then do a direct read. | |
27301 | + */ | |
27302 | + if (count < 0 || count > WRITE_DIRECT_SIZE) { | |
27303 | + if ((retval = flush_cached_blocks(channel, data, 0))) | |
27304 | + return retval; | |
27305 | + return raw_read_blk(channel, data, block, count, buf); | |
27306 | + } | |
27307 | + | |
27308 | + cp = buf; | |
27309 | + while (count > 0) { | |
27310 | + /* If it's in the cache, use it! */ | |
27311 | + if ((cache = find_cached_block(data, block, &reuse[0]))) { | |
27312 | +#ifdef DEBUG | |
27313 | + printf("Using cached block %d\n", block); | |
27314 | +#endif | |
27315 | + memcpy(cp, cache->buf, channel->block_size); | |
27316 | + count--; | |
27317 | + block++; | |
27318 | + cp += channel->block_size; | |
27319 | + continue; | |
27320 | + } | |
27321 | + /* | |
27322 | + * Find the number of uncached blocks so we can do a | |
27323 | + * single read request | |
27324 | + */ | |
27325 | + for (i=1; i < count; i++) | |
27326 | + if (find_cached_block(data, block+i, &reuse[i])) | |
27327 | + break; | |
27328 | +#ifdef DEBUG | |
27329 | + printf("Reading %d blocks starting at %d\n", i, block); | |
27330 | +#endif | |
27331 | + if ((retval = raw_read_blk(channel, data, block, i, cp))) | |
27332 | + return retval; | |
27333 | + | |
27334 | + /* Save the results in the cache */ | |
27335 | + for (j=0; j < i; j++) { | |
27336 | + count--; | |
27337 | + cache = reuse[j]; | |
27338 | + reuse_cache(channel, data, cache, block++); | |
27339 | + memcpy(cache->buf, cp, channel->block_size); | |
27340 | + cp += channel->block_size; | |
27341 | + } | |
27342 | + } | |
27343 | + return 0; | |
27344 | +#endif /* NO_IO_CACHE */ | |
27345 | +} | |
27346 | + | |
27347 | +static errcode_t unix_write_blk(io_channel channel, unsigned long block, | |
27348 | + int count, const void *buf) | |
27349 | +{ | |
27350 | + struct unix_private_data *data; | |
27351 | + struct unix_cache *cache, *reuse; | |
27352 | + errcode_t retval = 0; | |
27353 | + const char *cp; | |
27354 | + int writethrough; | |
27355 | + | |
27356 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
27357 | + data = (struct unix_private_data *) channel->private_data; | |
27358 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); | |
27359 | + | |
27360 | +#ifdef NO_IO_CACHE | |
27361 | + return raw_write_blk(channel, data, block, count, buf); | |
27362 | +#else | |
27363 | + /* | |
27364 | + * If we're doing an odd-sized write or a very large write, | |
27365 | + * flush out the cache completely and then do a direct write. | |
27366 | + */ | |
27367 | + if (count < 0 || count > WRITE_DIRECT_SIZE) { | |
27368 | + if ((retval = flush_cached_blocks(channel, data, 1))) | |
27369 | + return retval; | |
27370 | + return raw_write_blk(channel, data, block, count, buf); | |
27371 | + } | |
27372 | + | |
27373 | + /* | |
27374 | + * For a moderate-sized multi-block write, first force a write | |
27375 | + * if we're in write-through cache mode, and then fill the | |
27376 | + * cache with the blocks. | |
27377 | + */ | |
27378 | + writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; | |
27379 | + if (writethrough) | |
27380 | + retval = raw_write_blk(channel, data, block, count, buf); | |
27381 | + | |
27382 | + cp = buf; | |
27383 | + while (count > 0) { | |
27384 | + cache = find_cached_block(data, block, &reuse); | |
27385 | + if (!cache) { | |
27386 | + cache = reuse; | |
27387 | + reuse_cache(channel, data, cache, block); | |
27388 | + } | |
27389 | + memcpy(cache->buf, cp, channel->block_size); | |
27390 | + cache->dirty = !writethrough; | |
27391 | + count--; | |
27392 | + block++; | |
27393 | + cp += channel->block_size; | |
27394 | + } | |
27395 | + return retval; | |
27396 | +#endif /* NO_IO_CACHE */ | |
27397 | +} | |
27398 | + | |
27399 | +static errcode_t unix_write_byte(io_channel channel, unsigned long offset, | |
27400 | + int size, const void *buf) | |
27401 | +{ | |
27402 | + struct unix_private_data *data; | |
27403 | + errcode_t retval = 0; | |
27404 | + ssize_t actual; | |
27405 | + | |
27406 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
27407 | + data = (struct unix_private_data *) channel->private_data; | |
27408 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); | |
27409 | + | |
27410 | +#ifndef NO_IO_CACHE | |
27411 | + /* | |
27412 | + * Flush out the cache completely | |
27413 | + */ | |
27414 | + if ((retval = flush_cached_blocks(channel, data, 1))) | |
27415 | + return retval; | |
27416 | +#endif | |
27417 | + | |
27418 | + if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0) | |
27419 | + return errno; | |
27420 | + | |
27421 | + actual = write(data->dev, buf, size); | |
27422 | + if (actual != size) | |
27423 | + return EXT2_ET_SHORT_WRITE; | |
27424 | + | |
27425 | + return 0; | |
27426 | +} | |
27427 | + | |
27428 | +/* | |
27429 | + * Flush data buffers to disk. | |
27430 | + */ | |
27431 | +static errcode_t unix_flush(io_channel channel) | |
27432 | +{ | |
27433 | + struct unix_private_data *data; | |
27434 | + errcode_t retval = 0; | |
27435 | + | |
27436 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
27437 | + data = (struct unix_private_data *) channel->private_data; | |
27438 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); | |
27439 | + | |
27440 | +#ifndef NO_IO_CACHE | |
27441 | + retval = flush_cached_blocks(channel, data, 0); | |
27442 | +#endif | |
27443 | + fsync(data->dev); | |
27444 | + return retval; | |
27445 | +} | |
27446 | + | |
27447 | +static errcode_t unix_set_option(io_channel channel, const char *option, | |
27448 | + const char *arg) | |
27449 | +{ | |
27450 | + struct unix_private_data *data; | |
27451 | + unsigned long tmp; | |
27452 | + char *end; | |
27453 | + | |
27454 | + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); | |
27455 | + data = (struct unix_private_data *) channel->private_data; | |
27456 | + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); | |
27457 | + | |
27458 | + if (!strcmp(option, "offset")) { | |
27459 | + if (!arg) | |
27460 | + return EXT2_ET_INVALID_ARGUMENT; | |
27461 | + | |
27462 | + tmp = strtoul(arg, &end, 0); | |
27463 | + if (*end) | |
27464 | + return EXT2_ET_INVALID_ARGUMENT; | |
27465 | + data->offset = tmp; | |
27466 | + return 0; | |
27467 | + } | |
27468 | + return EXT2_ET_INVALID_ARGUMENT; | |
27469 | +} | |
27470 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/unlink.c busybox/e2fsprogs/ext2fs/unlink.c | |
27471 | --- busybox-1.00/e2fsprogs/ext2fs/unlink.c 1970-01-01 01:00:00.000000000 +0100 | |
27472 | +++ busybox/e2fsprogs/ext2fs/unlink.c 2005-06-04 08:20:16.000000000 +0200 | |
27473 | @@ -0,0 +1,99 @@ | |
27474 | +/* | |
27475 | + * unlink.c --- delete links in a ext2fs directory | |
27476 | + * | |
27477 | + * Copyright (C) 1993, 1994, 1997 Theodore Ts'o. | |
27478 | + * | |
27479 | + * %Begin-Header% | |
27480 | + * This file may be redistributed under the terms of the GNU Public | |
27481 | + * License. | |
27482 | + * %End-Header% | |
27483 | + */ | |
27484 | + | |
27485 | +#include <stdio.h> | |
27486 | +#include <string.h> | |
27487 | +#if HAVE_UNISTD_H | |
27488 | +#include <unistd.h> | |
27489 | +#endif | |
27490 | + | |
27491 | +#include "ext2_fs.h" | |
27492 | +#include "ext2fs.h" | |
27493 | + | |
27494 | +struct link_struct { | |
27495 | + const char *name; | |
27496 | + int namelen; | |
27497 | + ext2_ino_t inode; | |
27498 | + int flags; | |
27499 | + struct ext2_dir_entry *prev; | |
27500 | + int done; | |
27501 | +}; | |
27502 | + | |
27503 | +#ifdef __TURBOC__ | |
27504 | + #pragma argsused | |
27505 | +#endif | |
27506 | +static int unlink_proc(struct ext2_dir_entry *dirent, | |
27507 | + int offset EXT2FS_ATTR((unused)), | |
27508 | + int blocksize EXT2FS_ATTR((unused)), | |
27509 | + char *buf EXT2FS_ATTR((unused)), | |
27510 | + void *priv_data) | |
27511 | +{ | |
27512 | + struct link_struct *ls = (struct link_struct *) priv_data; | |
27513 | + struct ext2_dir_entry *prev; | |
27514 | + | |
27515 | + prev = ls->prev; | |
27516 | + ls->prev = dirent; | |
27517 | + | |
27518 | + if (ls->name) { | |
27519 | + if ((dirent->name_len & 0xFF) != ls->namelen) | |
27520 | + return 0; | |
27521 | + if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF)) | |
27522 | + return 0; | |
27523 | + } | |
27524 | + if (ls->inode) { | |
27525 | + if (dirent->inode != ls->inode) | |
27526 | + return 0; | |
27527 | + } else { | |
27528 | + if (!dirent->inode) | |
27529 | + return 0; | |
27530 | + } | |
27531 | + | |
27532 | + if (prev) | |
27533 | + prev->rec_len += dirent->rec_len; | |
27534 | + else | |
27535 | + dirent->inode = 0; | |
27536 | + ls->done++; | |
27537 | + return DIRENT_ABORT|DIRENT_CHANGED; | |
27538 | +} | |
27539 | + | |
27540 | +#ifdef __TURBOC__ | |
27541 | + #pragma argsused | |
27542 | +#endif | |
27543 | +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, | |
27544 | + const char *name, ext2_ino_t ino, | |
27545 | + int flags EXT2FS_ATTR((unused))) | |
27546 | +{ | |
27547 | + errcode_t retval; | |
27548 | + struct link_struct ls; | |
27549 | + | |
27550 | + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
27551 | + | |
27552 | + if (!name && !ino) | |
27553 | + return EXT2_ET_INVALID_ARGUMENT; | |
27554 | + | |
27555 | + if (!(fs->flags & EXT2_FLAG_RW)) | |
27556 | + return EXT2_ET_RO_FILSYS; | |
27557 | + | |
27558 | + ls.name = name; | |
27559 | + ls.namelen = name ? strlen(name) : 0; | |
27560 | + ls.inode = ino; | |
27561 | + ls.flags = 0; | |
27562 | + ls.done = 0; | |
27563 | + ls.prev = 0; | |
27564 | + | |
27565 | + retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, | |
27566 | + 0, unlink_proc, &ls); | |
27567 | + if (retval) | |
27568 | + return retval; | |
27569 | + | |
27570 | + return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE; | |
27571 | +} | |
27572 | + | |
27573 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/valid_blk.c busybox/e2fsprogs/ext2fs/valid_blk.c | |
27574 | --- busybox-1.00/e2fsprogs/ext2fs/valid_blk.c 1970-01-01 01:00:00.000000000 +0100 | |
27575 | +++ busybox/e2fsprogs/ext2fs/valid_blk.c 2005-06-04 08:20:16.000000000 +0200 | |
27576 | @@ -0,0 +1,56 @@ | |
27577 | +/* | |
27578 | + * valid_blk.c --- does the inode have valid blocks? | |
27579 | + * | |
27580 | + * Copyright 1997 by Theodore Ts'o | |
27581 | + * | |
27582 | + * %Begin-Header% | |
27583 | + * This file may be redistributed under the terms of the GNU Public | |
27584 | + * License. | |
27585 | + * %End-Header% | |
27586 | + * | |
27587 | + */ | |
27588 | + | |
27589 | +#include <stdio.h> | |
27590 | +#if HAVE_UNISTD_H | |
27591 | +#include <unistd.h> | |
27592 | +#endif | |
27593 | +#include <string.h> | |
27594 | +#include <time.h> | |
27595 | + | |
27596 | +#include "ext2_fs.h" | |
27597 | +#include "ext2fs.h" | |
27598 | + | |
27599 | +/* | |
27600 | + * This function returns 1 if the inode's block entries actually | |
27601 | + * contain block entries. | |
27602 | + */ | |
27603 | +int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode) | |
27604 | +{ | |
27605 | + /* | |
27606 | + * Only directories, regular files, and some symbolic links | |
27607 | + * have valid block entries. | |
27608 | + */ | |
27609 | + if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) && | |
27610 | + !LINUX_S_ISLNK(inode->i_mode)) | |
27611 | + return 0; | |
27612 | + | |
27613 | + /* | |
27614 | + * If the symbolic link is a "fast symlink", then the symlink | |
27615 | + * target is stored in the block entries. | |
27616 | + */ | |
27617 | + if (LINUX_S_ISLNK (inode->i_mode)) { | |
27618 | + if (inode->i_file_acl == 0) { | |
27619 | + /* With no EA block, we can rely on i_blocks */ | |
27620 | + if (inode->i_blocks == 0) | |
27621 | + return 0; | |
27622 | + } else { | |
27623 | + /* With an EA block, life gets more tricky */ | |
27624 | + if (inode->i_size >= EXT2_N_BLOCKS*4) | |
27625 | + return 1; /* definitely using i_block[] */ | |
27626 | + if (inode->i_size > 4 && inode->i_block[1] == 0) | |
27627 | + return 1; /* definitely using i_block[] */ | |
27628 | + return 0; /* Probably a fast symlink */ | |
27629 | + } | |
27630 | + } | |
27631 | + return 1; | |
27632 | +} | |
27633 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/version.c busybox/e2fsprogs/ext2fs/version.c | |
27634 | --- busybox-1.00/e2fsprogs/ext2fs/version.c 1970-01-01 01:00:00.000000000 +0100 | |
27635 | +++ busybox/e2fsprogs/ext2fs/version.c 2005-06-04 08:20:16.000000000 +0200 | |
27636 | @@ -0,0 +1,52 @@ | |
27637 | +/* | |
27638 | + * version.c --- Return the version of the ext2 library | |
27639 | + * | |
27640 | + * Copyright (C) 1997 Theodore Ts'o. | |
27641 | + * | |
27642 | + * %Begin-Header% | |
27643 | + * This file may be redistributed under the terms of the GNU Public | |
27644 | + * License. | |
27645 | + * %End-Header% | |
27646 | + */ | |
27647 | + | |
27648 | +#if HAVE_UNISTD_H | |
27649 | +#include <unistd.h> | |
27650 | +#endif | |
27651 | +#include <string.h> | |
27652 | +#include <stdio.h> | |
27653 | +#include <ctype.h> | |
27654 | + | |
27655 | +#include "ext2_fs.h" | |
27656 | +#include "ext2fs.h" | |
27657 | + | |
27658 | +//#include "../../version.h" | |
27659 | + | |
27660 | +static const char *lib_version = E2FSPROGS_VERSION; | |
27661 | +static const char *lib_date = E2FSPROGS_DATE; | |
27662 | + | |
27663 | +int ext2fs_parse_version_string(const char *ver_string) | |
27664 | +{ | |
27665 | + const char *cp; | |
27666 | + int version = 0; | |
27667 | + | |
27668 | + for (cp = ver_string; *cp; cp++) { | |
27669 | + if (*cp == '.') | |
27670 | + continue; | |
27671 | + if (!isdigit(*cp)) | |
27672 | + break; | |
27673 | + version = (version * 10) + (*cp - '0'); | |
27674 | + } | |
27675 | + return version; | |
27676 | +} | |
27677 | + | |
27678 | + | |
27679 | +int ext2fs_get_library_version(const char **ver_string, | |
27680 | + const char **date_string) | |
27681 | +{ | |
27682 | + if (ver_string) | |
27683 | + *ver_string = lib_version; | |
27684 | + if (date_string) | |
27685 | + *date_string = lib_date; | |
27686 | + | |
27687 | + return ext2fs_parse_version_string(lib_version); | |
27688 | +} | |
27689 | diff -Nur busybox-1.00/e2fsprogs/ext2fs/write_bb_file.c busybox/e2fsprogs/ext2fs/write_bb_file.c | |
27690 | --- busybox-1.00/e2fsprogs/ext2fs/write_bb_file.c 1970-01-01 01:00:00.000000000 +0100 | |
27691 | +++ busybox/e2fsprogs/ext2fs/write_bb_file.c 2005-06-04 08:20:16.000000000 +0200 | |
27692 | @@ -0,0 +1,34 @@ | |
27693 | +/* | |
27694 | + * write_bb_file.c --- write a list of bad blocks to a FILE * | |
27695 | + * | |
27696 | + * Copyright (C) 1994, 1995 Theodore Ts'o. | |
27697 | + * | |
27698 | + * %Begin-Header% | |
27699 | + * This file may be redistributed under the terms of the GNU Public | |
27700 | + * License. | |
27701 | + * %End-Header% | |
27702 | + */ | |
27703 | + | |
27704 | +#include <stdio.h> | |
27705 | + | |
27706 | +#include "ext2_fs.h" | |
27707 | +#include "ext2fs.h" | |
27708 | + | |
27709 | +errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, | |
27710 | + unsigned int flags EXT2FS_ATTR((unused)), | |
27711 | + FILE *f) | |
27712 | +{ | |
27713 | + badblocks_iterate bb_iter; | |
27714 | + blk_t blk; | |
27715 | + errcode_t retval; | |
27716 | + | |
27717 | + retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); | |
27718 | + if (retval) | |
27719 | + return retval; | |
27720 | + | |
27721 | + while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) { | |
27722 | + fprintf(f, "%d\n", blk); | |
27723 | + } | |
27724 | + ext2fs_badblocks_list_iterate_end(bb_iter); | |
27725 | + return 0; | |
27726 | +} | |
27727 | diff -Nur busybox-1.00/e2fsprogs/lsattr.c busybox/e2fsprogs/lsattr.c | |
27728 | --- busybox-1.00/e2fsprogs/lsattr.c 1970-01-01 01:00:00.000000000 +0100 | |
27729 | +++ busybox/e2fsprogs/lsattr.c 2005-06-04 08:20:16.000000000 +0200 | |
27730 | @@ -0,0 +1,141 @@ | |
27731 | +/* | |
27732 | + * lsattr.c - List file attributes on an ext2 file system | |
27733 | + * | |
27734 | + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> | |
27735 | + * Laboratoire MASI, Institut Blaise Pascal | |
27736 | + * Universite Pierre et Marie Curie (Paris VI) | |
27737 | + * | |
27738 | + * This file can be redistributed under the terms of the GNU General | |
27739 | + * Public License | |
27740 | + */ | |
27741 | + | |
27742 | +/* | |
27743 | + * History: | |
27744 | + * 93/10/30 - Creation | |
27745 | + * 93/11/13 - Replace stat() calls by lstat() to avoid loops | |
27746 | + * 94/02/27 - Integrated in Ted's distribution | |
27747 | + * 98/12/29 - Display version info only when -V specified (G M Sipe) | |
27748 | + */ | |
27749 | + | |
27750 | +#include <sys/types.h> | |
27751 | +#include <dirent.h> | |
27752 | +#include <errno.h> | |
27753 | +#include <fcntl.h> | |
27754 | +#include <getopt.h> | |
27755 | +#include <stdio.h> | |
27756 | +#include <unistd.h> | |
27757 | +#include <stdlib.h> | |
27758 | +#include <string.h> | |
27759 | +#include <sys/param.h> | |
27760 | +#include <sys/stat.h> | |
27761 | + | |
27762 | +#include <ext2fs/ext2_fs.h> | |
27763 | +#include "e2fsbb.h" | |
27764 | +#include "e2p/e2p.h" | |
27765 | + | |
27766 | +#ifdef __GNUC__ | |
27767 | +# define EXT2FS_ATTR(x) __attribute__(x) | |
27768 | +#else | |
27769 | +# define EXT2FS_ATTR(x) | |
27770 | +#endif | |
27771 | + | |
27772 | +#define OPT_RECUR 1 | |
27773 | +#define OPT_ALL 2 | |
27774 | +#define OPT_DIRS_OPT 4 | |
27775 | +#define OPT_PF_LONG 8 | |
27776 | +#define OPT_GENERATION 16 | |
27777 | +static int flags; | |
27778 | + | |
27779 | +#ifdef CONFIG_LFS | |
27780 | +# define LSTAT lstat64 | |
27781 | +# define STRUCT_STAT struct stat64 | |
27782 | +#else | |
27783 | +# define LSTAT lstat | |
27784 | +# define STRUCT_STAT struct stat | |
27785 | +#endif | |
27786 | + | |
27787 | +static void list_attributes(const char *name) | |
27788 | +{ | |
27789 | + unsigned long fsflags; | |
27790 | + unsigned long generation; | |
27791 | + | |
27792 | + if (fgetflags(name, &fsflags) == -1) | |
27793 | + goto read_err; | |
27794 | + if (flags & OPT_GENERATION) { | |
27795 | + if (fgetversion(name, &generation) == -1) | |
27796 | + goto read_err; | |
27797 | + printf("%5lu ", generation); | |
27798 | + } | |
27799 | + | |
27800 | + if (flags & OPT_PF_LONG) { | |
27801 | + printf("%-28s ", name); | |
27802 | + print_flags(stdout, fsflags, PFOPT_LONG); | |
27803 | + printf("\n"); | |
27804 | + } else { | |
27805 | + print_flags(stdout, fsflags, 0); | |
27806 | + printf(" %s\n", name); | |
27807 | + } | |
27808 | + | |
27809 | + return; | |
27810 | +read_err: | |
27811 | + bb_perror_msg("reading %s", name); | |
27812 | +} | |
27813 | + | |
27814 | +static int lsattr_dir_proc(const char *, struct dirent *, void *); | |
27815 | + | |
27816 | +static void lsattr_args(const char *name) | |
27817 | +{ | |
27818 | + STRUCT_STAT st; | |
27819 | + | |
27820 | + if (LSTAT(name, &st) == -1) { | |
27821 | + bb_perror_msg("stating %s", name); | |
27822 | + } else { | |
27823 | + if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT)) | |
27824 | + iterate_on_dir(name, lsattr_dir_proc, NULL); | |
27825 | + else | |
27826 | + list_attributes(name); | |
27827 | + } | |
27828 | +} | |
27829 | + | |
27830 | +static int lsattr_dir_proc(const char *dir_name, struct dirent *de, | |
27831 | + void *private EXT2FS_ATTR((unused))) | |
27832 | +{ | |
27833 | + STRUCT_STAT st; | |
27834 | + char *path; | |
27835 | + | |
27836 | + path = concat_path_file(dir_name, de->d_name); | |
27837 | + | |
27838 | + if (LSTAT(path, &st) == -1) | |
27839 | + bb_perror_msg(path); | |
27840 | + else { | |
27841 | + if (de->d_name[0] != '.' || (flags & OPT_ALL)) { | |
27842 | + list_attributes(path); | |
27843 | + if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) && | |
27844 | + (de->d_name[0] != '.' && (de->d_name[1] != '\0' || | |
27845 | + (de->d_name[1] != '.' && de->d_name[2] != '\0')))) { | |
27846 | + printf("\n%s:\n", path); | |
27847 | + iterate_on_dir(path, lsattr_dir_proc, NULL); | |
27848 | + printf("\n"); | |
27849 | + } | |
27850 | + } | |
27851 | + } | |
27852 | + | |
27853 | + free(path); | |
27854 | + | |
27855 | + return 0; | |
27856 | +} | |
27857 | + | |
27858 | +int lsattr_main(int argc, char **argv) | |
27859 | +{ | |
27860 | + int i; | |
27861 | + | |
27862 | + flags = bb_getopt_ulflags(argc, argv, "Radlv"); | |
27863 | + | |
27864 | + if (optind > argc - 1) | |
27865 | + lsattr_args("."); | |
27866 | + else | |
27867 | + for (i = optind; i < argc; i++) | |
27868 | + lsattr_args(argv[i]); | |
27869 | + | |
27870 | + return EXIT_SUCCESS; | |
27871 | +} | |
27872 | diff -Nur busybox-1.00/e2fsprogs/util.c busybox/e2fsprogs/util.c | |
27873 | --- busybox-1.00/e2fsprogs/util.c 1970-01-01 01:00:00.000000000 +0100 | |
27874 | +++ busybox/e2fsprogs/util.c 2005-06-04 08:20:16.000000000 +0200 | |
27875 | @@ -0,0 +1,207 @@ | |
27876 | +/* | |
27877 | + * util.c --- helper functions used by tune2fs and mke2fs | |
27878 | + * | |
27879 | + * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. | |
27880 | + * | |
27881 | + * %Begin-Header% | |
27882 | + * This file may be redistributed under the terms of the GNU Public | |
27883 | + * License. | |
27884 | + * %End-Header% | |
27885 | + */ | |
27886 | + | |
27887 | +#include <stdio.h> | |
27888 | +#include <string.h> | |
27889 | +#include <errno.h> | |
27890 | +#include <linux/major.h> | |
27891 | +#include <sys/stat.h> | |
27892 | + | |
27893 | +#include "e2fsbb.h" | |
27894 | +#include "e2p/e2p.h" | |
27895 | +#include "ext2fs/ext2_fs.h" | |
27896 | +#include "ext2fs/ext2fs.h" | |
27897 | +#include "blkid/blkid.h" | |
27898 | +#include "util.h" | |
27899 | + | |
27900 | +void proceed_question(void) | |
27901 | +{ | |
27902 | + fputs("Proceed anyway? (y,n) ", stdout); | |
27903 | + if (bb_ask_confirmation() == 0) | |
27904 | + exit(1); | |
27905 | +} | |
27906 | + | |
27907 | +void check_plausibility(const char *device) | |
27908 | +{ | |
27909 | + int val; | |
27910 | +#ifdef CONFIG_LFS | |
27911 | + struct stat64 s; | |
27912 | + val = stat64(device, &s); | |
27913 | +#else | |
27914 | + struct stat s; | |
27915 | + val = stat(device, &s); | |
27916 | +#endif | |
27917 | + | |
27918 | + if(val == -1) | |
27919 | + bb_perror_msg_and_die("Could not stat %s", device); | |
27920 | + if (!S_ISBLK(s.st_mode)) { | |
27921 | + printf("%s is not a block special device.\n", device); | |
27922 | + proceed_question(); | |
27923 | + return; | |
27924 | + } | |
27925 | + | |
27926 | +#ifdef HAVE_LINUX_MAJOR_H | |
27927 | +#ifndef MAJOR | |
27928 | +#define MAJOR(dev) ((dev)>>8) | |
27929 | +#define MINOR(dev) ((dev) & 0xff) | |
27930 | +#endif | |
27931 | +#ifndef SCSI_BLK_MAJOR | |
27932 | +#ifdef SCSI_DISK0_MAJOR | |
27933 | +#ifdef SCSI_DISK8_MAJOR | |
27934 | +#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ | |
27935 | + ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \ | |
27936 | + ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR)) | |
27937 | +#else | |
27938 | +#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ | |
27939 | + ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR)) | |
27940 | +#endif /* defined(SCSI_DISK8_MAJOR) */ | |
27941 | +#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR) | |
27942 | +#else | |
27943 | +#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR) | |
27944 | +#endif /* defined(SCSI_DISK0_MAJOR) */ | |
27945 | +#endif /* defined(SCSI_BLK_MAJOR) */ | |
27946 | + if (((MAJOR(s.st_rdev) == HD_MAJOR && | |
27947 | + MINOR(s.st_rdev)%64 == 0) || | |
27948 | + (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) && | |
27949 | + MINOR(s.st_rdev)%16 == 0))) { | |
27950 | + printf("%s is entire device, not just one partition!\n", device); | |
27951 | + proceed_question(); | |
27952 | + } | |
27953 | +#endif | |
27954 | +} | |
27955 | + | |
27956 | +void check_mount(const char *device, int force, const char *type) | |
27957 | +{ | |
27958 | + errcode_t retval; | |
27959 | + int mount_flags; | |
27960 | + | |
27961 | + retval = ext2fs_check_if_mounted(device, &mount_flags); | |
27962 | + if (retval) { | |
27963 | + bb_error_msg("Could not determine if %s is mounted", device); | |
27964 | + return; | |
27965 | + } | |
27966 | + if (!(mount_flags & EXT2_MF_MOUNTED)) | |
27967 | + return; | |
27968 | + | |
27969 | + bb_error_msg("%s is mounted !", device); | |
27970 | + if (force) | |
27971 | + bb_error_msg("forcing anyways and ignoring /etc/mtab status"); | |
27972 | + else | |
27973 | + bb_error_msg_and_die("will not make a %s here!", type); | |
27974 | +} | |
27975 | + | |
27976 | +void parse_journal_opts(char **journal_device, int *journal_flags, | |
27977 | + int *journal_size, const char *opts) | |
27978 | +{ | |
27979 | + char *buf, *token, *next, *p, *arg; | |
27980 | + int journal_usage = 0; | |
27981 | +#if 0 | |
27982 | + int len; | |
27983 | + len = strlen(opts); | |
27984 | + buf = xmalloc(len+1); | |
27985 | + strcpy(buf, opts); | |
27986 | +#else | |
27987 | + buf = bb_xstrdup(opts); | |
27988 | +#endif | |
27989 | + for (token = buf; token && *token; token = next) { | |
27990 | + p = strchr(token, ','); | |
27991 | + next = 0; | |
27992 | + if (p) { | |
27993 | + *p = 0; | |
27994 | + next = p+1; | |
27995 | + } | |
27996 | + arg = strchr(token, '='); | |
27997 | + if (arg) { | |
27998 | + *arg = 0; | |
27999 | + arg++; | |
28000 | + } | |
28001 | + if (strcmp(token, "device") == 0) { | |
28002 | + *journal_device = blkid_get_devname(NULL, arg, NULL); | |
28003 | + if (!journal_device) { | |
28004 | + journal_usage++; | |
28005 | + continue; | |
28006 | + } | |
28007 | + } else if (strcmp(token, "size") == 0) { | |
28008 | + if (!arg) { | |
28009 | + journal_usage++; | |
28010 | + continue; | |
28011 | + } | |
28012 | + (*journal_size) = strtoul(arg, &p, 0); | |
28013 | + if (*p) | |
28014 | + journal_usage++; | |
28015 | + } else if (strcmp(token, "v1_superblock") == 0) { | |
28016 | + (*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER; | |
28017 | + continue; | |
28018 | + } else | |
28019 | + journal_usage++; | |
28020 | + } | |
28021 | + if (journal_usage) | |
28022 | + bb_error_msg_and_die( | |
28023 | + "\nBad journal options specified.\n\n" | |
28024 | + "Journal options are separated by commas, " | |
28025 | + "and may take an argument which\n" | |
28026 | + "\tis set off by an equals ('=') sign.\n\n" | |
28027 | + "Valid journal options are:\n" | |
28028 | + "\tsize=<journal size in megabytes>\n" | |
28029 | + "\tdevice=<journal device>\n\n" | |
28030 | + "The journal size must be between " | |
28031 | + "1024 and 102400 filesystem blocks.\n\n"); | |
28032 | +} | |
28033 | + | |
28034 | +/* | |
28035 | + * Determine the number of journal blocks to use, either via | |
28036 | + * user-specified # of megabytes, or via some intelligently selected | |
28037 | + * defaults. | |
28038 | + * | |
28039 | + * Find a reasonable journal file size (in blocks) given the number of blocks | |
28040 | + * in the filesystem. For very small filesystems, it is not reasonable to | |
28041 | + * have a journal that fills more than half of the filesystem. | |
28042 | + */ | |
28043 | +int figure_journal_size(int size, ext2_filsys fs) | |
28044 | +{ | |
28045 | + blk_t j_blocks; | |
28046 | + | |
28047 | + if (fs->super->s_blocks_count < 2048) { | |
28048 | + bb_error_msg("Filesystem too small for a journal"); | |
28049 | + return 0; | |
28050 | + } | |
28051 | + | |
28052 | + if (size >= 0) { | |
28053 | + j_blocks = size * 1024 / (fs->blocksize / 1024); | |
28054 | + if (j_blocks < 1024 || j_blocks > 102400) | |
28055 | + bb_error_msg_and_die("\nThe requested journal " | |
28056 | + "size is %d blocks;\n it must be " | |
28057 | + "between 1024 and 102400 blocks; Aborting", | |
28058 | + j_blocks); | |
28059 | + if (j_blocks > fs->super->s_free_blocks_count) | |
28060 | + bb_error_msg_and_die("Journal size too big for filesystem"); | |
28061 | + return j_blocks; | |
28062 | + } | |
28063 | + | |
28064 | + if (fs->super->s_blocks_count < 32768) | |
28065 | + j_blocks = 1024; | |
28066 | + else if (fs->super->s_blocks_count < 262144) | |
28067 | + j_blocks = 4096; | |
28068 | + else | |
28069 | + j_blocks = 8192; | |
28070 | + | |
28071 | + return j_blocks; | |
28072 | +} | |
28073 | + | |
28074 | +void print_check_message(ext2_filsys fs) | |
28075 | +{ | |
28076 | + printf("This filesystem will be automatically " | |
28077 | + "checked every %d mounts or\n" | |
28078 | + "%g days, whichever comes first. " | |
28079 | + "Use tune2fs -c or -i to override.\n", | |
28080 | + fs->super->s_max_mnt_count, | |
28081 | + (double)fs->super->s_checkinterval / (3600 * 24)); | |
28082 | +} | |
28083 | diff -Nur busybox-1.00/e2fsprogs/util.h busybox/e2fsprogs/util.h | |
28084 | --- busybox-1.00/e2fsprogs/util.h 1970-01-01 01:00:00.000000000 +0100 | |
28085 | +++ busybox/e2fsprogs/util.h 2005-06-04 08:20:16.000000000 +0200 | |
28086 | @@ -0,0 +1,18 @@ | |
28087 | +/* | |
28088 | + * util.h --- header file defining prototypes for helper functions | |
28089 | + * used by tune2fs and mke2fs | |
28090 | + * | |
28091 | + * Copyright 2000 by Theodore Ts'o. | |
28092 | + * | |
28093 | + * %Begin-Header% | |
28094 | + * This file may be redistributed under the terms of the GNU Public | |
28095 | + * License. | |
28096 | + * %End-Header% | |
28097 | + */ | |
28098 | + | |
28099 | +extern void proceed_question(void); | |
28100 | +extern void check_plausibility(const char *device); | |
28101 | +extern void parse_journal_opts(char **, int *, int *, const char *opts); | |
28102 | +extern void check_mount(const char *device, int force, const char *type); | |
28103 | +extern int figure_journal_size(int size, ext2_filsys fs); | |
28104 | +extern void print_check_message(ext2_filsys fs); | |
28105 | diff -Nur busybox-1.00/e2fsprogs/uuid/clear.c busybox/e2fsprogs/uuid/clear.c | |
28106 | --- busybox-1.00/e2fsprogs/uuid/clear.c 1970-01-01 01:00:00.000000000 +0100 | |
28107 | +++ busybox/e2fsprogs/uuid/clear.c 2005-06-04 08:20:16.000000000 +0200 | |
28108 | @@ -0,0 +1,43 @@ | |
28109 | +/* | |
28110 | + * clear.c -- Clear a UUID | |
28111 | + * | |
28112 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28113 | + * | |
28114 | + * %Begin-Header% | |
28115 | + * Redistribution and use in source and binary forms, with or without | |
28116 | + * modification, are permitted provided that the following conditions | |
28117 | + * are met: | |
28118 | + * 1. Redistributions of source code must retain the above copyright | |
28119 | + * notice, and the entire permission notice in its entirety, | |
28120 | + * including the disclaimer of warranties. | |
28121 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28122 | + * notice, this list of conditions and the following disclaimer in the | |
28123 | + * documentation and/or other materials provided with the distribution. | |
28124 | + * 3. The name of the author may not be used to endorse or promote | |
28125 | + * products derived from this software without specific prior | |
28126 | + * written permission. | |
28127 | + * | |
28128 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28129 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28130 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28131 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28132 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28133 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28134 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28135 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28136 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28137 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28138 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28139 | + * DAMAGE. | |
28140 | + * %End-Header% | |
28141 | + */ | |
28142 | + | |
28143 | +#include "string.h" | |
28144 | + | |
28145 | +#include "uuidP.h" | |
28146 | + | |
28147 | +void uuid_clear(uuid_t uu) | |
28148 | +{ | |
28149 | + memset(uu, 0, 16); | |
28150 | +} | |
28151 | + | |
28152 | diff -Nur busybox-1.00/e2fsprogs/uuid/compare.c busybox/e2fsprogs/uuid/compare.c | |
28153 | --- busybox-1.00/e2fsprogs/uuid/compare.c 1970-01-01 01:00:00.000000000 +0100 | |
28154 | +++ busybox/e2fsprogs/uuid/compare.c 2005-06-04 08:20:16.000000000 +0200 | |
28155 | @@ -0,0 +1,55 @@ | |
28156 | +/* | |
28157 | + * compare.c --- compare whether or not two UUID's are the same | |
28158 | + * | |
28159 | + * Returns 0 if the two UUID's are different, and 1 if they are the same. | |
28160 | + * | |
28161 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28162 | + * | |
28163 | + * %Begin-Header% | |
28164 | + * Redistribution and use in source and binary forms, with or without | |
28165 | + * modification, are permitted provided that the following conditions | |
28166 | + * are met: | |
28167 | + * 1. Redistributions of source code must retain the above copyright | |
28168 | + * notice, and the entire permission notice in its entirety, | |
28169 | + * including the disclaimer of warranties. | |
28170 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28171 | + * notice, this list of conditions and the following disclaimer in the | |
28172 | + * documentation and/or other materials provided with the distribution. | |
28173 | + * 3. The name of the author may not be used to endorse or promote | |
28174 | + * products derived from this software without specific prior | |
28175 | + * written permission. | |
28176 | + * | |
28177 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28178 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28179 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28180 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28181 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28182 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28183 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28184 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28185 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28186 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28187 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28188 | + * DAMAGE. | |
28189 | + * %End-Header% | |
28190 | + */ | |
28191 | + | |
28192 | +#include "uuidP.h" | |
28193 | +#include <string.h> | |
28194 | + | |
28195 | +#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1); | |
28196 | + | |
28197 | +int uuid_compare(const uuid_t uu1, const uuid_t uu2) | |
28198 | +{ | |
28199 | + struct uuid uuid1, uuid2; | |
28200 | + | |
28201 | + uuid_unpack(uu1, &uuid1); | |
28202 | + uuid_unpack(uu2, &uuid2); | |
28203 | + | |
28204 | + UUCMP(uuid1.time_low, uuid2.time_low); | |
28205 | + UUCMP(uuid1.time_mid, uuid2.time_mid); | |
28206 | + UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version); | |
28207 | + UUCMP(uuid1.clock_seq, uuid2.clock_seq); | |
28208 | + return memcmp(uuid1.node, uuid2.node, 6); | |
28209 | +} | |
28210 | + | |
28211 | diff -Nur busybox-1.00/e2fsprogs/uuid/copy.c busybox/e2fsprogs/uuid/copy.c | |
28212 | --- busybox-1.00/e2fsprogs/uuid/copy.c 1970-01-01 01:00:00.000000000 +0100 | |
28213 | +++ busybox/e2fsprogs/uuid/copy.c 2005-06-04 08:20:16.000000000 +0200 | |
28214 | @@ -0,0 +1,45 @@ | |
28215 | +/* | |
28216 | + * copy.c --- copy UUIDs | |
28217 | + * | |
28218 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28219 | + * | |
28220 | + * %Begin-Header% | |
28221 | + * Redistribution and use in source and binary forms, with or without | |
28222 | + * modification, are permitted provided that the following conditions | |
28223 | + * are met: | |
28224 | + * 1. Redistributions of source code must retain the above copyright | |
28225 | + * notice, and the entire permission notice in its entirety, | |
28226 | + * including the disclaimer of warranties. | |
28227 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28228 | + * notice, this list of conditions and the following disclaimer in the | |
28229 | + * documentation and/or other materials provided with the distribution. | |
28230 | + * 3. The name of the author may not be used to endorse or promote | |
28231 | + * products derived from this software without specific prior | |
28232 | + * written permission. | |
28233 | + * | |
28234 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28235 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28236 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28237 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28238 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28239 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28240 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28241 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28242 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28243 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28244 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28245 | + * DAMAGE. | |
28246 | + * %End-Header% | |
28247 | + */ | |
28248 | + | |
28249 | +#include "uuidP.h" | |
28250 | + | |
28251 | +void uuid_copy(uuid_t dst, const uuid_t src) | |
28252 | +{ | |
28253 | + unsigned char *cp1; | |
28254 | + const unsigned char *cp2; | |
28255 | + int i; | |
28256 | + | |
28257 | + for (i=0, cp1 = dst, cp2 = src; i < 16; i++) | |
28258 | + *cp1++ = *cp2++; | |
28259 | +} | |
28260 | diff -Nur busybox-1.00/e2fsprogs/uuid/gen_uuid.c busybox/e2fsprogs/uuid/gen_uuid.c | |
28261 | --- busybox-1.00/e2fsprogs/uuid/gen_uuid.c 1970-01-01 01:00:00.000000000 +0100 | |
28262 | +++ busybox/e2fsprogs/uuid/gen_uuid.c 2005-06-04 08:20:16.000000000 +0200 | |
28263 | @@ -0,0 +1,310 @@ | |
28264 | +/* | |
28265 | + * gen_uuid.c --- generate a DCE-compatible uuid | |
28266 | + * | |
28267 | + * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. | |
28268 | + * | |
28269 | + * %Begin-Header% | |
28270 | + * Redistribution and use in source and binary forms, with or without | |
28271 | + * modification, are permitted provided that the following conditions | |
28272 | + * are met: | |
28273 | + * 1. Redistributions of source code must retain the above copyright | |
28274 | + * notice, and the entire permission notice in its entirety, | |
28275 | + * including the disclaimer of warranties. | |
28276 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28277 | + * notice, this list of conditions and the following disclaimer in the | |
28278 | + * documentation and/or other materials provided with the distribution. | |
28279 | + * 3. The name of the author may not be used to endorse or promote | |
28280 | + * products derived from this software without specific prior | |
28281 | + * written permission. | |
28282 | + * | |
28283 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28284 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28285 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28286 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28287 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28288 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28289 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28290 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28291 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28292 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28293 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28294 | + * DAMAGE. | |
28295 | + * %End-Header% | |
28296 | + */ | |
28297 | + | |
28298 | +#ifdef HAVE_UNISTD_H | |
28299 | +#include <unistd.h> | |
28300 | +#endif | |
28301 | +#ifdef HAVE_STDLIB_H | |
28302 | +#include <stdlib.h> | |
28303 | +#endif | |
28304 | +#include <string.h> | |
28305 | +#include <fcntl.h> | |
28306 | +#include <errno.h> | |
28307 | +#include <sys/types.h> | |
28308 | +#include <sys/time.h> | |
28309 | +#include <sys/stat.h> | |
28310 | +#include <sys/file.h> | |
28311 | +#ifdef HAVE_SYS_IOCTL_H | |
28312 | +#include <sys/ioctl.h> | |
28313 | +#endif | |
28314 | +#ifdef HAVE_SYS_SOCKET_H | |
28315 | +#include <sys/socket.h> | |
28316 | +#endif | |
28317 | +#ifdef HAVE_SYS_SOCKIO_H | |
28318 | +#include <sys/sockio.h> | |
28319 | +#endif | |
28320 | +#ifdef HAVE_NET_IF_H | |
28321 | +#include <net/if.h> | |
28322 | +#endif | |
28323 | +#ifdef HAVE_NETINET_IN_H | |
28324 | +#include <netinet/in.h> | |
28325 | +#endif | |
28326 | +#ifdef HAVE_NET_IF_DL_H | |
28327 | +#include <net/if_dl.h> | |
28328 | +#endif | |
28329 | + | |
28330 | +#include "uuidP.h" | |
28331 | + | |
28332 | +#ifdef HAVE_SRANDOM | |
28333 | +#define srand(x) srandom(x) | |
28334 | +#define rand() random() | |
28335 | +#endif | |
28336 | + | |
28337 | +static int get_random_fd(void) | |
28338 | +{ | |
28339 | + struct timeval tv; | |
28340 | + static int fd = -2; | |
28341 | + int i; | |
28342 | + | |
28343 | + if (fd == -2) { | |
28344 | + gettimeofday(&tv, 0); | |
28345 | + fd = open("/dev/urandom", O_RDONLY); | |
28346 | + if (fd == -1) | |
28347 | + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); | |
28348 | + srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); | |
28349 | + } | |
28350 | + /* Crank the random number generator a few times */ | |
28351 | + gettimeofday(&tv, 0); | |
28352 | + for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) | |
28353 | + rand(); | |
28354 | + return fd; | |
28355 | +} | |
28356 | + | |
28357 | + | |
28358 | +/* | |
28359 | + * Generate a series of random bytes. Use /dev/urandom if possible, | |
28360 | + * and if not, use srandom/random. | |
28361 | + */ | |
28362 | +static void get_random_bytes(void *buf, int nbytes) | |
28363 | +{ | |
28364 | + int i, n = nbytes, fd = get_random_fd(); | |
28365 | + int lose_counter = 0; | |
28366 | + unsigned char *cp = (unsigned char *) buf; | |
28367 | + | |
28368 | + if (fd >= 0) { | |
28369 | + while (n > 0) { | |
28370 | + i = read(fd, cp, n); | |
28371 | + if (i <= 0) { | |
28372 | + if (lose_counter++ > 16) | |
28373 | + break; | |
28374 | + continue; | |
28375 | + } | |
28376 | + n -= i; | |
28377 | + cp += i; | |
28378 | + lose_counter = 0; | |
28379 | + } | |
28380 | + } | |
28381 | + | |
28382 | + /* | |
28383 | + * We do this all the time, but this is the only source of | |
28384 | + * randomness if /dev/random/urandom is out to lunch. | |
28385 | + */ | |
28386 | + for (cp = buf, i = 0; i < nbytes; i++) | |
28387 | + *cp++ ^= (rand() >> 7) & 0xFF; | |
28388 | + return; | |
28389 | +} | |
28390 | + | |
28391 | +/* | |
28392 | + * Get the ethernet hardware address, if we can find it... | |
28393 | + */ | |
28394 | +static int get_node_id(unsigned char *node_id) | |
28395 | +{ | |
28396 | +#ifdef HAVE_NET_IF_H | |
28397 | + int sd; | |
28398 | + struct ifreq ifr, *ifrp; | |
28399 | + struct ifconf ifc; | |
28400 | + char buf[1024]; | |
28401 | + int n, i; | |
28402 | + unsigned char *a; | |
28403 | +#ifdef HAVE_NET_IF_DL_H | |
28404 | + struct sockaddr_dl *sdlp; | |
28405 | +#endif | |
28406 | + | |
28407 | +/* | |
28408 | + * BSD 4.4 defines the size of an ifreq to be | |
28409 | + * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len | |
28410 | + * However, under earlier systems, sa_len isn't present, so the size is | |
28411 | + * just sizeof(struct ifreq) | |
28412 | + */ | |
28413 | +#ifdef HAVE_SA_LEN | |
28414 | +#ifndef max | |
28415 | +#define max(a,b) ((a) > (b) ? (a) : (b)) | |
28416 | +#endif | |
28417 | +#define ifreq_size(i) max(sizeof(struct ifreq),\ | |
28418 | + sizeof((i).ifr_name)+(i).ifr_addr.sa_len) | |
28419 | +#else | |
28420 | +#define ifreq_size(i) sizeof(struct ifreq) | |
28421 | +#endif /* HAVE_SA_LEN*/ | |
28422 | + | |
28423 | + sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); | |
28424 | + if (sd < 0) { | |
28425 | + return -1; | |
28426 | + } | |
28427 | + memset(buf, 0, sizeof(buf)); | |
28428 | + ifc.ifc_len = sizeof(buf); | |
28429 | + ifc.ifc_buf = buf; | |
28430 | + if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { | |
28431 | + close(sd); | |
28432 | + return -1; | |
28433 | + } | |
28434 | + n = ifc.ifc_len; | |
28435 | + for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { | |
28436 | + ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); | |
28437 | + strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); | |
28438 | +#ifdef SIOCGIFHWADDR | |
28439 | + if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) | |
28440 | + continue; | |
28441 | + a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; | |
28442 | +#else | |
28443 | +#ifdef SIOCGENADDR | |
28444 | + if (ioctl(sd, SIOCGENADDR, &ifr) < 0) | |
28445 | + continue; | |
28446 | + a = (unsigned char *) ifr.ifr_enaddr; | |
28447 | +#else | |
28448 | +#ifdef HAVE_NET_IF_DL_H | |
28449 | + sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; | |
28450 | + if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) | |
28451 | + continue; | |
28452 | + a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; | |
28453 | +#else | |
28454 | + /* | |
28455 | + * XXX we don't have a way of getting the hardware | |
28456 | + * address | |
28457 | + */ | |
28458 | + close(sd); | |
28459 | + return 0; | |
28460 | +#endif /* HAVE_NET_IF_DL_H */ | |
28461 | +#endif /* SIOCGENADDR */ | |
28462 | +#endif /* SIOCGIFHWADDR */ | |
28463 | + if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) | |
28464 | + continue; | |
28465 | + if (node_id) { | |
28466 | + memcpy(node_id, a, 6); | |
28467 | + close(sd); | |
28468 | + return 1; | |
28469 | + } | |
28470 | + } | |
28471 | + close(sd); | |
28472 | +#endif | |
28473 | + return 0; | |
28474 | +} | |
28475 | + | |
28476 | +/* Assume that the gettimeofday() has microsecond granularity */ | |
28477 | +#define MAX_ADJUSTMENT 10 | |
28478 | + | |
28479 | +static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq) | |
28480 | +{ | |
28481 | + static int adjustment = 0; | |
28482 | + static struct timeval last = {0, 0}; | |
28483 | + static uint16_t clock_seq; | |
28484 | + struct timeval tv; | |
28485 | + unsigned long long clock_reg; | |
28486 | + | |
28487 | +try_again: | |
28488 | + gettimeofday(&tv, 0); | |
28489 | + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { | |
28490 | + get_random_bytes(&clock_seq, sizeof(clock_seq)); | |
28491 | + clock_seq &= 0x3FFF; | |
28492 | + last = tv; | |
28493 | + last.tv_sec--; | |
28494 | + } | |
28495 | + if ((tv.tv_sec < last.tv_sec) || | |
28496 | + ((tv.tv_sec == last.tv_sec) && | |
28497 | + (tv.tv_usec < last.tv_usec))) { | |
28498 | + clock_seq = (clock_seq+1) & 0x3FFF; | |
28499 | + adjustment = 0; | |
28500 | + last = tv; | |
28501 | + } else if ((tv.tv_sec == last.tv_sec) && | |
28502 | + (tv.tv_usec == last.tv_usec)) { | |
28503 | + if (adjustment >= MAX_ADJUSTMENT) | |
28504 | + goto try_again; | |
28505 | + adjustment++; | |
28506 | + } else { | |
28507 | + adjustment = 0; | |
28508 | + last = tv; | |
28509 | + } | |
28510 | + | |
28511 | + clock_reg = tv.tv_usec*10 + adjustment; | |
28512 | + clock_reg += ((unsigned long long) tv.tv_sec)*10000000; | |
28513 | + clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; | |
28514 | + | |
28515 | + *clock_high = clock_reg >> 32; | |
28516 | + *clock_low = clock_reg; | |
28517 | + *ret_clock_seq = clock_seq; | |
28518 | + return 0; | |
28519 | +} | |
28520 | + | |
28521 | +void uuid_generate_time(uuid_t out) | |
28522 | +{ | |
28523 | + static unsigned char node_id[6]; | |
28524 | + static int has_init = 0; | |
28525 | + struct uuid uu; | |
28526 | + uint32_t clock_mid; | |
28527 | + | |
28528 | + if (!has_init) { | |
28529 | + if (get_node_id(node_id) <= 0) { | |
28530 | + get_random_bytes(node_id, 6); | |
28531 | + /* | |
28532 | + * Set multicast bit, to prevent conflicts | |
28533 | + * with IEEE 802 addresses obtained from | |
28534 | + * network cards | |
28535 | + */ | |
28536 | + node_id[0] |= 0x01; | |
28537 | + } | |
28538 | + has_init = 1; | |
28539 | + } | |
28540 | + get_clock(&clock_mid, &uu.time_low, &uu.clock_seq); | |
28541 | + uu.clock_seq |= 0x8000; | |
28542 | + uu.time_mid = (uint16_t) clock_mid; | |
28543 | + uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; | |
28544 | + memcpy(uu.node, node_id, 6); | |
28545 | + uuid_pack(&uu, out); | |
28546 | +} | |
28547 | + | |
28548 | +void uuid_generate_random(uuid_t out) | |
28549 | +{ | |
28550 | + uuid_t buf; | |
28551 | + struct uuid uu; | |
28552 | + | |
28553 | + get_random_bytes(buf, sizeof(buf)); | |
28554 | + uuid_unpack(buf, &uu); | |
28555 | + | |
28556 | + uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; | |
28557 | + uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; | |
28558 | + uuid_pack(&uu, out); | |
28559 | +} | |
28560 | + | |
28561 | +/* | |
28562 | + * This is the generic front-end to uuid_generate_random and | |
28563 | + * uuid_generate_time. It uses uuid_generate_random only if | |
28564 | + * /dev/urandom is available, since otherwise we won't have | |
28565 | + * high-quality randomness. | |
28566 | + */ | |
28567 | +void uuid_generate(uuid_t out) | |
28568 | +{ | |
28569 | + if (get_random_fd() >= 0) | |
28570 | + uuid_generate_random(out); | |
28571 | + else | |
28572 | + uuid_generate_time(out); | |
28573 | +} | |
28574 | diff -Nur busybox-1.00/e2fsprogs/uuid/isnull.c busybox/e2fsprogs/uuid/isnull.c | |
28575 | --- busybox-1.00/e2fsprogs/uuid/isnull.c 1970-01-01 01:00:00.000000000 +0100 | |
28576 | +++ busybox/e2fsprogs/uuid/isnull.c 2005-06-04 08:20:16.000000000 +0200 | |
28577 | @@ -0,0 +1,48 @@ | |
28578 | +/* | |
28579 | + * isnull.c --- Check whether or not the UUID is null | |
28580 | + * | |
28581 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28582 | + * | |
28583 | + * %Begin-Header% | |
28584 | + * Redistribution and use in source and binary forms, with or without | |
28585 | + * modification, are permitted provided that the following conditions | |
28586 | + * are met: | |
28587 | + * 1. Redistributions of source code must retain the above copyright | |
28588 | + * notice, and the entire permission notice in its entirety, | |
28589 | + * including the disclaimer of warranties. | |
28590 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28591 | + * notice, this list of conditions and the following disclaimer in the | |
28592 | + * documentation and/or other materials provided with the distribution. | |
28593 | + * 3. The name of the author may not be used to endorse or promote | |
28594 | + * products derived from this software without specific prior | |
28595 | + * written permission. | |
28596 | + * | |
28597 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28598 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28599 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28600 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28601 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28602 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28603 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28604 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28605 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28606 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28607 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28608 | + * DAMAGE. | |
28609 | + * %End-Header% | |
28610 | + */ | |
28611 | + | |
28612 | +#include "uuidP.h" | |
28613 | + | |
28614 | +/* Returns 1 if the uuid is the NULL uuid */ | |
28615 | +int uuid_is_null(const uuid_t uu) | |
28616 | +{ | |
28617 | + const unsigned char *cp; | |
28618 | + int i; | |
28619 | + | |
28620 | + for (i=0, cp = uu; i < 16; i++) | |
28621 | + if (*cp++) | |
28622 | + return 0; | |
28623 | + return 1; | |
28624 | +} | |
28625 | + | |
28626 | diff -Nur busybox-1.00/e2fsprogs/uuid/pack.c busybox/e2fsprogs/uuid/pack.c | |
28627 | --- busybox-1.00/e2fsprogs/uuid/pack.c 1970-01-01 01:00:00.000000000 +0100 | |
28628 | +++ busybox/e2fsprogs/uuid/pack.c 2005-06-04 08:20:16.000000000 +0200 | |
28629 | @@ -0,0 +1,69 @@ | |
28630 | +/* | |
28631 | + * Internal routine for packing UUID's | |
28632 | + * | |
28633 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28634 | + * | |
28635 | + * %Begin-Header% | |
28636 | + * Redistribution and use in source and binary forms, with or without | |
28637 | + * modification, are permitted provided that the following conditions | |
28638 | + * are met: | |
28639 | + * 1. Redistributions of source code must retain the above copyright | |
28640 | + * notice, and the entire permission notice in its entirety, | |
28641 | + * including the disclaimer of warranties. | |
28642 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28643 | + * notice, this list of conditions and the following disclaimer in the | |
28644 | + * documentation and/or other materials provided with the distribution. | |
28645 | + * 3. The name of the author may not be used to endorse or promote | |
28646 | + * products derived from this software without specific prior | |
28647 | + * written permission. | |
28648 | + * | |
28649 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28650 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28651 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28652 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28653 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28654 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28655 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28656 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28657 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28658 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28659 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28660 | + * DAMAGE. | |
28661 | + * %End-Header% | |
28662 | + */ | |
28663 | + | |
28664 | +#include <string.h> | |
28665 | +#include "uuidP.h" | |
28666 | + | |
28667 | +void uuid_pack(const struct uuid *uu, uuid_t ptr) | |
28668 | +{ | |
28669 | + uint32_t tmp; | |
28670 | + unsigned char *out = ptr; | |
28671 | + | |
28672 | + tmp = uu->time_low; | |
28673 | + out[3] = (unsigned char) tmp; | |
28674 | + tmp >>= 8; | |
28675 | + out[2] = (unsigned char) tmp; | |
28676 | + tmp >>= 8; | |
28677 | + out[1] = (unsigned char) tmp; | |
28678 | + tmp >>= 8; | |
28679 | + out[0] = (unsigned char) tmp; | |
28680 | + | |
28681 | + tmp = uu->time_mid; | |
28682 | + out[5] = (unsigned char) tmp; | |
28683 | + tmp >>= 8; | |
28684 | + out[4] = (unsigned char) tmp; | |
28685 | + | |
28686 | + tmp = uu->time_hi_and_version; | |
28687 | + out[7] = (unsigned char) tmp; | |
28688 | + tmp >>= 8; | |
28689 | + out[6] = (unsigned char) tmp; | |
28690 | + | |
28691 | + tmp = uu->clock_seq; | |
28692 | + out[9] = (unsigned char) tmp; | |
28693 | + tmp >>= 8; | |
28694 | + out[8] = (unsigned char) tmp; | |
28695 | + | |
28696 | + memcpy(out+10, uu->node, 6); | |
28697 | +} | |
28698 | + | |
28699 | diff -Nur busybox-1.00/e2fsprogs/uuid/parse.c busybox/e2fsprogs/uuid/parse.c | |
28700 | --- busybox-1.00/e2fsprogs/uuid/parse.c 1970-01-01 01:00:00.000000000 +0100 | |
28701 | +++ busybox/e2fsprogs/uuid/parse.c 2005-06-04 08:20:16.000000000 +0200 | |
28702 | @@ -0,0 +1,79 @@ | |
28703 | +/* | |
28704 | + * parse.c --- UUID parsing | |
28705 | + * | |
28706 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28707 | + * | |
28708 | + * %Begin-Header% | |
28709 | + * Redistribution and use in source and binary forms, with or without | |
28710 | + * modification, are permitted provided that the following conditions | |
28711 | + * are met: | |
28712 | + * 1. Redistributions of source code must retain the above copyright | |
28713 | + * notice, and the entire permission notice in its entirety, | |
28714 | + * including the disclaimer of warranties. | |
28715 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28716 | + * notice, this list of conditions and the following disclaimer in the | |
28717 | + * documentation and/or other materials provided with the distribution. | |
28718 | + * 3. The name of the author may not be used to endorse or promote | |
28719 | + * products derived from this software without specific prior | |
28720 | + * written permission. | |
28721 | + * | |
28722 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28723 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28724 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28725 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28726 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28727 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28728 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28729 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28730 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28731 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28732 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28733 | + * DAMAGE. | |
28734 | + * %End-Header% | |
28735 | + */ | |
28736 | + | |
28737 | +#include <stdlib.h> | |
28738 | +#include <stdio.h> | |
28739 | +#include <ctype.h> | |
28740 | +#include <string.h> | |
28741 | + | |
28742 | +#include "uuidP.h" | |
28743 | + | |
28744 | +int uuid_parse(const char *in, uuid_t uu) | |
28745 | +{ | |
28746 | + struct uuid uuid; | |
28747 | + int i; | |
28748 | + const char *cp; | |
28749 | + char buf[3]; | |
28750 | + | |
28751 | + if (strlen(in) != 36) | |
28752 | + return -1; | |
28753 | + for (i=0, cp = in; i <= 36; i++,cp++) { | |
28754 | + if ((i == 8) || (i == 13) || (i == 18) || | |
28755 | + (i == 23)) { | |
28756 | + if (*cp == '-') | |
28757 | + continue; | |
28758 | + else | |
28759 | + return -1; | |
28760 | + } | |
28761 | + if (i== 36) | |
28762 | + if (*cp == 0) | |
28763 | + continue; | |
28764 | + if (!isxdigit(*cp)) | |
28765 | + return -1; | |
28766 | + } | |
28767 | + uuid.time_low = strtoul(in, NULL, 16); | |
28768 | + uuid.time_mid = strtoul(in+9, NULL, 16); | |
28769 | + uuid.time_hi_and_version = strtoul(in+14, NULL, 16); | |
28770 | + uuid.clock_seq = strtoul(in+19, NULL, 16); | |
28771 | + cp = in+24; | |
28772 | + buf[2] = 0; | |
28773 | + for (i=0; i < 6; i++) { | |
28774 | + buf[0] = *cp++; | |
28775 | + buf[1] = *cp++; | |
28776 | + uuid.node[i] = strtoul(buf, NULL, 16); | |
28777 | + } | |
28778 | + | |
28779 | + uuid_pack(&uuid, uu); | |
28780 | + return 0; | |
28781 | +} | |
28782 | diff -Nur busybox-1.00/e2fsprogs/uuid/unpack.c busybox/e2fsprogs/uuid/unpack.c | |
28783 | --- busybox-1.00/e2fsprogs/uuid/unpack.c 1970-01-01 01:00:00.000000000 +0100 | |
28784 | +++ busybox/e2fsprogs/uuid/unpack.c 2005-06-04 08:20:16.000000000 +0200 | |
28785 | @@ -0,0 +1,63 @@ | |
28786 | +/* | |
28787 | + * Internal routine for unpacking UUID | |
28788 | + * | |
28789 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28790 | + * | |
28791 | + * %Begin-Header% | |
28792 | + * Redistribution and use in source and binary forms, with or without | |
28793 | + * modification, are permitted provided that the following conditions | |
28794 | + * are met: | |
28795 | + * 1. Redistributions of source code must retain the above copyright | |
28796 | + * notice, and the entire permission notice in its entirety, | |
28797 | + * including the disclaimer of warranties. | |
28798 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28799 | + * notice, this list of conditions and the following disclaimer in the | |
28800 | + * documentation and/or other materials provided with the distribution. | |
28801 | + * 3. The name of the author may not be used to endorse or promote | |
28802 | + * products derived from this software without specific prior | |
28803 | + * written permission. | |
28804 | + * | |
28805 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28806 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28807 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28808 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28809 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28810 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28811 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28812 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28813 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28814 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28815 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28816 | + * DAMAGE. | |
28817 | + * %End-Header% | |
28818 | + */ | |
28819 | + | |
28820 | +#include <string.h> | |
28821 | +#include "uuidP.h" | |
28822 | + | |
28823 | +void uuid_unpack(const uuid_t in, struct uuid *uu) | |
28824 | +{ | |
28825 | + const uint8_t *ptr = in; | |
28826 | + uint32_t tmp; | |
28827 | + | |
28828 | + tmp = *ptr++; | |
28829 | + tmp = (tmp << 8) | *ptr++; | |
28830 | + tmp = (tmp << 8) | *ptr++; | |
28831 | + tmp = (tmp << 8) | *ptr++; | |
28832 | + uu->time_low = tmp; | |
28833 | + | |
28834 | + tmp = *ptr++; | |
28835 | + tmp = (tmp << 8) | *ptr++; | |
28836 | + uu->time_mid = tmp; | |
28837 | + | |
28838 | + tmp = *ptr++; | |
28839 | + tmp = (tmp << 8) | *ptr++; | |
28840 | + uu->time_hi_and_version = tmp; | |
28841 | + | |
28842 | + tmp = *ptr++; | |
28843 | + tmp = (tmp << 8) | *ptr++; | |
28844 | + uu->clock_seq = tmp; | |
28845 | + | |
28846 | + memcpy(uu->node, ptr, 6); | |
28847 | +} | |
28848 | + | |
28849 | diff -Nur busybox-1.00/e2fsprogs/uuid/unparse.c busybox/e2fsprogs/uuid/unparse.c | |
28850 | --- busybox-1.00/e2fsprogs/uuid/unparse.c 1970-01-01 01:00:00.000000000 +0100 | |
28851 | +++ busybox/e2fsprogs/uuid/unparse.c 2005-06-04 08:20:16.000000000 +0200 | |
28852 | @@ -0,0 +1,76 @@ | |
28853 | +/* | |
28854 | + * unparse.c -- convert a UUID to string | |
28855 | + * | |
28856 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
28857 | + * | |
28858 | + * %Begin-Header% | |
28859 | + * Redistribution and use in source and binary forms, with or without | |
28860 | + * modification, are permitted provided that the following conditions | |
28861 | + * are met: | |
28862 | + * 1. Redistributions of source code must retain the above copyright | |
28863 | + * notice, and the entire permission notice in its entirety, | |
28864 | + * including the disclaimer of warranties. | |
28865 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28866 | + * notice, this list of conditions and the following disclaimer in the | |
28867 | + * documentation and/or other materials provided with the distribution. | |
28868 | + * 3. The name of the author may not be used to endorse or promote | |
28869 | + * products derived from this software without specific prior | |
28870 | + * written permission. | |
28871 | + * | |
28872 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28873 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28874 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28875 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28876 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28877 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28878 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28879 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28880 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28881 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28882 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28883 | + * DAMAGE. | |
28884 | + * %End-Header% | |
28885 | + */ | |
28886 | + | |
28887 | +#include <stdio.h> | |
28888 | + | |
28889 | +#include "uuidP.h" | |
28890 | + | |
28891 | +static const char *fmt_lower = | |
28892 | + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; | |
28893 | + | |
28894 | +static const char *fmt_upper = | |
28895 | + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; | |
28896 | + | |
28897 | +#ifdef UUID_UNPARSE_DEFAULT_UPPER | |
28898 | +#define FMT_DEFAULT fmt_upper | |
28899 | +#else | |
28900 | +#define FMT_DEFAULT fmt_lower | |
28901 | +#endif | |
28902 | + | |
28903 | +static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt) | |
28904 | +{ | |
28905 | + struct uuid uuid; | |
28906 | + | |
28907 | + uuid_unpack(uu, &uuid); | |
28908 | + sprintf(out, fmt, | |
28909 | + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, | |
28910 | + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, | |
28911 | + uuid.node[0], uuid.node[1], uuid.node[2], | |
28912 | + uuid.node[3], uuid.node[4], uuid.node[5]); | |
28913 | +} | |
28914 | + | |
28915 | +void uuid_unparse_lower(const uuid_t uu, char *out) | |
28916 | +{ | |
28917 | + uuid_unparse_x(uu, out, fmt_lower); | |
28918 | +} | |
28919 | + | |
28920 | +void uuid_unparse_upper(const uuid_t uu, char *out) | |
28921 | +{ | |
28922 | + uuid_unparse_x(uu, out, fmt_upper); | |
28923 | +} | |
28924 | + | |
28925 | +void uuid_unparse(const uuid_t uu, char *out) | |
28926 | +{ | |
28927 | + uuid_unparse_x(uu, out, FMT_DEFAULT); | |
28928 | +} | |
28929 | diff -Nur busybox-1.00/e2fsprogs/uuid/uuid.h busybox/e2fsprogs/uuid/uuid.h | |
28930 | --- busybox-1.00/e2fsprogs/uuid/uuid.h 1970-01-01 01:00:00.000000000 +0100 | |
28931 | +++ busybox/e2fsprogs/uuid/uuid.h 2005-06-04 08:20:16.000000000 +0200 | |
28932 | @@ -0,0 +1,101 @@ | |
28933 | +/* | |
28934 | + * Public include file for the UUID library | |
28935 | + * | |
28936 | + * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. | |
28937 | + * | |
28938 | + * %Begin-Header% | |
28939 | + * Redistribution and use in source and binary forms, with or without | |
28940 | + * modification, are permitted provided that the following conditions | |
28941 | + * are met: | |
28942 | + * 1. Redistributions of source code must retain the above copyright | |
28943 | + * notice, and the entire permission notice in its entirety, | |
28944 | + * including the disclaimer of warranties. | |
28945 | + * 2. Redistributions in binary form must reproduce the above copyright | |
28946 | + * notice, this list of conditions and the following disclaimer in the | |
28947 | + * documentation and/or other materials provided with the distribution. | |
28948 | + * 3. The name of the author may not be used to endorse or promote | |
28949 | + * products derived from this software without specific prior | |
28950 | + * written permission. | |
28951 | + * | |
28952 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
28953 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
28954 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28955 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
28956 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
28957 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
28958 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
28959 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28960 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28961 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
28962 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
28963 | + * DAMAGE. | |
28964 | + * %End-Header% | |
28965 | + */ | |
28966 | + | |
28967 | +#ifndef _UUID_UUID_H | |
28968 | +#define _UUID_UUID_H | |
28969 | + | |
28970 | +#include <sys/types.h> | |
28971 | +#include <sys/time.h> | |
28972 | +#include <time.h> | |
28973 | + | |
28974 | +typedef unsigned char uuid_t[16]; | |
28975 | + | |
28976 | +/* UUID Variant definitions */ | |
28977 | +#define UUID_VARIANT_NCS 0 | |
28978 | +#define UUID_VARIANT_DCE 1 | |
28979 | +#define UUID_VARIANT_MICROSOFT 2 | |
28980 | +#define UUID_VARIANT_OTHER 3 | |
28981 | + | |
28982 | +/* UUID Type definitions */ | |
28983 | +#define UUID_TYPE_DCE_TIME 1 | |
28984 | +#define UUID_TYPE_DCE_RANDOM 4 | |
28985 | + | |
28986 | +/* Allow UUID constants to be defined */ | |
28987 | +#ifdef __GNUC__ | |
28988 | +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ | |
28989 | + static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} | |
28990 | +#else | |
28991 | +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ | |
28992 | + static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} | |
28993 | +#endif | |
28994 | + | |
28995 | +#ifdef __cplusplus | |
28996 | +extern "C" { | |
28997 | +#endif | |
28998 | + | |
28999 | +/* clear.c */ | |
29000 | +void uuid_clear(uuid_t uu); | |
29001 | + | |
29002 | +/* compare.c */ | |
29003 | +int uuid_compare(const uuid_t uu1, const uuid_t uu2); | |
29004 | + | |
29005 | +/* copy.c */ | |
29006 | +void uuid_copy(uuid_t dst, const uuid_t src); | |
29007 | + | |
29008 | +/* gen_uuid.c */ | |
29009 | +void uuid_generate(uuid_t out); | |
29010 | +void uuid_generate_random(uuid_t out); | |
29011 | +void uuid_generate_time(uuid_t out); | |
29012 | + | |
29013 | +/* isnull.c */ | |
29014 | +int uuid_is_null(const uuid_t uu); | |
29015 | + | |
29016 | +/* parse.c */ | |
29017 | +int uuid_parse(const char *in, uuid_t uu); | |
29018 | + | |
29019 | +/* unparse.c */ | |
29020 | +void uuid_unparse(const uuid_t uu, char *out); | |
29021 | +void uuid_unparse_lower(const uuid_t uu, char *out); | |
29022 | +void uuid_unparse_upper(const uuid_t uu, char *out); | |
29023 | + | |
29024 | +/* uuid_time.c */ | |
29025 | +time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); | |
29026 | +int uuid_type(const uuid_t uu); | |
29027 | +int uuid_variant(const uuid_t uu); | |
29028 | + | |
29029 | +#ifdef __cplusplus | |
29030 | +} | |
29031 | +#endif | |
29032 | + | |
29033 | +#endif /* _UUID_UUID_H */ | |
29034 | diff -Nur busybox-1.00/e2fsprogs/uuid/uuidP.h busybox/e2fsprogs/uuid/uuidP.h | |
29035 | --- busybox-1.00/e2fsprogs/uuid/uuidP.h 1970-01-01 01:00:00.000000000 +0100 | |
29036 | +++ busybox/e2fsprogs/uuid/uuidP.h 2005-06-04 08:20:16.000000000 +0200 | |
29037 | @@ -0,0 +1,63 @@ | |
29038 | +/* | |
29039 | + * uuid.h -- private header file for uuids | |
29040 | + * | |
29041 | + * Copyright (C) 1996, 1997 Theodore Ts'o. | |
29042 | + * | |
29043 | + * %Begin-Header% | |
29044 | + * Redistribution and use in source and binary forms, with or without | |
29045 | + * modification, are permitted provided that the following conditions | |
29046 | + * are met: | |
29047 | + * 1. Redistributions of source code must retain the above copyright | |
29048 | + * notice, and the entire permission notice in its entirety, | |
29049 | + * including the disclaimer of warranties. | |
29050 | + * 2. Redistributions in binary form must reproduce the above copyright | |
29051 | + * notice, this list of conditions and the following disclaimer in the | |
29052 | + * documentation and/or other materials provided with the distribution. | |
29053 | + * 3. The name of the author may not be used to endorse or promote | |
29054 | + * products derived from this software without specific prior | |
29055 | + * written permission. | |
29056 | + * | |
29057 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
29058 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
29059 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
29060 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
29061 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
29062 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
29063 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
29064 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
29065 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29066 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
29067 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
29068 | + * DAMAGE. | |
29069 | + * %End-Header% | |
29070 | + */ | |
29071 | + | |
29072 | +#ifdef HAVE_INTTYPES_H | |
29073 | +#include <inttypes.h> | |
29074 | +#else | |
29075 | +#include <uuid/uuid_types.h> | |
29076 | +#endif | |
29077 | +#include <sys/types.h> | |
29078 | + | |
29079 | +#include "uuid.h" | |
29080 | + | |
29081 | +/* | |
29082 | + * Offset between 15-Oct-1582 and 1-Jan-70 | |
29083 | + */ | |
29084 | +#define TIME_OFFSET_HIGH 0x01B21DD2 | |
29085 | +#define TIME_OFFSET_LOW 0x13814000 | |
29086 | + | |
29087 | +struct uuid { | |
29088 | + uint32_t time_low; | |
29089 | + uint16_t time_mid; | |
29090 | + uint16_t time_hi_and_version; | |
29091 | + uint16_t clock_seq; | |
29092 | + uint8_t node[6]; | |
29093 | +}; | |
29094 | + | |
29095 | + | |
29096 | +/* | |
29097 | + * prototypes | |
29098 | + */ | |
29099 | +void uuid_pack(const struct uuid *uu, uuid_t ptr); | |
29100 | +void uuid_unpack(const uuid_t in, struct uuid *uu); | |
29101 | diff -Nur busybox-1.00/e2fsprogs/uuid/uuid_time.c busybox/e2fsprogs/uuid/uuid_time.c | |
29102 | --- busybox-1.00/e2fsprogs/uuid/uuid_time.c 1970-01-01 01:00:00.000000000 +0100 | |
29103 | +++ busybox/e2fsprogs/uuid/uuid_time.c 2005-06-04 08:20:16.000000000 +0200 | |
29104 | @@ -0,0 +1,161 @@ | |
29105 | +/* | |
29106 | + * uuid_time.c --- Interpret the time field from a uuid. This program | |
29107 | + * violates the UUID abstraction barrier by reaching into the guts | |
29108 | + * of a UUID and interpreting it. | |
29109 | + * | |
29110 | + * Copyright (C) 1998, 1999 Theodore Ts'o. | |
29111 | + * | |
29112 | + * %Begin-Header% | |
29113 | + * Redistribution and use in source and binary forms, with or without | |
29114 | + * modification, are permitted provided that the following conditions | |
29115 | + * are met: | |
29116 | + * 1. Redistributions of source code must retain the above copyright | |
29117 | + * notice, and the entire permission notice in its entirety, | |
29118 | + * including the disclaimer of warranties. | |
29119 | + * 2. Redistributions in binary form must reproduce the above copyright | |
29120 | + * notice, this list of conditions and the following disclaimer in the | |
29121 | + * documentation and/or other materials provided with the distribution. | |
29122 | + * 3. The name of the author may not be used to endorse or promote | |
29123 | + * products derived from this software without specific prior | |
29124 | + * written permission. | |
29125 | + * | |
29126 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
29127 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
29128 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
29129 | + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
29130 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
29131 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
29132 | + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
29133 | + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
29134 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29135 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
29136 | + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
29137 | + * DAMAGE. | |
29138 | + * %End-Header% | |
29139 | + */ | |
29140 | + | |
29141 | +#include <stdio.h> | |
29142 | +#include <unistd.h> | |
29143 | +#include <stdlib.h> | |
29144 | +#include <sys/types.h> | |
29145 | +#include <sys/time.h> | |
29146 | +#include <time.h> | |
29147 | + | |
29148 | +#include "uuidP.h" | |
29149 | + | |
29150 | +time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) | |
29151 | +{ | |
29152 | + struct uuid uuid; | |
29153 | + uint32_t high; | |
29154 | + struct timeval tv; | |
29155 | + unsigned long long clock_reg; | |
29156 | + | |
29157 | + uuid_unpack(uu, &uuid); | |
29158 | + | |
29159 | + high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); | |
29160 | + clock_reg = uuid.time_low | ((unsigned long long) high << 32); | |
29161 | + | |
29162 | + clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; | |
29163 | + tv.tv_sec = clock_reg / 10000000; | |
29164 | + tv.tv_usec = (clock_reg % 10000000) / 10; | |
29165 | + | |
29166 | + if (ret_tv) | |
29167 | + *ret_tv = tv; | |
29168 | + | |
29169 | + return tv.tv_sec; | |
29170 | +} | |
29171 | + | |
29172 | +int uuid_type(const uuid_t uu) | |
29173 | +{ | |
29174 | + struct uuid uuid; | |
29175 | + | |
29176 | + uuid_unpack(uu, &uuid); | |
29177 | + return ((uuid.time_hi_and_version >> 12) & 0xF); | |
29178 | +} | |
29179 | + | |
29180 | +int uuid_variant(const uuid_t uu) | |
29181 | +{ | |
29182 | + struct uuid uuid; | |
29183 | + int var; | |
29184 | + | |
29185 | + uuid_unpack(uu, &uuid); | |
29186 | + var = uuid.clock_seq; | |
29187 | + | |
29188 | + if ((var & 0x8000) == 0) | |
29189 | + return UUID_VARIANT_NCS; | |
29190 | + if ((var & 0x4000) == 0) | |
29191 | + return UUID_VARIANT_DCE; | |
29192 | + if ((var & 0x2000) == 0) | |
29193 | + return UUID_VARIANT_MICROSOFT; | |
29194 | + return UUID_VARIANT_OTHER; | |
29195 | +} | |
29196 | + | |
29197 | +#ifdef DEBUG | |
29198 | +static const char *variant_string(int variant) | |
29199 | +{ | |
29200 | + switch (variant) { | |
29201 | + case UUID_VARIANT_NCS: | |
29202 | + return "NCS"; | |
29203 | + case UUID_VARIANT_DCE: | |
29204 | + return "DCE"; | |
29205 | + case UUID_VARIANT_MICROSOFT: | |
29206 | + return "Microsoft"; | |
29207 | + default: | |
29208 | + return "Other"; | |
29209 | + } | |
29210 | +} | |
29211 | + | |
29212 | + | |
29213 | +int | |
29214 | +main(int argc, char **argv) | |
29215 | +{ | |
29216 | + uuid_t buf; | |
29217 | + time_t time_reg; | |
29218 | + struct timeval tv; | |
29219 | + int type, variant; | |
29220 | + | |
29221 | + if (argc != 2) { | |
29222 | + fprintf(stderr, "Usage: %s uuid\n", argv[0]); | |
29223 | + exit(1); | |
29224 | + } | |
29225 | + if (uuid_parse(argv[1], buf)) { | |
29226 | + fprintf(stderr, "Invalid UUID: %s\n", argv[1]); | |
29227 | + exit(1); | |
29228 | + } | |
29229 | + variant = uuid_variant(buf); | |
29230 | + type = uuid_type(buf); | |
29231 | + time_reg = uuid_time(buf, &tv); | |
29232 | + | |
29233 | + printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); | |
29234 | + if (variant != UUID_VARIANT_DCE) { | |
29235 | + printf("Warning: This program only knows how to interpret " | |
29236 | + "DCE UUIDs.\n\tThe rest of the output is likely " | |
29237 | + "to be incorrect!!\n"); | |
29238 | + } | |
29239 | + printf("UUID type is %d", type); | |
29240 | + switch (type) { | |
29241 | + case 1: | |
29242 | + printf(" (time based)\n"); | |
29243 | + break; | |
29244 | + case 2: | |
29245 | + printf(" (DCE)\n"); | |
29246 | + break; | |
29247 | + case 3: | |
29248 | + printf(" (name-based)\n"); | |
29249 | + break; | |
29250 | + case 4: | |
29251 | + printf(" (random)\n"); | |
29252 | + break; | |
29253 | + default: | |
29254 | + printf("\n"); | |
29255 | + } | |
29256 | + if (type != 1) { | |
29257 | + printf("Warning: not a time-based UUID, so UUID time " | |
29258 | + "decoding will likely not work!\n"); | |
29259 | + } | |
29260 | + printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec, | |
29261 | + ctime(&time_reg)); | |
29262 | + | |
29263 | + return 0; | |
29264 | +} | |
29265 | +#endif | |
29266 | diff -Nur busybox-1.00/editors/sed.c busybox/editors/sed.c | |
29267 | --- busybox-1.00/editors/sed.c 2004-05-26 12:03:33.000000000 +0200 | |
29268 | +++ busybox/editors/sed.c 2005-06-04 08:20:21.000000000 +0200 | |
29269 | @@ -34,7 +34,10 @@ | |
29270 | resulting sed_cmd_t structures are appended to a linked list | |
29271 | (sed_cmd_head/sed_cmd_tail). | |
29272 | ||
29273 | - process_file() does actual sedding, reading data lines from an input FILE * | |
29274 | + add_input_file() adds a FILE * to the list of input files. We need to | |
29275 | + know them all ahead of time to find the last line for the $ match. | |
29276 | + | |
29277 | + process_files() does actual sedding, reading data lines from each input FILE * | |
29278 | (which could be stdin) and applying the sed command list (sed_cmd_head) to | |
29279 | each of the resulting lines. | |
29280 | ||
29281 | @@ -54,7 +57,7 @@ | |
29282 | - grouped commands: {cmd1;cmd2} | |
29283 | - transliteration (y/source-chars/dest-chars/) | |
29284 | - pattern space hold space storing / swapping (g, h, x) | |
29285 | - - labels / branching (: label, b, t) | |
29286 | + - labels / branching (: label, b, t, T) | |
29287 | ||
29288 | (Note: Specifying an address (range) to match is *optional*; commands | |
29289 | default to the whole pattern space if no specific address match was | |
29290 | @@ -62,7 +65,7 @@ | |
29291 | ||
29292 | Unsupported features: | |
29293 | ||
29294 | - - GNU extensions | |
29295 | + - most GNU extensions | |
29296 | - and more. | |
29297 | ||
29298 | Todo: | |
29299 | @@ -112,17 +115,20 @@ | |
29300 | ||
29301 | /* globals */ | |
29302 | /* options */ | |
29303 | -static int be_quiet = 0, in_place=0, regex_type=0; | |
29304 | -FILE *nonstdout; | |
29305 | -char *outname; | |
29306 | - | |
29307 | +static int be_quiet, in_place, regex_type; | |
29308 | +static FILE *nonstdout; | |
29309 | +static char *outname,*hold_space; | |
29310 | + | |
29311 | +/* List of input files */ | |
29312 | +static int input_file_count,current_input_file; | |
29313 | +static FILE **input_file_list; | |
29314 | ||
29315 | static const char bad_format_in_subst[] = | |
29316 | "bad format in substitution expression"; | |
29317 | -const char *const semicolon_whitespace = "; \n\r\t\v"; | |
29318 | +static const char *const semicolon_whitespace = "; \n\r\t\v"; | |
29319 | ||
29320 | -regmatch_t regmatch[10]; | |
29321 | -static regex_t *previous_regex_ptr = NULL; | |
29322 | +static regmatch_t regmatch[10]; | |
29323 | +static regex_t *previous_regex_ptr; | |
29324 | ||
29325 | /* linked list of sed commands */ | |
29326 | static sed_cmd_t sed_cmd_head; | |
29327 | @@ -133,7 +139,7 @@ | |
29328 | char *string; | |
29329 | struct append_list *next; | |
29330 | }; | |
29331 | -struct append_list *append_head=NULL, *append_tail=NULL; | |
29332 | +static struct append_list *append_head=NULL, *append_tail=NULL; | |
29333 | ||
29334 | #ifdef CONFIG_FEATURE_CLEAN_UP | |
29335 | static void free_and_close_stuff(void) | |
29336 | @@ -169,6 +175,11 @@ | |
29337 | free(sed_cmd); | |
29338 | sed_cmd = sed_cmd_next; | |
29339 | } | |
29340 | + | |
29341 | + if(hold_space) free(hold_space); | |
29342 | + | |
29343 | + while(current_input_file<input_file_count) | |
29344 | + fclose(input_file_list[current_input_file++]); | |
29345 | } | |
29346 | #endif | |
29347 | ||
29348 | @@ -429,7 +440,7 @@ | |
29349 | if(sed_cmd->cmd=='w') | |
29350 | sed_cmd->file=bb_xfopen(sed_cmd->string,"w"); | |
29351 | /* handle branch commands */ | |
29352 | - } else if (strchr(":bt", sed_cmd->cmd)) { | |
29353 | + } else if (strchr(":btT", sed_cmd->cmd)) { | |
29354 | int length; | |
29355 | ||
29356 | while(isspace(*cmdstr)) cmdstr++; | |
29357 | @@ -471,7 +482,7 @@ | |
29358 | ||
29359 | /* Parse address+command sets, skipping comment lines. */ | |
29360 | ||
29361 | -void add_cmd(char *cmdstr) | |
29362 | +static void add_cmd(char *cmdstr) | |
29363 | { | |
29364 | static char *add_cmd_line=NULL; | |
29365 | sed_cmd_t *sed_cmd; | |
29366 | @@ -563,7 +574,9 @@ | |
29367 | } | |
29368 | } | |
29369 | ||
29370 | -struct pipeline { | |
29371 | +/* Append to a string, reallocating memory as necessary. */ | |
29372 | + | |
29373 | +static struct pipeline { | |
29374 | char *buf; /* Space to hold string */ | |
29375 | int idx; /* Space used */ | |
29376 | int len; /* Space allocated */ | |
29377 | @@ -571,7 +584,7 @@ | |
29378 | ||
29379 | #define PIPE_GROW 64 | |
29380 | ||
29381 | -void pipe_putc(char c) | |
29382 | +static void pipe_putc(char c) | |
29383 | { | |
29384 | if(pipeline.idx==pipeline.len) { | |
29385 | pipeline.buf = xrealloc(pipeline.buf, pipeline.len + PIPE_GROW); | |
29386 | @@ -716,20 +729,29 @@ | |
29387 | append_head=append_tail=NULL; | |
29388 | } | |
29389 | ||
29390 | -/* Get next line of input, flushing append buffer and noting if we hit EOF | |
29391 | - * without a newline on the last line. | |
29392 | +static void add_input_file(FILE *file) | |
29393 | +{ | |
29394 | + input_file_list=xrealloc(input_file_list,(input_file_count+1)*sizeof(FILE *)); | |
29395 | + input_file_list[input_file_count++]=file; | |
29396 | +} | |
29397 | + | |
29398 | +/* Get next line of input from input_file_list, flushing append buffer and | |
29399 | + * noting if we ran out of files without a newline on the last line we read. | |
29400 | */ | |
29401 | -static char *get_next_line(FILE * file, int *no_newline) | |
29402 | +static char *get_next_line(int *no_newline) | |
29403 | { | |
29404 | - char *temp; | |
29405 | + char *temp=NULL; | |
29406 | int len; | |
29407 | ||
29408 | flush_append(); | |
29409 | - temp=bb_get_line_from_file(file); | |
29410 | - if(temp) { | |
29411 | - len=strlen(temp); | |
29412 | - if(len && temp[len-1]=='\n') temp[len-1]=0; | |
29413 | - else *no_newline=1; | |
29414 | + while(current_input_file<input_file_count) { | |
29415 | + temp=bb_get_line_from_file(input_file_list[current_input_file]); | |
29416 | + if(temp) { | |
29417 | + len=strlen(temp); | |
29418 | + *no_newline=!(len && temp[len-1]=='\n'); | |
29419 | + if(!*no_newline) temp[len-1]=0; | |
29420 | + break; | |
29421 | + } else fclose(input_file_list[current_input_file++]); | |
29422 | } | |
29423 | ||
29424 | return temp; | |
29425 | @@ -755,15 +777,15 @@ | |
29426 | ||
29427 | #define sed_puts(s,n) missing_newline=puts_maybe_newline(s,nonstdout,missing_newline,n) | |
29428 | ||
29429 | -static void process_file(FILE *file) | |
29430 | +static void process_files(void) | |
29431 | { | |
29432 | - char *pattern_space, *next_line, *hold_space=NULL; | |
29433 | - static int linenum = 0, missing_newline=0; | |
29434 | + char *pattern_space, *next_line; | |
29435 | + int linenum = 0, missing_newline=0; | |
29436 | int no_newline,next_no_newline=0; | |
29437 | ||
29438 | - next_line = get_next_line(file,&next_no_newline); | |
29439 | + next_line = get_next_line(&next_no_newline); | |
29440 | ||
29441 | - /* go through every line in the file */ | |
29442 | + /* go through every line in each file */ | |
29443 | for(;;) { | |
29444 | sed_cmd_t *sed_cmd; | |
29445 | int substituted=0; | |
29446 | @@ -773,7 +795,7 @@ | |
29447 | no_newline=next_no_newline; | |
29448 | ||
29449 | /* Read one line in advance so we can act on the last line, the '$' address */ | |
29450 | - next_line = get_next_line(file,&next_no_newline); | |
29451 | + next_line = get_next_line(&next_no_newline); | |
29452 | linenum++; | |
29453 | restart: | |
29454 | /* for every line, go through all the commands */ | |
29455 | @@ -908,7 +930,7 @@ | |
29456 | /* Cut and paste text (replace) */ | |
29457 | case 'c': | |
29458 | /* Only triggers on last line of a matching range. */ | |
29459 | - if (!sed_cmd->in_match) sed_puts(sed_cmd->string,1); | |
29460 | + if (!sed_cmd->in_match) sed_puts(sed_cmd->string,0); | |
29461 | goto discard_line; | |
29462 | ||
29463 | /* Read file, append contents to output */ | |
29464 | @@ -942,7 +964,7 @@ | |
29465 | free(pattern_space); | |
29466 | pattern_space = next_line; | |
29467 | no_newline=next_no_newline; | |
29468 | - next_line = get_next_line(file,&next_no_newline); | |
29469 | + next_line = get_next_line(&next_no_newline); | |
29470 | linenum++; | |
29471 | break; | |
29472 | } | |
29473 | @@ -972,17 +994,21 @@ | |
29474 | pattern_space[len]='\n'; | |
29475 | strcpy(pattern_space+len+1, next_line); | |
29476 | no_newline=next_no_newline; | |
29477 | - next_line = get_next_line(file,&next_no_newline); | |
29478 | + next_line = get_next_line(&next_no_newline); | |
29479 | linenum++; | |
29480 | } | |
29481 | break; | |
29482 | } | |
29483 | ||
29484 | - /* Test if substition worked, branch if so. */ | |
29485 | + /* Test/branch if substitution occurred */ | |
29486 | case 't': | |
29487 | - if (!substituted) break; | |
29488 | + if(!substituted) break; | |
29489 | substituted=0; | |
29490 | - /* Fall through */ | |
29491 | + /* Fall through */ | |
29492 | + /* Test/branch if substitution didn't occur */ | |
29493 | + case 'T': | |
29494 | + if (substituted) break; | |
29495 | + /* Fall through */ | |
29496 | /* Branch to label */ | |
29497 | case 'b': | |
29498 | if (!sed_cmd->string) goto discard_commands; | |
29499 | @@ -1007,10 +1033,7 @@ | |
29500 | } | |
29501 | case 'g': /* Replace pattern space with hold space */ | |
29502 | free(pattern_space); | |
29503 | - if (hold_space) { | |
29504 | - pattern_space = strdup(hold_space); | |
29505 | - no_newline=0; | |
29506 | - } | |
29507 | + pattern_space = strdup(hold_space ? hold_space : ""); | |
29508 | break; | |
29509 | case 'G': /* Append newline and hold space to pattern space */ | |
29510 | { | |
29511 | @@ -1096,9 +1119,7 @@ | |
29512 | ||
29513 | extern int sed_main(int argc, char **argv) | |
29514 | { | |
29515 | - int status = EXIT_SUCCESS; | |
29516 | - int opt; | |
29517 | - uint8_t getpat = 1; | |
29518 | + int status = EXIT_SUCCESS, opt, getpat = 1; | |
29519 | ||
29520 | #ifdef CONFIG_FEATURE_CLEAN_UP | |
29521 | /* destroy command strings on exit */ | |
29522 | @@ -1153,8 +1174,7 @@ | |
29523 | } | |
29524 | } | |
29525 | ||
29526 | - /* if we didn't get a pattern from a -e and no command file was specified, | |
29527 | - * argv[optind] should be the pattern. no pattern, no worky */ | |
29528 | + /* if we didn't get a pattern from -e or -f, use argv[optind] */ | |
29529 | if(getpat) { | |
29530 | if (argv[optind] == NULL) | |
29531 | bb_show_usage(); | |
29532 | @@ -1171,49 +1191,47 @@ | |
29533 | * files were specified or '-' was specified, take input from stdin. | |
29534 | * Otherwise, we process all the files specified. */ | |
29535 | if (argv[optind] == NULL) { | |
29536 | - if(in_place) { | |
29537 | - fprintf(stderr,"sed: Filename required for -i\n"); | |
29538 | - exit(1); | |
29539 | - } | |
29540 | - process_file(stdin); | |
29541 | + if(in_place) bb_error_msg_and_die("Filename required for -i"); | |
29542 | + add_input_file(stdin); | |
29543 | + process_files(); | |
29544 | } else { | |
29545 | int i; | |
29546 | FILE *file; | |
29547 | ||
29548 | for (i = optind; i < argc; i++) { | |
29549 | if(!strcmp(argv[i], "-") && !in_place) { | |
29550 | - process_file(stdin); | |
29551 | + add_input_file(stdin); | |
29552 | + process_files(); | |
29553 | } else { | |
29554 | file = bb_wfopen(argv[i], "r"); | |
29555 | if (file) { | |
29556 | if(in_place) { | |
29557 | struct stat statbuf; | |
29558 | + int nonstdoutfd; | |
29559 | + | |
29560 | outname=bb_xstrndup(argv[i],strlen(argv[i])+6); | |
29561 | strcat(outname,"XXXXXX"); | |
29562 | + if(-1==(nonstdoutfd=mkstemp(outname))) | |
29563 | + bb_error_msg_and_die("no temp file"); | |
29564 | + nonstdout=fdopen(nonstdoutfd,"w"); | |
29565 | /* Set permissions of output file */ | |
29566 | fstat(fileno(file),&statbuf); | |
29567 | - mkstemp(outname); | |
29568 | - nonstdout=bb_wfopen(outname,"w"); | |
29569 | - /* Set permissions of output file */ | |
29570 | - fstat(fileno(file),&statbuf); | |
29571 | - fchmod(fileno(nonstdout),statbuf.st_mode); | |
29572 | - atexit(cleanup_outname); | |
29573 | - } | |
29574 | - process_file(file); | |
29575 | - fclose(file); | |
29576 | - if(in_place) { | |
29577 | + fchmod(nonstdoutfd,statbuf.st_mode); | |
29578 | + add_input_file(file); | |
29579 | + process_files(); | |
29580 | fclose(nonstdout); | |
29581 | nonstdout=stdout; | |
29582 | unlink(argv[i]); | |
29583 | rename(outname,argv[i]); | |
29584 | free(outname); | |
29585 | outname=0; | |
29586 | - } | |
29587 | + } else add_input_file(file); | |
29588 | } else { | |
29589 | status = EXIT_FAILURE; | |
29590 | } | |
29591 | } | |
29592 | } | |
29593 | + if(input_file_count>current_input_file) process_files(); | |
29594 | } | |
29595 | ||
29596 | return status; | |
29597 | diff -Nur busybox-1.00/editors/vi.c busybox/editors/vi.c | |
29598 | --- busybox-1.00/editors/vi.c 2004-08-19 21:15:06.000000000 +0200 | |
29599 | +++ busybox/editors/vi.c 2005-06-04 08:20:21.000000000 +0200 | |
29600 | @@ -19,7 +19,7 @@ | |
29601 | */ | |
29602 | ||
29603 | static const char vi_Version[] = | |
29604 | - "$Id$"; | |
29605 | + "$Id$"; | |
29606 | ||
29607 | /* | |
29608 | * To compile for standalone use: | |
29609 | @@ -2340,7 +2340,7 @@ | |
29610 | } | |
29611 | ||
29612 | //----- IO Routines -------------------------------------------- | |
29613 | -static Byte get_one_char() | |
29614 | +static Byte get_one_char(void) | |
29615 | { | |
29616 | static Byte c; | |
29617 | ||
29618 | @@ -2600,25 +2600,25 @@ | |
29619 | } | |
29620 | ||
29621 | //----- Erase from cursor to end of line ----------------------- | |
29622 | -static void clear_to_eol() | |
29623 | +static void clear_to_eol(void) | |
29624 | { | |
29625 | write1(Ceol); // Erase from cursor to end of line | |
29626 | } | |
29627 | ||
29628 | //----- Erase from cursor to end of screen ----------------------- | |
29629 | -static void clear_to_eos() | |
29630 | +static void clear_to_eos(void) | |
29631 | { | |
29632 | write1(Ceos); // Erase from cursor to end of screen | |
29633 | } | |
29634 | ||
29635 | //----- Start standout mode ------------------------------------ | |
29636 | -static void standout_start() // send "start reverse video" sequence | |
29637 | +static void standout_start(void) // send "start reverse video" sequence | |
29638 | { | |
29639 | write1(SOs); // Start reverse video mode | |
29640 | } | |
29641 | ||
29642 | //----- End standout mode -------------------------------------- | |
29643 | -static void standout_end() // send "end reverse video" sequence | |
29644 | +static void standout_end(void) // send "end reverse video" sequence | |
29645 | { | |
29646 | write1(SOn); // End reverse video mode | |
29647 | } | |
29648 | @@ -2648,7 +2648,7 @@ | |
29649 | ||
29650 | //----- Screen[] Routines -------------------------------------- | |
29651 | //----- Erase the Screen[] memory ------------------------------ | |
29652 | -static void screen_erase() | |
29653 | +static void screen_erase(void) | |
29654 | { | |
29655 | memset(screen, ' ', screensize); // clear new screen | |
29656 | } | |
29657 | diff -Nur busybox-1.00/examples/depmod.pl busybox/examples/depmod.pl | |
29658 | --- busybox-1.00/examples/depmod.pl 2004-03-15 09:28:33.000000000 +0100 | |
29659 | +++ busybox/examples/depmod.pl 2005-06-04 08:20:22.000000000 +0200 | |
29660 | @@ -233,5 +233,5 @@ | |
29661 | ||
29662 | =cut | |
29663 | ||
29664 | -# $Id$ | |
29665 | +# $Id$ | |
29666 | ||
29667 | diff -Nur busybox-1.00/examples/zcip.script busybox/examples/zcip.script | |
29668 | --- busybox-1.00/examples/zcip.script 1970-01-01 01:00:00.000000000 +0100 | |
29669 | +++ busybox/examples/zcip.script 2005-06-04 08:20:22.000000000 +0200 | |
29670 | @@ -0,0 +1,38 @@ | |
29671 | +#!/bin/sh | |
29672 | + | |
29673 | +# only for use as a "zcip" callback script | |
29674 | +if [ "x$interface" = x ] | |
29675 | +then | |
29676 | + exit 1 | |
29677 | +fi | |
29678 | + | |
29679 | +# zcip should start on boot/resume and various media changes | |
29680 | +case "$1" in | |
29681 | +init) | |
29682 | + # for now, zcip requires the link to be already up, | |
29683 | + # and it drops links when they go down. that isn't | |
29684 | + # the most robust model... | |
29685 | + exit 0 | |
29686 | + ;; | |
29687 | +config) | |
29688 | + if [ "x$ip" = x ] | |
29689 | + then | |
29690 | + exit 1 | |
29691 | + fi | |
29692 | + # remember $ip for $interface, to use on restart | |
29693 | + if [ "x$IP" != x -a -w "$IP.$interface" ] | |
29694 | + then | |
29695 | + echo $ip > "$IP.$interface" | |
29696 | + fi | |
29697 | + exec ip address add dev $interface \ | |
29698 | + scope link local "$ip/16" broadcast + | |
29699 | + ;; | |
29700 | +deconfig) | |
29701 | + if [ x$ip = x ] | |
29702 | + then | |
29703 | + exit 1 | |
29704 | + fi | |
29705 | + exec ip address del dev $interface local $ip | |
29706 | + ;; | |
29707 | +esac | |
29708 | +exit 1 | |
29709 | diff -Nur busybox-1.00/findutils/find.c busybox/findutils/find.c | |
29710 | --- busybox-1.00/findutils/find.c 2004-03-15 09:28:37.000000000 +0100 | |
29711 | +++ busybox/findutils/find.c 2005-06-04 08:20:20.000000000 +0200 | |
29712 | @@ -59,7 +59,7 @@ | |
29713 | #endif | |
29714 | ||
29715 | #ifdef CONFIG_FEATURE_FIND_NEWER | |
29716 | -time_t newer_mtime; | |
29717 | +static time_t newer_mtime; | |
29718 | #endif | |
29719 | ||
29720 | #ifdef CONFIG_FEATURE_FIND_INUM | |
29721 | diff -Nur busybox-1.00/findutils/grep.c busybox/findutils/grep.c | |
29722 | --- busybox-1.00/findutils/grep.c 2004-10-08 10:10:57.000000000 +0200 | |
29723 | +++ busybox/findutils/grep.c 2005-06-04 08:20:20.000000000 +0200 | |
29724 | @@ -98,7 +98,7 @@ | |
29725 | } | |
29726 | last_line_printed = linenum; | |
29727 | #endif | |
29728 | - if (print_filename) | |
29729 | + if (print_filename > 0) | |
29730 | printf("%s%c", cur_file, decoration); | |
29731 | if (print_line_num) | |
29732 | printf("%i%c", linenum, decoration); | |
29733 | @@ -219,7 +219,7 @@ | |
29734 | ||
29735 | /* grep -c: print [filename:]count, even if count is zero */ | |
29736 | if (print_match_counts) { | |
29737 | - if (print_filename) | |
29738 | + if (print_filename > 0) | |
29739 | printf("%s:", cur_file); | |
29740 | printf("%d\n", nmatches); | |
29741 | } | |
29742 | diff -Nur busybox-1.00/include/applets.h busybox/include/applets.h | |
29743 | --- busybox-1.00/include/applets.h 2004-08-27 01:01:34.000000000 +0200 | |
29744 | +++ busybox/include/applets.h 2005-06-04 08:20:17.000000000 +0200 | |
29745 | @@ -16,40 +16,41 @@ | |
29746 | ||
29747 | ||
29748 | #if defined(PROTOTYPES) | |
29749 | - #define APPLET(a,b,c,d) extern int b(int argc, char **argv); | |
29750 | - #define APPLET_NOUSAGE(a,b,c,d) extern int b(int argc, char **argv); | |
29751 | - #define APPLET_ODDNAME(a,b,c,d,e) extern int b(int argc, char **argv); | |
29752 | +# define APPLET(a,b,c,d) extern int b(int argc, char **argv); | |
29753 | +# define APPLET_NOUSAGE(a,b,c,d) extern int b(int argc, char **argv); | |
29754 | +# define APPLET_ODDNAME(a,b,c,d,e) extern int b(int argc, char **argv); | |
29755 | extern const char usage_messages[]; | |
29756 | #elif defined(MAKE_USAGE) | |
29757 | - #ifdef CONFIG_FEATURE_VERBOSE_USAGE | |
29758 | - #define APPLET(a,b,c,d) a##_trivial_usage "\n\n" a##_full_usage "\0" | |
29759 | - #define APPLET_NOUSAGE(a,b,c,d) "\b\0" | |
29760 | - #define APPLET_ODDNAME(a,b,c,d,e) e##_trivial_usage "\n\n" e##_full_usage "\0" | |
29761 | - #else | |
29762 | - #define APPLET(a,b,c,d) a##_trivial_usage "\0" | |
29763 | - #define APPLET_NOUSAGE(a,b,c,d) "\b\0" | |
29764 | - #define APPLET_ODDNAME(a,b,c,d,e) e##_trivial_usage "\0" | |
29765 | - #endif | |
29766 | +# ifdef CONFIG_FEATURE_VERBOSE_USAGE | |
29767 | +# define APPLET(a,b,c,d) a##_trivial_usage "\n\n" a##_full_usage "\0" | |
29768 | +# define APPLET_NOUSAGE(a,b,c,d) "\b\0" | |
29769 | +# define APPLET_ODDNAME(a,b,c,d,e) e##_trivial_usage "\n\n" e##_full_usage "\0" | |
29770 | +# else | |
29771 | +# define APPLET(a,b,c,d) a##_trivial_usage "\0" | |
29772 | +# define APPLET_NOUSAGE(a,b,c,d) "\b\0" | |
29773 | +# define APPLET_ODDNAME(a,b,c,d,e) e##_trivial_usage "\0" | |
29774 | +# endif | |
29775 | #elif defined(MAKE_LINKS) | |
29776 | -# define APPLET(a,b,c,d) LINK c a | |
29777 | -# define APPLET_NOUSAGE(a,b,c,d) LINK c a | |
29778 | -# define APPLET_ODDNAME(a,b,c,d,e) LINK c a | |
29779 | +# define APPLET(a,b,c,d) LINK c a | |
29780 | +# define APPLET_NOUSAGE(a,b,c,d) LINK c a | |
29781 | +# define APPLET_ODDNAME(a,b,c,d,e) LINK c a | |
29782 | #else | |
29783 | const struct BB_applet applets[] = { | |
29784 | - #define APPLET(a,b,c,d) {#a,b,c,d}, | |
29785 | - #define APPLET_NOUSAGE(a,b,c,d) {a,b,c,d}, | |
29786 | - #define APPLET_ODDNAME(a,b,c,d,e) {a,b,c,d}, | |
29787 | +# define APPLET(a,b,c,d) {#a,b,c,d}, | |
29788 | +# define APPLET_NOUSAGE(a,b,c,d) {a,b,c,d}, | |
29789 | +# define APPLET_ODDNAME(a,b,c,d,e) {a,b,c,d}, | |
29790 | #endif | |
29791 | ||
29792 | #ifdef CONFIG_INSTALL_NO_USR | |
29793 | -#define _BB_DIR_USR_BIN _BB_DIR_BIN | |
29794 | -#define _BB_DIR_USR_SBIN _BB_DIR_SBIN | |
29795 | +# define _BB_DIR_USR_BIN _BB_DIR_BIN | |
29796 | +# define _BB_DIR_USR_SBIN _BB_DIR_SBIN | |
29797 | #endif | |
29798 | ||
29799 | ||
29800 | ||
29801 | #ifdef CONFIG_TEST | |
29802 | APPLET_NOUSAGE("[", test_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29803 | + APPLET_NOUSAGE("[[", test_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29804 | #endif | |
29805 | #ifdef CONFIG_ADDGROUP | |
29806 | APPLET(addgroup, addgroup_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29807 | @@ -88,6 +89,9 @@ | |
29808 | #ifdef CONFIG_CAT | |
29809 | APPLET(cat, cat_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29810 | #endif | |
29811 | +#ifdef CONFIG_CHATTR | |
29812 | + APPLET(chattr, chattr_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29813 | +#endif | |
29814 | #ifdef CONFIG_CHGRP | |
29815 | APPLET(chgrp, chgrp_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29816 | #endif | |
29817 | @@ -109,6 +113,9 @@ | |
29818 | #ifdef CONFIG_CMP | |
29819 | APPLET(cmp, cmp_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29820 | #endif | |
29821 | +#ifdef CONFIG_COMM | |
29822 | + APPLET(comm, comm_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29823 | +#endif | |
29824 | #ifdef CONFIG_CP | |
29825 | APPLET(cp, cp_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29826 | #endif | |
29827 | @@ -170,7 +177,7 @@ | |
29828 | APPLET(dumpkmap, dumpkmap_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29829 | #endif | |
29830 | #ifdef CONFIG_DUMPLEASES | |
29831 | - APPLET(dumpleases, dumpleases_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29832 | + APPLET(dumpleases, dumpleases_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29833 | #endif | |
29834 | #ifdef CONFIG_ECHO | |
29835 | APPLET(echo, echo_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29836 | @@ -178,12 +185,21 @@ | |
29837 | #if defined(CONFIG_FEATURE_GREP_EGREP_ALIAS) | |
29838 | APPLET_NOUSAGE("egrep", grep_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29839 | #endif | |
29840 | +#ifdef CONFIG_EJECT | |
29841 | + APPLET(eject, eject_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29842 | +#endif | |
29843 | #ifdef CONFIG_ENV | |
29844 | APPLET(env, env_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29845 | #endif | |
29846 | +#ifdef CONFIG_ETHER_WAKE | |
29847 | + APPLET_ODDNAME("ether-wake", etherwake_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER, ether_wake) | |
29848 | +#endif | |
29849 | #ifdef CONFIG_EXPR | |
29850 | APPLET(expr, expr_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29851 | #endif | |
29852 | +#ifdef CONFIG_FAKEIDENTD | |
29853 | + APPLET(fakeidentd, fakeidentd_main, _BB_DIR_USR_SBIN, _BB_SUID_NEVER) | |
29854 | +#endif | |
29855 | #ifdef CONFIG_FALSE | |
29856 | APPLET(false, false_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29857 | #endif | |
29858 | @@ -355,6 +371,9 @@ | |
29859 | #ifdef CONFIG_LS | |
29860 | APPLET(ls, ls_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29861 | #endif | |
29862 | +#ifdef CONFIG_LSATTR | |
29863 | + APPLET(lsattr, lsattr_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29864 | +#endif | |
29865 | #ifdef CONFIG_LSMOD | |
29866 | APPLET(lsmod, lsmod_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29867 | #endif | |
29868 | @@ -412,6 +431,9 @@ | |
29869 | #ifdef CONFIG_NETSTAT | |
29870 | APPLET(netstat, netstat_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29871 | #endif | |
29872 | +#ifdef CONFIG_NICE | |
29873 | + APPLET(nice, nice_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29874 | +#endif | |
29875 | #ifdef CONFIG_NSLOOKUP | |
29876 | APPLET(nslookup, nslookup_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29877 | #endif | |
29878 | @@ -440,11 +462,14 @@ | |
29879 | APPLET_NOUSAGE("pipe_progress", pipe_progress_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29880 | #endif | |
29881 | #ifdef CONFIG_PIVOT_ROOT | |
29882 | - APPLET(pivot_root, pivot_root_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29883 | + APPLET(pivot_root, pivot_root_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29884 | #endif | |
29885 | #ifdef CONFIG_POWEROFF | |
29886 | APPLET(poweroff, poweroff_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29887 | #endif | |
29888 | +#ifdef CONFIG_PRINTENV | |
29889 | + APPLET(printenv, printenv_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29890 | +#endif | |
29891 | #ifdef CONFIG_PRINTF | |
29892 | APPLET(printf, printf_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29893 | #endif | |
29894 | @@ -460,6 +485,9 @@ | |
29895 | #ifdef CONFIG_READLINK | |
29896 | APPLET(readlink, readlink_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29897 | #endif | |
29898 | +#ifdef CONFIG_READPROFILE | |
29899 | + APPLET(readprofile, readprofile_main, _BB_DIR_USR_SBIN, _BB_SUID_NEVER) | |
29900 | +#endif | |
29901 | #ifdef CONFIG_REALPATH | |
29902 | APPLET(realpath, realpath_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29903 | #endif | |
29904 | @@ -482,7 +510,7 @@ | |
29905 | APPLET(rmmod, rmmod_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29906 | #endif | |
29907 | #ifdef CONFIG_ROUTE | |
29908 | - APPLET(route, route_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29909 | + APPLET(route, route_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29910 | #endif | |
29911 | #ifdef CONFIG_RPM | |
29912 | APPLET(rpm, rpm_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29913 | @@ -524,7 +552,10 @@ | |
29914 | APPLET(sort, sort_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29915 | #endif | |
29916 | #ifdef CONFIG_START_STOP_DAEMON | |
29917 | - APPLET_ODDNAME("start-stop-daemon", start_stop_daemon_main, _BB_DIR_SBIN, _BB_SUID_NEVER, start_stop_daemon) | |
29918 | + APPLET_ODDNAME("start-stop-daemon", start_stop_daemon_main, _BB_DIR_SBIN, _BB_SUID_NEVER, start_stop_daemon) | |
29919 | +#endif | |
29920 | +#ifdef CONFIG_STAT | |
29921 | + APPLET(stat, stat_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29922 | #endif | |
29923 | #ifdef CONFIG_STRINGS | |
29924 | APPLET(strings, strings_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29925 | @@ -538,6 +569,9 @@ | |
29926 | #ifdef CONFIG_SULOGIN | |
29927 | APPLET(sulogin, sulogin_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29928 | #endif | |
29929 | +#ifdef CONFIG_SUM | |
29930 | + APPLET(sum, sum_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
29931 | +#endif | |
29932 | #ifdef CONFIG_SWAPONOFF | |
29933 | APPLET(swapoff, swap_on_off_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29934 | #endif | |
29935 | @@ -599,7 +633,7 @@ | |
29936 | APPLET(udhcpc, udhcpc_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29937 | #endif | |
29938 | #ifdef CONFIG_UDHCPD | |
29939 | - APPLET(udhcpd, udhcpd_main, _BB_DIR_USR_SBIN, _BB_SUID_NEVER) | |
29940 | + APPLET(udhcpd, udhcpd_main, _BB_DIR_USR_SBIN, _BB_SUID_NEVER) | |
29941 | #endif | |
29942 | #ifdef CONFIG_UMOUNT | |
29943 | APPLET(umount, umount_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29944 | @@ -670,6 +704,9 @@ | |
29945 | #ifdef CONFIG_GUNZIP | |
29946 | APPLET(zcat, gunzip_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
29947 | #endif | |
29948 | +#ifdef CONFIG_ZCIP | |
29949 | + APPLET(zcip, zcip_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | |
29950 | +#endif | |
29951 | ||
29952 | #if !defined(PROTOTYPES) && !defined(MAKE_USAGE) | |
29953 | { 0,NULL,0 } | |
29954 | diff -Nur busybox-1.00/include/busybox.h busybox/include/busybox.h | |
29955 | --- busybox-1.00/include/busybox.h 2004-03-15 09:28:38.000000000 +0100 | |
29956 | +++ busybox/include/busybox.h 2005-06-04 08:20:17.000000000 +0200 | |
29957 | @@ -32,10 +32,10 @@ | |
29958 | #include <sys/stat.h> | |
29959 | #include <sys/types.h> | |
29960 | ||
29961 | -#if __GNU_LIBRARY__ < 5 | |
29962 | -#ifndef __dietlibc__ | |
29963 | -#error "Sorry, libc5 is not supported" | |
29964 | -#endif | |
29965 | +#if __GNU_LIBRARY__ < 5 && \ | |
29966 | + !defined(__dietlibc__) && \ | |
29967 | + !defined(_NEWLIB_VERSION) | |
29968 | +#error "Sorry, this libc version is not supported :(" | |
29969 | #endif | |
29970 | ||
29971 | #ifndef BB_EXTRA_VERSION | |
29972 | diff -Nur busybox-1.00/include/inet_common.h busybox/include/inet_common.h | |
29973 | --- busybox-1.00/include/inet_common.h 2004-03-10 08:42:37.000000000 +0100 | |
29974 | +++ busybox/include/inet_common.h 2005-06-04 08:20:17.000000000 +0200 | |
29975 | @@ -4,7 +4,7 @@ | |
29976 | * | |
29977 | * Heavily modified by Manuel Novoa III Mar 12, 2001 | |
29978 | * | |
29979 | - * Version: $Id$ | |
29980 | + * Version: $Id$ | |
29981 | * | |
29982 | */ | |
29983 | ||
29984 | @@ -29,5 +29,7 @@ | |
29985 | extern int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, | |
29986 | int numeric, unsigned int netmask); | |
29987 | ||
29988 | +#ifdef CONFIG_FEATURE_IPV6 | |
29989 | extern int INET6_resolve(const char *name, struct sockaddr_in6 *sin6); | |
29990 | extern int INET6_rresolve(char *name, size_t len, struct sockaddr_in6 *sin6, int numeric); | |
29991 | +#endif | |
29992 | diff -Nur busybox-1.00/include/libbb.h busybox/include/libbb.h | |
29993 | --- busybox-1.00/include/libbb.h 2004-09-15 05:04:07.000000000 +0200 | |
29994 | +++ busybox/include/libbb.h 2005-06-04 08:20:17.000000000 +0200 | |
29995 | @@ -43,7 +43,7 @@ | |
29996 | ||
29997 | #include "config.h" | |
29998 | #ifdef CONFIG_SELINUX | |
29999 | -#include <proc_secure.h> | |
30000 | +#include <selinux/selinux.h> | |
30001 | #endif | |
30002 | ||
30003 | #include "pwd_.h" | |
30004 | @@ -137,6 +137,7 @@ | |
30005 | extern char *find_real_root_device_name(void); | |
30006 | extern char *bb_get_line_from_file(FILE *file); | |
30007 | extern char *bb_get_chomped_line_from_file(FILE *file); | |
30008 | +extern char *bb_get_chunk_from_file(FILE *file); | |
30009 | extern int bb_copyfd_size(int fd1, int fd2, const off_t size); | |
30010 | extern int bb_copyfd_eof(int fd1, int fd2); | |
30011 | extern void bb_xprint_and_close_file(FILE *file); | |
30012 | @@ -150,6 +151,7 @@ | |
30013 | extern int bb_fclose_nonstdin(FILE *f); | |
30014 | extern void bb_fflush_stdout_and_exit(int retval) __attribute__ ((noreturn)); | |
30015 | ||
30016 | +#define BB_GETOPT_ERROR 0x80000000UL | |
30017 | extern const char *bb_opt_complementaly; | |
30018 | extern const struct option *bb_applet_long_options; | |
30019 | extern unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts, ...); | |
30020 | @@ -323,6 +325,7 @@ | |
30021 | extern const char * const bb_msg_memory_exhausted; | |
30022 | extern const char * const bb_msg_invalid_date; | |
30023 | extern const char * const bb_msg_io_error; | |
30024 | +extern const char * const bb_msg_read_error; | |
30025 | extern const char * const bb_msg_write_error; | |
30026 | extern const char * const bb_msg_name_longer_than_foo; | |
30027 | extern const char * const bb_msg_unknown; | |
30028 | @@ -421,11 +424,11 @@ | |
30029 | #define FAIL_DELAY 3 | |
30030 | extern void change_identity ( const struct passwd *pw ); | |
30031 | extern const char *change_identity_e2str ( const struct passwd *pw ); | |
30032 | -extern void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args | |
30033 | +extern void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args); | |
30034 | #ifdef CONFIG_SELINUX | |
30035 | - , security_id_t sid | |
30036 | -#endif | |
30037 | -); | |
30038 | +extern void renew_current_security_context(void); | |
30039 | +extern void set_current_security_context(security_context_t sid); | |
30040 | +#endif | |
30041 | extern int run_parts(char **args, const unsigned char test_mode, char **env); | |
30042 | extern int restricted_shell ( const char *shell ); | |
30043 | extern void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw ); | |
30044 | @@ -456,11 +459,7 @@ | |
30045 | char short_cmd[16]; | |
30046 | } procps_status_t; | |
30047 | ||
30048 | -extern procps_status_t * procps_scan(int save_user_arg0 | |
30049 | -#ifdef CONFIG_SELINUX | |
30050 | - , int use_selinux, security_id_t *sid | |
30051 | -#endif | |
30052 | -); | |
30053 | +extern procps_status_t * procps_scan(int save_user_arg0); | |
30054 | extern unsigned short compare_string_array(const char *string_array[], const char *key); | |
30055 | ||
30056 | extern int my_query_module(const char *name, int which, void **buf, size_t *bufsize, size_t *ret); | |
30057 | diff -Nur busybox-1.00/include/usage.h busybox/include/usage.h | |
30058 | --- busybox-1.00/include/usage.h 2004-09-14 18:23:56.000000000 +0200 | |
30059 | +++ busybox/include/usage.h 2005-06-04 08:20:17.000000000 +0200 | |
30060 | @@ -46,7 +46,7 @@ | |
30061 | "\t-v\t\tverbosely list files processed" | |
30062 | ||
30063 | #define arping_trivial_usage \ | |
30064 | - "[-fqbDUA] [-c count] [-w timeout] [-I device] [-s sender] target\n" | |
30065 | + "[-fqbDUA] [-c count] [-w timeout] [-I device] [-s sender] target" | |
30066 | #define arping_full_usage \ | |
30067 | "Ping hosts by ARP requests/replies.\n\n" \ | |
30068 | "Options:\n" \ | |
30069 | @@ -64,7 +64,7 @@ | |
30070 | ||
30071 | #define ash_trivial_usage \ | |
30072 | "[FILE]...\n" \ | |
30073 | - "or: ash -c command [args]...\n" | |
30074 | + "or: ash -c command [args]..." | |
30075 | #define ash_full_usage \ | |
30076 | "The ash shell (command interpreter)" | |
30077 | ||
30078 | @@ -103,12 +103,12 @@ | |
30079 | "Uncompress to stdout." | |
30080 | ||
30081 | #define cal_trivial_usage \ | |
30082 | - "[-jy] [[month] year]" | |
30083 | + "[-jy] [[month] year]" | |
30084 | #define cal_full_usage \ | |
30085 | - "Display a calendar.\n" \ | |
30086 | - "\nOptions:\n" \ | |
30087 | - "\t-j\tUse julian dates.\n" \ | |
30088 | - "\t-y\tDisplay the entire year." | |
30089 | + "Display a calendar.\n" \ | |
30090 | + "\nOptions:\n" \ | |
30091 | + "\t-j\tUse julian dates\n" \ | |
30092 | + "\t-y\tDisplay the entire year" | |
30093 | ||
30094 | #define cat_trivial_usage \ | |
30095 | "[-u] [FILE]..." | |
30096 | @@ -120,12 +120,36 @@ | |
30097 | "$ cat /proc/uptime\n" \ | |
30098 | "110716.72 17.67" | |
30099 | ||
30100 | +#define chattr_trivial_usage \ | |
30101 | + "[-R] [-+=AacDdijsStTu] [-v version] files..." | |
30102 | +#define chattr_full_usage \ | |
30103 | + "change file attributes on an ext2 fs\n\n" \ | |
30104 | + "Modifiers:\n" \ | |
30105 | + "\t-\tremove attributes\n" \ | |
30106 | + "\t+\tadd attributes\n" \ | |
30107 | + "\t=\tset attributes\n" \ | |
30108 | + "Attributes:\n" \ | |
30109 | + "\tA\tdon't track atime\n" \ | |
30110 | + "\ta\tappend mode only\n" \ | |
30111 | + "\tc\tenable compress\n" \ | |
30112 | + "\tD\twrite dir contents synchronously\n" \ | |
30113 | + "\td\tdo not backup with dump\n" \ | |
30114 | + "\ti\tcannot be modified (immutable)\n" \ | |
30115 | + "\tj\twrite all data to journal first\n" \ | |
30116 | + "\ts\tzero disk storage when deleted\n" \ | |
30117 | + "\tS\twrite file contents synchronously\n" \ | |
30118 | + "\tt\tdisable tail-merging of partial blocks with other files\n" \ | |
30119 | + "\tu\tallow file to be undeleted\n" \ | |
30120 | + "Options:\n" \ | |
30121 | + "\t-R\trecursively list subdirectories\n" \ | |
30122 | + "\t-v\tset the file's version/generation number" | |
30123 | + | |
30124 | #define chgrp_trivial_usage \ | |
30125 | "[OPTION]... GROUP FILE..." | |
30126 | #define chgrp_full_usage \ | |
30127 | "Change the group membership of each FILE to GROUP.\n" \ | |
30128 | "\nOptions:\n" \ | |
30129 | - "\t-R\tChanges files and directories recursively." | |
30130 | + "\t-R\tChanges files and directories recursively" | |
30131 | #define chgrp_example_usage \ | |
30132 | "$ ls -l /tmp/foo\n" \ | |
30133 | "-r--r--r-- 1 andersen andersen 0 Apr 12 18:25 /tmp/foo\n" \ | |
30134 | @@ -139,7 +163,7 @@ | |
30135 | "Each MODE is one or more of the letters ugoa, one of the\n" \ | |
30136 | "symbols +-= and one or more of the letters rwxst.\n\n" \ | |
30137 | "Options:\n" \ | |
30138 | - "\t-R\tChanges files and directories recursively." | |
30139 | + "\t-R\tChanges files and directories recursively" | |
30140 | #define chmod_example_usage \ | |
30141 | "$ ls -l /tmp/foo\n" \ | |
30142 | "-rw-rw-r-- 1 root root 0 Apr 12 18:25 /tmp/foo\n" \ | |
30143 | @@ -155,8 +179,8 @@ | |
30144 | #define chown_full_usage \ | |
30145 | "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" \ | |
30146 | "\nOptions:\n" \ | |
30147 | - "\t-R\tChanges files and directories recursively.\n" \ | |
30148 | - "\t-h\tDo not dereference symbolic links." | |
30149 | + "\t-R\tChanges files and directories recursively\n" \ | |
30150 | + "\t-h\tDo not dereference symbolic links" | |
30151 | #define chown_example_usage \ | |
30152 | "$ ls -l /tmp/foo\n" \ | |
30153 | "-r--r--r-- 1 andersen andersen 0 Apr 12 18:25 /tmp/foo\n" \ | |
30154 | @@ -192,19 +216,29 @@ | |
30155 | #define cmp_trivial_usage \ | |
30156 | "[-l] [-s] FILE1 [FILE2]" | |
30157 | #define cmp_full_usage \ | |
30158 | - "Compare files. Compares FILE1 vs stdin if FILE2 is not specified.\n\n" \ | |
30159 | + "Compares FILE1 vs stdin if FILE2 is not specified.\n\n" \ | |
30160 | "Options:\n" \ | |
30161 | "\t-l\tWrite the byte numbers (decimal) and values (octal)\n" \ | |
30162 | - "\t\t for all differing bytes.\n" \ | |
30163 | + "\t\t for all differing bytes\n" \ | |
30164 | "\t-s\tquiet mode - do not print" | |
30165 | ||
30166 | +#define comm_trivial_usage \ | |
30167 | + "[-123] FILE1 FILE2" | |
30168 | +#define comm_full_usage \ | |
30169 | + "Compares FILE1 to FILE2, or to stdin if = is specified.\n\n" \ | |
30170 | + "Options:\n" \ | |
30171 | + "\t-1\tSuppress lines unique to FILE1\n" \ | |
30172 | + "\t-2\tSuppress lines unique to FILE2\n" \ | |
30173 | + "\t-3\tSuppress lines common to both files" | |
30174 | + | |
30175 | #define cp_trivial_usage \ | |
30176 | "[OPTION]... SOURCE DEST" | |
30177 | #define cp_full_usage \ | |
30178 | "Copies SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" \ | |
30179 | "\n" \ | |
30180 | "\t-a\tSame as -dpR\n" \ | |
30181 | - "\t-d\tPreserves links\n" \ | |
30182 | + "\t-d,-P\tPreserves links\n" \ | |
30183 | + "\t-H,-L\tDereference all symlinks (implied by default)\n" \ | |
30184 | "\t-p\tPreserves file attributes if possible\n" \ | |
30185 | "\t-f\tforce (implied; ignored) - always set\n" \ | |
30186 | "\t-i\tinteractive, prompt before overwrite\n" \ | |
30187 | @@ -259,9 +293,9 @@ | |
30188 | "\t-f N\t\tPrint only these fields\n" \ | |
30189 | "\t-n\t\tIgnored" | |
30190 | #define cut_example_usage \ | |
30191 | - "$ echo "Hello world" | cut -f 1 -d ' '\n" \ | |
30192 | + "$ echo \"Hello world\" | cut -f 1 -d ' '\n" \ | |
30193 | "Hello\n" \ | |
30194 | - "$ echo "Hello world" | cut -f 2 -d ' '\n" \ | |
30195 | + "$ echo \"Hello world\" | cut -f 2 -d ' '\n" \ | |
30196 | "world\n" | |
30197 | ||
30198 | #ifdef CONFIG_FEATURE_DATE_ISOFMT | |
30199 | @@ -277,10 +311,10 @@ | |
30200 | "\nOptions:\n" \ | |
30201 | "\t-R\t\tOutputs RFC-822 compliant date string\n" \ | |
30202 | "\t-d STRING\tDisplays time described by STRING, not `now'\n" \ | |
30203 | - USAGE_DATE_ISOFMT("\t-I[TIMESPEC]\tOutputs an ISO-8601 compliant date/time string.\n" \ | |
30204 | + USAGE_DATE_ISOFMT("\t-I[TIMESPEC]\tOutputs an ISO-8601 compliant date/time string\n" \ | |
30205 | "\t\t\tTIMESPEC=`date' (or missing) for date only,\n" \ | |
30206 | "\t\t\t`hours', `minutes', or `seconds' for date and,\n" \ | |
30207 | - "\t\t\ttime to the indicated precision.\n") \ | |
30208 | + "\t\t\ttime to the indicated precision\n") \ | |
30209 | "\t-s\t\tSets time described by STRING\n" \ | |
30210 | "\t-r FILE\t\tDisplays the last modification time of FILE\n" \ | |
30211 | "\t-u\t\tPrints or sets Coordinated Universal Time" | |
30212 | @@ -292,14 +326,14 @@ | |
30213 | "expression ..." | |
30214 | #define dc_full_usage \ | |
30215 | "This is a Tiny RPN calculator that understands the\n" \ | |
30216 | - "following operations: +, add, -, sub, *, mul, /, div, %, mod, "\ | |
30217 | + "following operations: +, add, -, sub, *, mul, /, div, %, mod, " \ | |
30218 | "**, exp, and, or, not, eor.\n" \ | |
30219 | "For example: 'dc 2 2 add' -> 4, and 'dc 8 8 \\* 2 2 + /' -> 16.\n" \ | |
30220 | "\nOptions:\n" \ | |
30221 | - "p - Prints the value on the top of the stack, without altering the stack.\n" \ | |
30222 | - "f - Prints the entire contents of the stack without altering anything.\n" \ | |
30223 | - "o - Pops the value off the top of the stack and uses it to set the output radix.\n" \ | |
30224 | - " Only 10 and 16 are supported." | |
30225 | + "p - Prints the value on the top of the stack, without altering the stack\n" \ | |
30226 | + "f - Prints the entire contents of the stack without altering anything\n" \ | |
30227 | + "o - Pops the value off the top of the stack and uses it to set the output radix\n" \ | |
30228 | + " Only 10 and 16 are supported" | |
30229 | #define dc_example_usage \ | |
30230 | "$ dc 2 2 + p\n" \ | |
30231 | "4\n" \ | |
30232 | @@ -328,7 +362,7 @@ | |
30233 | "\tconv=sync\tpad blocks with zeros\n" \ | |
30234 | "\n" \ | |
30235 | "Numbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),\n" \ | |
30236 | - "MD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)." | |
30237 | + "MD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)" | |
30238 | #define dd_example_usage \ | |
30239 | "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" \ | |
30240 | "4+0 records in\n" \ | |
30241 | @@ -350,13 +384,13 @@ | |
30242 | "Deletes user USER from the system" | |
30243 | ||
30244 | #ifdef CONFIG_DEVFSD_FG_NP | |
30245 | - #define USAGE_DEVFSD_FG_NP(a) a | |
30246 | +# define USAGE_DEVFSD_FG_NP(a) a | |
30247 | #else | |
30248 | - #define USAGE_DEVFSD_FG_NP(a) | |
30249 | +# define USAGE_DEVFSD_FG_NP(a) | |
30250 | #endif | |
30251 | ||
30252 | #define devfsd_trivial_usage \ | |
30253 | - "mntpnt [-v]"\ | |
30254 | + "mntpnt [-v]" \ | |
30255 | USAGE_DEVFSD_FG_NP("[-fg][-np]" ) | |
30256 | #define devfsd_full_usage \ | |
30257 | "Optional daemon for managing devfs permissions and old device name symlinks.\n" \ | |
30258 | @@ -370,11 +404,11 @@ | |
30259 | "\t\tDo not poll for events.") | |
30260 | ||
30261 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | |
30262 | - #define USAGE_HUMAN_READABLE(a) a | |
30263 | - #define USAGE_NOT_HUMAN_READABLE(a) | |
30264 | +# define USAGE_HUMAN_READABLE(a) a | |
30265 | +# define USAGE_NOT_HUMAN_READABLE(a) | |
30266 | #else | |
30267 | - #define USAGE_HUMAN_READABLE(a) | |
30268 | - #define USAGE_NOT_HUMAN_READABLE(a) a | |
30269 | +# define USAGE_HUMAN_READABLE(a) | |
30270 | +# define USAGE_NOT_HUMAN_READABLE(a) a | |
30271 | #endif | |
30272 | #define df_trivial_usage \ | |
30273 | "[-" USAGE_HUMAN_READABLE("hm") USAGE_NOT_HUMAN_READABLE("") "k] [FILESYSTEM ...]" | |
30274 | @@ -508,9 +542,9 @@ | |
30275 | "\t-a,\t--absolute\tInterpret lease times as expire time" | |
30276 | ||
30277 | #ifdef CONFIG_FEATURE_FANCY_ECHO | |
30278 | - #define USAGE_FANCY_ECHO(a) a | |
30279 | +# define USAGE_FANCY_ECHO(a) a | |
30280 | #else | |
30281 | - #define USAGE_FANCY_ECHO(a) | |
30282 | +# define USAGE_FANCY_ECHO(a) | |
30283 | #endif | |
30284 | ||
30285 | #define echo_trivial_usage \ | |
30286 | @@ -522,15 +556,22 @@ | |
30287 | "\t-e\tinterpret backslash-escaped characters (i.e., \\t=tab)\n" \ | |
30288 | "\t-E\tdisable interpretation of backslash-escaped characters") | |
30289 | #define echo_example_usage \ | |
30290 | - "$ echo "Erik is cool"\n" \ | |
30291 | + "$ echo \"Erik is cool\"\n" \ | |
30292 | "Erik is cool\n" \ | |
30293 | - USAGE_FANCY_ECHO("$ echo -e "Erik\\nis\\ncool"\n" \ | |
30294 | + USAGE_FANCY_ECHO("$ echo -e \"Erik\\nis\\ncool\"\n" \ | |
30295 | "Erik\n" \ | |
30296 | "is\n" \ | |
30297 | "cool\n" \ | |
30298 | - "$ echo "Erik\\nis\\ncool"\n" \ | |
30299 | + "$ echo \"Erik\\nis\\ncool\"\n" \ | |
30300 | "Erik\\nis\\ncool\n") | |
30301 | ||
30302 | +#define eject_trivial_usage \ | |
30303 | + "[-t] [DEVICE]" | |
30304 | +#define eject_full_usage \ | |
30305 | + "Eject specified DEVICE (or default /dev/cdrom).\n\n" \ | |
30306 | + "Options:\n" \ | |
30307 | + "\t-t\tclose tray" | |
30308 | + | |
30309 | #define env_trivial_usage \ | |
30310 | "[-iu] [-] [name=value]... [command]" | |
30311 | #define env_full_usage \ | |
30312 | @@ -540,6 +581,17 @@ | |
30313 | "\t-, -i\tstart with an empty environment\n" \ | |
30314 | "\t-u\tremove variable from the environment" | |
30315 | ||
30316 | +#define ether_wake_trivial_usage \ | |
30317 | + "[-b] [-i iface] [-p aa:bb:cc:dd[:ee:ff]] MAC" | |
30318 | +#define ether_wake_full_usage \ | |
30319 | + "Send a magic packet to wake up sleeping machines.\n" \ | |
30320 | + "MAC must be a station address (00:11:22:33:44:55) or\n" \ | |
30321 | + " a hostname with a known 'ethers' entry.\n\n" \ | |
30322 | + "Options:\n" \ | |
30323 | + "\t-b\t\tSend wake-up packet to the broadcast address\n" \ | |
30324 | + "\t-i iface\tUse interface ifname instead of the default \"eth0\"\n" \ | |
30325 | + "\t-p pass\tAppend the four or six byte password PW to the packet\n" | |
30326 | + | |
30327 | #define expr_trivial_usage \ | |
30328 | "EXPRESSION" | |
30329 | #define expr_full_usage \ | |
30330 | @@ -574,6 +626,13 @@ | |
30331 | "\\( and \\) or null; if \\( and \\) are not used, they return the number \n" \ | |
30332 | "of characters matched or 0." | |
30333 | ||
30334 | +#define fakeidentd_trivial_usage \ | |
30335 | + "[-b ip] [STRING]" | |
30336 | +#define fakeidentd_full_usage \ | |
30337 | + "Returns a set string to auth requests\n\n" \ | |
30338 | + "\t-b\tBind to ip address\n" \ | |
30339 | + "\tSTRING\tThe ident answer string (default is nobody)" | |
30340 | + | |
30341 | #define false_trivial_usage \ | |
30342 | "" | |
30343 | #define false_full_usage \ | |
30344 | @@ -589,7 +648,7 @@ | |
30345 | "Show and modify frame buffer settings" | |
30346 | #define fbset_example_usage \ | |
30347 | "$ fbset\n" \ | |
30348 | - "mode "1024x768-76"\n" \ | |
30349 | + "mode \"1024x768-76\"\n" \ | |
30350 | "\t# D: 78.653 MHz, H: 59.949 kHz, V: 75.694 Hz\n" \ | |
30351 | "\tgeometry 1024 768 1024 768 16\n" \ | |
30352 | "\ttimings 12714 128 32 16 4 128 4\n" \ | |
30353 | @@ -624,29 +683,29 @@ | |
30354 | "\t-v Give fdisk version" | |
30355 | ||
30356 | #ifdef CONFIG_FEATURE_FIND_TYPE | |
30357 | - #define USAGE_FIND_TYPE(a) a | |
30358 | +# define USAGE_FIND_TYPE(a) a | |
30359 | #else | |
30360 | - #define USAGE_FIND_TYPE(a) | |
30361 | +# define USAGE_FIND_TYPE(a) | |
30362 | #endif | |
30363 | #ifdef CONFIG_FEATURE_FIND_PERM | |
30364 | - #define USAGE_FIND_PERM(a) a | |
30365 | +# define USAGE_FIND_PERM(a) a | |
30366 | #else | |
30367 | - #define USAGE_FIND_PERM(a) | |
30368 | +# define USAGE_FIND_PERM(a) | |
30369 | #endif | |
30370 | #ifdef CONFIG_FEATURE_FIND_MTIME | |
30371 | - #define USAGE_FIND_MTIME(a) a | |
30372 | +# define USAGE_FIND_MTIME(a) a | |
30373 | #else | |
30374 | - #define USAGE_FIND_MTIME(a) | |
30375 | +# define USAGE_FIND_MTIME(a) | |
30376 | #endif | |
30377 | #ifdef CONFIG_FEATURE_FIND_NEWER | |
30378 | - #define USAGE_FIND_NEWER(a) a | |
30379 | +# define USAGE_FIND_NEWER(a) a | |
30380 | #else | |
30381 | - #define USAGE_FIND_NEWER(a) | |
30382 | +# define USAGE_FIND_NEWER(a) | |
30383 | #endif | |
30384 | #ifdef CONFIG_FEATURE_FIND_INUM | |
30385 | - #define USAGE_FIND_INUM(a) a | |
30386 | +# define USAGE_FIND_INUM(a) a | |
30387 | #else | |
30388 | - #define USAGE_FIND_INUM(a) | |
30389 | +# define USAGE_FIND_INUM(a) | |
30390 | #endif | |
30391 | ||
30392 | #define find_trivial_usage \ | |
30393 | @@ -655,9 +714,9 @@ | |
30394 | "Search for files in a directory hierarchy. The default PATH is\n" \ | |
30395 | "the current directory; default EXPRESSION is '-print'\n" \ | |
30396 | "\nEXPRESSION may consist of:\n" \ | |
30397 | - "\t-follow\t\tDereference symbolic links.\n" \ | |
30398 | - "\t-name PATTERN\tFile name (leading directories removed) matches PATTERN.\n" \ | |
30399 | - "\t-print\t\tPrint (default and assumed).\n" \ | |
30400 | + "\t-follow\t\tDereference symbolic links\n" \ | |
30401 | + "\t-name PATTERN\tFile name (leading directories removed) matches PATTERN\n" \ | |
30402 | + "\t-print\t\tPrint (default and assumed)\n" \ | |
30403 | USAGE_FIND_TYPE( \ | |
30404 | "\n\t-type X\t\tFiletype matches X (where X is one of: f,d,l,b,c,...)" \ | |
30405 | ) USAGE_FIND_PERM( \ | |
30406 | @@ -711,7 +770,7 @@ | |
30407 | "\t-v\tverbose\n" \ | |
30408 | "\t-s\tOutputs super-block information\n" \ | |
30409 | "\t-m\tActivates MINIX-like \"mode not cleared\" warnings\n" \ | |
30410 | - "\t-f\tForce file system check." | |
30411 | + "\t-f\tForce file system check" | |
30412 | ||
30413 | #define ftpget_trivial_usage \ | |
30414 | "[options] remote-host local-file remote-file" | |
30415 | @@ -748,42 +807,42 @@ | |
30416 | "\t-T, --test Test for getopt(1) version\n" \ | |
30417 | "\t-u, --unquoted Do not quote the output" | |
30418 | #define getopt_example_usage \ | |
30419 | - "$ cat getopt.test\n" \ | |
30420 | - "#!/bin/sh\n" \ | |
30421 | - "GETOPT=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \\\n" \ | |
30422 | - " -n 'example.busybox' -- "$@"`\n" \ | |
30423 | - "if [ $? != 0 ] ; then exit 1 ; fi\n" \ | |
30424 | - "eval set -- "$GETOPT"\n" \ | |
30425 | - "while true ; do\n" \ | |
30426 | - " case $1 in\n" \ | |
30427 | - " -a|--a-long) echo \"Option a\" ; shift ;;\n" \ | |
30428 | - " -b|--b-long) echo \"Option b, argument `$2'\" ; shift 2 ;;\n" \ | |
30429 | - " -c|--c-long)\n" \ | |
30430 | - " case "$2" in\n" \ | |
30431 | - " \"\") echo \"Option c, no argument\"; shift 2 ;;\n" \ | |
30432 | - " *) echo \"Option c, argument `$2'\" ; shift 2 ;;\n" \ | |
30433 | - " esac ;;\n" \ | |
30434 | - " --) shift ; break ;;\n" \ | |
30435 | - " *) echo \"Internal error!\" ; exit 1 ;;\n" \ | |
30436 | - " esac\n" \ | |
30437 | - "done\n" | |
30438 | + "$ cat getopt.test\n" \ | |
30439 | + "#!/bin/sh\n" \ | |
30440 | + "GETOPT=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \\\n" \ | |
30441 | + " -n 'example.busybox' -- \"$@\"`\n" \ | |
30442 | + "if [ $? != 0 ] ; then exit 1 ; fi\n" \ | |
30443 | + "eval set -- \"$GETOPT\"\n" \ | |
30444 | + "while true ; do\n" \ | |
30445 | + " case $1 in\n" \ | |
30446 | + " -a|--a-long) echo \"Option a\" ; shift ;;\n" \ | |
30447 | + " -b|--b-long) echo \"Option b, argument `$2'\" ; shift 2 ;;\n" \ | |
30448 | + " -c|--c-long)\n" \ | |
30449 | + " case \"$2\" in\n" \ | |
30450 | + " \"\") echo \"Option c, no argument\"; shift 2 ;;\n" \ | |
30451 | + " *) echo \"Option c, argument `$2'\" ; shift 2 ;;\n" \ | |
30452 | + " esac ;;\n" \ | |
30453 | + " --) shift ; break ;;\n" \ | |
30454 | + " *) echo \"Internal error!\" ; exit 1 ;;\n" \ | |
30455 | + " esac\n" \ | |
30456 | + "done\n" | |
30457 | ||
30458 | #define getty_trivial_usage \ | |
30459 | "[OPTIONS]... baud_rate,... line [termtype]" | |
30460 | #define getty_full_usage \ | |
30461 | "Opens a tty, prompts for a login name, then invokes /bin/login\n\n" \ | |
30462 | "Options:\n" \ | |
30463 | - "\t-h\t\tEnable hardware (RTS/CTS) flow control.\n" \ | |
30464 | - "\t-i\t\tDo not display /etc/issue before running login.\n" \ | |
30465 | - "\t-L\t\tLocal line, so do not do carrier detect.\n" \ | |
30466 | - "\t-m\t\tGet baud rate from modem's CONNECT status message.\n" \ | |
30467 | - "\t-w\t\tWait for a CR or LF before sending /etc/issue.\n" \ | |
30468 | - "\t-n\t\tDo not prompt the user for a login name.\n" \ | |
30469 | - "\t-f issue_file\tDisplay issue_file instead of /etc/issue.\n" \ | |
30470 | - "\t-l login_app\tInvoke login_app instead of /bin/login.\n" \ | |
30471 | - "\t-t timeout\tTerminate after timeout if no username is read.\n" \ | |
30472 | - "\t-I initstring\tSets the init string to send before anything else.\n" \ | |
30473 | - "\t-H login_host\tLog login_host into the utmp file as the hostname." | |
30474 | + "\t-h\t\tEnable hardware (RTS/CTS) flow control\n" \ | |
30475 | + "\t-i\t\tDo not display /etc/issue before running login\n" \ | |
30476 | + "\t-L\t\tLocal line, so do not do carrier detect\n" \ | |
30477 | + "\t-m\t\tGet baud rate from modem's CONNECT status message\n" \ | |
30478 | + "\t-w\t\tWait for a CR or LF before sending /etc/issue\n" \ | |
30479 | + "\t-n\t\tDo not prompt the user for a login name\n" \ | |
30480 | + "\t-f issue_file\tDisplay issue_file instead of /etc/issue\n" \ | |
30481 | + "\t-l login_app\tInvoke login_app instead of /bin/login\n" \ | |
30482 | + "\t-t timeout\tTerminate after timeout if no username is read\n" \ | |
30483 | + "\t-I initstring\tSets the init string to send before anything else\n" \ | |
30484 | + "\t-H login_host\tLog login_host into the utmp file as the hostname" | |
30485 | ||
30486 | ||
30487 | #define grep_trivial_usage \ | |
30488 | @@ -841,7 +900,7 @@ | |
30489 | #define halt_full_usage \ | |
30490 | "Halt the system.\n" \ | |
30491 | "Options:\n" \ | |
30492 | - "\t-d\t\tdelay interval for halting." | |
30493 | + "\t-d\t\tdelay interval for halting" | |
30494 | ||
30495 | #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY | |
30496 | #define USAGE_HDPARM_IDENT(a) a | |
30497 | @@ -951,7 +1010,7 @@ | |
30498 | "[-[bcdefnosvx]] [OPTION] FILE" | |
30499 | #define hexdump_full_usage \ | |
30500 | "The hexdump utility is a filter which displays the specified files,\n" \ | |
30501 | - "or the standard input, if no files are specified, in a user specified\n"\ | |
30502 | + "or the standard input, if no files are specified, in a user specified\n" \ | |
30503 | "format\n" \ | |
30504 | "\t-b\t\tOne-byte octal display\n" \ | |
30505 | "\t-c\t\tOne-byte character display\n" \ | |
30506 | @@ -985,26 +1044,26 @@ | |
30507 | "sage\n" | |
30508 | ||
30509 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | |
30510 | - #define USAGE_HTTPD_BASIC_AUTH(a) a | |
30511 | - #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 | |
30512 | - #define USAGE_HTTPD_AUTH_MD5(a) a | |
30513 | - #else | |
30514 | - #define USAGE_HTTPD_AUTH_MD5(a) | |
30515 | - #endif | |
30516 | +# define USAGE_HTTPD_BASIC_AUTH(a) a | |
30517 | +# ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 | |
30518 | +# define USAGE_HTTPD_AUTH_MD5(a) a | |
30519 | +# else | |
30520 | +# define USAGE_HTTPD_AUTH_MD5(a) | |
30521 | +# endif | |
30522 | #else | |
30523 | - #define USAGE_HTTPD_BASIC_AUTH(a) | |
30524 | - #define USAGE_HTTPD_AUTH_MD5(a) | |
30525 | +# define USAGE_HTTPD_BASIC_AUTH(a) | |
30526 | +# define USAGE_HTTPD_AUTH_MD5(a) | |
30527 | #endif | |
30528 | #ifdef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY | |
30529 | - #define USAGE_HTTPD_STANDALONE(a) | |
30530 | - #define USAGE_HTTPD_SETUID(a) | |
30531 | +# define USAGE_HTTPD_STANDALONE(a) | |
30532 | +# define USAGE_HTTPD_SETUID(a) | |
30533 | #else | |
30534 | - #define USAGE_HTTPD_STANDALONE(a) a | |
30535 | - #ifdef CONFIG_FEATURE_HTTPD_SETUID | |
30536 | - #define USAGE_HTTPD_SETUID(a) a | |
30537 | - #else | |
30538 | - #define USAGE_HTTPD_SETUID(a) | |
30539 | - #endif | |
30540 | +# define USAGE_HTTPD_STANDALONE(a) a | |
30541 | +# ifdef CONFIG_FEATURE_HTTPD_SETUID | |
30542 | +# define USAGE_HTTPD_SETUID(a) a | |
30543 | +# else | |
30544 | +# define USAGE_HTTPD_SETUID(a) | |
30545 | +# endif | |
30546 | #endif | |
30547 | #define httpd_trivial_usage \ | |
30548 | "[-c <conf file>]" \ | |
30549 | @@ -1015,16 +1074,16 @@ | |
30550 | " [-h home]" \ | |
30551 | " [-d/-e <string>]" | |
30552 | #define httpd_full_usage \ | |
30553 | - "Listens for incoming http server requests.\n\n"\ | |
30554 | - "Options:\n" \ | |
30555 | - "\t-c FILE\t\tSpecifies configuration file. (default httpd.conf)\n" \ | |
30556 | - USAGE_HTTPD_STANDALONE("\t-p PORT\tServer port (default 80)\n") \ | |
30557 | - USAGE_HTTPD_SETUID("\t-u USER\tSet uid to USER after listening privileges port\n") \ | |
30558 | - USAGE_HTTPD_BASIC_AUTH("\t-r REALM\tAuthentication Realm for Basic Authentication\n") \ | |
30559 | - USAGE_HTTPD_AUTH_MD5("\t-m PASS\t\tCrypt PASS with md5 algorithm\n") \ | |
30560 | - "\t-h HOME \tSpecifies http HOME directory (default ./)\n" \ | |
30561 | - "\t-e STRING\tHtml encode STRING\n" \ | |
30562 | - "\t-d STRING\tURL decode STRING" | |
30563 | + "Listens for incoming http server requests.\n\n" \ | |
30564 | + "Options:\n" \ | |
30565 | + "\t-c FILE\t\tSpecifies configuration file. (default httpd.conf)\n" \ | |
30566 | + USAGE_HTTPD_STANDALONE("\t-p PORT\tServer port (default 80)\n") \ | |
30567 | + USAGE_HTTPD_SETUID("\t-u USER\tSet uid to USER after listening privileges port\n") \ | |
30568 | + USAGE_HTTPD_BASIC_AUTH("\t-r REALM\tAuthentication Realm for Basic Authentication\n") \ | |
30569 | + USAGE_HTTPD_AUTH_MD5("\t-m PASS\t\tCrypt PASS with md5 algorithm\n") \ | |
30570 | + "\t-h HOME \tSpecifies http HOME directory (default ./)\n" \ | |
30571 | + "\t-e STRING\tHtml encode STRING\n" \ | |
30572 | + "\t-d STRING\tURL decode STRING" | |
30573 | ||
30574 | #define hwclock_trivial_usage \ | |
30575 | "[-r|--show] [-s|--hctosys] [-w|--systohc] [-l|--localtime] [-u|--utc]" | |
30576 | @@ -1038,9 +1097,9 @@ | |
30577 | "\t-l\tthe hardware clock is kept in local time" | |
30578 | ||
30579 | #ifdef CONFIG_SELINUX | |
30580 | - #define USAGE_SELINUX(a) a | |
30581 | +# define USAGE_SELINUX(a) a | |
30582 | #else | |
30583 | - #define USAGE_SELINUX(a) | |
30584 | +# define USAGE_SELINUX(a) | |
30585 | #endif | |
30586 | ||
30587 | #define id_trivial_usage \ | |
30588 | @@ -1058,29 +1117,29 @@ | |
30589 | "uid=1000(andersen) gid=1000(andersen)\n" | |
30590 | ||
30591 | #ifdef CONFIG_FEATURE_IFCONFIG_SLIP | |
30592 | - #define USAGE_SIOCSKEEPALIVE(a) a | |
30593 | +# define USAGE_SIOCSKEEPALIVE(a) a | |
30594 | #else | |
30595 | - #define USAGE_SIOCSKEEPALIVE(a) | |
30596 | +# define USAGE_SIOCSKEEPALIVE(a) | |
30597 | #endif | |
30598 | #ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ | |
30599 | - #define USAGE_IFCONFIG_MII(a) a | |
30600 | +# define USAGE_IFCONFIG_MII(a) a | |
30601 | #else | |
30602 | - #define USAGE_IFCONFIG_MII(a) | |
30603 | +# define USAGE_IFCONFIG_MII(a) | |
30604 | #endif | |
30605 | #ifdef CONFIG_FEATURE_IFCONFIG_HW | |
30606 | - #define USAGE_IFCONFIG_HW(a) a | |
30607 | +# define USAGE_IFCONFIG_HW(a) a | |
30608 | #else | |
30609 | - #define USAGE_IFCONFIG_HW(a) | |
30610 | +# define USAGE_IFCONFIG_HW(a) | |
30611 | #endif | |
30612 | #ifdef CONFIG_FEATURE_IFCONFIG_STATUS | |
30613 | - #define USAGE_IFCONFIG_OPT_A(a) a | |
30614 | +# define USAGE_IFCONFIG_OPT_A(a) a | |
30615 | #else | |
30616 | - #define USAGE_IFCONFIG_OPT_A(a) | |
30617 | +# define USAGE_IFCONFIG_OPT_A(a) | |
30618 | #endif | |
30619 | #ifdef CONFIG_FEATURE_IPV6 | |
30620 | - #define USAGE_IPV6(a) a | |
30621 | +# define USAGE_IPV6(a) a | |
30622 | #else | |
30623 | - #define USAGE_IPV6(a) | |
30624 | +# define USAGE_IPV6(a) | |
30625 | #endif | |
30626 | ||
30627 | #define ifconfig_trivial_usage \ | |
30628 | @@ -1094,7 +1153,7 @@ | |
30629 | "\t[netmask <address>] [dstaddr <address>]\n" \ | |
30630 | USAGE_SIOCSKEEPALIVE("\t[outfill <NN>] [keepalive <NN>]\n") \ | |
30631 | "\t" USAGE_IFCONFIG_HW("[hw ether <address>] ") \ | |
30632 | - "[metric <NN>] [mtu <NN>]\n" \ | |
30633 | + "[metric <NN>] [mtu <NN>]\n" \ | |
30634 | "\t[[-]trailers] [[-]arp] [[-]allmulti]\n" \ | |
30635 | "\t[multicast] [[-]promisc] [txqueuelen <NN>] [[-]dynamic]\n" \ | |
30636 | USAGE_IFCONFIG_MII("\t[mem_start <NN>] [io_addr <NN>] [irq <NN>]\n") \ | |
30637 | @@ -1134,7 +1193,7 @@ | |
30638 | "Listens for network connections and launches programs\n\n" \ | |
30639 | "Option:\n" \ | |
30640 | "\t-q\tSets the size of the socket listen queue to\n" \ | |
30641 | - "\t\tthe specified value. Default is 128." | |
30642 | + "\t\tthe specified value. Default is 128" | |
30643 | ||
30644 | #define init_trivial_usage \ | |
30645 | "" | |
30646 | @@ -1172,7 +1231,7 @@ | |
30647 | " WARNING: This field has a non-traditional meaning for BusyBox init!\n" \ | |
30648 | " The id field is used by BusyBox init to specify the controlling tty for\n" \ | |
30649 | " the specified process to run on. The contents of this field are\n" \ | |
30650 | -" appended to "/dev/" and used as-is. There is no need for this field to\n" \ | |
30651 | +" appended to \"/dev/\" and used as-is. There is no need for this field to\n" \ | |
30652 | " be unique, although if it isn't you may have strange results. If this\n" \ | |
30653 | " field is left blank, the controlling tty is set to the console. Also\n" \ | |
30654 | " note that if BusyBox detects that a serial console is in use, then only\n" \ | |
30655 | @@ -1218,7 +1277,7 @@ | |
30656 | " it. Unlike sysvinit, BusyBox init does not stop processes from\n" \ | |
30657 | " respawning out of control. The 'askfirst' actions acts just like\n" \ | |
30658 | " respawn, except that before running the specified process it\n" \ | |
30659 | -" displays the line "Please press Enter to activate this console."\n" \ | |
30660 | +" displays the line \"Please press Enter to activate this console.\"\n" \ | |
30661 | " and then waits for the user to press enter before starting the\n" \ | |
30662 | " specified process.\n" \ | |
30663 | "\n" \ | |
30664 | @@ -1238,9 +1297,9 @@ | |
30665 | " \n" \ | |
30666 | " # /bin/sh invocations on selected ttys\n" \ | |
30667 | " #\n" \ | |
30668 | -" # Start an "askfirst" shell on the console (whatever that may be)\n" \ | |
30669 | +" # Start an \"askfirst\" shell on the console (whatever that may be)\n" \ | |
30670 | " ::askfirst:-/bin/sh\n" \ | |
30671 | -" # Start an "askfirst" shell on /dev/tty2-4\n" \ | |
30672 | +" # Start an \"askfirst\" shell on /dev/tty2-4\n" \ | |
30673 | " tty2::askfirst:-/bin/sh\n" \ | |
30674 | " tty3::askfirst:-/bin/sh\n" \ | |
30675 | " tty4::askfirst:-/bin/sh\n" \ | |
30676 | @@ -1268,17 +1327,17 @@ | |
30677 | " ::shutdown:/sbin/swapoff -a\n" | |
30678 | ||
30679 | #ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP | |
30680 | - #define USAGE_INSMOD_MAP(a) a | |
30681 | +# define USAGE_INSMOD_MAP(a) a | |
30682 | #else | |
30683 | - #define USAGE_INSMOD_MAP(a) | |
30684 | +# define USAGE_INSMOD_MAP(a) | |
30685 | #endif | |
30686 | #define insmod_trivial_usage \ | |
30687 | "[OPTION]... MODULE [symbol=value]..." | |
30688 | #define insmod_full_usage \ | |
30689 | "Loads the specified kernel modules into the kernel.\n\n" \ | |
30690 | "Options:\n" \ | |
30691 | - "\t-f\tForce module to load into the wrong kernel version.\n" \ | |
30692 | - "\t-k\tMake module autoclean-able.\n" \ | |
30693 | + "\t-f\tForce module to load into the wrong kernel version\n" \ | |
30694 | + "\t-k\tMake module autoclean-able\n" \ | |
30695 | "\t-v\tverbose output\n" \ | |
30696 | "\t-q\tquiet output\n" \ | |
30697 | "\t-L\tLock to prevent simultaneous loads of a module\n" \ | |
30698 | @@ -1319,21 +1378,21 @@ | |
30699 | "\t\t\tSCOPE-ID := [ host | link | global | NUMBER ]" | |
30700 | ||
30701 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | |
30702 | - #define XUSAGE_IPCALC_FANCY(a) a | |
30703 | +# define XUSAGE_IPCALC_FANCY(a) a | |
30704 | #else | |
30705 | - #define XUSAGE_IPCALC_FANCY(a) | |
30706 | +# define XUSAGE_IPCALC_FANCY(a) | |
30707 | #endif | |
30708 | #define ipcalc_trivial_usage \ | |
30709 | "[OPTION]... <ADDRESS>[[/]<NETMASK>] [NETMASK]" | |
30710 | #define ipcalc_full_usage \ | |
30711 | "Calculate IP network settings from a IP address\n\n" \ | |
30712 | "Options:\n" \ | |
30713 | - "\t-b\t--broadcast\tDisplay calculated broadcast address.\n" \ | |
30714 | - "\t-n\t--network\tDisplay calculated network address.\n" \ | |
30715 | + "\t-b\t--broadcast\tDisplay calculated broadcast address\n" \ | |
30716 | + "\t-n\t--network\tDisplay calculated network address\n" \ | |
30717 | "\t-m\t--netmask\tDisplay default netmask for IP." \ | |
30718 | - XUSAGE_IPCALC_FANCY(\ | |
30719 | + XUSAGE_IPCALC_FANCY( \ | |
30720 | "\n\t-p\t--prefix\tDisplay the prefix for IP/NETMASK." \ | |
30721 | - "\t-h\t--hostname\tDisplay first resolved host name.\n" \ | |
30722 | + "\t-h\t--hostname\tDisplay first resolved host name\n" \ | |
30723 | "\t-s\t--silent\tDon't ever display error messages.") | |
30724 | ||
30725 | #define iplink_trivial_usage \ | |
30726 | @@ -1368,9 +1427,9 @@ | |
30727 | #define kill_trivial_usage \ | |
30728 | "[-signal] process-id [process-id ...]" | |
30729 | #define kill_full_usage \ | |
30730 | - "Send a signal (default is SIGTERM) to the specified process(es).\n\n"\ | |
30731 | + "Send a signal (default is SIGTERM) to the specified process(es).\n\n" \ | |
30732 | "Options:\n" \ | |
30733 | - "\t-l\tList all signal names and numbers." | |
30734 | + "\t-l\tList all signal names and numbers" | |
30735 | #define kill_example_usage \ | |
30736 | "$ ps | grep apache\n" \ | |
30737 | "252 root root S [apache]\n" \ | |
30738 | @@ -1384,20 +1443,20 @@ | |
30739 | #define killall_trivial_usage \ | |
30740 | "[-q] [-signal] process-name [process-name ...]" | |
30741 | #define killall_full_usage \ | |
30742 | - "Send a signal (default is SIGTERM) to the specified process(es).\n\n"\ | |
30743 | + "Send a signal (default is SIGTERM) to the specified process(es).\n\n" \ | |
30744 | "Options:\n" \ | |
30745 | - "\t-l\tList all signal names and numbers.\n"\ | |
30746 | - "\t-q\tDo not complain if no processes were killed." | |
30747 | + "\t-l\tList all signal names and numbers\n" \ | |
30748 | + "\t-q\tDo not complain if no processes were killed" | |
30749 | #define killall_example_usage \ | |
30750 | "$ killall apache\n" | |
30751 | ||
30752 | #define klogd_trivial_usage \ | |
30753 | "[-c n] [-n]" | |
30754 | #define klogd_full_usage \ | |
30755 | - "Kernel logger.\n"\ | |
30756 | - "Options:\n"\ | |
30757 | - "\t-c n\tSets the default log level of console messages to n.\n"\ | |
30758 | - "\t-n\tRun as a foreground process." | |
30759 | + "Kernel logger.\n" \ | |
30760 | + "Options:\n" \ | |
30761 | + "\t-c n\tSets the default log level of console messages to n\n" \ | |
30762 | + "\t-n\tRun as a foreground process" | |
30763 | ||
30764 | #define length_trivial_usage \ | |
30765 | "STRING" | |
30766 | @@ -1410,12 +1469,14 @@ | |
30767 | #define ln_trivial_usage \ | |
30768 | "[OPTION] TARGET... LINK_NAME|DIRECTORY" | |
30769 | #define ln_full_usage \ | |
30770 | - "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n"\ | |
30771 | + "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n" \ | |
30772 | "\nYou may use '--' to indicate that all following arguments are non-options.\n\n" \ | |
30773 | "Options:\n" \ | |
30774 | "\t-s\tmake symbolic links instead of hard links\n" \ | |
30775 | "\t-f\tremove existing destination files\n" \ | |
30776 | - "\t-n\tno dereference symlinks - treat like normal file" | |
30777 | + "\t-n\tno dereference symlinks - treat like normal file\n" \ | |
30778 | + "\t-b\tmake a backup of the target (if exists) before link operation\n" \ | |
30779 | + "\t-S suffix\tuse suffix instead of ~ when making backup files" | |
30780 | #define ln_example_usage \ | |
30781 | "$ ln -s BusyBox /tmp/ls\n" \ | |
30782 | "$ ls -l /tmp/ls\n" \ | |
30783 | @@ -1440,12 +1501,12 @@ | |
30784 | #define logger_full_usage \ | |
30785 | "Write MESSAGE to the system log. If MESSAGE is omitted, log stdin.\n\n" \ | |
30786 | "Options:\n" \ | |
30787 | - "\t-s\tLog to stderr as well as the system log.\n" \ | |
30788 | - "\t-t TAG\tLog using the specified tag (defaults to user name).\n" \ | |
30789 | - "\t-p PRIORITY\tEnter the message with the specified priority.\n" \ | |
30790 | - "\t\tThis may be numerical or a ``facility.level'' pair." | |
30791 | + "\t-s\tLog to stderr as well as the system log\n" \ | |
30792 | + "\t-t TAG\tLog using the specified tag (defaults to user name)\n" \ | |
30793 | + "\t-p PRIORITY\tEnter the message with the specified priority\n" \ | |
30794 | + "\t\tThis may be numerical or a ``facility.level'' pair" | |
30795 | #define logger_example_usage \ | |
30796 | - "$ logger "hello"\n" | |
30797 | + "$ logger \"hello\"\n" | |
30798 | ||
30799 | #define login_trivial_usage \ | |
30800 | "[OPTION]... [username] [ENV=VAR ...]" | |
30801 | @@ -1453,8 +1514,8 @@ | |
30802 | "Begin a new session on the system\n\n" \ | |
30803 | "Options:\n" \ | |
30804 | "\t-f\tDo not authenticate (user already authenticated)\n" \ | |
30805 | - "\t-h\tName of the remote host for this login.\n" \ | |
30806 | - "\t-p\tPreserve environment." | |
30807 | + "\t-h\tName of the remote host for this login\n" \ | |
30808 | + "\t-p\tPreserve environment" | |
30809 | ||
30810 | #define logname_trivial_usage \ | |
30811 | "" | |
30812 | @@ -1467,7 +1528,7 @@ | |
30813 | #define logread_trivial_usage \ | |
30814 | "[OPTION]..." | |
30815 | #define logread_full_usage \ | |
30816 | - "Shows the messages from syslogd (using circular buffer).\n\n" \ | |
30817 | + "Shows the messages from syslogd (using circular buffer).\n\n" \ | |
30818 | "Options:\n" \ | |
30819 | "\t-f\t\toutput data as the log grows" | |
30820 | ||
30821 | @@ -1477,38 +1538,38 @@ | |
30822 | #define losetup_full_usage \ | |
30823 | "Associate LOOPDEVICE with FILE.\n\n" \ | |
30824 | "Options:\n" \ | |
30825 | - "\t-d\t\tDisassociate LOOPDEVICE.\n" \ | |
30826 | - "\t-o OFFSET\tStart OFFSET bytes into FILE." | |
30827 | + "\t-d\t\tDisassociate LOOPDEVICE\n" \ | |
30828 | + "\t-o OFFSET\tStart OFFSET bytes into FILE" | |
30829 | ||
30830 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS | |
30831 | - #define USAGE_LS_TIMESTAMPS(a) a | |
30832 | +# define USAGE_LS_TIMESTAMPS(a) a | |
30833 | #else | |
30834 | - #define USAGE_LS_TIMESTAMPS(a) | |
30835 | +# define USAGE_LS_TIMESTAMPS(a) | |
30836 | #endif | |
30837 | #ifdef CONFIG_FEATURE_LS_FILETYPES | |
30838 | - #define USAGE_LS_FILETYPES(a) a | |
30839 | +# define USAGE_LS_FILETYPES(a) a | |
30840 | #else | |
30841 | - #define USAGE_LS_FILETYPES(a) | |
30842 | +# define USAGE_LS_FILETYPES(a) | |
30843 | #endif | |
30844 | #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS | |
30845 | - #define USAGE_LS_FOLLOWLINKS(a) a | |
30846 | +# define USAGE_LS_FOLLOWLINKS(a) a | |
30847 | #else | |
30848 | - #define USAGE_LS_FOLLOWLINKS(a) | |
30849 | +# define USAGE_LS_FOLLOWLINKS(a) | |
30850 | #endif | |
30851 | #ifdef CONFIG_FEATURE_LS_RECURSIVE | |
30852 | - #define USAGE_LS_RECURSIVE(a) a | |
30853 | +# define USAGE_LS_RECURSIVE(a) a | |
30854 | #else | |
30855 | - #define USAGE_LS_RECURSIVE(a) | |
30856 | +# define USAGE_LS_RECURSIVE(a) | |
30857 | #endif | |
30858 | #ifdef CONFIG_FEATURE_LS_SORTFILES | |
30859 | - #define USAGE_LS_SORTFILES(a) a | |
30860 | +# define USAGE_LS_SORTFILES(a) a | |
30861 | #else | |
30862 | - #define USAGE_LS_SORTFILES(a) | |
30863 | +# define USAGE_LS_SORTFILES(a) | |
30864 | #endif | |
30865 | #ifdef CONFIG_FEATURE_AUTOWIDTH | |
30866 | - #define USAGE_AUTOWIDTH(a) a | |
30867 | +# define USAGE_AUTOWIDTH(a) a | |
30868 | #else | |
30869 | - #define USAGE_AUTOWIDTH(a) | |
30870 | +# define USAGE_AUTOWIDTH(a) | |
30871 | #endif | |
30872 | ||
30873 | #define ls_trivial_usage \ | |
30874 | @@ -1545,6 +1606,17 @@ | |
30875 | USAGE_SELINUX("\t-k\tprint security context\n") \ | |
30876 | USAGE_SELINUX("\t-K\tprint security context in long format\n") | |
30877 | ||
30878 | +#define lsattr_trivial_usage \ | |
30879 | + "[-Radlv] [files...]" | |
30880 | +#define lsattr_full_usage \ | |
30881 | + "list file attributes on an ext2 fs\n\n" \ | |
30882 | + "Options:\n" \ | |
30883 | + "\t-R\trecursively list subdirectories\n" \ | |
30884 | + "\t-a\tdo not hide entries starting with .\n" \ | |
30885 | + "\t-d\tlist directory entries instead of contents\n" \ | |
30886 | + "\t-l\tprint long flag names\n" \ | |
30887 | + "\t-v\tlist the file's version/generation number" | |
30888 | + | |
30889 | #define lsmod_trivial_usage \ | |
30890 | "" | |
30891 | #define lsmod_full_usage \ | |
30892 | @@ -1559,7 +1631,7 @@ | |
30893 | "\tc or u:\tMake a character (un-buffered) device.\n" \ | |
30894 | "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes.\n\n" \ | |
30895 | "FIRST specifies the number appended to NAME to create the first device.\n" \ | |
30896 | - "LAST specifies the number of the last item that should be created.\n" \ | |
30897 | + "LAST specifies the number of the last item that should be created\n" \ | |
30898 | "If 's' is the last argument, the base device is created as well.\n\n" \ | |
30899 | "For example:\n" \ | |
30900 | "\tmakedevs /dev/ttyS c 4 66 2 63 -> ttyS2-ttyS63\n" \ | |
30901 | @@ -1602,8 +1674,8 @@ | |
30902 | "[y|n]" | |
30903 | #define mesg_full_usage \ | |
30904 | "mesg controls write access to your terminal\n" \ | |
30905 | - "\ty\tAllow write access to your terminal.\n" \ | |
30906 | - "\tn\tDisallow write access to your terminal.\n" | |
30907 | + "\ty\tAllow write access to your terminal\n" \ | |
30908 | + "\tn\tDisallow write access to your terminal" | |
30909 | ||
30910 | #define mkdir_trivial_usage \ | |
30911 | "[OPTION] DIRECTORY..." | |
30912 | @@ -1645,9 +1717,9 @@ | |
30913 | "Options:\n" \ | |
30914 | "\t-m\tcreate the special file using the specified mode (default a=rw)\n\n" \ | |
30915 | "TYPEs include:\n" \ | |
30916 | - "\tb:\tMake a block (buffered) device.\n" \ | |
30917 | - "\tc or u:\tMake a character (un-buffered) device.\n" \ | |
30918 | - "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes." | |
30919 | + "\tb:\tMake a block (buffered) device\n" \ | |
30920 | + "\tc or u:\tMake a character (un-buffered) device\n" \ | |
30921 | + "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes" | |
30922 | #define mknod_example_usage \ | |
30923 | "$ mknod /dev/fd0 b 2 0\n" \ | |
30924 | "$ mknod -m 644 /tmp/pipe p\n" | |
30925 | @@ -1657,10 +1729,10 @@ | |
30926 | #define mkswap_full_usage \ | |
30927 | "Prepare a disk partition to be used as a swap partition.\n\n" \ | |
30928 | "Options:\n" \ | |
30929 | - "\t-c\t\tCheck for read-ability.\n" \ | |
30930 | - "\t-v0\t\tMake version 0 swap [max 128 Megs].\n" \ | |
30931 | - "\t-v1\t\tMake version 1 swap [big!] (default for kernels >\n\t\t\t2.1.117).\n" \ | |
30932 | - "\tblock-count\tNumber of block to use (default is entire partition)." | |
30933 | + "\t-c\t\tCheck for read-ability\n" \ | |
30934 | + "\t-v0\t\tMake version 0 swap [max 128 Megs]\n" \ | |
30935 | + "\t-v1\t\tMake version 1 swap [big!] (default for kernels >\n\t\t\t2.1.117)\n" \ | |
30936 | + "\tblock-count\tNumber of block to use (default is entire partition)" | |
30937 | ||
30938 | #define mktemp_trivial_usage \ | |
30939 | "[-dq] TEMPLATE" | |
30940 | @@ -1681,12 +1753,12 @@ | |
30941 | #define modprobe_full_usage \ | |
30942 | "Used for high level module loading and unloading.\n\n" \ | |
30943 | "Options:\n" \ | |
30944 | - "\t-k\tMake module autoclean-able.\n" \ | |
30945 | - "\t-n\tJust show what would be done.\n" \ | |
30946 | - "\t-q\tQuiet output.\n" \ | |
30947 | - "\t-r\tRemove module (stacks) or do autoclean.\n" \ | |
30948 | - "\t-s\tReport via syslog instead of stderr.\n" \ | |
30949 | - "\t-v\tVerbose output." | |
30950 | + "\t-k\tMake module autoclean-able\n" \ | |
30951 | + "\t-n\tJust show what would be done\n" \ | |
30952 | + "\t-q\tQuiet output\n" \ | |
30953 | + "\t-r\tRemove module (stacks) or do autoclean\n" \ | |
30954 | + "\t-s\tReport via syslog instead of stderr\n" \ | |
30955 | + "\t-v\tVerbose output" | |
30956 | #define modprobe_example_usage \ | |
30957 | "$ modprobe cdrom\n" | |
30958 | ||
30959 | @@ -1698,14 +1770,14 @@ | |
30960 | "$ dmesg | more\n" | |
30961 | ||
30962 | #ifdef CONFIG_FEATURE_MOUNT_LOOP | |
30963 | - #define USAGE_MOUNT_LOOP(a) a | |
30964 | +# define USAGE_MOUNT_LOOP(a) a | |
30965 | #else | |
30966 | - #define USAGE_MOUNT_LOOP(a) | |
30967 | +# define USAGE_MOUNT_LOOP(a) | |
30968 | #endif | |
30969 | #ifdef CONFIG_FEATURE_MTAB_SUPPORT | |
30970 | - #define USAGE_MTAB(a) a | |
30971 | +# define USAGE_MTAB(a) a | |
30972 | #else | |
30973 | - #define USAGE_MTAB(a) | |
30974 | +# define USAGE_MTAB(a) | |
30975 | #endif | |
30976 | #define mount_trivial_usage \ | |
30977 | "[flags] DEVICE NODE [-o options,more-options]" | |
30978 | @@ -1713,30 +1785,30 @@ | |
30979 | "Mount a filesystem. Autodetection of filesystem type requires the\n" \ | |
30980 | "/proc filesystem be already mounted.\n\n" \ | |
30981 | "Flags:\n" \ | |
30982 | - "\t-a:\t\tMount all filesystems in fstab.\n" \ | |
30983 | + "\t-a:\t\tMount all filesystems in fstab\n" \ | |
30984 | USAGE_MTAB( \ | |
30985 | - "\t-f:\t\t\"Fake\" Add entry to mount table but don't mount it.\n" \ | |
30986 | - "\t-n:\t\tDon't write a mount table entry.\n" \ | |
30987 | + "\t-f:\t\t\"Fake\" Add entry to mount table but don't mount it\n" \ | |
30988 | + "\t-n:\t\tDon't write a mount table entry\n" \ | |
30989 | ) \ | |
30990 | - "\t-o option:\tOne of many filesystem options, listed below.\n" \ | |
30991 | - "\t-r:\t\tMount the filesystem read-only.\n" \ | |
30992 | - "\t-t fs-type:\tSpecify the filesystem type.\n" \ | |
30993 | - "\t-w:\t\tMount for reading and writing (default).\n" \ | |
30994 | + "\t-o option:\tOne of many filesystem options, listed below\n" \ | |
30995 | + "\t-r:\t\tMount the filesystem read-only\n" \ | |
30996 | + "\t-t fs-type:\tSpecify the filesystem type\n" \ | |
30997 | + "\t-w:\t\tMount for reading and writing (default)\n" \ | |
30998 | "\n" \ | |
30999 | "Options for use with the \"-o\" flag:\n" \ | |
31000 | - "\tasync/sync:\tWrites are asynchronous / synchronous.\n" \ | |
31001 | - "\tatime/noatime:\tEnable / disable updates to inode access times.\n" \ | |
31002 | - "\tdev/nodev:\tAllow use of special device files / disallow them.\n" \ | |
31003 | - "\texec/noexec:\tAllow use of executable files / disallow them.\n" \ | |
31004 | + "\tasync/sync:\tWrites are asynchronous / synchronous\n" \ | |
31005 | + "\tatime/noatime:\tEnable / disable updates to inode access times\n" \ | |
31006 | + "\tdev/nodev:\tAllow use of special device files / disallow them\n" \ | |
31007 | + "\texec/noexec:\tAllow use of executable files / disallow them\n" \ | |
31008 | USAGE_MOUNT_LOOP( \ | |
31009 | - "\tloop:\t\tMounts a file via loop device.\n" \ | |
31010 | + "\tloop:\t\tMounts a file via loop device\n" \ | |
31011 | ) \ | |
31012 | - "\tsuid/nosuid:\tAllow set-user-id-root programs / disallow them.\n" \ | |
31013 | - "\tremount:\tRe-mount a mounted filesystem, changing its flags.\n" \ | |
31014 | - "\tro/rw:\t\tMount for read-only / read-write.\n" \ | |
31015 | - "\tbind:\t\tUse the linux 2.4.x \"bind\" feature.\n" \ | |
31016 | - "\nThere are EVEN MORE flags that are specific to each filesystem.\n" \ | |
31017 | - "You'll have to see the written documentation for those filesystems." | |
31018 | + "\tsuid/nosuid:\tAllow set-user-id-root programs / disallow them\n" \ | |
31019 | + "\tremount:\tRe-mount a mounted filesystem, changing its flags\n" \ | |
31020 | + "\tro/rw:\t\tMount for read-only / read-write\n" \ | |
31021 | + "\tbind:\t\tUse the linux 2.4.x \"bind\" feature\n" \ | |
31022 | + "\nThere are EVEN MORE flags that are specific to each filesystem\n" \ | |
31023 | + "You'll have to see the written documentation for those filesystems" | |
31024 | #define mount_example_usage \ | |
31025 | "$ mount\n" \ | |
31026 | "/dev/hda3 on / type minix (rw)\n" \ | |
31027 | @@ -1772,13 +1844,18 @@ | |
31028 | "Nameif renaming network interface while it in the down state.\n\n" \ | |
31029 | "Options:\n" \ | |
31030 | "\t-c FILE\t\tUse configuration file (default is /etc/mactab)\n" \ | |
31031 | - "\t-s\t\tUse syslog (LOCAL0 facility).\n" \ | |
31032 | + "\t-s\t\tUse syslog (LOCAL0 facility)\n" \ | |
31033 | "\tIFNAME MACADDR\tnew_interface_name interface_mac_address" | |
31034 | #define nameif_example_usage \ | |
31035 | "$ nameif -s dmz0 00:A0:C9:8C:F6:3F\n" \ | |
31036 | " or\n" \ | |
31037 | "$ nameif -c /etc/my_mactab_file\n" \ | |
31038 | ||
31039 | +#ifdef CONFIG_NC_GAPING_SECURITY_HOLE | |
31040 | +# define USAGE_NC_EXEC(a) a | |
31041 | +#else | |
31042 | +# define USAGE_NC_EXEC(a) | |
31043 | +#endif | |
31044 | #define nc_trivial_usage \ | |
31045 | "[OPTIONS] [IP] [port]" | |
31046 | #define nc_full_usage \ | |
31047 | @@ -1787,7 +1864,10 @@ | |
31048 | "\t-l\t\tlisten mode, for inbound connects\n" \ | |
31049 | "\t-p PORT\t\tlocal port number\n" \ | |
31050 | "\t-i SECS\t\tdelay interval for lines sent\n" \ | |
31051 | - "\t-e PROG\t\tprogram to exec after connect (dangerous!)" | |
31052 | + USAGE_NC_EXEC( \ | |
31053 | + "\t-e PROG\t\tprogram to exec after connect (dangerous!)\n" \ | |
31054 | + ) \ | |
31055 | + "\t-w SECS\t\ttimeout for connects and final net reads" | |
31056 | #define nc_example_usage \ | |
31057 | "$ nc foobar.somedomain.com 25\n" \ | |
31058 | "220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \ | |
31059 | @@ -1813,6 +1893,13 @@ | |
31060 | "\t-w raw sockets\n" \ | |
31061 | "\t-x unix sockets" | |
31062 | ||
31063 | +#define nice_trivial_usage \ | |
31064 | + "[-n ADJUST] [COMMAND [ARG] ...]" | |
31065 | +#define nice_full_usage \ | |
31066 | + "Nice runs a program with modified scheduling priority.\n\n" \ | |
31067 | + "Options:\n" \ | |
31068 | + "\t-n ADJUST\tAdjust the scheduling priority by ADJUST" | |
31069 | + | |
31070 | #define nslookup_trivial_usage \ | |
31071 | "[HOST] [SERVER]" | |
31072 | #define nslookup_full_usage \ | |
31073 | @@ -1829,7 +1916,7 @@ | |
31074 | #define od_trivial_usage \ | |
31075 | "[-aBbcDdeFfHhIiLlOovXx] [FILE]" | |
31076 | #define od_full_usage \ | |
31077 | - "Write an unambiguous representation, octal bytes by default, of FILE\n"\ | |
31078 | + "Write an unambiguous representation, octal bytes by default, of FILE\n" \ | |
31079 | "to standard output. With no FILE, or when FILE is -, read standard input." | |
31080 | ||
31081 | #define openvt_trivial_usage \ | |
31082 | @@ -1840,9 +1927,9 @@ | |
31083 | "openvt 2 /bin/ash\n" | |
31084 | ||
31085 | #ifdef CONFIG_FEATURE_SHA1_PASSWORDS | |
31086 | - #define PASSWORD_ALG_TYPES(a) a | |
31087 | +# define PASSWORD_ALG_TYPES(a) a | |
31088 | #else | |
31089 | - #define PASSWORD_ALG_TYPES(a) | |
31090 | +# define PASSWORD_ALG_TYPES(a) | |
31091 | #endif | |
31092 | #define passwd_trivial_usage \ | |
31093 | "[OPTION] [name]" | |
31094 | @@ -1850,12 +1937,12 @@ | |
31095 | "Change a user password. If no name is specified,\n" \ | |
31096 | "changes the password for the current user.\n" \ | |
31097 | "Options:\n" \ | |
31098 | - "\t-a\tDefine which algorithm shall be used for the password.\n" \ | |
31099 | + "\t-a\tDefine which algorithm shall be used for the password\n" \ | |
31100 | "\t\t\t(Choices: des, md5" \ | |
31101 | PASSWORD_ALG_TYPES(", sha1") \ | |
31102 | - ")\n\t-d\tDelete the password for the specified user account.\n" \ | |
31103 | - "\t-l\tLocks (disables) the specified user account.\n" \ | |
31104 | - "\t-u\tUnlocks (re-enables) the specified user account." | |
31105 | + ")\n\t-d\tDelete the password for the specified user account\n" \ | |
31106 | + "\t-l\tLocks (disables) the specified user account\n" \ | |
31107 | + "\t-u\tUnlocks (re-enables) the specified user account" | |
31108 | ||
31109 | #define patch_trivial_usage \ | |
31110 | "[-p<num>]" | |
31111 | @@ -1870,7 +1957,7 @@ | |
31112 | "Lists the PIDs of all processes with names that match the\n" \ | |
31113 | "names on the command line.\n" \ | |
31114 | "Options:\n" \ | |
31115 | - "\t-s\t\tdisplay only a single PID." | |
31116 | + "\t-s\t\tdisplay only a single PID" | |
31117 | #define pidof_example_usage \ | |
31118 | "$ pidof init\n" \ | |
31119 | "1\n" | |
31120 | @@ -1884,10 +1971,10 @@ | |
31121 | #define ping_full_usage \ | |
31122 | "Send ICMP ECHO_REQUEST packets to network hosts.\n\n" \ | |
31123 | "Options:\n" \ | |
31124 | - "\t-c COUNT\tSend only COUNT pings.\n" \ | |
31125 | - "\t-s SIZE\t\tSend SIZE data bytes in packets (default=56).\n" \ | |
31126 | + "\t-c COUNT\tSend only COUNT pings\n" \ | |
31127 | + "\t-s SIZE\t\tSend SIZE data bytes in packets (default=56)\n" \ | |
31128 | "\t-q\t\tQuiet mode, only displays output at start\n" \ | |
31129 | - "\t\t\tand when finished." | |
31130 | + "\t\t\tand when finished" | |
31131 | #endif | |
31132 | #define ping_example_usage \ | |
31133 | "$ ping localhost\n" \ | |
31134 | @@ -1907,10 +1994,10 @@ | |
31135 | #define ping6_full_usage \ | |
31136 | "Send ICMP ECHO_REQUEST packets to network hosts.\n\n" \ | |
31137 | "Options:\n" \ | |
31138 | - "\t-c COUNT\tSend only COUNT pings.\n" \ | |
31139 | - "\t-s SIZE\t\tSend SIZE data bytes in packets (default=56).\n" \ | |
31140 | + "\t-c COUNT\tSend only COUNT pings\n" \ | |
31141 | + "\t-s SIZE\t\tSend SIZE data bytes in packets (default=56)\n" \ | |
31142 | "\t-q\t\tQuiet mode, only displays output at start\n" \ | |
31143 | - "\t\t\tand when finished." | |
31144 | + "\t\t\tand when finished" | |
31145 | #endif | |
31146 | #define ping6_example_usage \ | |
31147 | "$ ping6 ip6-localhost\n" \ | |
31148 | @@ -1932,7 +2019,13 @@ | |
31149 | #define poweroff_full_usage \ | |
31150 | "Halt the system and request that the kernel shut off the power.\n" \ | |
31151 | "Options:\n" \ | |
31152 | - "\t-d\t\tdelay interval for shutting off." | |
31153 | + "\t-d\t\tdelay interval for shutting off" | |
31154 | + | |
31155 | +#define printenv_trivial_usage \ | |
31156 | + "[VARIABLES...]" | |
31157 | +#define printenv_full_usage \ | |
31158 | + "print all or part of environment\n\n" \ | |
31159 | + "If no environment VARIABLE specified, print them all." | |
31160 | ||
31161 | #define printf_trivial_usage \ | |
31162 | "FORMAT [ARGUMENT...]" | |
31163 | @@ -1940,7 +2033,7 @@ | |
31164 | "Formats and prints ARGUMENT(s) according to FORMAT,\n" \ | |
31165 | "Where FORMAT controls the output exactly as in C printf." | |
31166 | #define printf_example_usage \ | |
31167 | - "$ printf "Val=%d\\n" 5\n" \ | |
31168 | + "$ printf \"Val=%d\\n\" 5\n" \ | |
31169 | "Val=5\n" | |
31170 | ||
31171 | #ifdef CONFIG_SELINUX | |
31172 | @@ -1982,13 +2075,36 @@ | |
31173 | #define rdate_full_usage \ | |
31174 | "Get and possibly set the system date and time from a remote HOST.\n\n" \ | |
31175 | "Options:\n" \ | |
31176 | - "\t-s\tSet the system date and time (default).\n" \ | |
31177 | - "\t-p\tPrint the date and time." | |
31178 | + "\t-s\tSet the system date and time (default)\n" \ | |
31179 | + "\t-p\tPrint the date and time" | |
31180 | + | |
31181 | +#ifdef CONFIG_FEATURE_READLINK_FOLLOW | |
31182 | +#define USAGE_READLINK_FOLLOW(a) a | |
31183 | +#else | |
31184 | +#define USAGE_READLINK_FOLLOW(a) | |
31185 | +#endif | |
31186 | ||
31187 | #define readlink_trivial_usage \ | |
31188 | - "" | |
31189 | + USAGE_READLINK_FOLLOW("[-f] ") "FILE" | |
31190 | #define readlink_full_usage \ | |
31191 | - "Displays the value of a symbolic link." | |
31192 | + "Displays the value of a symbolic link." \ | |
31193 | + USAGE_READLINK_FOLLOW("\n\nOptions:\n" \ | |
31194 | + "\t-f\tcanonicalize by following all symlinks") | |
31195 | + | |
31196 | +#define readprofile_trivial_usage \ | |
31197 | + "[OPTIONS]..." | |
31198 | +#define readprofile_full_usage \ | |
31199 | + "Options:\n" \ | |
31200 | + "\t -m <mapfile> (default: /boot/System.map)\n" \ | |
31201 | + "\t -p <profile> (default: /proc/profile)\n" \ | |
31202 | + "\t -M <mult> set the profiling multiplier to <mult>\n" \ | |
31203 | + "\t -i print only info about the sampling step\n" \ | |
31204 | + "\t -v print verbose data\n" \ | |
31205 | + "\t -a print all symbols, even if count is 0\n" \ | |
31206 | + "\t -b print individual histogram-bin counts\n" \ | |
31207 | + "\t -s print individual counters within functions\n" \ | |
31208 | + "\t -r reset all the counters (root only)\n" \ | |
31209 | + "\t -n disable byte order auto-detection" | |
31210 | ||
31211 | #define realpath_trivial_usage \ | |
31212 | "pathname ..." | |
31213 | @@ -2000,14 +2116,17 @@ | |
31214 | #define reboot_full_usage \ | |
31215 | "Reboot the system.\n" \ | |
31216 | "Options:\n" \ | |
31217 | - "\t-d\t\tdelay interval for rebooting." | |
31218 | + "\t-d\t\tdelay interval for rebooting" | |
31219 | ||
31220 | #define renice_trivial_usage \ | |
31221 | - "priority pid [pid ...]" | |
31222 | + "{{-n INCREMENT} | PRIORITY} [[ -p | -g | -u ] ID ...]" | |
31223 | #define renice_full_usage \ | |
31224 | - "Changes priority of running processes. Allowed priorities range\n" \ | |
31225 | - "from 20 (the process runs only when nothing else is running) to 0\n" \ | |
31226 | - "(default priority) to -20 (almost nothing else ever gets to run)." | |
31227 | + "Changes priority of running processes.\n\n" \ | |
31228 | + "Options:\n" \ | |
31229 | + "\t-n\tadjusts current nice value (smaller is faster)\n" \ | |
31230 | + "\t-p\tprocess id(s) (default)\n" \ | |
31231 | + "\t-g\tprocess group id(s)\n" \ | |
31232 | + "\t-u\tprocess user name(s) and/or id(s)" | |
31233 | ||
31234 | #define reset_trivial_usage \ | |
31235 | "" | |
31236 | @@ -2043,9 +2162,9 @@ | |
31237 | "$ rmmod tulip\n" | |
31238 | ||
31239 | #ifdef CONFIG_FEATURE_IPV6 | |
31240 | - #define USAGE_ROUTE_IPV6(a) a | |
31241 | +# define USAGE_ROUTE_IPV6(a) a | |
31242 | #else | |
31243 | - #define USAGE_ROUTE_IPV6(a) "\t" | |
31244 | +# define USAGE_ROUTE_IPV6(a) "\t" | |
31245 | #endif | |
31246 | ||
31247 | ||
31248 | @@ -2054,9 +2173,9 @@ | |
31249 | #define route_full_usage \ | |
31250 | "Edit the kernel's routing tables.\n\n" \ | |
31251 | "Options:\n" \ | |
31252 | - "\t-n\t\tDont resolve names.\n" \ | |
31253 | - "\t-e\t\tDisplay other/more information.\n" \ | |
31254 | - "\t-A inet" USAGE_ROUTE_IPV6("{6}") "\tSelect address family." | |
31255 | + "\t-n\t\tDont resolve names\n" \ | |
31256 | + "\t-e\t\tDisplay other/more information\n" \ | |
31257 | + "\t-A inet" USAGE_ROUTE_IPV6("{6}") "\tSelect address family" | |
31258 | ||
31259 | #define rpm_trivial_usage \ | |
31260 | "-i -q[ildc]p package.rpm" | |
31261 | @@ -2081,9 +2200,9 @@ | |
31262 | #define run_parts_full_usage \ | |
31263 | "Run a bunch of scripts in a directory.\n\n" \ | |
31264 | "Options:\n" \ | |
31265 | - "\t-t\tPrints what would be run, but does not actually run anything.\n" \ | |
31266 | - "\t-a ARG\tPass ARG as an argument for every program invoked.\n" \ | |
31267 | - "\t-u MASK\tSet the umask to MASK before executing every program." | |
31268 | + "\t-t\tPrints what would be run, but does not actually run anything\n" \ | |
31269 | + "\t-a ARG\tPass ARG as an argument for every program invoked\n" \ | |
31270 | + "\t-u MASK\tSet the umask to MASK before executing every program" | |
31271 | ||
31272 | #define rx_trivial_usage \ | |
31273 | "FILE" | |
31274 | @@ -2098,18 +2217,18 @@ | |
31275 | "Options:\n" \ | |
31276 | "\t-e script\tadd the script to the commands to be executed\n" \ | |
31277 | "\t-f scriptfile\tadd script-file contents to the\n" \ | |
31278 | - "\t\t\tcommands to be executed\n" \ | |
31279 | + "\t\t\tcommands to be executed\n" \ | |
31280 | "\t-i\t\tedit files in-place\n" \ | |
31281 | "\t-n\t\tsuppress automatic printing of pattern space\n" \ | |
31282 | "\t-r\t\tuse extended regular expression syntax\n" \ | |
31283 | "\n" \ | |
31284 | - "If no -e or -f is given, the first non-option argument is taken as the sed\n"\ | |
31285 | - "script to interpret. All remaining arguments are names of input files; if no\n"\ | |
31286 | + "If no -e or -f is given, the first non-option argument is taken as the sed\n" \ | |
31287 | + "script to interpret. All remaining arguments are names of input files; if no\n" \ | |
31288 | "input files are specified, then the standard input is read. Source files\n" \ | |
31289 | "will not be modified unless -i option is given." | |
31290 | ||
31291 | #define sed_example_usage \ | |
31292 | - "$ echo "foo" | sed -e 's/f[a-zA-Z]o/bar/g'\n" \ | |
31293 | + "$ echo \"foo\" | sed -e 's/f[a-zA-Z]o/bar/g'\n" \ | |
31294 | "bar\n" | |
31295 | ||
31296 | #define seq_trivial_usage \ | |
31297 | @@ -2142,7 +2261,7 @@ | |
31298 | "Use lash just as you would use any other shell. It properly handles pipes,\n" \ | |
31299 | "redirects, job control, can be used as the shell for scripts, and has a\n" \ | |
31300 | "sufficient set of builtins to do what is needed. It does not (yet) support\n" \ | |
31301 | - "Bourne Shell syntax. If you need things like "if-then-else", "while", and such\n" \ | |
31302 | + "Bourne Shell syntax. If you need things like \"if-then-else\", \"while\", and such\n" \ | |
31303 | "use ash or bash. If you just need a very simple and extremely small shell,\n" \ | |
31304 | "this will do the job." | |
31305 | ||
31306 | @@ -2165,11 +2284,11 @@ | |
31307 | "\t-w\twarn about improperly formated SHA1 checksum lines") | |
31308 | ||
31309 | #ifdef CONFIG_FEATURE_FANCY_SLEEP | |
31310 | - #define USAGE_FANCY_SLEEP(a) a | |
31311 | - #define USAGE_NOT_FANCY_SLEEP(a) | |
31312 | +# define USAGE_FANCY_SLEEP(a) a | |
31313 | +# define USAGE_NOT_FANCY_SLEEP(a) | |
31314 | #else | |
31315 | - #define USAGE_FANCY_SLEEP(a) | |
31316 | - #define USAGE_NOT_FANCY_SLEEP(a) a | |
31317 | +# define USAGE_FANCY_SLEEP(a) | |
31318 | +# define USAGE_NOT_FANCY_SLEEP(a) a | |
31319 | #endif | |
31320 | ||
31321 | #define sleep_trivial_usage \ | |
31322 | @@ -2185,24 +2304,39 @@ | |
31323 | USAGE_FANCY_SLEEP("$ sleep 1d 3h 22m 8s\n" \ | |
31324 | "[98528 second delay results]\n") | |
31325 | ||
31326 | -#ifdef CONFIG_FEATURE_SORT_UNIQUE | |
31327 | - #define USAGE_SORT_UNIQUE(a) a | |
31328 | -#else | |
31329 | - #define USAGE_SORT_UNIQUE(a) | |
31330 | -#endif | |
31331 | -#ifdef CONFIG_FEATURE_SORT_REVERSE | |
31332 | - #define USAGE_SORT_REVERSE(a) a | |
31333 | +#ifdef CONFIG_SORT_BIG | |
31334 | +# define USAGE_SORT_BIG(a) a | |
31335 | #else | |
31336 | - #define USAGE_SORT_REVERSE(a) | |
31337 | +# define USAGE_SORT_BIG(a) | |
31338 | #endif | |
31339 | + | |
31340 | #define sort_trivial_usage \ | |
31341 | - "[-n" USAGE_SORT_REVERSE("r") USAGE_SORT_UNIQUE("u") "] [FILE]..." | |
31342 | + "[-nru" USAGE_SORT_BIG("gMcszbdfimSTokt] [-o outfile] [-k start[.offset][opts][,end[.offset][opts]] [-t char") "] [FILE]..." | |
31343 | #define sort_full_usage \ | |
31344 | - "Sorts lines of text in the specified files\n\n"\ | |
31345 | + "Sorts lines of text in the specified files\n\n" \ | |
31346 | "Options:\n" \ | |
31347 | - USAGE_SORT_UNIQUE("\t-u\tsuppress duplicate lines\n") \ | |
31348 | - USAGE_SORT_REVERSE("\t-r\tsort in reverse order\n") \ | |
31349 | - "\t-n\tsort numerics" | |
31350 | + USAGE_SORT_BIG( \ | |
31351 | + "\t-b\tignore leading blanks\n" \ | |
31352 | + "\t-c\tcheck whether input is sorted\n" \ | |
31353 | + "\t-d\tdictionary order (blank or alphanumeric only)\n" \ | |
31354 | + "\t-f\tignore case\n" \ | |
31355 | + "\t-g\tgeneral numerical sort\n" \ | |
31356 | + "\t-i\tignore unprintable characters\n" \ | |
31357 | + "\t-k\tspecify sort key\n" \ | |
31358 | + "\t-M\tsort month\n" \ | |
31359 | + ) \ | |
31360 | + "\t-n\tsort numbers\n" \ | |
31361 | + USAGE_SORT_BIG( \ | |
31362 | + "\t-o\toutput to file\n" \ | |
31363 | + "\t-k\tsort by key\n" \ | |
31364 | + "\t-t\tuse key separator other than whitespace\n" \ | |
31365 | + ) \ | |
31366 | + "\t-r\treverse sort order\n" \ | |
31367 | + USAGE_SORT_BIG("\t-s\tstable (don't sort ties alphabetically)\n") \ | |
31368 | + "\t-u\tsuppress duplicate lines" \ | |
31369 | + USAGE_SORT_BIG("\n\t-z\tinput terminated by nulls, not newlines\n") \ | |
31370 | + USAGE_SORT_BIG("\t-mST\tignored for GNU compatability") \ | |
31371 | + "" | |
31372 | #define sort_example_usage \ | |
31373 | "$ echo -e \"e\\nf\\nb\\nd\\nc\\na\" | sort\n" \ | |
31374 | "a\n" \ | |
31375 | @@ -2210,34 +2344,98 @@ | |
31376 | "c\n" \ | |
31377 | "d\n" \ | |
31378 | "e\n" \ | |
31379 | - "f\n" | |
31380 | + "f\n" \ | |
31381 | + USAGE_SORT_BIG( \ | |
31382 | + "$ echo -e \"c 3\\nb 2\\nd 2\" | $SORT -k 2,2n -k 1,1r\n" \ | |
31383 | + "d 2\n" \ | |
31384 | + "b 2\n" \ | |
31385 | + "c 3\n" \ | |
31386 | + ) \ | |
31387 | + "" | |
31388 | ||
31389 | #define start_stop_daemon_trivial_usage \ | |
31390 | - "[OPTIONS] [--start|--stop] ... [-- arguments...]\n" | |
31391 | + "[OPTIONS] [--start|--stop] ... [-- arguments...]" | |
31392 | #define start_stop_daemon_full_usage \ | |
31393 | - "Program to start and stop services."\ | |
31394 | - "\n\nOptions:"\ | |
31395 | - "\n\t-S|--start\t\t\tstart"\ | |
31396 | - "\n\t-K|--stop\t\t\tstop"\ | |
31397 | - "\n\t-a|--startas <pathname>\t\tstarts process specified by pathname"\ | |
31398 | - "\n\t-b|--background\t\t\tforce process into background"\ | |
31399 | - "\n\t-u|--user <username>|<uid>\tstop this user's processes"\ | |
31400 | - "\n\t-x|--exec <executable>\t\tprogram to either start or check"\ | |
31401 | - "\n\t-m|--make-pidfile <filename>\tcreate the -p file and enter pid in it"\ | |
31402 | - "\n\t-n|--name <process-name>\tstop processes with this name"\ | |
31403 | - "\n\t-p|--pidfile <pid-file>\t\tsave or load pid using a pid-file"\ | |
31404 | + "Program to start and stop services." \ | |
31405 | + "\n\nOptions:" \ | |
31406 | + "\n\t-S|--start\t\t\tstart" \ | |
31407 | + "\n\t-K|--stop\t\t\tstop" \ | |
31408 | + "\n\t-a|--startas <pathname>\t\tstarts process specified by pathname" \ | |
31409 | + "\n\t-b|--background\t\t\tforce process into background" \ | |
31410 | + "\n\t-u|--user <username>|<uid>\tstop this user's processes" \ | |
31411 | + "\n\t-x|--exec <executable>\t\tprogram to either start or check" \ | |
31412 | + "\n\t-m|--make-pidfile <filename>\tcreate the -p file and enter pid in it" \ | |
31413 | + "\n\t-n|--name <process-name>\tstop processes with this name" \ | |
31414 | + "\n\t-p|--pidfile <pid-file>\t\tsave or load pid using a pid-file" \ | |
31415 | "\n\t-q|--quiet\t\t\tbe quiet" \ | |
31416 | "\n\t-s|--signal <signal>\t\tsignal to send (default TERM)" | |
31417 | ||
31418 | +#ifdef CONFIG_FEATURE_STAT_FORMAT | |
31419 | +# define USAGE_STAT_FORMAT(a) a | |
31420 | +#else | |
31421 | +# define USAGE_STAT_FORMAT(a) | |
31422 | +#endif | |
31423 | +#define stat_trivial_usage \ | |
31424 | + "[OPTION] FILE..." | |
31425 | +#define stat_full_usage \ | |
31426 | + "display file (default) or filesystem status.\n\n" \ | |
31427 | + "Options:\n" \ | |
31428 | + USAGE_STAT_FORMAT("\t-c fmt\tuse the specified format\n") \ | |
31429 | + "\t-f\tdisplay filesystem status\n" \ | |
31430 | + "\t-L,-l\tdereference links\n" \ | |
31431 | + "\t-t\tdisplay info in terse form\n" \ | |
31432 | + USAGE_STAT_FORMAT( \ | |
31433 | + "\nValid format sequences for files:\n" \ | |
31434 | + " %a Access rights in octal\n" \ | |
31435 | + " %A Access rights in human readable form\n" \ | |
31436 | + " %b Number of blocks allocated (see %B)\n" \ | |
31437 | + " %B The size in bytes of each block reported by %b\n" \ | |
31438 | + " %d Device number in decimal\n" \ | |
31439 | + " %D Device number in hex\n" \ | |
31440 | + " %f Raw mode in hex\n" \ | |
31441 | + " %F File type\n" \ | |
31442 | + " %g Group ID of owner\n" \ | |
31443 | + " %G Group name of owner\n" \ | |
31444 | + " %h Number of hard links\n" \ | |
31445 | + " %i Inode number\n" \ | |
31446 | + " %n File name\n" \ | |
31447 | + " %N Quoted file name with dereference if symbolic link\n" \ | |
31448 | + " %o I/O block size\n" \ | |
31449 | + " %s Total size, in bytes\n" \ | |
31450 | + " %t Major device type in hex\n" \ | |
31451 | + " %T Minor device type in hex\n" \ | |
31452 | + " %u User ID of owner\n" \ | |
31453 | + " %U User name of owner\n" \ | |
31454 | + " %x Time of last access\n" \ | |
31455 | + " %X Time of last access as seconds since Epoch\n" \ | |
31456 | + " %y Time of last modification\n" \ | |
31457 | + " %Y Time of last modification as seconds since Epoch\n" \ | |
31458 | + " %z Time of last change\n" \ | |
31459 | + " %Z Time of last change as seconds since Epoch\n" \ | |
31460 | + "\nValid format sequences for file systems:\n" \ | |
31461 | + " %a Free blocks available to non-superuser\n" \ | |
31462 | + " %b Total data blocks in file system\n" \ | |
31463 | + " %c Total file nodes in file system\n" \ | |
31464 | + " %d Free file nodes in file system\n" \ | |
31465 | + " %f Free blocks in file system\n" \ | |
31466 | + " %i File System ID in hex\n" \ | |
31467 | + " %l Maximum length of filenames\n" \ | |
31468 | + " %n File name\n" \ | |
31469 | + " %s Block size (for faster transfers)\n" \ | |
31470 | + " %S Fundamental block size (for block counts)\n" \ | |
31471 | + " %t Type in hex\n" \ | |
31472 | + " %T Type in human readable form\n" \ | |
31473 | + ) | |
31474 | + | |
31475 | #define strings_trivial_usage \ | |
31476 | "[-afo] [-n length] [file ... ]" | |
31477 | #define strings_full_usage \ | |
31478 | "Display printable strings in a binary file." \ | |
31479 | "\n\nOptions:" \ | |
31480 | - "\n\t-a\tScan the whole files (this is the default)."\ | |
31481 | + "\n\t-a\tScan the whole files (this is the default)." \ | |
31482 | "\n\t-f\tPrecede each string with the name of the file where it was found." \ | |
31483 | "\n\t-n N\tSpecifies that at least N characters forms a sequence (default 4)" \ | |
31484 | - "\n\t-o\tEach string is preceded by its decimal offset in the file." | |
31485 | + "\n\t-o\tEach string is preceded by its decimal offset in the file" | |
31486 | ||
31487 | #define stty_trivial_usage \ | |
31488 | "[-a|g] [-F DEVICE] [SETTING]..." | |
31489 | @@ -2263,8 +2461,16 @@ | |
31490 | "Single user login\n" \ | |
31491 | "Options:\n" \ | |
31492 | "\t-f\tDo not authenticate (user already authenticated)\n" \ | |
31493 | - "\t-h\tName of the remote host for this login.\n" \ | |
31494 | - "\t-p\tPreserve environment." | |
31495 | + "\t-h\tName of the remote host for this login\n" \ | |
31496 | + "\t-p\tPreserve environment" | |
31497 | + | |
31498 | +#define sum_trivial_usage \ | |
31499 | + "[rs] [files...]" | |
31500 | +#define sum_full_usage \ | |
31501 | + "checksum and count the blocks in a file\n\n" \ | |
31502 | + "Options:\n" \ | |
31503 | + "\t-r\tuse BSD sum algorithm (1K blocks)\n" \ | |
31504 | + "\t-s\tuse System V sum algorithm (512byte blocks)" | |
31505 | ||
31506 | #define swapoff_trivial_usage \ | |
31507 | "[OPTION] [DEVICE]" | |
31508 | @@ -2287,32 +2493,32 @@ | |
31509 | ||
31510 | ||
31511 | #ifdef CONFIG_FEATURE_ROTATE_LOGFILE | |
31512 | - #define USAGE_ROTATE_LOGFILE(a) a | |
31513 | +# define USAGE_ROTATE_LOGFILE(a) a | |
31514 | #else | |
31515 | - #define USAGE_ROTATE_LOGFILE(a) | |
31516 | +# define USAGE_ROTATE_LOGFILE(a) | |
31517 | #endif | |
31518 | #ifdef CONFIG_FEATURE_REMOTE_LOG | |
31519 | - #define USAGE_REMOTE_LOG(a) a | |
31520 | +# define USAGE_REMOTE_LOG(a) a | |
31521 | #else | |
31522 | - #define USAGE_REMOTE_LOG(a) | |
31523 | +# define USAGE_REMOTE_LOG(a) | |
31524 | #endif | |
31525 | #ifdef CONFIG_FEATURE_IPC_SYSLOG | |
31526 | - #define USAGE_IPC_LOG(a) a | |
31527 | +# define USAGE_IPC_LOG(a) a | |
31528 | #else | |
31529 | - #define USAGE_IPC_LOG(a) | |
31530 | +# define USAGE_IPC_LOG(a) | |
31531 | #endif | |
31532 | ||
31533 | #ifdef CONFIG_SYSCTL | |
31534 | #define sysctl_trivial_usage \ | |
31535 | - "[OPTIONS]... [VALUE]...\n" | |
31536 | + "[OPTIONS]... [VALUE]..." | |
31537 | #define sysctl_full_usage | |
31538 | "sysctl - configure kernel parameters at runtime\n\n" \ | |
31539 | "Options:\n" \ | |
31540 | - "\t-n\tUse this option to disable printing of the key name when printing values.\n" \ | |
31541 | - "\t-w\tUse this option when you want to change a sysctl setting.\n" \ | |
31542 | - "\t-p\tLoad in sysctl settings from the file specified or /etc/sysctl.conf if none given.\n" \ | |
31543 | - "\t-a\tDisplay all values currently available.\n" \ | |
31544 | - "\t-A\tDisplay all values currently available in table form." | |
31545 | + "\t-n\tUse this option to disable printing of the key name when printing values\n" \ | |
31546 | + "\t-w\tUse this option when you want to change a sysctl setting\n" \ | |
31547 | + "\t-p\tLoad in sysctl settings from the file specified or /etc/sysctl.conf if none given\n" \ | |
31548 | + "\t-a\tDisplay all values currently available\n" \ | |
31549 | + "\t-A\tDisplay all values currently available in table form" | |
31550 | #define sysctl_example_usage | |
31551 | "sysctl [-n] variable ...\n" \ | |
31552 | "sysctl [-n] -w variable=value ...\n" \ | |
31553 | @@ -2345,9 +2551,9 @@ | |
31554 | ||
31555 | ||
31556 | #ifndef CONFIG_FEATURE_FANCY_TAIL | |
31557 | - #define USAGE_UNSIMPLE_TAIL(a) | |
31558 | +# define USAGE_UNSIMPLE_TAIL(a) | |
31559 | #else | |
31560 | - #define USAGE_UNSIMPLE_TAIL(a) a | |
31561 | +# define USAGE_UNSIMPLE_TAIL(a) a | |
31562 | #endif | |
31563 | #define tail_trivial_usage \ | |
31564 | "[OPTION]... [FILE]..." | |
31565 | @@ -2370,29 +2576,29 @@ | |
31566 | "nameserver 10.0.0.1\n" | |
31567 | ||
31568 | #ifdef CONFIG_FEATURE_TAR_CREATE | |
31569 | - #define USAGE_TAR_CREATE(a) a | |
31570 | +# define USAGE_TAR_CREATE(a) a | |
31571 | #else | |
31572 | - #define USAGE_TAR_CREATE(a) | |
31573 | +# define USAGE_TAR_CREATE(a) | |
31574 | #endif | |
31575 | #ifdef CONFIG_FEATURE_TAR_EXCLUDE | |
31576 | - #define USAGE_TAR_EXCLUDE(a) a | |
31577 | +# define USAGE_TAR_EXCLUDE(a) a | |
31578 | #else | |
31579 | - #define USAGE_TAR_EXCLUDE(a) | |
31580 | +# define USAGE_TAR_EXCLUDE(a) | |
31581 | #endif | |
31582 | #ifdef CONFIG_FEATURE_TAR_GZIP | |
31583 | - #define USAGE_TAR_GZIP(a) a | |
31584 | +# define USAGE_TAR_GZIP(a) a | |
31585 | #else | |
31586 | - #define USAGE_TAR_GZIP(a) | |
31587 | +# define USAGE_TAR_GZIP(a) | |
31588 | #endif | |
31589 | #ifdef CONFIG_FEATURE_TAR_BZIP2 | |
31590 | - #define USAGE_TAR_BZIP2(a) a | |
31591 | +# define USAGE_TAR_BZIP2(a) a | |
31592 | #else | |
31593 | - #define USAGE_TAR_BZIP2(a) | |
31594 | +# define USAGE_TAR_BZIP2(a) | |
31595 | #endif | |
31596 | #ifdef CONFIG_FEATURE_TAR_COMPRESS | |
31597 | - #define USAGE_TAR_COMPRESS(a) a | |
31598 | +# define USAGE_TAR_COMPRESS(a) a | |
31599 | #else | |
31600 | - #define USAGE_TAR_COMPRESS(a) | |
31601 | +# define USAGE_TAR_COMPRESS(a) | |
31602 | #endif | |
31603 | ||
31604 | #define tar_trivial_usage \ | |
31605 | @@ -2430,7 +2636,7 @@ | |
31606 | "\t-a\tappend to the given FILEs, do not overwrite\n" \ | |
31607 | "\t-i\tignore interrupt signals (SIGINT)" | |
31608 | #define tee_example_usage \ | |
31609 | - "$ echo "Hello" | tee /tmp/foo\n" \ | |
31610 | + "$ echo \"Hello\" | tee /tmp/foo\n" \ | |
31611 | "$ cat /tmp/foo\n" \ | |
31612 | "Hello\n" | |
31613 | ||
31614 | @@ -2441,17 +2647,17 @@ | |
31615 | "Telnet is used to establish interactive communication with another\n" \ | |
31616 | "computer over a network using the TELNET protocol.\n\n" \ | |
31617 | "Options:\n" \ | |
31618 | - "\t-a\t\tAttempt an automatic login with the USER variable.\n" \ | |
31619 | - "\t-l USER\t\tAttempt an automatic login with the USER argument.\n" \ | |
31620 | + "\t-a\t\tAttempt an automatic login with the USER variable\n" \ | |
31621 | + "\t-l USER\t\tAttempt an automatic login with the USER argument\n" \ | |
31622 | "\tHOST\t\tThe official name, alias or the IP address of the\n" \ | |
31623 | "\t\t\tremote host.\n" \ | |
31624 | - "\tPORT\t\tThe remote port number to connect to. If it is not\n" \ | |
31625 | + "\tPORT\t\tThe remote port number to connect to. If it is not\n" \ | |
31626 | "\t\t\tspecified, the default telnet (23) port is used." | |
31627 | #else | |
31628 | #define telnet_trivial_usage \ | |
31629 | "HOST [PORT]" | |
31630 | #define telnet_full_usage \ | |
31631 | - "Telnet is used to establish interactive communication with another\n"\ | |
31632 | + "Telnet is used to establish interactive communication with another\n" \ | |
31633 | "computer over a network using the TELNET protocol." | |
31634 | #endif | |
31635 | ||
31636 | @@ -2459,19 +2665,19 @@ | |
31637 | #define telnetd_trivial_usage \ | |
31638 | "(inetd mode) [OPTION]" | |
31639 | #define telnetd_full_usage \ | |
31640 | - "Telnetd uses incoming TELNET connections via inetd.\n"\ | |
31641 | + "Telnetd uses incoming TELNET connections via inetd.\n" \ | |
31642 | "Options:\n" \ | |
31643 | "\t-l LOGIN\texec LOGIN on connect (default /bin/sh)\n" \ | |
31644 | - "\t-f issue_file\tDisplay issue_file instead of /etc/issue." | |
31645 | + "\t-f issue_file\tDisplay issue_file instead of /etc/issue" | |
31646 | #else | |
31647 | #define telnetd_trivial_usage \ | |
31648 | "[OPTION]" | |
31649 | #define telnetd_full_usage \ | |
31650 | - "Telnetd listens for incoming TELNET connections on PORT.\n"\ | |
31651 | + "Telnetd listens for incoming TELNET connections on PORT.\n" \ | |
31652 | "Options:\n" \ | |
31653 | - "\t-p PORT\tlisten for connections on PORT (default 23)\n"\ | |
31654 | - "\t-l LOGIN\texec LOGIN on connect (default /bin/sh)\n"\ | |
31655 | - "\t-f issue_file\tDisplay issue_file instead of /etc/issue." | |
31656 | + "\t-p PORT\tlisten for connections on PORT (default 23)\n" \ | |
31657 | + "\t-l LOGIN\texec LOGIN on connect (default /bin/sh)\n" \ | |
31658 | + "\t-f issue_file\tDisplay issue_file instead of /etc/issue" | |
31659 | #endif | |
31660 | ||
31661 | #define test_trivial_usage \ | |
31662 | @@ -2494,19 +2700,19 @@ | |
31663 | "1\n" | |
31664 | ||
31665 | #ifdef CONFIG_FEATURE_TFTP_GET | |
31666 | - #define USAGE_TFTP_GET(a) a | |
31667 | +# define USAGE_TFTP_GET(a) a | |
31668 | #else | |
31669 | - #define USAGE_TFTP_GET(a) | |
31670 | +# define USAGE_TFTP_GET(a) | |
31671 | #endif | |
31672 | #ifdef CONFIG_FEATURE_TFTP_PUT | |
31673 | - #define USAGE_TFTP_PUT(a) a | |
31674 | +# define USAGE_TFTP_PUT(a) a | |
31675 | #else | |
31676 | - #define USAGE_TFTP_PUT(a) | |
31677 | +# define USAGE_TFTP_PUT(a) | |
31678 | #endif | |
31679 | #ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE | |
31680 | - #define USAGE_TFTP_BS(a) a | |
31681 | +# define USAGE_TFTP_BS(a) a | |
31682 | #else | |
31683 | - #define USAGE_TFTP_BS(a) | |
31684 | +# define USAGE_TFTP_BS(a) | |
31685 | #endif | |
31686 | ||
31687 | #define tftp_trivial_usage \ | |
31688 | @@ -2514,16 +2720,16 @@ | |
31689 | #define tftp_full_usage \ | |
31690 | "Transfers a file from/to a tftp server using \"octet\" mode.\n\n" \ | |
31691 | "Options:\n" \ | |
31692 | - "\t-l FILE\tLocal FILE.\n" \ | |
31693 | - "\t-r FILE\tRemote FILE." \ | |
31694 | - USAGE_TFTP_GET( \ | |
31695 | - "\n\t-g\tGet file." \ | |
31696 | - ) \ | |
31697 | - USAGE_TFTP_PUT( \ | |
31698 | - "\n\t-p\tPut file." \ | |
31699 | + "\t-l FILE\tLocal FILE\n" \ | |
31700 | + "\t-r FILE\tRemote FILE" \ | |
31701 | + USAGE_TFTP_GET( \ | |
31702 | + "\n\t-g\tGet file" \ | |
31703 | + ) \ | |
31704 | + USAGE_TFTP_PUT( \ | |
31705 | + "\n\t-p\tPut file" \ | |
31706 | ) \ | |
31707 | USAGE_TFTP_BS( \ | |
31708 | - "\n\t-b SIZE\tTransfer blocks of SIZE octets." \ | |
31709 | + "\n\t-b SIZE\tTransfer blocks of SIZE octets" \ | |
31710 | ) | |
31711 | #define time_trivial_usage \ | |
31712 | "[OPTION]... COMMAND [ARGS...]" | |
31713 | @@ -2531,7 +2737,7 @@ | |
31714 | "Runs the program COMMAND with arguments ARGS. When COMMAND finishes,\n" \ | |
31715 | "COMMAND's resource usage information is displayed\n\n" \ | |
31716 | "Options:\n" \ | |
31717 | - "\t-v\tDisplays verbose resource usage information." | |
31718 | + "\t-v\tDisplays verbose resource usage information" | |
31719 | ||
31720 | #define top_trivial_usage \ | |
31721 | "[-d <seconds>]" | |
31722 | @@ -2565,11 +2771,11 @@ | |
31723 | "\t-d\tdelete input characters coded STRING1\n" \ | |
31724 | "\t-s\tsqueeze multiple output characters of STRING2 into one character" | |
31725 | #define tr_example_usage \ | |
31726 | - "$ echo "gdkkn vnqkc" | tr [a-y] [b-z]\n" \ | |
31727 | + "$ echo \"gdkkn vnqkc\" | tr [a-y] [b-z]\n" \ | |
31728 | "hello world\n" | |
31729 | ||
31730 | #define traceroute_trivial_usage \ | |
31731 | - "[-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n"\ | |
31732 | + "[-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n" \ | |
31733 | "\t[-s src_addr] [-t tos] [-w wait] host [data size]" | |
31734 | #define traceroute_full_usage \ | |
31735 | "trace the route ip packets follow going to \"host\"\n" \ | |
31736 | @@ -2587,7 +2793,7 @@ | |
31737 | "\t-t tos\tSet the type-of-service in probe packets to the following value\n" \ | |
31738 | "\t\t(default 0)\n" \ | |
31739 | "\t-w wait\tSet the time (in seconds) to wait for a response to a probe\n" \ | |
31740 | - "\t\t(default 3 sec.)." | |
31741 | + "\t\t(default 3 sec.)" | |
31742 | ||
31743 | ||
31744 | #define true_trivial_usage \ | |
31745 | @@ -2602,7 +2808,7 @@ | |
31746 | #define tty_trivial_usage \ | |
31747 | "" | |
31748 | #define tty_full_usage \ | |
31749 | - "Print the file name of the terminal connected to standard input.\n\n"\ | |
31750 | + "Print the file name of the terminal connected to standard input.\n\n" \ | |
31751 | "Options:\n" \ | |
31752 | "\t-s\tprint nothing, only return an exit status" | |
31753 | #define tty_example_usage \ | |
31754 | @@ -2616,9 +2822,9 @@ | |
31755 | "\t-H,\t--hostname=HOSTNAME\tClient hostname\n" \ | |
31756 | "\t-h,\t \tAlias for -H\n" \ | |
31757 | "\t-f,\t--foreground\tDo not fork after getting lease\n" \ | |
31758 | - "\t-b,\t--background\tFork to background if lease cannot be immediately negotiated.\n" \ | |
31759 | + "\t-b,\t--background\tFork to background if lease cannot be immediately negotiated\n" \ | |
31760 | "\t-i,\t--interface=INTERFACE\tInterface to use (default: eth0)\n" \ | |
31761 | - "\t-n,\t--now\tExit with failure if lease cannot be immediately negotiated.\n" \ | |
31762 | + "\t-n,\t--now\tExit with failure if lease cannot be immediately negotiated\n" \ | |
31763 | "\t-p,\t--pidfile=file\tStore process ID of daemon in file\n" \ | |
31764 | "\t-q,\t--quit\tQuit after obtaining lease\n" \ | |
31765 | "\t-r,\t--request=IP\tIP address to request (default: none)\n" \ | |
31766 | @@ -2632,9 +2838,9 @@ | |
31767 | "" | |
31768 | ||
31769 | #ifdef CONFIG_FEATURE_MOUNT_FORCE | |
31770 | - #define USAGE_MOUNT_FORCE(a) a | |
31771 | +# define USAGE_MOUNT_FORCE(a) a | |
31772 | #else | |
31773 | - #define USAGE_MOUNT_FORCE(a) | |
31774 | +# define USAGE_MOUNT_FORCE(a) | |
31775 | #endif | |
31776 | #define umount_trivial_usage \ | |
31777 | "[flags] FILESYSTEM|DIRECTORY" | |
31778 | @@ -2769,7 +2975,7 @@ | |
31779 | #define vi_full_usage \ | |
31780 | "edit FILE.\n\n" \ | |
31781 | "Options:\n" \ | |
31782 | - "\t-R\tRead-only- do not write to the file." | |
31783 | + "\t-R\tRead-only- do not write to the file" | |
31784 | ||
31785 | #define vlock_trivial_usage \ | |
31786 | "[OPTIONS]" | |
31787 | @@ -2783,7 +2989,7 @@ | |
31788 | #define watch_full_usage \ | |
31789 | "Executes a program periodically.\n" \ | |
31790 | "Options:\n" \ | |
31791 | - "\t-n\tLoop period in seconds - default is 2." | |
31792 | + "\t-n\tLoop period in seconds - default is 2" | |
31793 | #define watch_example_usage \ | |
31794 | "$ watch date\n" \ | |
31795 | "Mon Dec 17 10:31:40 GMT 2000\n" \ | |
31796 | @@ -2795,7 +3001,7 @@ | |
31797 | #define watchdog_full_usage \ | |
31798 | "Periodically write to watchdog device DEV.\n" \ | |
31799 | "Options:\n" \ | |
31800 | - "\t-t\tTimer period in seconds - default is 30." | |
31801 | + "\t-t\tTimer period in seconds - default is 30" | |
31802 | ||
31803 | #define wc_trivial_usage \ | |
31804 | "[OPTION]... [FILE]..." | |
31805 | @@ -2832,9 +3038,9 @@ | |
31806 | "/bin/login\n" | |
31807 | ||
31808 | #define who_trivial_usage \ | |
31809 | - " " | |
31810 | + " " | |
31811 | #define who_full_usage \ | |
31812 | - "Prints the current user names and related information" | |
31813 | + "Prints the current user names and related information" | |
31814 | ||
31815 | #define whoami_trivial_usage \ | |
31816 | "" | |
31817 | @@ -2867,7 +3073,7 @@ | |
31818 | "\t-r\tDo not run command for empty readed lines\n" \ | |
31819 | USAGE_XARGS_TERMOPT("\t-x\tExit if the size is exceeded\n") \ | |
31820 | USAGE_XARGS_ZERO_TERM("\t-0\tInput filenames are terminated by a null character\n") \ | |
31821 | - "\t-t\tPrint the command line on stderr before executing it." | |
31822 | + "\t-t\tPrint the command line on stderr before executing it" | |
31823 | #define xargs_example_usage \ | |
31824 | "$ ls | xargs gzip\n" \ | |
31825 | "$ find . -name '*.c' -print | xargs rm\n" | |
31826 | @@ -2882,4 +3088,14 @@ | |
31827 | #define zcat_full_usage \ | |
31828 | "Uncompress to stdout." | |
31829 | ||
31830 | +#define zcip_trivial_usage \ | |
31831 | + "[OPTIONS] ifname script" | |
31832 | +#define zcip_full_usage \ | |
31833 | + "zcip manages a ZeroConf IPv4 link-local address.\n" \ | |
31834 | + "Options:\n" \ | |
31835 | + "\t-f foreground mode\n" \ | |
31836 | + "\t-q quit after address (no daemon)\n" \ | |
31837 | + "\t-r 169.254.x.x request this address first\n" \ | |
31838 | + "\t-v verbose; show version\n" | |
31839 | + | |
31840 | #endif /* __BB_USAGE_H__ */ | |
31841 | diff -Nur busybox-1.00/init/init.c busybox/init/init.c | |
31842 | --- busybox-1.00/init/init.c 2004-10-08 10:21:54.000000000 +0200 | |
31843 | +++ busybox/init/init.c 2005-06-04 08:20:20.000000000 +0200 | |
31844 | @@ -453,6 +453,7 @@ | |
31845 | signal(SIGINT, SIG_DFL); | |
31846 | signal(SIGTERM, SIG_DFL); | |
31847 | signal(SIGHUP, SIG_DFL); | |
31848 | + signal(SIGQUIT, SIG_DFL); | |
31849 | signal(SIGCONT, SIG_DFL); | |
31850 | signal(SIGSTOP, SIG_DFL); | |
31851 | signal(SIGTSTP, SIG_DFL); | |
31852 | @@ -693,6 +694,7 @@ | |
31853 | /* first disable all our signals */ | |
31854 | sigemptyset(&block_signals); | |
31855 | sigaddset(&block_signals, SIGHUP); | |
31856 | + sigaddset(&block_signals, SIGQUIT); | |
31857 | sigaddset(&block_signals, SIGCHLD); | |
31858 | sigaddset(&block_signals, SIGUSR1); | |
31859 | sigaddset(&block_signals, SIGUSR2); | |
31860 | @@ -737,6 +739,7 @@ | |
31861 | /* unblock all signals, blocked in shutdown_system() */ | |
31862 | sigemptyset(&unblock_signals); | |
31863 | sigaddset(&unblock_signals, SIGHUP); | |
31864 | + sigaddset(&unblock_signals, SIGQUIT); | |
31865 | sigaddset(&unblock_signals, SIGCHLD); | |
31866 | sigaddset(&unblock_signals, SIGUSR1); | |
31867 | sigaddset(&unblock_signals, SIGUSR2); | |
31868 | @@ -1097,6 +1100,7 @@ | |
31869 | /* Set up sig handlers -- be sure to | |
31870 | * clear all of these in run() */ | |
31871 | signal(SIGHUP, exec_signal); | |
31872 | + signal(SIGQUIT, exec_signal); | |
31873 | signal(SIGUSR1, halt_signal); | |
31874 | signal(SIGUSR2, halt_signal); | |
31875 | signal(SIGINT, ctrlaltdel_signal); | |
31876 | diff -Nur busybox-1.00/libbb/Makefile.in busybox/libbb/Makefile.in | |
31877 | --- busybox-1.00/libbb/Makefile.in 2004-10-08 09:45:31.000000000 +0200 | |
31878 | +++ busybox/libbb/Makefile.in 2005-06-04 08:20:15.000000000 +0200 | |
31879 | @@ -53,7 +53,7 @@ | |
31880 | LIBBB_MSRC0:=$(srcdir)/messages.c | |
31881 | LIBBB_MOBJ0:=full_version.o \ | |
31882 | memory_exhausted.o invalid_date.o io_error.o \ | |
31883 | - write_error.o name_longer_than_foo.o unknown.o \ | |
31884 | + read_error.o write_error.o name_longer_than_foo.o unknown.o \ | |
31885 | can_not_create_raw_socket.o perm_denied_are_you_root.o \ | |
31886 | shadow_file.o passwd_file.o group_file.o gshadow_file.o nologin_file.o \ | |
31887 | securetty_file.o motd_file.o \ | |
31888 | diff -Nur busybox-1.00/libbb/concat_path_file.c busybox/libbb/concat_path_file.c | |
31889 | --- busybox-1.00/libbb/concat_path_file.c 2004-03-15 09:28:41.000000000 +0100 | |
31890 | +++ busybox/libbb/concat_path_file.c 2005-06-04 08:20:15.000000000 +0200 | |
31891 | @@ -34,11 +34,11 @@ | |
31892 | char *lc; | |
31893 | ||
31894 | if (!path) | |
31895 | - path=""; | |
31896 | + path = ""; | |
31897 | lc = last_char_is(path, '/'); | |
31898 | while (*filename == '/') | |
31899 | filename++; | |
31900 | - bb_xasprintf(&outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename); | |
31901 | + bb_xasprintf(&outbuf, "%s%s%s", path, (lc==NULL ? "/" : ""), filename); | |
31902 | ||
31903 | return outbuf; | |
31904 | } | |
31905 | diff -Nur busybox-1.00/libbb/copy_file.c busybox/libbb/copy_file.c | |
31906 | --- busybox-1.00/libbb/copy_file.c 2004-04-19 14:28:02.000000000 +0200 | |
31907 | +++ busybox/libbb/copy_file.c 2005-06-04 08:20:15.000000000 +0200 | |
31908 | @@ -54,10 +54,11 @@ | |
31909 | } | |
31910 | } else { | |
31911 | if (source_stat.st_dev == dest_stat.st_dev && | |
31912 | - source_stat.st_ino == dest_stat.st_ino) { | |
31913 | - bb_error_msg("`%s' and `%s' are the same file", source, dest); | |
31914 | - return -1; | |
31915 | - } | |
31916 | + source_stat.st_ino == dest_stat.st_ino) | |
31917 | + { | |
31918 | + bb_error_msg("`%s' and `%s' are the same file", source, dest); | |
31919 | + return -1; | |
31920 | + } | |
31921 | dest_exists = 1; | |
31922 | } | |
31923 | ||
31924 | diff -Nur busybox-1.00/libbb/copyfd.c busybox/libbb/copyfd.c | |
31925 | --- busybox-1.00/libbb/copyfd.c 2004-03-15 09:28:41.000000000 +0100 | |
31926 | +++ busybox/libbb/copyfd.c 2005-06-04 08:20:15.000000000 +0200 | |
31927 | @@ -2,7 +2,7 @@ | |
31928 | /* | |
31929 | * Utility routines. | |
31930 | * | |
31931 | - * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | |
31932 | + * Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> | |
31933 | * | |
31934 | * This program is free software; you can redistribute it and/or modify | |
31935 | * it under the terms of the GNU General Public License as published by | |
31936 | @@ -25,6 +25,7 @@ | |
31937 | #include <unistd.h> | |
31938 | ||
31939 | #include "busybox.h" | |
31940 | +#include "libbb.h" | |
31941 | ||
31942 | ||
31943 | #if BUFSIZ < 4096 | |
31944 | @@ -33,46 +34,59 @@ | |
31945 | #endif | |
31946 | ||
31947 | ||
31948 | -/* If size is 0 copy until EOF */ | |
31949 | -static size_t bb_full_fd_action(int src_fd, int dst_fd, const size_t size) | |
31950 | +static size_t bb_full_fd_action(int src_fd, int dst_fd, const size_t size2) | |
31951 | { | |
31952 | - size_t read_total = 0; | |
31953 | - RESERVE_CONFIG_BUFFER(buffer,BUFSIZ); | |
31954 | + int status; | |
31955 | + size_t xread, wrote, total, size = size2; | |
31956 | ||
31957 | - while ((size == 0) || (read_total < size)) { | |
31958 | - size_t read_try; | |
31959 | - ssize_t read_actual; | |
31960 | - | |
31961 | - if ((size == 0) || (size - read_total > BUFSIZ)) { | |
31962 | - read_try = BUFSIZ; | |
31963 | - } else { | |
31964 | - read_try = size - read_total; | |
31965 | - } | |
31966 | + if (src_fd < 0) { | |
31967 | + return -1; | |
31968 | + } | |
31969 | ||
31970 | - read_actual = safe_read(src_fd, buffer, read_try); | |
31971 | - if (read_actual > 0) { | |
31972 | - if ((dst_fd >= 0) && (bb_full_write(dst_fd, buffer, (size_t) read_actual) != read_actual)) { | |
31973 | - bb_perror_msg(bb_msg_write_error); /* match Read error below */ | |
31974 | + if (size == 0) { | |
31975 | + /* If size is 0 copy until EOF */ | |
31976 | + size = ULONG_MAX; | |
31977 | + } | |
31978 | + | |
31979 | + { | |
31980 | + RESERVE_CONFIG_BUFFER(buffer,BUFSIZ); | |
31981 | + total = 0; | |
31982 | + wrote = 0; | |
31983 | + status = -1; | |
31984 | + while (total < size) | |
31985 | + { | |
31986 | + xread = BUFSIZ; | |
31987 | + if (size < (total + BUFSIZ)) | |
31988 | + xread = size - total; | |
31989 | + xread = bb_full_read(src_fd, buffer, xread); | |
31990 | + if (xread > 0) { | |
31991 | + if (dst_fd < 0) { | |
31992 | + /* A -1 dst_fd means we need to fake it... */ | |
31993 | + wrote = xread; | |
31994 | + } else { | |
31995 | + wrote = bb_full_write(dst_fd, buffer, xread); | |
31996 | + } | |
31997 | + if (wrote < xread) { | |
31998 | + bb_perror_msg(bb_msg_write_error); | |
31999 | + break; | |
32000 | + } | |
32001 | + total += wrote; | |
32002 | + } else if (xread < 0) { | |
32003 | + bb_perror_msg(bb_msg_read_error); | |
32004 | + break; | |
32005 | + } else if (xread == 0) { | |
32006 | + /* All done. */ | |
32007 | + status = 0; | |
32008 | break; | |
32009 | } | |
32010 | } | |
32011 | - else if (read_actual == 0) { | |
32012 | - if (size) { | |
32013 | - bb_error_msg("Unable to read all data"); | |
32014 | - } | |
32015 | - break; | |
32016 | - } else { | |
32017 | - /* read_actual < 0 */ | |
32018 | - bb_perror_msg("Read error"); | |
32019 | - break; | |
32020 | - } | |
32021 | - | |
32022 | - read_total += read_actual; | |
32023 | + RELEASE_CONFIG_BUFFER(buffer); | |
32024 | } | |
32025 | ||
32026 | - RELEASE_CONFIG_BUFFER(buffer); | |
32027 | - | |
32028 | - return(read_total); | |
32029 | + if (status == 0 || total) | |
32030 | + return total; | |
32031 | + /* Some sortof error occured */ | |
32032 | + return -1; | |
32033 | } | |
32034 | ||
32035 | ||
32036 | diff -Nur busybox-1.00/libbb/find_pid_by_name.c busybox/libbb/find_pid_by_name.c | |
32037 | --- busybox-1.00/libbb/find_pid_by_name.c 2004-03-15 09:28:42.000000000 +0100 | |
32038 | +++ busybox/libbb/find_pid_by_name.c 2005-06-04 08:20:15.000000000 +0200 | |
32039 | @@ -45,11 +45,8 @@ | |
32040 | procps_status_t * p; | |
32041 | ||
32042 | pidList = xmalloc(sizeof(long)); | |
32043 | -#ifdef CONFIG_SELINUX | |
32044 | - while ((p = procps_scan(0, 0, NULL)) != 0) { | |
32045 | -#else | |
32046 | - while ((p = procps_scan(0)) != 0) { | |
32047 | -#endif | |
32048 | + while ((p = procps_scan(0)) != 0) | |
32049 | + { | |
32050 | if (strncmp(p->short_cmd, pidName, COMM_LEN-1) == 0) { | |
32051 | pidList=xrealloc( pidList, sizeof(long) * (i+2)); | |
32052 | pidList[i++]=p->pid; | |
32053 | diff -Nur busybox-1.00/libbb/get_line_from_file.c busybox/libbb/get_line_from_file.c | |
32054 | --- busybox-1.00/libbb/get_line_from_file.c 2004-03-15 09:28:42.000000000 +0100 | |
32055 | +++ busybox/libbb/get_line_from_file.c 2005-06-04 08:20:15.000000000 +0200 | |
32056 | @@ -44,7 +44,8 @@ | |
32057 | linebuf = xrealloc(linebuf, linebufsz += GROWBY); | |
32058 | } | |
32059 | linebuf[idx++] = (char)ch; | |
32060 | - if (ch == '\n' || ch == '\0') { | |
32061 | + if (!ch) return linebuf; | |
32062 | + if (c<2 && ch == '\n') { | |
32063 | if (c) { | |
32064 | --idx; | |
32065 | } | |
32066 | @@ -71,6 +72,11 @@ | |
32067 | return private_get_line_from_file(file, 1); | |
32068 | } | |
32069 | ||
32070 | +extern char *bb_get_chunk_from_file(FILE *file) | |
32071 | +{ | |
32072 | + return private_get_line_from_file(file, 2); | |
32073 | +} | |
32074 | + | |
32075 | ||
32076 | /* END CODE */ | |
32077 | /* | |
32078 | diff -Nur busybox-1.00/libbb/getopt_ulflags.c busybox/libbb/getopt_ulflags.c | |
32079 | --- busybox-1.00/libbb/getopt_ulflags.c 2004-02-05 14:49:29.000000000 +0100 | |
32080 | +++ busybox/libbb/getopt_ulflags.c 2005-06-04 08:20:15.000000000 +0200 | |
32081 | @@ -26,146 +26,270 @@ | |
32082 | #include <stdlib.h> | |
32083 | #include "libbb.h" | |
32084 | ||
32085 | -/* | |
32086 | -You can set bb_opt_complementaly as string with one or more | |
32087 | -complementaly or incongruously options. | |
32088 | -If sequential founded option haved from this string | |
32089 | -then your incongruously pairs unsets and complementaly make add sets. | |
32090 | -Format: | |
32091 | -one char - option for check, | |
32092 | -chars - complementaly option for add sets. | |
32093 | -- chars - option triggered for unsets. | |
32094 | -~ chars - option incongruously. | |
32095 | -* - option list, called add_to_list(*ptr_from_usaged, optarg) | |
32096 | -: - separator. | |
32097 | -Example: du applet can have options "-s" and "-d size" | |
32098 | -If getopt found -s then -d option flag unset or if found -d then -s unset. | |
32099 | -For this result you must set bb_opt_complementaly = "s-d:d-s". | |
32100 | -Result have last option flag only from called arguments. | |
32101 | -Warning! You can check returned flag, pointer to "d:" argument seted | |
32102 | -to own optarg always. | |
32103 | -Example two: cut applet must only one type of list may be specified, | |
32104 | -and -b, -c and -f incongruously option, overwited option is error also. | |
32105 | -You must set bb_opt_complementaly = "b~cf:c~bf:f~bc". | |
32106 | -If called have more one specified, return value have error flag - | |
32107 | -high bite set (0x80000000UL). | |
32108 | -Example three: grep applet can have one or more "-e pattern" arguments. | |
32109 | -You should use bb_getopt_ulflags() as | |
32110 | -llist_t *paterns; | |
32111 | -bb_opt_complementaly = "e*"; | |
32112 | -bb_getopt_ulflags (argc, argv, "e:", &paterns); | |
32113 | +/* Documentation ! | |
32114 | + | |
32115 | +unsigned long | |
32116 | +bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |
32117 | + | |
32118 | + The command line options must be declared in const char | |
32119 | + *applet_opts as a string of chars, for example: | |
32120 | + | |
32121 | + flags = bb_getopt_ulflags(argc, argv, "rnug"); | |
32122 | + | |
32123 | + If one of the given options is found, a flag value is added to | |
32124 | + the return value (an unsigned long). | |
32125 | + | |
32126 | + The flag value is determined by the position of the char in | |
32127 | + applet_opts string. For example, in the above case: | |
32128 | + | |
32129 | + flags = bb_getopt_ulflags(argc, argv, "rnug"); | |
32130 | + | |
32131 | + "r" will add 1 (bit 1 : 0x01) | |
32132 | + "n" will add 2 (bit 2 : 0x02) | |
32133 | + "u will add 4 (bit 3 : 0x03) | |
32134 | + "g" will add 8 (bit 4 : 0x04) | |
32135 | + | |
32136 | + and so on. You can also look at the return value as a bit | |
32137 | + field and each option sets one of bits. | |
32138 | + | |
32139 | + ":" If one of the options requires an argument, then add a ":" | |
32140 | + after the char in applet_opts and provide a pointer to store | |
32141 | + the argument. For example: | |
32142 | + | |
32143 | + char *pointer_to_arg_for_a; | |
32144 | + char *pointer_to_arg_for_b; | |
32145 | + char *pointer_to_arg_for_c; | |
32146 | + char *pointer_to_arg_for_d; | |
32147 | + | |
32148 | + flags = bb_getopt_ulflags(argc, argv, "a:b:c:d:", | |
32149 | + &pointer_to_arg_for_a, &pointer_to_arg_for_b, | |
32150 | + &pointer_to_arg_for_c, &pointer_to_arg_for_d); | |
32151 | + | |
32152 | + The type of the pointer (char* or llist_t *) may be controlled | |
32153 | + by the "*" special character that is set in the external string | |
32154 | + bb_opt_complementaly (see below for more info). | |
32155 | + | |
32156 | +static const struct option bb_default_long_options[] | |
32157 | + | |
32158 | + This struct allows you to define long options. The syntax for | |
32159 | + declaring the array is just like that of getopt's longopts. | |
32160 | + | |
32161 | + static const struct option applet_long_options[] = { | |
32162 | + { "verbose", 0, 0, "v" }, | |
32163 | + { 0, 0, 0, 0 } | |
32164 | + }; | |
32165 | + bb_applet_long_options = applet_long_options; | |
32166 | + | |
32167 | + The first parameter is the long option name that you would pass | |
32168 | + to the applet (without the dashes). | |
32169 | + | |
32170 | + The second field determines whether the option has an argument. | |
32171 | + You can set this to 0, 1, or 2, or you can use the long named | |
32172 | + defines of no_argument, required_argument, and optional_argument. | |
32173 | + | |
32174 | + The third argument is used only when the long option does not | |
32175 | + have a corresponding short option. In that case, it should be | |
32176 | + an integer pointer. Otherwise (and normally), it should just | |
32177 | + bet set to NULL. | |
32178 | + | |
32179 | + The last argument is the corresponding short option (if there | |
32180 | + is one of course). | |
32181 | + | |
32182 | + Note: a good applet will make long options configurable via the | |
32183 | + config process and not a required feature. The current standard | |
32184 | + is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS. | |
32185 | + | |
32186 | +const char *bb_opt_complementaly | |
32187 | + | |
32188 | + ":" The colon (":") is used to separate groups of two or more chars | |
32189 | + and/or groups of chars and special characters (stating some | |
32190 | + conditions to be checked). | |
32191 | + | |
32192 | + "abc" If groups of two or more chars are specified, the first char | |
32193 | + is the main option and the other chars are secondary options. | |
32194 | + Their flags will be turned on if the main option is found even | |
32195 | + if they are not specifed on the command line. For example: | |
32196 | + | |
32197 | + bb_opt_complementaly = "abc"; | |
32198 | + | |
32199 | + flags = bb_getopt_ulflags(argc, argv, "abcd") | |
32200 | + | |
32201 | + If getopt() finds "-a" on the command line, then | |
32202 | + bb_getopt_ulflags's return value will be as if "-a -b -c" were | |
32203 | + found. | |
32204 | + | |
32205 | +Special characters: | |
32206 | + | |
32207 | + "-" A dash between two options causes the second of the two | |
32208 | + to be unset (and ignored) if it is given on the command line. | |
32209 | + | |
32210 | + For example: | |
32211 | + The du applet has the options "-s" and "-d depth". If | |
32212 | + bb_getopt_ulflags finds -s, then -d is unset or if it finds -d | |
32213 | + then -s is unset. (Note: busybox implements the GNU | |
32214 | + "--max-depth" option as "-d".) To obtain this behavior, you | |
32215 | + set bb_opt_complementaly = "s-d:d-s". Only one flag value is | |
32216 | + added to bb_getopt_ulflags's return value depending on the | |
32217 | + position of the options on the command line. If one of the | |
32218 | + two options requires an argument pointer (":" in applet_opts | |
32219 | + as in "d:") optarg is set accordingly. | |
32220 | + | |
32221 | + char *smax_print_depth; | |
32222 | + | |
32223 | + bb_opt_complementaly = "s-d:d-s"; | |
32224 | + opt = bb_getopt_ulflags(argc, argv, "sd:", &smax_print_depth); | |
32225 | + | |
32226 | + if (opt & 2) { | |
32227 | + max_print_depth = bb_xgetularg10_bnd(smax_print_depth, | |
32228 | + 0, INT_MAX); | |
32229 | + } | |
32230 | + | |
32231 | + "~" A tilde between two options, or between an option and a group | |
32232 | + of options, means that they are mutually exclusive. Unlike | |
32233 | + the "-" case above, an error will be forced if the options | |
32234 | + are used together. | |
32235 | + | |
32236 | + For example: | |
32237 | + The cut applet must have only one type of list specified, so | |
32238 | + -b, -c and -f are mutally exclusive and should raise an error | |
32239 | + if specified together. In this case you must set | |
32240 | + bb_opt_complementaly = "b~cf:c~bf:f~bc". If two of the | |
32241 | + mutually exclusive options are found, bb_getopt_ulflags's | |
32242 | + return value will have the error flag set (BB_GETOPT_ERROR) so | |
32243 | + that we can check for it: | |
32244 | + | |
32245 | + if (flags & BB_GETOPT_ERROR) | |
32246 | + bb_show_usage(); | |
32247 | + | |
32248 | + "*" A star after a char in bb_opt_complementaly means that the | |
32249 | + option can occur multiple times: | |
32250 | + | |
32251 | + For example: | |
32252 | + The grep applet can have one or more "-e pattern" arguments. | |
32253 | + In this case you should use bb_getopt_ulflags() as follows: | |
32254 | + | |
32255 | + llist_t *patterns = NULL; | |
32256 | + | |
32257 | + (this pointer must be initializated to NULL if the list is empty | |
32258 | + as required by *llist_add_to(llist_t *old_head, char *new_item).) | |
32259 | + | |
32260 | + bb_opt_complementaly = "e*"; | |
32261 | + | |
32262 | + bb_getopt_ulflags(argc, argv, "e:", &patterns); | |
32263 | + $ grep -e user -e root /etc/passwd | |
32264 | + root:x:0:0:root:/root:/bin/bash | |
32265 | + user:x:500:500::/home/user:/bin/bash | |
32266 | + | |
32267 | */ | |
32268 | ||
32269 | const char *bb_opt_complementaly; | |
32270 | ||
32271 | -typedef struct | |
32272 | -{ | |
32273 | +typedef struct { | |
32274 | unsigned char opt; | |
32275 | char list_flg; | |
32276 | unsigned long switch_on; | |
32277 | unsigned long switch_off; | |
32278 | unsigned long incongruously; | |
32279 | - void **optarg; /* char **optarg or llist_t **optarg */ | |
32280 | + void **optarg; /* char **optarg or llist_t **optarg */ | |
32281 | } t_complementaly; | |
32282 | ||
32283 | /* You can set bb_applet_long_options for parse called long options */ | |
32284 | ||
32285 | static const struct option bb_default_long_options[] = { | |
32286 | - /* { "help", 0, NULL, '?' }, */ | |
32287 | +/* { "help", 0, NULL, '?' }, */ | |
32288 | { 0, 0, 0, 0 } | |
32289 | }; | |
32290 | ||
32291 | const struct option *bb_applet_long_options = bb_default_long_options; | |
32292 | ||
32293 | - | |
32294 | unsigned long | |
32295 | bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |
32296 | { | |
32297 | - unsigned long flags = 0; | |
32298 | - t_complementaly complementaly[sizeof(flags) * 8 + 1]; | |
32299 | - int c; | |
32300 | - const unsigned char *s; | |
32301 | - t_complementaly *on_off; | |
32302 | - va_list p; | |
32303 | - | |
32304 | - va_start (p, applet_opts); | |
32305 | - | |
32306 | - /* skip GNU extension */ | |
32307 | - s = applet_opts; | |
32308 | - if(*s == '+' || *s == '-') | |
32309 | - s++; | |
32310 | - | |
32311 | - c = 0; | |
32312 | - on_off = complementaly; | |
32313 | - for (; *s; s++) { | |
32314 | - if(c >= (sizeof(flags)*8)) | |
32315 | - break; | |
32316 | - on_off->opt = *s; | |
32317 | - on_off->switch_on = (1 << c); | |
32318 | - on_off->list_flg = 0; | |
32319 | - on_off->switch_off = 0; | |
32320 | - on_off->incongruously = 0; | |
32321 | - on_off->optarg = NULL; | |
32322 | - if (s[1] == ':') { | |
32323 | - on_off->optarg = va_arg (p, void **); | |
32324 | - do | |
32325 | + unsigned long flags = 0; | |
32326 | + t_complementaly complementaly[sizeof(flags) * 8 + 1]; | |
32327 | + int c; | |
32328 | + const unsigned char *s; | |
32329 | + t_complementaly *on_off; | |
32330 | + va_list p; | |
32331 | + | |
32332 | + va_start (p, applet_opts); | |
32333 | + | |
32334 | + /* skip GNU extension */ | |
32335 | + s = applet_opts; | |
32336 | + if(*s == '+' || *s == '-') | |
32337 | s++; | |
32338 | - while (s[1] == ':'); | |
32339 | + | |
32340 | + c = 0; | |
32341 | + on_off = complementaly; | |
32342 | + for (; *s; s++) { | |
32343 | + if(c >= (sizeof(flags)*8)) | |
32344 | + break; | |
32345 | + on_off->opt = *s; | |
32346 | + on_off->switch_on = (1 << c); | |
32347 | + on_off->list_flg = 0; | |
32348 | + on_off->switch_off = 0; | |
32349 | + on_off->incongruously = 0; | |
32350 | + on_off->optarg = NULL; | |
32351 | + if (s[1] == ':') { | |
32352 | + on_off->optarg = va_arg (p, void **); | |
32353 | + do | |
32354 | + s++; | |
32355 | + while (s[1] == ':'); | |
32356 | + } | |
32357 | + on_off++; | |
32358 | + c++; | |
32359 | } | |
32360 | - on_off++; | |
32361 | - c++; | |
32362 | - } | |
32363 | - on_off->opt = 0; | |
32364 | - c = 0; | |
32365 | - for (s = bb_opt_complementaly; s && *s; s++) { | |
32366 | - t_complementaly *pair; | |
32367 | - | |
32368 | - if (*s == ':') { | |
32369 | - c = 0; | |
32370 | - continue; | |
32371 | - } | |
32372 | - if (c) | |
32373 | - continue; | |
32374 | - for (on_off = complementaly; on_off->opt; on_off++) | |
32375 | - if (on_off->opt == *s) | |
32376 | - break; | |
32377 | - pair = on_off; | |
32378 | - for(s++; *s && *s != ':'; s++) { | |
32379 | - if (*s == '-' || *s == '~') { | |
32380 | - c = *s; | |
32381 | - } else if(*s == '*') { | |
32382 | - pair->list_flg++; | |
32383 | - } else { | |
32384 | - unsigned long *pair_switch = &(pair->switch_on); | |
32385 | - | |
32386 | - if(c) | |
32387 | - pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); | |
32388 | - for (on_off = complementaly; on_off->opt; on_off++) | |
32389 | - if (on_off->opt == *s) { | |
32390 | - *pair_switch |= on_off->switch_on; | |
32391 | - break; | |
32392 | - } | |
32393 | - } | |
32394 | - } | |
32395 | - s--; | |
32396 | - } | |
32397 | - | |
32398 | - while ((c = getopt_long (argc, argv, applet_opts, | |
32399 | - bb_applet_long_options, NULL)) > 0) { | |
32400 | - for (on_off = complementaly; on_off->opt != c; on_off++) { | |
32401 | - if(!on_off->opt) | |
32402 | - bb_show_usage (); | |
32403 | + on_off->opt = 0; | |
32404 | + c = 0; | |
32405 | + for (s = bb_opt_complementaly; s && *s; s++) { | |
32406 | + t_complementaly *pair; | |
32407 | + | |
32408 | + if (*s == ':') { | |
32409 | + c = 0; | |
32410 | + continue; | |
32411 | + } | |
32412 | + if (c) | |
32413 | + continue; | |
32414 | + for (on_off = complementaly; on_off->opt; on_off++) | |
32415 | + if (on_off->opt == *s) | |
32416 | + break; | |
32417 | + pair = on_off; | |
32418 | + for(s++; *s && *s != ':'; s++) { | |
32419 | + if (*s == '-' || *s == '~') { | |
32420 | + c = *s; | |
32421 | + } else if(*s == '*') { | |
32422 | + pair->list_flg++; | |
32423 | + } else { | |
32424 | + unsigned long *pair_switch = &(pair->switch_on); | |
32425 | + if(c) | |
32426 | + pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); | |
32427 | + for (on_off = complementaly; on_off->opt; on_off++) | |
32428 | + if (on_off->opt == *s) { | |
32429 | + *pair_switch |= on_off->switch_on; | |
32430 | + break; | |
32431 | + } | |
32432 | + } | |
32433 | + } | |
32434 | + s--; | |
32435 | } | |
32436 | - if(flags & on_off->incongruously) | |
32437 | - flags |= 0x80000000UL; | |
32438 | - flags &= ~on_off->switch_off; | |
32439 | - flags |= on_off->switch_on; | |
32440 | - if(on_off->list_flg) { | |
32441 | - *(llist_t **)(on_off->optarg) = | |
32442 | - llist_add_to(*(llist_t **)(on_off->optarg), optarg); | |
32443 | - } else if (on_off->optarg) { | |
32444 | - *(char **)(on_off->optarg) = optarg; | |
32445 | + | |
32446 | + while ((c = getopt_long (argc, argv, applet_opts, | |
32447 | + bb_applet_long_options, NULL)) > 0) { | |
32448 | + for (on_off = complementaly; on_off->opt != c; on_off++) { | |
32449 | + if(!on_off->opt) | |
32450 | + bb_show_usage (); | |
32451 | + } | |
32452 | + if(flags & on_off->incongruously) | |
32453 | + flags |= BB_GETOPT_ERROR; | |
32454 | + flags &= ~on_off->switch_off; | |
32455 | + flags |= on_off->switch_on; | |
32456 | + if(on_off->list_flg) { | |
32457 | + *(llist_t **)(on_off->optarg) = | |
32458 | + llist_add_to(*(llist_t **)(on_off->optarg), optarg); | |
32459 | + } else if (on_off->optarg) { | |
32460 | + *(char **)(on_off->optarg) = optarg; | |
32461 | + } | |
32462 | } | |
32463 | - } | |
32464 | - return flags; | |
32465 | + | |
32466 | + return flags; | |
32467 | } | |
32468 | diff -Nur busybox-1.00/libbb/hash_fd.c busybox/libbb/hash_fd.c | |
32469 | --- busybox-1.00/libbb/hash_fd.c 2004-03-15 09:28:42.000000000 +0100 | |
32470 | +++ busybox/libbb/hash_fd.c 2005-06-04 08:20:15.000000000 +0200 | |
32471 | @@ -197,7 +197,7 @@ | |
32472 | static uint32_t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 }; | |
32473 | # endif /* __BYTE_ORDER */ | |
32474 | ||
32475 | -void sha1_end(unsigned char hval[], struct sha1_ctx_t *ctx) | |
32476 | +static void sha1_end(unsigned char hval[], struct sha1_ctx_t *ctx) | |
32477 | { | |
32478 | uint32_t i, cnt = (uint32_t) (ctx->count[0] & SHA1_MASK); | |
32479 | ||
32480 | diff -Nur busybox-1.00/libbb/inet_common.c busybox/libbb/inet_common.c | |
32481 | --- busybox-1.00/libbb/inet_common.c 2004-03-10 08:42:38.000000000 +0100 | |
32482 | +++ busybox/libbb/inet_common.c 2005-06-04 08:20:15.000000000 +0200 | |
32483 | @@ -4,7 +4,7 @@ | |
32484 | * | |
32485 | * Heavily modified by Manuel Novoa III Mar 12, 2001 | |
32486 | * | |
32487 | - * Version: $Id$ | |
32488 | + * Version: $Id$ | |
32489 | * | |
32490 | */ | |
32491 | ||
32492 | diff -Nur busybox-1.00/libbb/interface.c busybox/libbb/interface.c | |
32493 | --- busybox-1.00/libbb/interface.c 2004-08-26 23:45:21.000000000 +0200 | |
32494 | +++ busybox/libbb/interface.c 2005-06-04 08:20:15.000000000 +0200 | |
32495 | @@ -15,7 +15,7 @@ | |
32496 | * that either displays or sets the characteristics of | |
32497 | * one or more of the system's networking interfaces. | |
32498 | * | |
32499 | - * Version: $Id$ | |
32500 | + * Version: $Id$ | |
32501 | * | |
32502 | * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> | |
32503 | * and others. Copyright 1993 MicroWalt Corporation | |
32504 | @@ -888,6 +888,20 @@ | |
32505 | return sfd; | |
32506 | } | |
32507 | ||
32508 | +#ifdef CONFIG_FEATURE_CLEAN_UP | |
32509 | +static void sockets_close(void) | |
32510 | +{ | |
32511 | + struct aftype **aft; | |
32512 | + for (aft = aftypes; *aft != NULL; aft++) { | |
32513 | + struct aftype *af = *aft; | |
32514 | + if( af->fd != -1 ) { | |
32515 | + close(af->fd); | |
32516 | + af->fd = -1; | |
32517 | + } | |
32518 | + } | |
32519 | +} | |
32520 | +#endif | |
32521 | + | |
32522 | /* like strcmp(), but knows about numbers */ | |
32523 | static int nstrcmp(const char *a, const char *b) | |
32524 | { | |
32525 | @@ -986,7 +1000,7 @@ | |
32526 | return err; | |
32527 | } | |
32528 | ||
32529 | -char *get_name(char *name, char *p) | |
32530 | +static char *get_name(char *name, char *p) | |
32531 | { | |
32532 | /* Extract <name>[:<alias>] from nul-terminated p where p matches | |
32533 | <name>[:<alias>]: after leading whitespace. | |
32534 | @@ -1223,17 +1237,13 @@ | |
32535 | } | |
32536 | #endif | |
32537 | ||
32538 | +#ifdef SIOCGIFMAP | |
32539 | strcpy(ifr.ifr_name, ifname); | |
32540 | - if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) | |
32541 | - memset(&ife->map, 0, sizeof(struct ifmap)); | |
32542 | + if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) | |
32543 | + ife->map = ifr.ifr_map; | |
32544 | else | |
32545 | - memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap)); | |
32546 | - | |
32547 | - strcpy(ifr.ifr_name, ifname); | |
32548 | - if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) | |
32549 | +#endif | |
32550 | memset(&ife->map, 0, sizeof(struct ifmap)); | |
32551 | - else | |
32552 | - ife->map = ifr.ifr_map; | |
32553 | ||
32554 | #ifdef HAVE_TXQUEUELEN | |
32555 | strcpy(ifr.ifr_name, ifname); | |
32556 | @@ -1374,7 +1384,7 @@ | |
32557 | #if HAVE_HWETHER | |
32558 | #include <net/if_arp.h> | |
32559 | ||
32560 | -#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 | |
32561 | +#if (__GLIBC__ >=2 && __GLIBC_MINOR >= 1) || defined(_NEWLIB_VERSION) | |
32562 | #include <net/ethernet.h> | |
32563 | #else | |
32564 | #include <linux/if_ether.h> | |
32565 | @@ -2078,6 +2088,8 @@ | |
32566 | ||
32567 | /* Do we have to show the current setup? */ | |
32568 | status = if_print(ifname); | |
32569 | - close(skfd); | |
32570 | +#ifdef CONFIG_FEATURE_CLEAN_UP | |
32571 | + sockets_close(); | |
32572 | +#endif | |
32573 | exit(status < 0); | |
32574 | } | |
32575 | diff -Nur busybox-1.00/libbb/loop.c busybox/libbb/loop.c | |
32576 | --- busybox-1.00/libbb/loop.c 2004-08-16 10:36:28.000000000 +0200 | |
32577 | +++ busybox/libbb/loop.c 2005-06-04 08:20:15.000000000 +0200 | |
32578 | @@ -19,6 +19,10 @@ | |
32579 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
32580 | */ | |
32581 | ||
32582 | +#include <features.h> | |
32583 | +#if defined (__GLIBC__) && !defined(__UCLIBC__) | |
32584 | +#include <linux/posix_types.h> | |
32585 | +#endif | |
32586 | #include <stdio.h> | |
32587 | #include <errno.h> | |
32588 | #include <fcntl.h> | |
32589 | @@ -30,7 +34,6 @@ | |
32590 | /* Grumble... The 2.6.x kernel breaks asm/posix_types.h | |
32591 | * so we get to try and cope as best we can... */ | |
32592 | #include <linux/version.h> | |
32593 | -#include <asm/posix_types.h> | |
32594 | ||
32595 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | |
32596 | #define __bb_kernel_dev_t __kernel_old_dev_t | |
32597 | diff -Nur busybox-1.00/libbb/messages.c busybox/libbb/messages.c | |
32598 | --- busybox-1.00/libbb/messages.c 2004-03-15 09:28:42.000000000 +0100 | |
32599 | +++ busybox/libbb/messages.c 2005-06-04 08:20:15.000000000 +0200 | |
32600 | @@ -36,6 +36,9 @@ | |
32601 | #ifdef L_write_error | |
32602 | const char * const bb_msg_write_error = "Write Error"; | |
32603 | #endif | |
32604 | +#ifdef L_read_error | |
32605 | + const char * const bb_msg_read_error = "Read Error"; | |
32606 | +#endif | |
32607 | #ifdef L_name_longer_than_foo | |
32608 | const char * const bb_msg_name_longer_than_foo = "Names longer than %d chars not supported."; | |
32609 | #endif | |
32610 | diff -Nur busybox-1.00/libbb/procps.c busybox/libbb/procps.c | |
32611 | --- busybox-1.00/libbb/procps.c 2004-08-27 00:18:58.000000000 +0200 | |
32612 | +++ busybox/libbb/procps.c 2005-06-04 08:20:15.000000000 +0200 | |
32613 | @@ -16,11 +16,7 @@ | |
32614 | ||
32615 | #include "libbb.h" | |
32616 | ||
32617 | -extern procps_status_t * procps_scan(int save_user_arg0 | |
32618 | -#ifdef CONFIG_SELINUX | |
32619 | - , int use_selinux , security_id_t *sid | |
32620 | -#endif | |
32621 | - ) | |
32622 | +extern procps_status_t * procps_scan(int save_user_arg0) | |
32623 | { | |
32624 | static DIR *dir; | |
32625 | struct dirent *entry; | |
32626 | @@ -60,16 +56,9 @@ | |
32627 | my_getpwuid(curstatus.user, sb.st_uid, sizeof(curstatus.user)); | |
32628 | ||
32629 | sprintf(status, "/proc/%d/stat", pid); | |
32630 | + | |
32631 | if((fp = fopen(status, "r")) == NULL) | |
32632 | continue; | |
32633 | -#ifdef CONFIG_SELINUX | |
32634 | - if(use_selinux) | |
32635 | - { | |
32636 | - if(fstat_secure(fileno(fp), &sb, sid)) | |
32637 | - continue; | |
32638 | - } | |
32639 | - else | |
32640 | -#endif | |
32641 | name = fgets(buf, sizeof(buf), fp); | |
32642 | fclose(fp); | |
32643 | if(name == NULL) | |
32644 | diff -Nur busybox-1.00/libbb/run_shell.c busybox/libbb/run_shell.c | |
32645 | --- busybox-1.00/libbb/run_shell.c 2004-03-15 09:28:43.000000000 +0100 | |
32646 | +++ busybox/libbb/run_shell.c 2005-06-04 08:20:15.000000000 +0200 | |
32647 | @@ -37,7 +37,33 @@ | |
32648 | #include <ctype.h> | |
32649 | #include "libbb.h" | |
32650 | #ifdef CONFIG_SELINUX | |
32651 | -#include <proc_secure.h> | |
32652 | +#include <selinux/selinux.h> /* for setexeccon */ | |
32653 | +#endif | |
32654 | + | |
32655 | +#ifdef CONFIG_SELINUX | |
32656 | +static security_context_t current_sid=NULL; | |
32657 | + | |
32658 | +void | |
32659 | +renew_current_security_context(void) | |
32660 | +{ | |
32661 | + if (current_sid) | |
32662 | + freecon(current_sid); /* Release old context */ | |
32663 | + | |
32664 | + getcon(¤t_sid); /* update */ | |
32665 | + | |
32666 | + return; | |
32667 | +} | |
32668 | +void | |
32669 | +set_current_security_context(security_context_t sid) | |
32670 | +{ | |
32671 | + if (current_sid) | |
32672 | + freecon(current_sid); /* Release old context */ | |
32673 | + | |
32674 | + current_sid=sid; | |
32675 | + | |
32676 | + return; | |
32677 | +} | |
32678 | + | |
32679 | #endif | |
32680 | ||
32681 | /* Run SHELL, or DEFAULT_SHELL if SHELL is empty. | |
32682 | @@ -45,11 +71,7 @@ | |
32683 | If ADDITIONAL_ARGS is nonzero, pass it to the shell as more | |
32684 | arguments. */ | |
32685 | ||
32686 | -void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args | |
32687 | -#ifdef CONFIG_SELINUX | |
32688 | - , security_id_t sid | |
32689 | -#endif | |
32690 | -) | |
32691 | +void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args) | |
32692 | { | |
32693 | const char **args; | |
32694 | int argno = 1; | |
32695 | @@ -78,10 +100,11 @@ | |
32696 | } | |
32697 | args [argno] = 0; | |
32698 | #ifdef CONFIG_SELINUX | |
32699 | - if(sid) | |
32700 | - execve_secure(shell, (char **) args, environ, sid); | |
32701 | - else | |
32702 | + if ( (current_sid) && (!setexeccon(current_sid)) ) { | |
32703 | + freecon(current_sid); | |
32704 | + execve(shell, (char **) args, environ); | |
32705 | + } else | |
32706 | #endif | |
32707 | - execv ( shell, (char **) args ); | |
32708 | + execv ( shell, (char **) args ); | |
32709 | bb_perror_msg_and_die ( "cannot run %s", shell ); | |
32710 | } | |
32711 | diff -Nur busybox-1.00/libbb/syscalls.c busybox/libbb/syscalls.c | |
32712 | --- busybox-1.00/libbb/syscalls.c 2004-03-15 09:28:43.000000000 +0100 | |
32713 | +++ busybox/libbb/syscalls.c 2005-06-04 08:20:15.000000000 +0200 | |
32714 | @@ -29,7 +29,7 @@ | |
32715 | #include <sys/syscall.h> | |
32716 | #include "libbb.h" | |
32717 | ||
32718 | -int sysfs( int option, unsigned int fs_index, char * buf) | |
32719 | +int sysfs(int option, unsigned int fs_index, char * buf) | |
32720 | { | |
32721 | return(syscall(__NR_sysfs, option, fs_index, buf)); | |
32722 | } | |
32723 | @@ -39,60 +39,59 @@ | |
32724 | #ifndef __NR_pivot_root | |
32725 | #warning This kernel does not support the pivot_root syscall | |
32726 | #warning -> The pivot_root system call is being stubbed out... | |
32727 | - /* BusyBox was compiled against a kernel that did not support | |
32728 | - * the pivot_root system call. To make this application work, | |
32729 | - * you will need to recompile with a kernel supporting the | |
32730 | - * pivot_root system call. | |
32731 | - */ | |
32732 | - bb_error_msg("\n\nTo make this application work, you will need to recompile\n" | |
32733 | - "BusyBox with a kernel supporting the pivot_root system call.\n"); | |
32734 | - errno=ENOSYS; | |
32735 | - return -1; | |
32736 | + /* BusyBox was compiled against a kernel that did not support | |
32737 | + * the pivot_root system call. To make this application work, | |
32738 | + * you will need to recompile with a kernel supporting the | |
32739 | + * pivot_root system call. | |
32740 | + */ | |
32741 | + bb_error_msg("\n\nTo make this application work, you will need to recompile\n" | |
32742 | + "BusyBox with a kernel supporting the pivot_root system call.\n"); | |
32743 | + errno = ENOSYS; | |
32744 | + return -1; | |
32745 | #else | |
32746 | - return(syscall(__NR_pivot_root, new_root, put_old)); | |
32747 | -#endif | |
32748 | + return(syscall(__NR_pivot_root, new_root, put_old)); | |
32749 | +#endif /* __NR_pivot_root */ | |
32750 | } | |
32751 | ||
32752 | ||
32753 | - | |
32754 | -/* These syscalls are not included in ancient glibc versions */ | |
32755 | +/* These syscalls are not included in ancient glibc versions, | |
32756 | + so we have to define them ourselves, whee ! */ | |
32757 | #if ((__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)) | |
32758 | ||
32759 | int bdflush(int func, int data) | |
32760 | { | |
32761 | - return(syscall(__NR_bdflush, func, data)); | |
32762 | + return(syscall(__NR_bdflush, func, data)); | |
32763 | } | |
32764 | ||
32765 | #ifndef __alpha__ | |
32766 | # define __NR_klogctl __NR_syslog | |
32767 | int klogctl(int type, char *b, int len) | |
32768 | { | |
32769 | - return(syscall(__NR_klogctl, type, b, len)); | |
32770 | + return(syscall(__NR_klogctl, type, b, len)); | |
32771 | } | |
32772 | -#endif | |
32773 | +#endif /* __alpha__ */ | |
32774 | ||
32775 | ||
32776 | int umount2(const char * special_file, int flags) | |
32777 | { | |
32778 | -#ifndef __NR_pivot_root | |
32779 | +#ifndef __NR_umount2 | |
32780 | #warning This kernel does not support the umount2 syscall | |
32781 | #warning -> The umount2 system call is being stubbed out... | |
32782 | - /* BusyBox was compiled against a kernel that did not support | |
32783 | - * the umount2 system call. To make this application work, | |
32784 | - * you will need to recompile with a kernel supporting the | |
32785 | - * umount2 system call. | |
32786 | - */ | |
32787 | - bb_error_msg("\n\nTo make this application work, you will need to recompile\n" | |
32788 | - "BusyBox with a kernel supporting the umount2 system call.\n"); | |
32789 | - errno=ENOSYS; | |
32790 | - return -1; | |
32791 | + /* BusyBox was compiled against a kernel that did not support | |
32792 | + * the umount2 system call. To make this application work, | |
32793 | + * you will need to recompile with a kernel supporting the | |
32794 | + * umount2 system call. | |
32795 | + */ | |
32796 | + bb_error_msg("\n\nTo make this application work, you will need to recompile\n" | |
32797 | + "BusyBox with a kernel supporting the umount2 system call.\n"); | |
32798 | + errno = ENOSYS; | |
32799 | + return -1; | |
32800 | #else | |
32801 | - return(syscall(__NR_umount2, special_file, flags)); | |
32802 | -#endif | |
32803 | + return(syscall(__NR_umount2, special_file, flags)); | |
32804 | +#endif /* __NR_pivot_root */ | |
32805 | } | |
32806 | ||
32807 | - | |
32808 | -#endif | |
32809 | +#endif /* old glibc check */ | |
32810 | ||
32811 | ||
32812 | /* END CODE */ | |
32813 | diff -Nur busybox-1.00/loginutils/delgroup.c busybox/loginutils/delgroup.c | |
32814 | --- busybox-1.00/loginutils/delgroup.c 2003-07-14 23:50:51.000000000 +0200 | |
32815 | +++ busybox/loginutils/delgroup.c 2005-06-04 08:20:18.000000000 +0200 | |
32816 | @@ -59,4 +59,4 @@ | |
32817 | return (EXIT_SUCCESS); | |
32818 | } | |
32819 | ||
32820 | -/* $Id$ */ | |
32821 | +/* $Id$ */ | |
32822 | diff -Nur busybox-1.00/loginutils/delline.c busybox/loginutils/delline.c | |
32823 | --- busybox-1.00/loginutils/delline.c 2003-07-14 23:50:51.000000000 +0200 | |
32824 | +++ busybox/loginutils/delline.c 2005-06-04 08:20:18.000000000 +0200 | |
32825 | @@ -110,4 +110,4 @@ | |
32826 | } | |
32827 | ||
32828 | ||
32829 | -/* $Id$ */ | |
32830 | +/* $Id$ */ | |
32831 | diff -Nur busybox-1.00/loginutils/deluser.c busybox/loginutils/deluser.c | |
32832 | --- busybox-1.00/loginutils/deluser.c 2003-07-14 22:20:45.000000000 +0200 | |
32833 | +++ busybox/loginutils/deluser.c 2005-06-04 08:20:18.000000000 +0200 | |
32834 | @@ -65,4 +65,4 @@ | |
32835 | return (EXIT_SUCCESS); | |
32836 | } | |
32837 | ||
32838 | -/* $Id$ */ | |
32839 | +/* $Id$ */ | |
32840 | diff -Nur busybox-1.00/loginutils/getty.c busybox/loginutils/getty.c | |
32841 | --- busybox-1.00/loginutils/getty.c 2004-08-27 00:26:26.000000000 +0200 | |
32842 | +++ busybox/loginutils/getty.c 2005-06-04 08:20:18.000000000 +0200 | |
32843 | @@ -85,7 +85,7 @@ | |
32844 | #define DEF_QUIT CTL('\\') /* default quit char */ | |
32845 | #define DEF_KILL CTL('U') /* default kill char */ | |
32846 | #define DEF_EOF CTL('D') /* default EOF char */ | |
32847 | -#define DEF_EOL 0 | |
32848 | +#define DEF_EOL '\n' | |
32849 | #define DEF_SWITCH 0 /* default switch char */ | |
32850 | ||
32851 | /* | |
32852 | @@ -151,7 +151,7 @@ | |
32853 | ||
32854 | /* Storage for things detected while the login name was read. */ | |
32855 | ||
32856 | -struct chardata { | |
32857 | +static struct chardata { | |
32858 | int erase; /* erase character */ | |
32859 | int kill; /* kill character */ | |
32860 | int eol; /* end-of-line character */ | |
32861 | @@ -161,7 +161,7 @@ | |
32862 | ||
32863 | /* Initial values for the above. */ | |
32864 | ||
32865 | -struct chardata init_chardata = { | |
32866 | +static struct chardata init_chardata = { | |
32867 | DEF_ERASE, /* default erase character */ | |
32868 | DEF_KILL, /* default kill character */ | |
32869 | 13, /* default eol char */ | |
32870 | diff -Nur busybox-1.00/loginutils/login.c busybox/loginutils/login.c | |
32871 | --- busybox-1.00/loginutils/login.c 2004-08-27 00:26:26.000000000 +0200 | |
32872 | +++ busybox/loginutils/login.c 2005-06-04 08:20:18.000000000 +0200 | |
32873 | @@ -17,10 +17,10 @@ | |
32874 | ||
32875 | #include "busybox.h" | |
32876 | #ifdef CONFIG_SELINUX | |
32877 | -#include <flask_util.h> | |
32878 | -#include <get_sid_list.h> | |
32879 | -#include <proc_secure.h> | |
32880 | -#include <fs_secure.h> | |
32881 | +#include <selinux/selinux.h> /* for is_selinux_enabled() */ | |
32882 | +#include <selinux/get_context_list.h> /* for get_default_context() */ | |
32883 | +#include <selinux/flask.h> /* for security class definitions */ | |
32884 | +#include <errno.h> | |
32885 | #endif | |
32886 | ||
32887 | #ifdef CONFIG_FEATURE_U_W_TMP | |
32888 | @@ -28,7 +28,7 @@ | |
32889 | static void checkutmp(int picky); | |
32890 | static void setutmp(const char *name, const char *line); | |
32891 | /* Stuff global to this file */ | |
32892 | -struct utmp utent; | |
32893 | +static struct utmp utent; | |
32894 | #endif | |
32895 | ||
32896 | // login defines | |
32897 | @@ -79,8 +79,7 @@ | |
32898 | char *opt_host = 0; | |
32899 | int alarmstarted = 0; | |
32900 | #ifdef CONFIG_SELINUX | |
32901 | - int flask_enabled = is_flask_enabled(); | |
32902 | - security_id_t sid = 0, old_tty_sid, new_tty_sid; | |
32903 | + security_context_t stat_sid = NULL, sid = NULL, old_tty_sid=NULL, new_tty_sid=NULL; | |
32904 | #endif | |
32905 | ||
32906 | username[0]=0; | |
32907 | @@ -225,41 +224,45 @@ | |
32908 | #ifdef CONFIG_FEATURE_U_W_TMP | |
32909 | setutmp ( username, tty ); | |
32910 | #endif | |
32911 | + | |
32912 | + if ( *tty != '/' ) | |
32913 | + snprintf ( full_tty, sizeof( full_tty ) - 1, "/dev/%s", tty); | |
32914 | + else | |
32915 | + safe_strncpy ( full_tty, tty, sizeof( full_tty ) - 1 ); | |
32916 | + | |
32917 | #ifdef CONFIG_SELINUX | |
32918 | - if (flask_enabled) | |
32919 | + if (is_selinux_enabled()) | |
32920 | { | |
32921 | struct stat st; | |
32922 | + int rc; | |
32923 | ||
32924 | - if (get_default_sid(username, 0, &sid)) | |
32925 | + if (get_default_context(username, NULL, &sid)) | |
32926 | { | |
32927 | fprintf(stderr, "Unable to get SID for %s\n", username); | |
32928 | exit(1); | |
32929 | } | |
32930 | - if (stat_secure(tty, &st, &old_tty_sid)) | |
32931 | + rc = getfilecon(full_tty,&stat_sid); | |
32932 | + freecon(stat_sid); | |
32933 | + if ((rc<0) || (stat(full_tty, &st)<0)) | |
32934 | { | |
32935 | - fprintf(stderr, "stat_secure(%.100s) failed: %.100s\n", tty, strerror(errno)); | |
32936 | + fprintf(stderr, "stat_secure(%.100s) failed: %.100s\n", full_tty, strerror(errno)); | |
32937 | return EXIT_FAILURE; | |
32938 | } | |
32939 | - if (security_change_sid (sid, old_tty_sid, SECCLASS_CHR_FILE, &new_tty_sid) != 0) | |
32940 | + if (security_compute_relabel (sid, old_tty_sid, SECCLASS_CHR_FILE, &new_tty_sid) != 0) | |
32941 | { | |
32942 | - fprintf(stderr, "security_change_sid(%.100s) failed: %.100s\n", tty, strerror(errno)); | |
32943 | + fprintf(stderr, "security_change_sid(%.100s) failed: %.100s\n", full_tty, strerror(errno)); | |
32944 | return EXIT_FAILURE; | |
32945 | } | |
32946 | - if(chsid(tty, new_tty_sid) != 0) | |
32947 | + if(setfilecon(full_tty, new_tty_sid) != 0) | |
32948 | { | |
32949 | - fprintf(stderr, "chsid(%.100s, %d) failed: %.100s\n", tty, new_tty_sid, strerror(errno)); | |
32950 | + fprintf(stderr, "chsid(%.100s, %s) failed: %.100s\n", full_tty, new_tty_sid, strerror(errno)); | |
32951 | return EXIT_FAILURE; | |
32952 | } | |
32953 | + freecon(sid); | |
32954 | + freecon(old_tty_sid); | |
32955 | + freecon(new_tty_sid); | |
32956 | } | |
32957 | - else | |
32958 | - sid = 0; | |
32959 | #endif | |
32960 | - | |
32961 | - if ( *tty != '/' ) | |
32962 | - snprintf ( full_tty, sizeof( full_tty ) - 1, "/dev/%s", tty); | |
32963 | - else | |
32964 | - safe_strncpy ( full_tty, tty, sizeof( full_tty ) - 1 ); | |
32965 | - | |
32966 | if ( !is_my_tty ( full_tty )) | |
32967 | syslog ( LOG_ERR, "unable to determine TTY name, got %s\n", full_tty ); | |
32968 | ||
32969 | @@ -279,11 +282,10 @@ | |
32970 | ||
32971 | if ( pw-> pw_uid == 0 ) | |
32972 | syslog ( LOG_INFO, "root login %s\n", fromhost ); | |
32973 | - run_shell ( tmp, 1, 0, 0 | |
32974 | #ifdef CONFIG_SELINUX | |
32975 | - , sid | |
32976 | + set_current_security_context(sid); | |
32977 | #endif | |
32978 | - ); /* exec the shell finally. */ | |
32979 | + run_shell ( tmp, 1, 0, 0); /* exec the shell finally. */ | |
32980 | ||
32981 | return EXIT_FAILURE; | |
32982 | } | |
32983 | @@ -387,7 +389,7 @@ | |
32984 | } | |
32985 | ||
32986 | ||
32987 | -static void motd ( ) | |
32988 | +static void motd (void) | |
32989 | { | |
32990 | FILE *fp; | |
32991 | register int c; | |
32992 | diff -Nur busybox-1.00/loginutils/passwd.c busybox/loginutils/passwd.c | |
32993 | --- busybox-1.00/loginutils/passwd.c 2004-09-15 04:39:09.000000000 +0200 | |
32994 | +++ busybox/loginutils/passwd.c 2005-06-04 08:20:18.000000000 +0200 | |
32995 | @@ -21,7 +21,7 @@ | |
32996 | static void set_filesize_limit(int blocks); | |
32997 | ||
32998 | ||
32999 | -int get_algo(char *a) | |
33000 | +static int get_algo(char *a) | |
33001 | { | |
33002 | int x = 1; /* standard: MD5 */ | |
33003 | ||
33004 | @@ -31,7 +31,7 @@ | |
33005 | } | |
33006 | ||
33007 | ||
33008 | -extern int update_passwd(const struct passwd *pw, char *crypt_pw) | |
33009 | +static int update_passwd(const struct passwd *pw, char *crypt_pw) | |
33010 | { | |
33011 | char filename[1024]; | |
33012 | char buf[1025]; | |
33013 | diff -Nur busybox-1.00/loginutils/su.c busybox/loginutils/su.c | |
33014 | --- busybox-1.00/loginutils/su.c 2004-03-15 09:28:46.000000000 +0100 | |
33015 | +++ busybox/loginutils/su.c 2005-06-04 08:20:18.000000000 +0200 | |
33016 | @@ -147,11 +147,10 @@ | |
33017 | ||
33018 | change_identity ( pw ); | |
33019 | setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw ); | |
33020 | - run_shell ( opt_shell, opt_loginshell, opt_command, (const char**)opt_args | |
33021 | #ifdef CONFIG_SELINUX | |
33022 | - , 0 | |
33023 | + set_current_security_context(NULL); | |
33024 | #endif | |
33025 | - ); | |
33026 | + run_shell ( opt_shell, opt_loginshell, opt_command, (const char**)opt_args); | |
33027 | ||
33028 | return EXIT_FAILURE; | |
33029 | } | |
33030 | diff -Nur busybox-1.00/loginutils/sulogin.c busybox/loginutils/sulogin.c | |
33031 | --- busybox-1.00/loginutils/sulogin.c 2004-05-01 03:27:30.000000000 +0200 | |
33032 | +++ busybox/loginutils/sulogin.c 2005-06-04 08:20:18.000000000 +0200 | |
33033 | @@ -153,6 +153,12 @@ | |
33034 | puts("Entering System Maintenance Mode\n"); | |
33035 | fflush(stdout); | |
33036 | syslog(LOG_INFO, "System Maintenance Mode\n"); | |
33037 | + | |
33038 | +#ifdef CONFIG_SELINUX | |
33039 | + renew_current_security_context(); | |
33040 | +#endif | |
33041 | + | |
33042 | run_shell(pwent.pw_shell, 1, 0, 0); | |
33043 | + | |
33044 | return (0); | |
33045 | } | |
33046 | diff -Nur busybox-1.00/loginutils/vlock.c busybox/loginutils/vlock.c | |
33047 | --- busybox-1.00/loginutils/vlock.c 2004-05-01 03:27:30.000000000 +0200 | |
33048 | +++ busybox/loginutils/vlock.c 2005-06-04 08:20:18.000000000 +0200 | |
33049 | @@ -51,7 +51,7 @@ | |
33050 | static struct spwd *spw; | |
33051 | ||
33052 | /* getspuid - get a shadow entry by uid */ | |
33053 | -struct spwd *getspuid(uid_t uid) | |
33054 | +static struct spwd *getspuid(uid_t uid) | |
33055 | { | |
33056 | struct spwd *sp; | |
33057 | struct passwd *mypw; | |
33058 | diff -Nur busybox-1.00/miscutils/Config.in busybox/miscutils/Config.in | |
33059 | --- busybox-1.00/miscutils/Config.in 2004-08-27 01:12:59.000000000 +0200 | |
33060 | +++ busybox/miscutils/Config.in 2005-06-04 08:20:16.000000000 +0200 | |
33061 | @@ -83,6 +83,12 @@ | |
33062 | help | |
33063 | Increases logging to stderr or syslog. | |
33064 | ||
33065 | +config CONFIG_EJECT | |
33066 | + bool "eject" | |
33067 | + default n | |
33068 | + help | |
33069 | + Used to eject cdroms. (defaults to /dev/cdrom) | |
33070 | + | |
33071 | config CONFIG_LAST | |
33072 | bool "last" | |
33073 | default n | |
33074 | diff -Nur busybox-1.00/miscutils/Makefile.in busybox/miscutils/Makefile.in | |
33075 | --- busybox-1.00/miscutils/Makefile.in 2004-10-08 09:45:39.000000000 +0200 | |
33076 | +++ busybox/miscutils/Makefile.in 2005-06-04 08:20:16.000000000 +0200 | |
33077 | @@ -24,19 +24,20 @@ | |
33078 | srcdir=$(top_srcdir)/miscutils | |
33079 | ||
33080 | MISCUTILS-y:= | |
33081 | -MISCUTILS-$(CONFIG_ADJTIMEX) += adjtimex.o | |
33082 | -MISCUTILS-$(CONFIG_CROND) += crond.o | |
33083 | -MISCUTILS-$(CONFIG_CRONTAB) += crontab.o | |
33084 | -MISCUTILS-$(CONFIG_DC) += dc.o | |
33085 | -MISCUTILS-$(CONFIG_DEVFSD) += devfsd.o | |
33086 | -MISCUTILS-$(CONFIG_HDPARM) += hdparm.o | |
33087 | -MISCUTILS-$(CONFIG_LAST) += last.o | |
33088 | -MISCUTILS-$(CONFIG_MAKEDEVS) += makedevs.o | |
33089 | -MISCUTILS-$(CONFIG_MT) += mt.o | |
33090 | -MISCUTILS-$(CONFIG_RX) += rx.o | |
33091 | -MISCUTILS-$(CONFIG_STRINGS) += strings.o | |
33092 | -MISCUTILS-$(CONFIG_TIME) += time.o | |
33093 | -MISCUTILS-$(CONFIG_WATCHDOG) += watchdog.o | |
33094 | +MISCUTILS-$(CONFIG_ADJTIMEX) += adjtimex.o | |
33095 | +MISCUTILS-$(CONFIG_CROND) += crond.o | |
33096 | +MISCUTILS-$(CONFIG_CRONTAB) += crontab.o | |
33097 | +MISCUTILS-$(CONFIG_DC) += dc.o | |
33098 | +MISCUTILS-$(CONFIG_DEVFSD) += devfsd.o | |
33099 | +MISCUTILS-$(CONFIG_EJECT) += eject.o | |
33100 | +MISCUTILS-$(CONFIG_HDPARM) += hdparm.o | |
33101 | +MISCUTILS-$(CONFIG_LAST) += last.o | |
33102 | +MISCUTILS-$(CONFIG_MAKEDEVS) += makedevs.o | |
33103 | +MISCUTILS-$(CONFIG_MT) += mt.o | |
33104 | +MISCUTILS-$(CONFIG_RX) += rx.o | |
33105 | +MISCUTILS-$(CONFIG_STRINGS) += strings.o | |
33106 | +MISCUTILS-$(CONFIG_TIME) += time.o | |
33107 | +MISCUTILS-$(CONFIG_WATCHDOG) += watchdog.o | |
33108 | ||
33109 | libraries-y+=$(MISCUTILS_DIR)$(MISCUTILS_AR) | |
33110 | ||
33111 | diff -Nur busybox-1.00/miscutils/eject.c busybox/miscutils/eject.c | |
33112 | --- busybox-1.00/miscutils/eject.c 1970-01-01 01:00:00.000000000 +0100 | |
33113 | +++ busybox/miscutils/eject.c 2005-06-04 08:20:16.000000000 +0200 | |
33114 | @@ -0,0 +1,63 @@ | |
33115 | +/* | |
33116 | + * eject implementation for busybox | |
33117 | + * | |
33118 | + * Copyright (C) 2004 Peter Willis <psyphreak@phreaker.net> | |
33119 | + * | |
33120 | + * This program is free software; you can redistribute it and/or modify | |
33121 | + * it under the terms of the GNU General Public License as published by | |
33122 | + * the Free Software Foundation; either version 2 of the License, or | |
33123 | + * (at your option) any later version. | |
33124 | + * | |
33125 | + * This program is distributed in the hope that it will be useful, | |
33126 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
33127 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
33128 | + * General Public License for more details. | |
33129 | + * | |
33130 | + * You should have received a copy of the GNU General Public License | |
33131 | + * along with this program; if not, write to the Free Software | |
33132 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
33133 | + * | |
33134 | + */ | |
33135 | + | |
33136 | +/* | |
33137 | + * This is a simple hack of eject based on something Erik posted in #uclibc. | |
33138 | + * Most of the dirty work blatantly ripped off from cat.c =) | |
33139 | + */ | |
33140 | + | |
33141 | +#include <fcntl.h> | |
33142 | +#include <sys/ioctl.h> | |
33143 | +#include <unistd.h> | |
33144 | +#include <sys/mount.h> | |
33145 | +#include <mntent.h> | |
33146 | +#include "busybox.h" | |
33147 | + | |
33148 | +/* various defines swiped from linux/cdrom.h */ | |
33149 | +#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */ | |
33150 | +#define CDROMEJECT 0x5309 /* Ejects the cdrom media */ | |
33151 | +#define DEFAULT_CDROM "/dev/cdrom" | |
33152 | + | |
33153 | +extern int eject_main(int argc, char **argv) | |
33154 | +{ | |
33155 | + unsigned long flags; | |
33156 | + char *device; | |
33157 | + struct mntent *m; | |
33158 | + | |
33159 | + flags = bb_getopt_ulflags(argc, argv, "t"); | |
33160 | + device=argv[optind] ? : DEFAULT_CDROM; | |
33161 | + | |
33162 | + if((m = find_mount_point(device, bb_path_mtab_file))) { | |
33163 | + if(umount(m->mnt_dir)) | |
33164 | + bb_error_msg_and_die("Can't umount"); | |
33165 | +#ifdef CONFIG_FEATURE_MTAB_SUPPORT | |
33166 | + else | |
33167 | + erase_mtab(m->mnt_fsname); | |
33168 | +#endif | |
33169 | + } | |
33170 | + if (ioctl(bb_xopen( device, | |
33171 | + (O_RDONLY | O_NONBLOCK)), | |
33172 | + ( flags ? CDROMCLOSETRAY : CDROMEJECT))) | |
33173 | + { | |
33174 | + bb_perror_msg_and_die(device); | |
33175 | + } | |
33176 | + return(EXIT_SUCCESS); | |
33177 | +} | |
33178 | diff -Nur busybox-1.00/miscutils/hdparm.c busybox/miscutils/hdparm.c | |
33179 | --- busybox-1.00/miscutils/hdparm.c 2004-07-21 00:53:59.000000000 +0200 | |
33180 | +++ busybox/miscutils/hdparm.c 2005-06-04 08:20:16.000000000 +0200 | |
33181 | @@ -467,8 +467,8 @@ | |
33182 | ||
33183 | /* Busybox messages and functions */ | |
33184 | ||
33185 | -const char * const bb_msg_shared_mem ="could not %s sharedmem buf"; | |
33186 | -const char * const bb_msg_op_not_supp =" operation not supported on %s disks"; | |
33187 | +static const char * const bb_msg_shared_mem ="could not %s sharedmem buf"; | |
33188 | +static const char * const bb_msg_op_not_supp =" operation not supported on %s disks"; | |
33189 | ||
33190 | static void bb_ioctl(int fd, int request, void *argp, const char *string) | |
33191 | { | |
33192 | diff -Nur busybox-1.00/miscutils/rx.c busybox/miscutils/rx.c | |
33193 | --- busybox-1.00/miscutils/rx.c 2004-03-15 09:28:46.000000000 +0100 | |
33194 | +++ busybox/miscutils/rx.c 2005-06-04 08:20:16.000000000 +0200 | |
33195 | @@ -1,6 +1,6 @@ | |
33196 | /*------------------------------------------------------------------------- | |
33197 | * Filename: xmodem.c | |
33198 | - * Version: $Id$ | |
33199 | + * Version: $Id$ | |
33200 | * Copyright: Copyright (C) 2001, Hewlett-Packard Company | |
33201 | * Author: Christopher Hoover <ch@hpl.hp.com> | |
33202 | * Description: xmodem functionality for uploading of kernels | |
33203 | diff -Nur busybox-1.00/modutils/Config.in busybox/modutils/Config.in | |
33204 | --- busybox-1.00/modutils/Config.in 2004-07-20 08:09:14.000000000 +0200 | |
33205 | +++ busybox/modutils/Config.in 2005-06-04 08:20:10.000000000 +0200 | |
33206 | @@ -21,7 +21,7 @@ | |
33207 | config CONFIG_FEATURE_2_6_MODULES | |
33208 | bool " Support version 2.6.x Linux kernels" | |
33209 | default n | |
33210 | - depends on CONFIG_INSMOD | |
33211 | + depends on CONFIG_INSMOD | |
33212 | help | |
33213 | Support module loading for newer 2.6.x Linux kernels. | |
33214 | ||
33215 | @@ -80,6 +80,14 @@ | |
33216 | help | |
33217 | lsmod is used to display a list of loaded modules. | |
33218 | ||
33219 | +config CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT | |
33220 | + bool " lsmod pretty output for 2.6.x Linux kernels " | |
33221 | + default n | |
33222 | + depends on CONFIG_LSMOD | |
33223 | + help | |
33224 | + This option makes output format of lsmod adjusted to | |
33225 | + the format of module-init-tools for Linux kernel 2.6. | |
33226 | + | |
33227 | config CONFIG_FEATURE_QUERY_MODULE_INTERFACE | |
33228 | bool | |
33229 | default y | |
33230 | diff -Nur busybox-1.00/modutils/insmod.c busybox/modutils/insmod.c | |
33231 | --- busybox-1.00/modutils/insmod.c 2004-09-03 01:03:25.000000000 +0200 | |
33232 | +++ busybox/modutils/insmod.c 2005-06-04 08:20:10.000000000 +0200 | |
33233 | @@ -109,6 +109,14 @@ | |
33234 | #endif | |
33235 | ||
33236 | ||
33237 | +/* Alpha */ | |
33238 | +#if defined(__alpha__) | |
33239 | +#define MATCH_MACHINE(x) (x == EM_ALPHA) | |
33240 | +#define SHT_RELM SHT_RELA | |
33241 | +#define Elf64_RelM Elf64_Rela | |
33242 | +#define ELFCLASSM ELFCLASS64 | |
33243 | +#endif | |
33244 | + | |
33245 | /* ARM support */ | |
33246 | #if defined(__arm__) | |
33247 | #define MATCH_MACHINE(x) (x == EM_ARM) | |
33248 | @@ -135,6 +143,19 @@ | |
33249 | #endif | |
33250 | #endif | |
33251 | ||
33252 | +/* PA-RISC / HP-PA */ | |
33253 | +#if defined(__hppa__) | |
33254 | +#define MATCH_MACHINE(x) (x == EM_PARISC) | |
33255 | +#define SHT_RELM SHT_RELA | |
33256 | +#if defined(__LP64__) | |
33257 | +#define Elf64_RelM Elf64_Rela | |
33258 | +#define ELFCLASSM ELFCLASS64 | |
33259 | +#else | |
33260 | +#define Elf32_RelM Elf32_Rela | |
33261 | +#define ELFCLASSM ELFCLASS32 | |
33262 | +#endif | |
33263 | +#endif | |
33264 | + | |
33265 | /* H8/300 */ | |
33266 | #if defined(__H8300H__) || defined(__H8300S__) | |
33267 | #define MATCH_MACHINE(x) (x == EM_H8_300) | |
33268 | @@ -269,8 +290,8 @@ | |
33269 | /* X86_64 */ | |
33270 | #if defined(__x86_64__) | |
33271 | #define MATCH_MACHINE(x) (x == EM_X86_64) | |
33272 | -#define SHT_RELM SHT_REL | |
33273 | -#define Elf64_RelM Elf64_Rel | |
33274 | +#define SHT_RELM SHT_RELA | |
33275 | +#define Elf64_RelM Elf64_Rela | |
33276 | #define ELFCLASSM ELFCLASS64 | |
33277 | #endif | |
33278 | ||
33279 | @@ -308,7 +329,7 @@ | |
33280 | #ifndef MODUTILS_MODULE_H | |
33281 | static const int MODUTILS_MODULE_H = 1; | |
33282 | ||
33283 | -#ident "$Id$" | |
33284 | +#ident "$Id$" | |
33285 | ||
33286 | /*======================================================================*/ | |
33287 | /* For sizeof() which are related to the module platform and not to the | |
33288 | @@ -466,7 +487,7 @@ | |
33289 | #ifndef MODUTILS_OBJ_H | |
33290 | static const int MODUTILS_OBJ_H = 1; | |
33291 | ||
33292 | -#ident "$Id$" | |
33293 | +#ident "$Id$" | |
33294 | ||
33295 | /* The relocatable object is manipulated using elfin types. */ | |
33296 | ||
33297 | @@ -3432,8 +3453,8 @@ | |
33298 | ".text", | |
33299 | ".rodata", | |
33300 | ".data", | |
33301 | - ".bss" | |
33302 | - ".sbss" | |
33303 | + ".bss", | |
33304 | + ".sbss" | |
33305 | }; | |
33306 | ||
33307 | if (realpath(filename, real)) { | |
33308 | diff -Nur busybox-1.00/modutils/lsmod.c busybox/modutils/lsmod.c | |
33309 | --- busybox-1.00/modutils/lsmod.c 2004-03-15 09:28:47.000000000 +0100 | |
33310 | +++ busybox/modutils/lsmod.c 2005-06-04 08:20:10.000000000 +0200 | |
33311 | @@ -164,10 +164,52 @@ | |
33312 | { | |
33313 | printf("Module Size Used by"); | |
33314 | check_tainted(); | |
33315 | +#if defined(CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT) | |
33316 | + { | |
33317 | + FILE *file; | |
33318 | + char line[4096]; | |
33319 | ||
33320 | + file = fopen("/proc/modules", "r"); | |
33321 | + | |
33322 | + if (!file) | |
33323 | + bb_error_msg_and_die("Opening /proc/modules"); | |
33324 | + | |
33325 | + while (fgets(line, sizeof(line), file)) { | |
33326 | + char *tok; | |
33327 | + | |
33328 | + tok = strtok(line, " \t"); | |
33329 | + printf("%-19s", tok); | |
33330 | + tok = strtok(NULL, " \t\n"); | |
33331 | + printf(" %8s", tok); | |
33332 | + tok = strtok(NULL, " \t\n"); | |
33333 | + /* Null if no module unloading support. */ | |
33334 | + if (tok) { | |
33335 | + printf(" %s", tok); | |
33336 | + tok = strtok(NULL, "\n"); | |
33337 | + if (!tok) | |
33338 | + tok = ""; | |
33339 | + /* New-style has commas, or -. If so, | |
33340 | + truncate (other fields might follow). */ | |
33341 | + else if (strchr(tok, ',')) { | |
33342 | + tok = strtok(tok, "\t "); | |
33343 | + /* Strip trailing comma. */ | |
33344 | + if (tok[strlen(tok)-1] == ',') | |
33345 | + tok[strlen(tok)-1] = '\0'; | |
33346 | + } else if (tok[0] == '-' | |
33347 | + && (tok[1] == '\0' || isspace(tok[1]))) | |
33348 | + tok = ""; | |
33349 | + printf(" %s", tok); | |
33350 | + } | |
33351 | + printf("\n"); | |
33352 | + } | |
33353 | + fclose(file); | |
33354 | + } | |
33355 | + return 0; /* Success */ | |
33356 | +#else | |
33357 | if (bb_xprint_file_by_name("/proc/modules") < 0) { | |
33358 | return 0; | |
33359 | } | |
33360 | +#endif /* CONFIG_FEATURE_2_6_MODULES */ | |
33361 | return 1; | |
33362 | } | |
33363 | ||
33364 | diff -Nur busybox-1.00/modutils/modprobe.c busybox/modutils/modprobe.c | |
33365 | --- busybox-1.00/modutils/modprobe.c 2004-09-24 11:18:55.000000000 +0200 | |
33366 | +++ busybox/modutils/modprobe.c 2005-06-04 08:20:10.000000000 +0200 | |
33367 | @@ -61,7 +61,7 @@ | |
33368 | static int autoclean, show_only, quiet, do_syslog, verbose; | |
33369 | static int k_version; | |
33370 | ||
33371 | -int parse_tag_value ( char *buffer, char **ptag, char **pvalue ) | |
33372 | +static int parse_tag_value ( char *buffer, char **ptag, char **pvalue ) | |
33373 | { | |
33374 | char *tag, *value; | |
33375 | ||
33376 | diff -Nur busybox-1.00/networking/Config.in busybox/networking/Config.in | |
33377 | --- busybox-1.00/networking/Config.in 2004-09-23 22:08:46.000000000 +0200 | |
33378 | +++ busybox/networking/Config.in 2005-06-04 08:20:05.000000000 +0200 | |
33379 | @@ -18,6 +18,19 @@ | |
33380 | help | |
33381 | Ping hosts by ARP packets | |
33382 | ||
33383 | +config CONFIG_ETHER_WAKE | |
33384 | + bool "ether-wake" | |
33385 | + default n | |
33386 | + help | |
33387 | + Send a magic packet to wake up sleeping machines. | |
33388 | + | |
33389 | +config CONFIG_FAKEIDENTD | |
33390 | + bool "fakeidentd" | |
33391 | + default n | |
33392 | + help | |
33393 | + fakeidentd listens to the ident port and returns a set fake | |
33394 | + value whatever it gets. | |
33395 | + | |
33396 | config CONFIG_FTPGET | |
33397 | bool "ftpget" | |
33398 | default n | |
33399 | @@ -415,6 +428,14 @@ | |
33400 | A simple Unix utility which reads and writes data across network | |
33401 | connections. | |
33402 | ||
33403 | +config CONFIG_NC_GAPING_SECURITY_HOLE | |
33404 | + bool "gaping security hole" | |
33405 | + default n | |
33406 | + depends on CONFIG_NC | |
33407 | + help | |
33408 | + Add support for executing a program after making or receiving a | |
33409 | + successful connection (-e option). | |
33410 | + | |
33411 | config CONFIG_NETSTAT | |
33412 | bool "netstat" | |
33413 | default n | |
33414 | @@ -630,5 +651,16 @@ | |
33415 | ||
33416 | source networking/udhcp/Config.in | |
33417 | ||
33418 | +config CONFIG_ZCIP | |
33419 | + bool "zcip" | |
33420 | + default n | |
33421 | + help | |
33422 | + ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927. | |
33423 | + It's a daemon that allocates and defends a dynamically assigned | |
33424 | + address on the 169.254/16 network, requiring no system administrator. | |
33425 | + | |
33426 | + See http://www.zeroconf.org for further details, and "zcip.script" | |
33427 | + in the busybox examples. | |
33428 | + | |
33429 | endmenu | |
33430 | ||
33431 | diff -Nur busybox-1.00/networking/Makefile.in busybox/networking/Makefile.in | |
33432 | --- busybox-1.00/networking/Makefile.in 2004-10-08 09:45:43.000000000 +0200 | |
33433 | +++ busybox/networking/Makefile.in 2005-06-04 08:20:05.000000000 +0200 | |
33434 | @@ -23,33 +23,36 @@ | |
33435 | endif | |
33436 | srcdir=$(top_srcdir)/networking | |
33437 | NETWORKING-y:= | |
33438 | -NETWORKING-$(CONFIG_ARPING) += arping.o | |
33439 | -NETWORKING-$(CONFIG_FTPGET) += ftpgetput.o | |
33440 | -NETWORKING-$(CONFIG_FTPPUT) += ftpgetput.o | |
33441 | -NETWORKING-$(CONFIG_HOSTNAME) += hostname.o | |
33442 | -NETWORKING-$(CONFIG_HTTPD) += httpd.o | |
33443 | -NETWORKING-$(CONFIG_IFCONFIG) += ifconfig.o | |
33444 | -NETWORKING-$(CONFIG_IFUPDOWN) += ifupdown.o | |
33445 | -NETWORKING-$(CONFIG_INETD) += inetd.o | |
33446 | -NETWORKING-$(CONFIG_IP) += ip.o | |
33447 | -NETWORKING-$(CONFIG_IPCALC) += ipcalc.o | |
33448 | -NETWORKING-$(CONFIG_IPADDR) += ipaddr.o | |
33449 | -NETWORKING-$(CONFIG_IPLINK) += iplink.o | |
33450 | -NETWORKING-$(CONFIG_IPROUTE) += iproute.o | |
33451 | -NETWORKING-$(CONFIG_IPTUNNEL) += iptunnel.o | |
33452 | -NETWORKING-$(CONFIG_NAMEIF) += nameif.o | |
33453 | -NETWORKING-$(CONFIG_NC) += nc.o | |
33454 | -NETWORKING-$(CONFIG_NETSTAT) += netstat.o | |
33455 | -NETWORKING-$(CONFIG_NSLOOKUP) += nslookup.o | |
33456 | -NETWORKING-$(CONFIG_PING) += ping.o | |
33457 | -NETWORKING-$(CONFIG_PING6) += ping6.o | |
33458 | -NETWORKING-$(CONFIG_ROUTE) += route.o | |
33459 | -NETWORKING-$(CONFIG_TELNET) += telnet.o | |
33460 | -NETWORKING-$(CONFIG_TELNETD) += telnetd.o | |
33461 | -NETWORKING-$(CONFIG_TFTP) += tftp.o | |
33462 | -NETWORKING-$(CONFIG_TRACEROUTE) += traceroute.o | |
33463 | -NETWORKING-$(CONFIG_VCONFIG) += vconfig.o | |
33464 | -NETWORKING-$(CONFIG_WGET) += wget.o | |
33465 | +NETWORKING-$(CONFIG_ARPING) += arping.o | |
33466 | +NETWORKING-$(CONFIG_ETHER_WAKE) += ether-wake.o | |
33467 | +NETWORKING-$(CONFIG_FAKEIDENTD) += fakeidentd.o | |
33468 | +NETWORKING-$(CONFIG_FTPGET) += ftpgetput.o | |
33469 | +NETWORKING-$(CONFIG_FTPPUT) += ftpgetput.o | |
33470 | +NETWORKING-$(CONFIG_HOSTNAME) += hostname.o | |
33471 | +NETWORKING-$(CONFIG_HTTPD) += httpd.o | |
33472 | +NETWORKING-$(CONFIG_IFCONFIG) += ifconfig.o | |
33473 | +NETWORKING-$(CONFIG_IFUPDOWN) += ifupdown.o | |
33474 | +NETWORKING-$(CONFIG_INETD) += inetd.o | |
33475 | +NETWORKING-$(CONFIG_IP) += ip.o | |
33476 | +NETWORKING-$(CONFIG_IPCALC) += ipcalc.o | |
33477 | +NETWORKING-$(CONFIG_IPADDR) += ipaddr.o | |
33478 | +NETWORKING-$(CONFIG_IPLINK) += iplink.o | |
33479 | +NETWORKING-$(CONFIG_IPROUTE) += iproute.o | |
33480 | +NETWORKING-$(CONFIG_IPTUNNEL) += iptunnel.o | |
33481 | +NETWORKING-$(CONFIG_NAMEIF) += nameif.o | |
33482 | +NETWORKING-$(CONFIG_NC) += nc.o | |
33483 | +NETWORKING-$(CONFIG_NETSTAT) += netstat.o | |
33484 | +NETWORKING-$(CONFIG_NSLOOKUP) += nslookup.o | |
33485 | +NETWORKING-$(CONFIG_PING) += ping.o | |
33486 | +NETWORKING-$(CONFIG_PING6) += ping6.o | |
33487 | +NETWORKING-$(CONFIG_ROUTE) += route.o | |
33488 | +NETWORKING-$(CONFIG_TELNET) += telnet.o | |
33489 | +NETWORKING-$(CONFIG_TELNETD) += telnetd.o | |
33490 | +NETWORKING-$(CONFIG_TFTP) += tftp.o | |
33491 | +NETWORKING-$(CONFIG_TRACEROUTE) += traceroute.o | |
33492 | +NETWORKING-$(CONFIG_VCONFIG) += vconfig.o | |
33493 | +NETWORKING-$(CONFIG_WGET) += wget.o | |
33494 | +NETWORKING-$(CONFIG_ZCIP) += zcip.o | |
33495 | ||
33496 | libraries-y+=$(NETWORKING_DIR)$(NETWORKING_AR) | |
33497 | ||
33498 | @@ -57,7 +60,7 @@ | |
33499 | needcrypt-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) := y | |
33500 | ||
33501 | ifeq ($(needcrypt-y),y) | |
33502 | - LIBRARIES += -lcrypt | |
33503 | + LIBRARIES += -lcrypt | |
33504 | endif | |
33505 | ||
33506 | $(NETWORKING_DIR)$(NETWORKING_AR): $(patsubst %,$(NETWORKING_DIR)%, $(NETWORKING-y)) | |
33507 | @@ -65,4 +68,3 @@ | |
33508 | ||
33509 | $(NETWORKING_DIR)%.o: $(srcdir)/%.c | |
33510 | $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< | |
33511 | - | |
33512 | diff -Nur busybox-1.00/networking/arping.c busybox/networking/arping.c | |
33513 | --- busybox-1.00/networking/arping.c 2003-09-26 02:33:18.000000000 +0200 | |
33514 | +++ busybox/networking/arping.c 2005-06-04 08:20:05.000000000 +0200 | |
33515 | @@ -106,7 +106,7 @@ | |
33516 | return err; | |
33517 | } | |
33518 | ||
33519 | -void finish(void) | |
33520 | +static void finish(void) | |
33521 | { | |
33522 | if (!quiet) { | |
33523 | printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent); | |
33524 | @@ -129,7 +129,7 @@ | |
33525 | exit(!received); | |
33526 | } | |
33527 | ||
33528 | -void catcher(void) | |
33529 | +static void catcher(void) | |
33530 | { | |
33531 | struct timeval tv; | |
33532 | static struct timeval start; | |
33533 | @@ -151,7 +151,7 @@ | |
33534 | alarm(1); | |
33535 | } | |
33536 | ||
33537 | -int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |
33538 | +static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |
33539 | { | |
33540 | struct timeval tv; | |
33541 | struct arphdr *ah = (struct arphdr *) buf; | |
33542 | diff -Nur busybox-1.00/networking/ether-wake.c busybox/networking/ether-wake.c | |
33543 | --- busybox-1.00/networking/ether-wake.c 1970-01-01 01:00:00.000000000 +0100 | |
33544 | +++ busybox/networking/ether-wake.c 2005-06-04 08:20:05.000000000 +0200 | |
33545 | @@ -0,0 +1,300 @@ | |
33546 | +/* | |
33547 | + * ether-wake.c - Send a magic packet to wake up sleeping machines. | |
33548 | + * | |
33549 | + * This program is free software; you can redistribute it and/or | |
33550 | + * modify it under the terms of the GNU General Public License | |
33551 | + * as published by the Free Software Foundation; either version | |
33552 | + * 2 of the License, or (at your option) any later version. | |
33553 | + * | |
33554 | + * Author: Donald Becker, http://www.scyld.com/"; http://www.scyld.com/wakeonlan.html | |
33555 | + * Busybox port: Christian Volkmann <haveaniceday@online.de> | |
33556 | + * Used version of ether-wake.c: v1.09 11/12/2003 Donald Becker, http://www.scyld.com/"; | |
33557 | + */ | |
33558 | + | |
33559 | +/* full usage according Donald Becker | |
33560 | + * usage: ether-wake [-i <ifname>] [-p aa:bb:cc:dd[:ee:ff]] 00:11:22:33:44:55\n" | |
33561 | + * | |
33562 | + * This program generates and transmits a Wake-On-LAN (WOL)\n" | |
33563 | + * \"Magic Packet\", used for restarting machines that have been\n" | |
33564 | + * soft-powered-down (ACPI D3-warm state).\n" | |
33565 | + * It currently generates the standard AMD Magic Packet format, with\n" | |
33566 | + * an optional password appended.\n" | |
33567 | + * | |
33568 | + * The single required parameter is the Ethernet MAC (station) address\n" | |
33569 | + * of the machine to wake or a host ID with known NSS 'ethers' entry.\n" | |
33570 | + * The MAC address may be found with the 'arp' program while the target\n" | |
33571 | + * machine is awake.\n" | |
33572 | + * | |
33573 | + * Options:\n" | |
33574 | + * -b Send wake-up packet to the broadcast address.\n" | |
33575 | + * -D Increase the debug level.\n" | |
33576 | + * -i ifname Use interface IFNAME instead of the default 'eth0'.\n" | |
33577 | + * -p <pw> Append the four or six byte password PW to the packet.\n" | |
33578 | + * A password is only required for a few adapter types.\n" | |
33579 | + * The password may be specified in ethernet hex format\n" | |
33580 | + * or dotted decimal (Internet address)\n" | |
33581 | + * -p 00:22:44:66:88:aa\n" | |
33582 | + * -p 192.168.1.1\n"; | |
33583 | + * | |
33584 | + * | |
33585 | + * This program generates and transmits a Wake-On-LAN (WOL) "Magic Packet", | |
33586 | + * used for restarting machines that have been soft-powered-down | |
33587 | + * (ACPI D3-warm state). It currently generates the standard AMD Magic Packet | |
33588 | + * format, with an optional password appended. | |
33589 | + * | |
33590 | + * This software may be used and distributed according to the terms | |
33591 | + * of the GNU Public License, incorporated herein by reference. | |
33592 | + * Contact the author for use under other terms. | |
33593 | + * | |
33594 | + * This source file was originally part of the network tricks package, and | |
33595 | + * is now distributed to support the Scyld Beowulf system. | |
33596 | + * Copyright 1999-2003 Donald Becker and Scyld Computing Corporation. | |
33597 | + * | |
33598 | + * The author may be reached as becker@scyld, or C/O | |
33599 | + * Scyld Computing Corporation | |
33600 | + * 914 Bay Ridge Road, Suite 220 | |
33601 | + * Annapolis MD 21403 | |
33602 | + * | |
33603 | + * Notes: | |
33604 | + * On some systems dropping root capability allows the process to be | |
33605 | + * dumped, traced or debugged. | |
33606 | + * If someone traces this program, they get control of a raw socket. | |
33607 | + * Linux handles this safely, but beware when porting this program. | |
33608 | + * | |
33609 | + * An alternative to needing 'root' is using a UDP broadcast socket, however | |
33610 | + * doing so only works with adapters configured for unicast+broadcast Rx | |
33611 | + * filter. That configuration consumes more power. | |
33612 | +*/ | |
33613 | + | |
33614 | + | |
33615 | +#include <unistd.h> | |
33616 | +#include <stdlib.h> | |
33617 | +#include <stdio.h> | |
33618 | +#include <errno.h> | |
33619 | +#include <ctype.h> | |
33620 | +#include <string.h> | |
33621 | + | |
33622 | +#include <sys/socket.h> | |
33623 | +#include <sys/types.h> | |
33624 | +#include <sys/ioctl.h> | |
33625 | +#include <features.h> | |
33626 | +#include <netpacket/packet.h> | |
33627 | +#include <net/ethernet.h> | |
33628 | +#include <netdb.h> | |
33629 | +#include <netinet/ether.h> | |
33630 | + | |
33631 | +#ifdef __linux__ | |
33632 | +#include <linux/if.h> | |
33633 | +#endif | |
33634 | + | |
33635 | +#include "busybox.h" | |
33636 | + | |
33637 | +/* Note: PF_INET, SOCK_DGRAM, IPPROTO_UDP would allow SIOCGIFHWADDR to | |
33638 | + * work as non-root, but we need SOCK_PACKET to specify the Ethernet | |
33639 | + * destination address. | |
33640 | + */ | |
33641 | +#ifdef PF_PACKET | |
33642 | +# define whereto_t sockaddr_ll | |
33643 | +# define make_socket() socket(PF_PACKET, SOCK_RAW, 0) | |
33644 | +#else | |
33645 | +# define whereto_t sockaddr | |
33646 | +# define make_socket() socket(AF_INET, SOCK_PACKET, SOCK_PACKET) | |
33647 | +#endif | |
33648 | + | |
33649 | +#ifdef DEBUG | |
33650 | +# define bb_debug_msg(fmt, args...) fprintf(stderr, fmt, ## args) | |
33651 | +void bb_debug_dump_packet(unsigned char *outpack, int pktsize) | |
33652 | +{ | |
33653 | + int i; | |
33654 | + printf("packet dump:\n"); | |
33655 | + for (i = 0; i < pktsize; ++i) { | |
33656 | + printf("%2.2x ", outpack[i]); | |
33657 | + if (i % 20 == 19) printf("\n"); | |
33658 | + } | |
33659 | + printf("\n\n"); | |
33660 | +} | |
33661 | +#else | |
33662 | +# define bb_debug_msg(fmt, args...) | |
33663 | +# define bb_debug_dump_packet(outpack, pktsize) | |
33664 | +#endif | |
33665 | + | |
33666 | +static inline void get_dest_addr(const char *arg, struct ether_addr *eaddr); | |
33667 | +static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast); | |
33668 | +static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd); | |
33669 | + | |
33670 | +int etherwake_main(int argc, char *argv[]) | |
33671 | +{ | |
33672 | + char *ifname = "eth0", *pass = NULL; | |
33673 | + unsigned long flags; | |
33674 | + unsigned char wol_passwd[6]; | |
33675 | + int wol_passwd_sz = 0; | |
33676 | + | |
33677 | + int s; /* Raw socket */ | |
33678 | + int pktsize; | |
33679 | + unsigned char outpack[1000]; | |
33680 | + | |
33681 | + struct ether_addr eaddr; | |
33682 | + struct whereto_t whereto; /* who to wake up */ | |
33683 | + | |
33684 | + /* handle misc user options */ | |
33685 | + flags = bb_getopt_ulflags(argc, argv, "bi:p:", &ifname, &pass); | |
33686 | + if (optind == argc) | |
33687 | + bb_show_usage(); | |
33688 | + if (pass) | |
33689 | + wol_passwd_sz = get_wol_pw(pass, wol_passwd); | |
33690 | + | |
33691 | + /* create the raw socket */ | |
33692 | + s = make_socket(); | |
33693 | + if (s < 0) | |
33694 | + bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); | |
33695 | + | |
33696 | + /* now that we have a raw socket we can drop root */ | |
33697 | + setuid(getuid()); | |
33698 | + | |
33699 | + /* look up the dest mac address */ | |
33700 | + get_dest_addr(argv[optind], &eaddr); | |
33701 | + | |
33702 | + /* fill out the header of the packet */ | |
33703 | + pktsize = get_fill(outpack, &eaddr, flags /*& 1 [OPT_BROADCAST]*/); | |
33704 | + | |
33705 | + bb_debug_dump_packet(outpack, pktsize); | |
33706 | + | |
33707 | + /* Fill in the source address, if possible. */ | |
33708 | +#ifdef __linux__ | |
33709 | + { | |
33710 | + struct ifreq if_hwaddr; | |
33711 | + | |
33712 | + strcpy(if_hwaddr.ifr_name, ifname); | |
33713 | + if (ioctl(s, SIOCGIFHWADDR, &if_hwaddr) < 0) | |
33714 | + bb_perror_msg_and_die("SIOCGIFHWADDR on %s failed", ifname); | |
33715 | + | |
33716 | + memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6); | |
33717 | + | |
33718 | +# ifdef DEBUG | |
33719 | + { | |
33720 | + unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data; | |
33721 | + printf("The hardware address (SIOCGIFHWADDR) of %s is type %d " | |
33722 | + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname, | |
33723 | + if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], | |
33724 | + hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); | |
33725 | + } | |
33726 | +# endif | |
33727 | + } | |
33728 | +#endif /* __linux__ */ | |
33729 | + | |
33730 | + bb_debug_dump_packet(outpack, pktsize); | |
33731 | + | |
33732 | + /* append the password if specified */ | |
33733 | + if (wol_passwd_sz > 0) { | |
33734 | + memcpy(outpack+pktsize, wol_passwd, wol_passwd_sz); | |
33735 | + pktsize += wol_passwd_sz; | |
33736 | + } | |
33737 | + | |
33738 | + bb_debug_dump_packet(outpack, pktsize); | |
33739 | + | |
33740 | + /* This is necessary for broadcasts to work */ | |
33741 | + if (flags /*& 1 [OPT_BROADCAST]*/) { | |
33742 | + int one = 1; | |
33743 | + if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (void *)&one, sizeof(one)) < 0) | |
33744 | + bb_perror_msg("SO_BROADCAST"); | |
33745 | + } | |
33746 | + | |
33747 | +#if defined(PF_PACKET) | |
33748 | + { | |
33749 | + struct ifreq ifr; | |
33750 | + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |
33751 | + if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) | |
33752 | + bb_perror_msg_and_die("SIOCGIFINDEX"); | |
33753 | + memset(&whereto, 0, sizeof(whereto)); | |
33754 | + whereto.sll_family = AF_PACKET; | |
33755 | + whereto.sll_ifindex = ifr.ifr_ifindex; | |
33756 | + /* The manual page incorrectly claims the address must be filled. | |
33757 | + We do so because the code may change to match the docs. */ | |
33758 | + whereto.sll_halen = ETH_ALEN; | |
33759 | + memcpy(whereto.sll_addr, outpack, ETH_ALEN); | |
33760 | + } | |
33761 | +#else | |
33762 | + whereto.sa_family = 0; | |
33763 | + strcpy(whereto.sa_data, ifname); | |
33764 | +#endif | |
33765 | + | |
33766 | + if (sendto(s, outpack, pktsize, 0, (struct sockaddr *)&whereto, sizeof(whereto)) < 0) | |
33767 | + bb_perror_msg(bb_msg_write_error); | |
33768 | + | |
33769 | + close(s); | |
33770 | + | |
33771 | + return EXIT_SUCCESS; | |
33772 | +} | |
33773 | + | |
33774 | +/* Convert the host ID string to a MAC address. | |
33775 | + * The string may be a: | |
33776 | + * Host name | |
33777 | + * IP address string | |
33778 | + * MAC address string | |
33779 | +*/ | |
33780 | +static inline void get_dest_addr(const char *hostid, struct ether_addr *eaddr) | |
33781 | +{ | |
33782 | + struct ether_addr *eap; | |
33783 | + | |
33784 | + eap = ether_aton(hostid); | |
33785 | + if (eap) { | |
33786 | + *eaddr = *eap; | |
33787 | + bb_debug_msg("The target station address is %s\n\n", ether_ntoa(eaddr)); | |
33788 | + } else if (ether_hostton(hostid, eaddr) == 0) { | |
33789 | + bb_debug_msg("Station address for hostname %s is %s\n\n", hostid, ether_ntoa(eaddr)); | |
33790 | + } else | |
33791 | + bb_show_usage(); | |
33792 | +} | |
33793 | + | |
33794 | +static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast) | |
33795 | +{ | |
33796 | + int offset, i; | |
33797 | + unsigned char *station_addr = eaddr->ether_addr_octet; | |
33798 | + | |
33799 | + if (broadcast) | |
33800 | + memset(pkt+0, 0xff, 6); | |
33801 | + else | |
33802 | + memcpy(pkt, station_addr, 6); | |
33803 | + memcpy(pkt+6, station_addr, 6); | |
33804 | + pkt[12] = 0x08; /* Or 0x0806 for ARP, 0x8035 for RARP */ | |
33805 | + pkt[13] = 0x42; | |
33806 | + offset = 14; | |
33807 | + | |
33808 | + memset(pkt+offset, 0xff, 6); | |
33809 | + offset += 6; | |
33810 | + | |
33811 | + for (i = 0; i < 16; ++i) { | |
33812 | + memcpy(pkt+offset, station_addr, 6); | |
33813 | + offset += 6; | |
33814 | + } | |
33815 | + | |
33816 | + return offset; | |
33817 | +} | |
33818 | + | |
33819 | +static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd) | |
33820 | +{ | |
33821 | + int passwd[6]; | |
33822 | + int byte_cnt, i; | |
33823 | + | |
33824 | + /* handle MAC format */ | |
33825 | + byte_cnt = sscanf(ethoptarg, "%2x:%2x:%2x:%2x:%2x:%2x", | |
33826 | + &passwd[0], &passwd[1], &passwd[2], | |
33827 | + &passwd[3], &passwd[4], &passwd[5]); | |
33828 | + /* handle IP format */ | |
33829 | + if (byte_cnt < 4) | |
33830 | + byte_cnt = sscanf(ethoptarg, "%d.%d.%d.%d", | |
33831 | + &passwd[0], &passwd[1], &passwd[2], &passwd[3]); | |
33832 | + if (byte_cnt < 4) { | |
33833 | + bb_error_msg("Unable to read the Wake-On-LAN pass"); | |
33834 | + return 0; | |
33835 | + } | |
33836 | + | |
33837 | + for (i = 0; i < byte_cnt; ++i) | |
33838 | + wol_passwd[i] = passwd[i]; | |
33839 | + | |
33840 | + bb_debug_msg("password: %2.2x %2.2x %2.2x %2.2x (%d)\n\n", | |
33841 | + wol_passwd[0], wol_passwd[1], wol_passwd[2], wol_passwd[3], | |
33842 | + byte_cnt); | |
33843 | + | |
33844 | + return byte_cnt; | |
33845 | +} | |
33846 | diff -Nur busybox-1.00/networking/fakeidentd.c busybox/networking/fakeidentd.c | |
33847 | --- busybox-1.00/networking/fakeidentd.c 1970-01-01 01:00:00.000000000 +0100 | |
33848 | +++ busybox/networking/fakeidentd.c 2005-06-04 08:20:05.000000000 +0200 | |
33849 | @@ -0,0 +1,432 @@ | |
33850 | +/* vi: set sw=4 ts=4: */ | |
33851 | +/* | |
33852 | + * A fake identd server | |
33853 | + * | |
33854 | + * Adapted to busybox by Thomas Lundquist <thomasez@zelow.no> | |
33855 | + * Original Author: Tomi Ollila <too@iki.fi> | |
33856 | + * http://www.guru-group.fi/~too/sw/ | |
33857 | + * | |
33858 | + * This program is free software; you can redistribute it and/or modify | |
33859 | + * it under the terms of the GNU General Public License as published by | |
33860 | + * the Free Software Foundation; either version 2 of the License, or | |
33861 | + * (at your option) any later version. | |
33862 | + * | |
33863 | + * This program is distributed in the hope that it will be useful, | |
33864 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
33865 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
33866 | + * General Public License for more details. | |
33867 | + * | |
33868 | + * You should have received a copy of the GNU General Public License | |
33869 | + * along with this program; if not, write to the Free Software | |
33870 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
33871 | + * | |
33872 | + */ | |
33873 | + | |
33874 | +#include <unistd.h> | |
33875 | +#include <stdio.h> | |
33876 | +#include <stdlib.h> | |
33877 | +#include <stdarg.h> | |
33878 | +#include <string.h> | |
33879 | +#include <fcntl.h> | |
33880 | +#include <signal.h> | |
33881 | +#include <sys/syslog.h> | |
33882 | + | |
33883 | +#include <pwd.h> | |
33884 | +#include <netdb.h> | |
33885 | + | |
33886 | +#include <sys/syslog.h> | |
33887 | +#include <sys/types.h> | |
33888 | +#include <sys/time.h> | |
33889 | +#include <time.h> | |
33890 | +#include <sys/socket.h> | |
33891 | +#include <netinet/in.h> | |
33892 | +#include <errno.h> | |
33893 | +#include <arpa/inet.h> | |
33894 | +#include <sys/uio.h> | |
33895 | + | |
33896 | +#include "busybox.h" | |
33897 | + | |
33898 | +#define IDENT_PORT 113 | |
33899 | +#define MAXCONNS 20 | |
33900 | +#define MAXIDLETIME 45 | |
33901 | + | |
33902 | +static const char ident_substr[] = " : USERID : UNIX : "; | |
33903 | +static const int ident_substr_len = sizeof(ident_substr) - 1; | |
33904 | +#define PIDFILE "/var/run/identd.pid" | |
33905 | + | |
33906 | +/* | |
33907 | + * We have to track the 'first connection socket' so that we | |
33908 | + * don't go around closing file descriptors for non-clients. | |
33909 | + * | |
33910 | + * descriptor setup normally | |
33911 | + * 0 = server socket | |
33912 | + * 1 = syslog fd (hopefully -- otherwise this won't work) | |
33913 | + * 2 = connection socket after detached from tty. standard error before that | |
33914 | + * 3 - 2 + MAXCONNS = rest connection sockets | |
33915 | + * | |
33916 | + * To try to make sure that syslog fd is what is "requested", the that fd | |
33917 | + * is closed before openlog() call. It can only severely fail if fd 0 | |
33918 | + * is initially closed. | |
33919 | + */ | |
33920 | +#define FCS 2 | |
33921 | + | |
33922 | +/* | |
33923 | + * FD of the connection is always the index of the connection structure | |
33924 | + * in `conns' array + FCS | |
33925 | + */ | |
33926 | +static struct { | |
33927 | + char buf[20]; | |
33928 | + int len; | |
33929 | + time_t lasttime; | |
33930 | +} conns[MAXCONNS]; | |
33931 | + | |
33932 | +/* When using global variables, bind those at least to a structure. */ | |
33933 | +static struct { | |
33934 | + const char *identuser; | |
33935 | + fd_set readfds; | |
33936 | + int conncnt; | |
33937 | +} G; | |
33938 | + | |
33939 | +/* | |
33940 | + * Prototypes | |
33941 | + */ | |
33942 | +static void reply(int s, char *buf); | |
33943 | +static void replyError(int s, char *buf); | |
33944 | + | |
33945 | +static const char *nobodystr = "nobody"; /* this needs to be declared like this */ | |
33946 | +static char *bind_ip_address = "0.0.0.0"; | |
33947 | + | |
33948 | +static inline void movefd(int from, int to) | |
33949 | +{ | |
33950 | + if (from != to) { | |
33951 | + dup2(from, to); | |
33952 | + close(from); | |
33953 | + } | |
33954 | +} | |
33955 | + | |
33956 | +static void inetbind(void) | |
33957 | +{ | |
33958 | + int s, port; | |
33959 | + struct sockaddr_in addr; | |
33960 | + int len = sizeof(addr); | |
33961 | + int one = 1; | |
33962 | + struct servent *se; | |
33963 | + | |
33964 | + if ((se = getservbyname("identd", "tcp")) == NULL) | |
33965 | + port = IDENT_PORT; | |
33966 | + else | |
33967 | + port = se->s_port; | |
33968 | + | |
33969 | + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) | |
33970 | + bb_perror_msg_and_die("Cannot create server socket"); | |
33971 | + | |
33972 | + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); | |
33973 | + | |
33974 | + memset(&addr, 0, sizeof(addr)); | |
33975 | + addr.sin_addr.s_addr = inet_addr(bind_ip_address); | |
33976 | + addr.sin_family = AF_INET; | |
33977 | + addr.sin_port = htons(port); | |
33978 | + | |
33979 | + if (bind(s, (struct sockaddr *)&addr, len) < 0) | |
33980 | + bb_perror_msg_and_die("Cannot bind() port %i", IDENT_PORT); | |
33981 | + | |
33982 | + if (listen(s, 5) < 0) | |
33983 | + bb_perror_msg_and_die("Cannot listen() on port %i", IDENT_PORT); | |
33984 | + | |
33985 | + movefd(s, 0); | |
33986 | +} | |
33987 | + | |
33988 | +static void delpidfile(void) | |
33989 | +{ | |
33990 | + /* | |
33991 | + * Usually nobody has no write/delete access to directory /var/run/ | |
33992 | + * therefore if file cannot be deleted, it is truncated | |
33993 | + */ | |
33994 | + if (unlink(PIDFILE) < 0) | |
33995 | + close(open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0644)); | |
33996 | +} | |
33997 | + | |
33998 | +static void handlexitsigs(int signum) | |
33999 | +{ | |
34000 | + delpidfile(); | |
34001 | + exit(0); | |
34002 | +} | |
34003 | + | |
34004 | +/* May succeed. If not, won't care. */ | |
34005 | +static inline void writepid(uid_t nobody, uid_t nogrp) | |
34006 | +{ | |
34007 | + char buf[24]; | |
34008 | + int fd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0664); | |
34009 | + | |
34010 | + if (fd < 0) | |
34011 | + return; | |
34012 | + | |
34013 | + snprintf(buf, 23, "%d\n", getpid()); | |
34014 | + write(fd, buf, strlen(buf)); | |
34015 | + fchown(fd, nobody, nogrp); | |
34016 | + close(fd); | |
34017 | + | |
34018 | + /* should this handle ILL, ... (see signal(7)) */ | |
34019 | + signal(SIGTERM, handlexitsigs); | |
34020 | + signal(SIGINT, handlexitsigs); | |
34021 | + signal(SIGQUIT, handlexitsigs); | |
34022 | +} | |
34023 | + | |
34024 | +/* return 0 as parent, 1 as child */ | |
34025 | +static int godaemon(void) | |
34026 | +{ | |
34027 | + uid_t nobody, nogrp; | |
34028 | + struct passwd *pw; | |
34029 | + | |
34030 | + switch (fork()) { | |
34031 | + case -1: | |
34032 | + bb_perror_msg_and_die("Could not fork"); | |
34033 | + | |
34034 | + case 0: | |
34035 | + pw = getpwnam(nobodystr); | |
34036 | + if (pw == NULL) | |
34037 | + bb_error_msg_and_die("Cannot find uid/gid of user '%s'", nobodystr); | |
34038 | + nobody = pw->pw_uid; | |
34039 | + nogrp = pw->pw_gid; | |
34040 | + writepid(nobody, nogrp); | |
34041 | + | |
34042 | + close(0); | |
34043 | + inetbind(); | |
34044 | + if (setgid(nogrp)) bb_error_msg_and_die("Could not setgid()"); | |
34045 | + if (setegid(nogrp)) bb_error_msg_and_die("Could not setegid()"); | |
34046 | + if (setuid(nobody)) bb_error_msg_and_die("Could not setuid()"); | |
34047 | + if (seteuid(nobody)) bb_error_msg_and_die("Could not seteuid()"); | |
34048 | + close(1); | |
34049 | + close(2); | |
34050 | + | |
34051 | + signal(SIGHUP, SIG_IGN); | |
34052 | + signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */ | |
34053 | + | |
34054 | + setsid(); | |
34055 | + | |
34056 | + openlog(bb_applet_name, 0, LOG_DAEMON); | |
34057 | + return 1; | |
34058 | + } | |
34059 | + | |
34060 | + return 0; | |
34061 | +} | |
34062 | + | |
34063 | +static void deleteConn(int s) | |
34064 | +{ | |
34065 | + int i = s - FCS; | |
34066 | + | |
34067 | + close(s); | |
34068 | + | |
34069 | + G.conncnt--; | |
34070 | + | |
34071 | + /* | |
34072 | + * Most of the time there is 0 connections. Most often that there | |
34073 | + * is connections, there is just one connection. When this one connection | |
34074 | + * closes, i == G.conncnt = 0 -> no copying. | |
34075 | + * When there is more than one connection, the oldest connections closes | |
34076 | + * earlier on average. When this happens, the code below starts copying | |
34077 | + * the connection structure w/ highest index to the place which which is | |
34078 | + * just deleted. This means that the connection structures are no longer | |
34079 | + * in chronological order. I'd quess this means that when there is more | |
34080 | + * than 1 connection, on average every other connection structure needs | |
34081 | + * to be copied over the time all these connections are deleted. | |
34082 | + */ | |
34083 | + if (i != G.conncnt) { | |
34084 | + memcpy(&conns[i], &conns[G.conncnt], sizeof(conns[0])); | |
34085 | + movefd(G.conncnt + FCS, s); | |
34086 | + } | |
34087 | + | |
34088 | + FD_CLR(G.conncnt + FCS, &G.readfds); | |
34089 | +} | |
34090 | + | |
34091 | +static int closeOldest(void) | |
34092 | +{ | |
34093 | + time_t min = conns[0].lasttime; | |
34094 | + int idx = 0; | |
34095 | + int i; | |
34096 | + | |
34097 | + for (i = 1; i < MAXCONNS; i++) | |
34098 | + if (conns[i].lasttime < min) | |
34099 | + idx = i; | |
34100 | + | |
34101 | + replyError(idx + FCS, "X-SERVER-TOO-BUSY"); | |
34102 | + close(idx + FCS); | |
34103 | + | |
34104 | + return idx; | |
34105 | +} | |
34106 | + | |
34107 | +static int checkInput(char *buf, int len, int l) | |
34108 | +{ | |
34109 | + int i; | |
34110 | + for (i = len; i < len + l; ++i) | |
34111 | + if (buf[i] == '\n') | |
34112 | + return 1; | |
34113 | + return 0; | |
34114 | +} | |
34115 | + | |
34116 | +int fakeidentd_main(int argc, char **argv) | |
34117 | +{ | |
34118 | + memset(conns, 0, sizeof(conns)); | |
34119 | + memset(&G, 0, sizeof(G)); | |
34120 | + FD_ZERO(&G.readfds); | |
34121 | + FD_SET(0, &G.readfds); | |
34122 | + | |
34123 | + /* handle -b <ip> parameter */ | |
34124 | + bb_getopt_ulflags(argc, argv, "b:", &bind_ip_address); | |
34125 | + /* handle optional REPLY STRING */ | |
34126 | + if (optind < argc) | |
34127 | + G.identuser = argv[optind]; | |
34128 | + else | |
34129 | + G.identuser = nobodystr; | |
34130 | + | |
34131 | + /* daemonize and have the parent return */ | |
34132 | + if (godaemon() == 0) | |
34133 | + return 0; | |
34134 | + | |
34135 | + /* main loop where we process all events and never exit */ | |
34136 | + while (1) { | |
34137 | + fd_set rfds = G.readfds; | |
34138 | + struct timeval tv = { 15, 0 }; | |
34139 | + int i; | |
34140 | + int tim = time(NULL); | |
34141 | + | |
34142 | + select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); | |
34143 | + | |
34144 | + for (i = G.conncnt - 1; i >= 0; i--) { | |
34145 | + int s = i + FCS; | |
34146 | + | |
34147 | + if (FD_ISSET(s, &rfds)) { | |
34148 | + char *buf = conns[i].buf; | |
34149 | + unsigned int len = conns[i].len; | |
34150 | + unsigned int l; | |
34151 | + | |
34152 | + if ((l = read(s, buf + len, sizeof(conns[0].buf) - len)) > 0) { | |
34153 | + if (checkInput(buf, len, l)) { | |
34154 | + reply(s, buf); | |
34155 | + goto deleteconn; | |
34156 | + } else if (len + l >= sizeof(conns[0].buf)) { | |
34157 | + replyError(s, "X-INVALID-REQUEST"); | |
34158 | + goto deleteconn; | |
34159 | + } else { | |
34160 | + conns[i].len += l; | |
34161 | + } | |
34162 | + } else { | |
34163 | + goto deleteconn; | |
34164 | + } | |
34165 | + | |
34166 | + conns[i].lasttime = tim; | |
34167 | + continue; | |
34168 | + | |
34169 | +deleteconn: | |
34170 | + deleteConn(s); | |
34171 | + } else { | |
34172 | + /* implement as time_after() in linux kernel sources ... */ | |
34173 | + if (conns[i].lasttime + MAXIDLETIME <= tim) { | |
34174 | + replyError(s, "X-TIMEOUT"); | |
34175 | + deleteConn(s); | |
34176 | + } | |
34177 | + } | |
34178 | + } | |
34179 | + | |
34180 | + if (FD_ISSET(0, &rfds)) { | |
34181 | + int s = accept(0, NULL, 0); | |
34182 | + | |
34183 | + if (s < 0) { | |
34184 | + if (errno != EINTR) /* EINTR */ | |
34185 | + syslog(LOG_ERR, "accept: %s", strerror(errno)); | |
34186 | + } else { | |
34187 | + if (G.conncnt == MAXCONNS) | |
34188 | + i = closeOldest(); | |
34189 | + else | |
34190 | + i = G.conncnt++; | |
34191 | + | |
34192 | + movefd(s, i + FCS); /* move if not already there */ | |
34193 | + FD_SET(i + FCS, &G.readfds); | |
34194 | + | |
34195 | + conns[i].len = 0; | |
34196 | + conns[i].lasttime = time(NULL); | |
34197 | + } | |
34198 | + } | |
34199 | + } /* end of while(1) */ | |
34200 | + | |
34201 | + return 0; | |
34202 | +} | |
34203 | + | |
34204 | +static int parseAddrs(char *ptr, char **myaddr, char **heraddr); | |
34205 | +static void reply(int s, char *buf) | |
34206 | +{ | |
34207 | + char *myaddr, *heraddr; | |
34208 | + | |
34209 | + myaddr = heraddr = NULL; | |
34210 | + | |
34211 | + if (parseAddrs(buf, &myaddr, &heraddr)) | |
34212 | + replyError(s, "X-INVALID-REQUEST"); | |
34213 | + else { | |
34214 | + struct iovec iv[6]; | |
34215 | + iv[0].iov_base = myaddr; iv[0].iov_len = strlen(myaddr); | |
34216 | + iv[1].iov_base = ", "; iv[1].iov_len = 2; | |
34217 | + iv[2].iov_base = heraddr; iv[2].iov_len = strlen(heraddr); | |
34218 | + iv[3].iov_base = (void *)ident_substr; iv[3].iov_len = ident_substr_len; | |
34219 | + iv[4].iov_base = (void *)G.identuser; iv[4].iov_len = strlen(G.identuser); | |
34220 | + iv[5].iov_base = "\r\n"; iv[5].iov_len = 2; | |
34221 | + writev(s, iv, 6); | |
34222 | + } | |
34223 | +} | |
34224 | + | |
34225 | +static void replyError(int s, char *buf) | |
34226 | +{ | |
34227 | + struct iovec iv[3]; | |
34228 | + iv[0].iov_base = "0, 0 : ERROR : "; iv[0].iov_len = 15; | |
34229 | + iv[1].iov_base = buf; iv[1].iov_len = strlen(buf); | |
34230 | + iv[2].iov_base = "\r\n"; iv[2].iov_len = 2; | |
34231 | + writev(s, iv, 3); | |
34232 | +} | |
34233 | + | |
34234 | +static int chmatch(char c, char *chars) | |
34235 | +{ | |
34236 | + for (; *chars; chars++) | |
34237 | + if (c == *chars) | |
34238 | + return 1; | |
34239 | + return 0; | |
34240 | +} | |
34241 | + | |
34242 | +static int skipchars(char **p, char *chars) | |
34243 | +{ | |
34244 | + while (chmatch(**p, chars)) | |
34245 | + (*p)++; | |
34246 | + if (**p == '\r' || **p == '\n') | |
34247 | + return 0; | |
34248 | + return 1; | |
34249 | +} | |
34250 | + | |
34251 | +static int parseAddrs(char *ptr, char **myaddr, char **heraddr) | |
34252 | +{ | |
34253 | + /* parse <port-on-server> , <port-on-client> */ | |
34254 | + | |
34255 | + if (!skipchars(&ptr, " \t")) | |
34256 | + return -1; | |
34257 | + | |
34258 | + *myaddr = ptr; | |
34259 | + | |
34260 | + if (!skipchars(&ptr, "1234567890")) | |
34261 | + return -1; | |
34262 | + | |
34263 | + if (!chmatch(*ptr, " \t,")) | |
34264 | + return -1; | |
34265 | + | |
34266 | + *ptr++ = '\0'; | |
34267 | + | |
34268 | + if (!skipchars(&ptr, " \t,") ) | |
34269 | + return -1; | |
34270 | + | |
34271 | + *heraddr = ptr; | |
34272 | + | |
34273 | + skipchars(&ptr, "1234567890"); | |
34274 | + | |
34275 | + if (!chmatch(*ptr, " \n\r")) | |
34276 | + return -1; | |
34277 | + | |
34278 | + *ptr = '\0'; | |
34279 | + | |
34280 | + return 0; | |
34281 | +} | |
34282 | diff -Nur busybox-1.00/networking/hostname.c busybox/networking/hostname.c | |
34283 | --- busybox-1.00/networking/hostname.c 2003-07-14 23:21:01.000000000 +0200 | |
34284 | +++ busybox/networking/hostname.c 2005-06-04 08:20:05.000000000 +0200 | |
34285 | @@ -1,6 +1,6 @@ | |
34286 | /* vi: set sw=4 ts=4: */ | |
34287 | /* | |
34288 | - * $Id$ | |
34289 | + * $Id$ | |
34290 | * Mini hostname implementation for busybox | |
34291 | * | |
34292 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | |
34293 | diff -Nur busybox-1.00/networking/ifconfig.c busybox/networking/ifconfig.c | |
34294 | --- busybox-1.00/networking/ifconfig.c 2004-03-31 13:30:08.000000000 +0200 | |
34295 | +++ busybox/networking/ifconfig.c 2005-06-04 08:20:05.000000000 +0200 | |
34296 | @@ -15,7 +15,7 @@ | |
34297 | * Foundation; either version 2 of the License, or (at | |
34298 | * your option) any later version. | |
34299 | * | |
34300 | - * $Id$ | |
34301 | + * $Id$ | |
34302 | * | |
34303 | */ | |
34304 | ||
34305 | @@ -46,8 +46,8 @@ | |
34306 | #include <netpacket/packet.h> | |
34307 | #include <net/ethernet.h> | |
34308 | #else | |
34309 | -#include <asm/types.h> | |
34310 | -#include <linux/if_ether.h> | |
34311 | +#include <sys/types.h> | |
34312 | +#include <netinet/if_ether.h> | |
34313 | #endif | |
34314 | #include "inet_common.h" | |
34315 | #include "busybox.h" | |
34316 | @@ -177,7 +177,7 @@ | |
34317 | ||
34318 | struct arg1opt { | |
34319 | const char *name; | |
34320 | - unsigned short selector; | |
34321 | + int selector; | |
34322 | unsigned short ifr_offset; | |
34323 | }; | |
34324 | ||
34325 | diff -Nur busybox-1.00/networking/ifupdown.c busybox/networking/ifupdown.c | |
34326 | --- busybox-1.00/networking/ifupdown.c 2004-09-14 19:24:58.000000000 +0200 | |
34327 | +++ busybox/networking/ifupdown.c 2005-06-04 08:20:05.000000000 +0200 | |
34328 | @@ -150,7 +150,7 @@ | |
34329 | ||
34330 | static char no_act = 0; | |
34331 | static char verbose = 0; | |
34332 | -static char **environ = NULL; | |
34333 | +static char **__myenviron = NULL; | |
34334 | ||
34335 | #ifdef CONFIG_FEATURE_IFUPDOWN_IP | |
34336 | ||
34337 | @@ -460,7 +460,7 @@ | |
34338 | { "loopback", loopback_up6, loopback_down6, }, | |
34339 | }; | |
34340 | ||
34341 | -struct address_family_t addr_inet6 = { | |
34342 | +static struct address_family_t addr_inet6 = { | |
34343 | "inet6", | |
34344 | sizeof(methods6) / sizeof(struct method_t), | |
34345 | methods6 | |
34346 | @@ -609,7 +609,7 @@ | |
34347 | { "loopback", loopback_up, loopback_down, }, | |
34348 | }; | |
34349 | ||
34350 | -struct address_family_t addr_inet = | |
34351 | +static struct address_family_t addr_inet = | |
34352 | { | |
34353 | "inet", | |
34354 | sizeof(methods) / sizeof(struct method_t), | |
34355 | @@ -961,16 +961,16 @@ | |
34356 | const int n_env_entries = iface->n_options + 5; | |
34357 | char **ppch; | |
34358 | ||
34359 | - if (environ != NULL) { | |
34360 | - for (ppch = environ; *ppch; ppch++) { | |
34361 | + if (__myenviron != NULL) { | |
34362 | + for (ppch = __myenviron; *ppch; ppch++) { | |
34363 | free(*ppch); | |
34364 | *ppch = NULL; | |
34365 | } | |
34366 | - free(environ); | |
34367 | - environ = NULL; | |
34368 | + free(__myenviron); | |
34369 | + __myenviron = NULL; | |
34370 | } | |
34371 | - environ = xmalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ )); | |
34372 | - environend = environ; | |
34373 | + __myenviron = xmalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ )); | |
34374 | + environend = __myenviron; | |
34375 | *environend = NULL; | |
34376 | ||
34377 | for (i = 0; i < iface->n_options; i++) { | |
34378 | @@ -1010,7 +1010,7 @@ | |
34379 | case -1: /* failure */ | |
34380 | return 0; | |
34381 | case 0: /* child */ | |
34382 | - execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, environ); | |
34383 | + execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, __myenviron); | |
34384 | exit(127); | |
34385 | } | |
34386 | waitpid(child, &status, 0); | |
34387 | diff -Nur busybox-1.00/networking/inetd.c busybox/networking/inetd.c | |
34388 | --- busybox-1.00/networking/inetd.c 2004-06-22 10:40:54.000000000 +0200 | |
34389 | +++ busybox/networking/inetd.c 2005-06-04 08:20:05.000000000 +0200 | |
34390 | @@ -560,7 +560,7 @@ | |
34391 | if (sep != 0) { | |
34392 | int i; | |
34393 | ||
34394 | -#define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} | |
34395 | +#define SWAP(type, a, b) {type c=(type)(a); (a)=(type)(b); (b)=(type)c;} | |
34396 | ||
34397 | sigprocmask(SIG_BLOCK, &emptymask, &oldmask); | |
34398 | /* | |
34399 | diff -Nur busybox-1.00/networking/libiproute/ipaddress.c busybox/networking/libiproute/ipaddress.c | |
34400 | --- busybox-1.00/networking/libiproute/ipaddress.c 2004-03-15 09:28:56.000000000 +0100 | |
34401 | +++ busybox/networking/libiproute/ipaddress.c 2005-06-04 08:20:04.000000000 +0200 | |
34402 | @@ -48,7 +48,7 @@ | |
34403 | struct rtnl_handle *rth; | |
34404 | } filter; | |
34405 | ||
34406 | -void print_link_flags(FILE *fp, unsigned flags, unsigned mdown) | |
34407 | +static void print_link_flags(FILE *fp, unsigned flags, unsigned mdown) | |
34408 | { | |
34409 | fprintf(fp, "<"); | |
34410 | flags &= ~IFF_RUNNING; | |
34411 | diff -Nur busybox-1.00/networking/libiproute/iptunnel.c busybox/networking/libiproute/iptunnel.c | |
34412 | --- busybox-1.00/networking/libiproute/iptunnel.c 2004-04-26 21:32:49.000000000 +0200 | |
34413 | +++ busybox/networking/libiproute/iptunnel.c 2005-06-04 08:20:04.000000000 +0200 | |
34414 | @@ -361,7 +361,7 @@ | |
34415 | return -1; | |
34416 | } | |
34417 | ||
34418 | -int do_del(int argc, char **argv) | |
34419 | +static int do_del(int argc, char **argv) | |
34420 | { | |
34421 | struct ip_tunnel_parm p; | |
34422 | ||
34423 | @@ -381,7 +381,7 @@ | |
34424 | return -1; | |
34425 | } | |
34426 | ||
34427 | -void print_tunnel(struct ip_tunnel_parm *p) | |
34428 | +static void print_tunnel(struct ip_tunnel_parm *p) | |
34429 | { | |
34430 | char s1[256]; | |
34431 | char s2[256]; | |
34432 | diff -Nur busybox-1.00/networking/libiproute/ll_proto.c busybox/networking/libiproute/ll_proto.c | |
34433 | --- busybox-1.00/networking/libiproute/ll_proto.c 2004-03-15 09:28:56.000000000 +0100 | |
34434 | +++ busybox/networking/libiproute/ll_proto.c 2005-06-04 08:20:04.000000000 +0200 | |
34435 | @@ -90,7 +90,7 @@ | |
34436 | #undef __PF | |
34437 | ||
34438 | ||
34439 | -char * ll_proto_n2a(unsigned short id, char *buf, int len) | |
34440 | +const char * ll_proto_n2a(unsigned short id, char *buf, int len) | |
34441 | { | |
34442 | int i; | |
34443 | ||
34444 | diff -Nur busybox-1.00/networking/libiproute/ll_types.c busybox/networking/libiproute/ll_types.c | |
34445 | --- busybox-1.00/networking/libiproute/ll_types.c 2003-06-20 11:05:00.000000000 +0200 | |
34446 | +++ busybox/networking/libiproute/ll_types.c 2005-06-04 08:20:04.000000000 +0200 | |
34447 | @@ -13,7 +13,7 @@ | |
34448 | ||
34449 | #include <linux/if_arp.h> | |
34450 | ||
34451 | -char * ll_type_n2a(int type, char *buf, int len) | |
34452 | +const char * ll_type_n2a(int type, char *buf, int len) | |
34453 | { | |
34454 | #define __PF(f,n) { ARPHRD_##f, #n }, | |
34455 | static struct { | |
34456 | diff -Nur busybox-1.00/networking/libiproute/rt_names.c busybox/networking/libiproute/rt_names.c | |
34457 | --- busybox-1.00/networking/libiproute/rt_names.c 2002-12-16 08:37:21.000000000 +0100 | |
34458 | +++ busybox/networking/libiproute/rt_names.c 2005-06-04 08:20:04.000000000 +0200 | |
34459 | @@ -76,7 +76,7 @@ | |
34460 | rtnl_rtprot_tab, 256); | |
34461 | } | |
34462 | ||
34463 | -char * rtnl_rtprot_n2a(int id, char *buf, int len) | |
34464 | +const char * rtnl_rtprot_n2a(int id, char *buf, int len) | |
34465 | { | |
34466 | if (id<0 || id>=256) { | |
34467 | snprintf(buf, len, "%d", id); | |
34468 | @@ -143,7 +143,7 @@ | |
34469 | rtnl_rtscope_tab, 256); | |
34470 | } | |
34471 | ||
34472 | -char * rtnl_rtscope_n2a(int id, char *buf, int len) | |
34473 | +const char * rtnl_rtscope_n2a(int id, char *buf, int len) | |
34474 | { | |
34475 | if (id<0 || id>=256) { | |
34476 | snprintf(buf, len, "%d", id); | |
34477 | @@ -206,7 +206,7 @@ | |
34478 | rtnl_rtrealm_tab, 256); | |
34479 | } | |
34480 | ||
34481 | -char * rtnl_rtrealm_n2a(int id, char *buf, int len) | |
34482 | +const char * rtnl_rtrealm_n2a(int id, char *buf, int len) | |
34483 | { | |
34484 | if (id<0 || id>=256) { | |
34485 | snprintf(buf, len, "%d", id); | |
34486 | @@ -272,7 +272,7 @@ | |
34487 | rtnl_rttable_tab, 256); | |
34488 | } | |
34489 | ||
34490 | -char * rtnl_rttable_n2a(int id, char *buf, int len) | |
34491 | +const char * rtnl_rttable_n2a(int id, char *buf, int len) | |
34492 | { | |
34493 | if (id<0 || id>=256) { | |
34494 | snprintf(buf, len, "%d", id); | |
34495 | @@ -334,7 +334,7 @@ | |
34496 | rtnl_rtdsfield_tab, 256); | |
34497 | } | |
34498 | ||
34499 | -char * rtnl_dsfield_n2a(int id, char *buf, int len) | |
34500 | +const char * rtnl_dsfield_n2a(int id, char *buf, int len) | |
34501 | { | |
34502 | if (id<0 || id>=256) { | |
34503 | snprintf(buf, len, "%d", id); | |
34504 | diff -Nur busybox-1.00/networking/libiproute/utils.c busybox/networking/libiproute/utils.c | |
34505 | --- busybox-1.00/networking/libiproute/utils.c 2003-03-19 10:12:42.000000000 +0100 | |
34506 | +++ busybox/networking/libiproute/utils.c 2005-06-04 08:20:04.000000000 +0200 | |
34507 | @@ -238,7 +238,7 @@ | |
34508 | return addr.data[0]; | |
34509 | } | |
34510 | ||
34511 | -void incomplete_command() | |
34512 | +void incomplete_command(void) | |
34513 | { | |
34514 | bb_error_msg("Command line is not complete. Try option \"help\""); | |
34515 | exit(-1); | |
34516 | diff -Nur busybox-1.00/networking/nameif.c busybox/networking/nameif.c | |
34517 | --- busybox-1.00/networking/nameif.c 2004-04-25 07:11:17.000000000 +0200 | |
34518 | +++ busybox/networking/nameif.c 2005-06-04 08:20:05.000000000 +0200 | |
34519 | @@ -86,7 +86,7 @@ | |
34520 | } | |
34521 | ||
34522 | /* Check ascii str_macaddr, convert and copy to *mac */ | |
34523 | -struct ether_addr *cc_macaddr(char *str_macaddr) | |
34524 | +static struct ether_addr *cc_macaddr(char *str_macaddr) | |
34525 | { | |
34526 | struct ether_addr *lmac, *mac; | |
34527 | ||
34528 | diff -Nur busybox-1.00/networking/nc.c busybox/networking/nc.c | |
34529 | --- busybox-1.00/networking/nc.c 2004-03-27 11:02:43.000000000 +0100 | |
34530 | +++ busybox/networking/nc.c 2005-06-04 08:20:05.000000000 +0200 | |
34531 | @@ -4,7 +4,7 @@ | |
34532 | ||
34533 | 0.0.1 6K It works. | |
34534 | 0.0.2 5K Smaller and you can also check the exit condition if you wish. | |
34535 | - 0.0.3 Uses select() | |
34536 | + 0.0.3 Uses select() | |
34537 | ||
34538 | 19980918 Busy Boxed! Dave Cinege | |
34539 | 19990512 Uses Select. Charles P. Wright | |
34540 | @@ -23,13 +23,13 @@ | |
34541 | You should have received a copy of the GNU General Public License | |
34542 | along with this program; if not, write to the Free Software | |
34543 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
34544 | - | |
34545 | */ | |
34546 | ||
34547 | #include <stdio.h> | |
34548 | #include <stdlib.h> | |
34549 | #include <string.h> | |
34550 | #include <unistd.h> | |
34551 | +#include <signal.h> | |
34552 | ||
34553 | #include <sys/types.h> | |
34554 | #include <sys/socket.h> | |
34555 | @@ -40,14 +40,17 @@ | |
34556 | #include <sys/ioctl.h> | |
34557 | #include "busybox.h" | |
34558 | ||
34559 | -#define GAPING_SECURITY_HOLE | |
34560 | +static void timeout(int signum) | |
34561 | +{ | |
34562 | + bb_error_msg_and_die("Timed out"); | |
34563 | +} | |
34564 | ||
34565 | int nc_main(int argc, char **argv) | |
34566 | { | |
34567 | - int do_listen = 0, lport = 0, delay = 0, tmpfd, opt, sfd, x; | |
34568 | + int do_listen = 0, lport = 0, delay = 0, wsecs = 0, tmpfd, opt, sfd, x; | |
34569 | char buf[BUFSIZ]; | |
34570 | -#ifdef GAPING_SECURITY_HOLE | |
34571 | - char * pr00gie = NULL; | |
34572 | +#ifdef CONFIG_NC_GAPING_SECURITY_HOLE | |
34573 | + char *pr00gie = NULL; | |
34574 | #endif | |
34575 | ||
34576 | struct sockaddr_in address; | |
34577 | @@ -55,7 +58,7 @@ | |
34578 | ||
34579 | fd_set readfds, testfds; | |
34580 | ||
34581 | - while ((opt = getopt(argc, argv, "lp:i:e:")) > 0) { | |
34582 | + while ((opt = getopt(argc, argv, "lp:i:e:w:")) > 0) { | |
34583 | switch (opt) { | |
34584 | case 'l': | |
34585 | do_listen++; | |
34586 | @@ -66,23 +69,25 @@ | |
34587 | case 'i': | |
34588 | delay = atoi(optarg); | |
34589 | break; | |
34590 | -#ifdef GAPING_SECURITY_HOLE | |
34591 | +#ifdef CONFIG_NC_GAPING_SECURITY_HOLE | |
34592 | case 'e': | |
34593 | pr00gie = optarg; | |
34594 | break; | |
34595 | #endif | |
34596 | + case 'w': | |
34597 | + wsecs = atoi(optarg); | |
34598 | + break; | |
34599 | default: | |
34600 | bb_show_usage(); | |
34601 | } | |
34602 | } | |
34603 | ||
34604 | -#ifdef GAPING_SECURITY_HOLE | |
34605 | +#ifdef CONFIG_NC_GAPING_SECURITY_HOLE | |
34606 | if (pr00gie) { | |
34607 | /* won't need stdin */ | |
34608 | - close (STDIN_FILENO); | |
34609 | + close(STDIN_FILENO); | |
34610 | } | |
34611 | -#endif /* GAPING_SECURITY_HOLE */ | |
34612 | - | |
34613 | +#endif /* CONFIG_NC_GAPING_SECURITY_HOLE */ | |
34614 | ||
34615 | if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc)) | |
34616 | bb_show_usage(); | |
34617 | @@ -90,10 +95,15 @@ | |
34618 | if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) | |
34619 | bb_perror_msg_and_die("socket"); | |
34620 | x = 1; | |
34621 | - if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1) | |
34622 | - bb_perror_msg_and_die ("reuseaddr failed"); | |
34623 | + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1) | |
34624 | + bb_perror_msg_and_die("reuseaddr"); | |
34625 | address.sin_family = AF_INET; | |
34626 | ||
34627 | + if (wsecs) { | |
34628 | + signal(SIGALRM, timeout); | |
34629 | + alarm(wsecs); | |
34630 | + } | |
34631 | + | |
34632 | if (lport != 0) { | |
34633 | memset(&address.sin_addr, 0, sizeof(address.sin_addr)); | |
34634 | address.sin_port = lport; | |
34635 | @@ -123,19 +133,23 @@ | |
34636 | bb_perror_msg_and_die("connect"); | |
34637 | } | |
34638 | ||
34639 | -#ifdef GAPING_SECURITY_HOLE | |
34640 | + if (wsecs) { | |
34641 | + alarm(0); | |
34642 | + signal(SIGALRM, SIG_DFL); | |
34643 | + } | |
34644 | + | |
34645 | +#ifdef CONFIG_NC_GAPING_SECURITY_HOLE | |
34646 | /* -e given? */ | |
34647 | if (pr00gie) { | |
34648 | dup2(sfd, 0); | |
34649 | close(sfd); | |
34650 | - dup2 (0, 1); | |
34651 | - dup2 (0, 2); | |
34652 | - execl (pr00gie, pr00gie, NULL); | |
34653 | + dup2(0, 1); | |
34654 | + dup2(0, 2); | |
34655 | + execl(pr00gie, pr00gie, NULL); | |
34656 | /* Don't print stuff or it will go over the wire.... */ | |
34657 | _exit(-1); | |
34658 | } | |
34659 | -#endif /* GAPING_SECURITY_HOLE */ | |
34660 | - | |
34661 | +#endif /* CONFIG_NC_GAPING_SECURITY_HOLE */ | |
34662 | ||
34663 | FD_ZERO(&readfds); | |
34664 | FD_SET(sfd, &readfds); | |
34665 | @@ -154,7 +168,7 @@ | |
34666 | for (fd = 0; fd < FD_SETSIZE; fd++) { | |
34667 | if (FD_ISSET(fd, &testfds)) { | |
34668 | if ((nread = safe_read(fd, buf, sizeof(buf))) < 0) | |
34669 | - bb_perror_msg_and_die("read"); | |
34670 | + bb_perror_msg_and_die(bb_msg_read_error); | |
34671 | ||
34672 | if (fd == sfd) { | |
34673 | if (nread == 0) | |
34674 | @@ -167,7 +181,7 @@ | |
34675 | } | |
34676 | ||
34677 | if (bb_full_write(ofd, buf, nread) < 0) | |
34678 | - bb_perror_msg_and_die("write"); | |
34679 | + bb_perror_msg_and_die(bb_msg_write_error); | |
34680 | if (delay > 0) { | |
34681 | sleep(delay); | |
34682 | } | |
34683 | diff -Nur busybox-1.00/networking/nslookup.c busybox/networking/nslookup.c | |
34684 | --- busybox-1.00/networking/nslookup.c 2004-10-13 09:25:01.000000000 +0200 | |
34685 | +++ busybox/networking/nslookup.c 2005-06-04 08:20:05.000000000 +0200 | |
34686 | @@ -203,4 +203,4 @@ | |
34687 | return EXIT_FAILURE; | |
34688 | } | |
34689 | ||
34690 | -/* $Id$ */ | |
34691 | +/* $Id$ */ | |
34692 | diff -Nur busybox-1.00/networking/ping.c busybox/networking/ping.c | |
34693 | --- busybox-1.00/networking/ping.c 2004-03-15 09:28:48.000000000 +0100 | |
34694 | +++ busybox/networking/ping.c 2005-06-04 08:20:05.000000000 +0200 | |
34695 | @@ -1,6 +1,6 @@ | |
34696 | /* vi: set sw=4 ts=4: */ | |
34697 | /* | |
34698 | - * $Id$ | |
34699 | + * $Id$ | |
34700 | * Mini ping implementation for busybox | |
34701 | * | |
34702 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | |
34703 | @@ -178,7 +178,10 @@ | |
34704 | static unsigned long tmin = ULONG_MAX, tmax, tsum; | |
34705 | static char rcvd_tbl[MAX_DUP_CHK / 8]; | |
34706 | ||
34707 | -struct hostent *hostent; | |
34708 | +#ifndef CONFIG_FEATURE_FANCY_PING6 | |
34709 | +static | |
34710 | +#endif | |
34711 | + struct hostent *hostent; | |
34712 | ||
34713 | static void sendping(int); | |
34714 | static void pingstats(int); | |
34715 | diff -Nur busybox-1.00/networking/ping6.c busybox/networking/ping6.c | |
34716 | --- busybox-1.00/networking/ping6.c 2004-03-15 09:28:48.000000000 +0100 | |
34717 | +++ busybox/networking/ping6.c 2005-06-04 08:20:05.000000000 +0200 | |
34718 | @@ -1,6 +1,6 @@ | |
34719 | /* vi: set sw=4 ts=4: */ | |
34720 | /* | |
34721 | - * $Id$ | |
34722 | + * $Id$ | |
34723 | * Mini ping implementation for busybox | |
34724 | * | |
34725 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | |
34726 | diff -Nur busybox-1.00/networking/route.c busybox/networking/route.c | |
34727 | --- busybox-1.00/networking/route.c 2004-03-20 00:27:08.000000000 +0100 | |
34728 | +++ busybox/networking/route.c 2005-06-04 08:20:05.000000000 +0200 | |
34729 | @@ -15,7 +15,7 @@ | |
34730 | * Foundation; either version 2 of the License, or (at | |
34731 | * your option) any later version. | |
34732 | * | |
34733 | - * $Id$ | |
34734 | + * $Id$ | |
34735 | * | |
34736 | * displayroute() code added by Vladimir N. Oleynik <dzo@simtreas.ru> | |
34737 | * adjustments by Larry Doolittle <LRDoolittle@lbl.gov> | |
34738 | @@ -485,6 +485,7 @@ | |
34739 | } | |
34740 | } | |
34741 | ||
34742 | +/* also used in netstat */ | |
34743 | void displayroutes(int noresolve, int netstatfmt) | |
34744 | { | |
34745 | char devname[64], flags[16], sdest[16], sgw[16]; | |
34746 | diff -Nur busybox-1.00/networking/telnetd.c busybox/networking/telnetd.c | |
34747 | --- busybox-1.00/networking/telnetd.c 2004-09-14 19:24:58.000000000 +0200 | |
34748 | +++ busybox/networking/telnetd.c 2005-06-04 08:20:05.000000000 +0200 | |
34749 | @@ -1,4 +1,4 @@ | |
34750 | -/* $Id$ | |
34751 | +/* $Id$ | |
34752 | * | |
34753 | * Simple telnet server | |
34754 | * Bjorn Wesen, Axis Communications AB (bjornw@axis.com) | |
34755 | @@ -49,6 +49,15 @@ | |
34756 | ||
34757 | #define BUFSIZE 4000 | |
34758 | ||
34759 | +#ifdef CONFIG_FEATURE_IPV6 | |
34760 | +#define SOCKET_TYPE AF_INET6 | |
34761 | +typedef struct sockaddr_in6 sockaddr_type; | |
34762 | +#else | |
34763 | +#define SOCKET_TYPE AF_INET | |
34764 | +typedef struct sockaddr_in sockaddr_type; | |
34765 | +#endif | |
34766 | + | |
34767 | + | |
34768 | #ifdef CONFIG_LOGIN | |
34769 | static const char *loginpath = "/bin/login"; | |
34770 | #else | |
34771 | @@ -373,7 +382,7 @@ | |
34772 | telnetd_main(int argc, char **argv) | |
34773 | { | |
34774 | #ifndef CONFIG_FEATURE_TELNETD_INETD | |
34775 | - struct sockaddr_in sa; | |
34776 | + sockaddr_type sa; | |
34777 | int master_fd; | |
34778 | #endif /* CONFIG_FEATURE_TELNETD_INETD */ | |
34779 | fd_set rdfdset, wrfdset; | |
34780 | @@ -431,7 +440,7 @@ | |
34781 | ||
34782 | /* Grab a TCP socket. */ | |
34783 | ||
34784 | - master_fd = socket(AF_INET, SOCK_STREAM, 0); | |
34785 | + master_fd = socket(SOCKET_TYPE, SOCK_STREAM, 0); | |
34786 | if (master_fd < 0) { | |
34787 | bb_perror_msg_and_die("socket"); | |
34788 | } | |
34789 | @@ -440,8 +449,13 @@ | |
34790 | /* Set it to listen to specified port. */ | |
34791 | ||
34792 | memset((void *)&sa, 0, sizeof(sa)); | |
34793 | +#ifdef CONFIG_FEATURE_IPV6 | |
34794 | + sa.sin6_family = AF_INET6; | |
34795 | + sa.sin6_port = htons(portnbr); | |
34796 | +#else | |
34797 | sa.sin_family = AF_INET; | |
34798 | sa.sin_port = htons(portnbr); | |
34799 | +#endif | |
34800 | ||
34801 | if (bind(master_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { | |
34802 | bb_perror_msg_and_die("bind"); | |
34803 | diff -Nur busybox-1.00/networking/tftp.c busybox/networking/tftp.c | |
34804 | --- busybox-1.00/networking/tftp.c 2004-09-14 19:24:58.000000000 +0200 | |
34805 | +++ busybox/networking/tftp.c 2005-06-04 08:20:05.000000000 +0200 | |
34806 | @@ -71,8 +71,8 @@ | |
34807 | "No such user" | |
34808 | }; | |
34809 | ||
34810 | -const int tftp_cmd_get = 1; | |
34811 | -const int tftp_cmd_put = 2; | |
34812 | +static const int tftp_cmd_get = 1; | |
34813 | +static const int tftp_cmd_put = 2; | |
34814 | ||
34815 | #ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE | |
34816 | ||
34817 | diff -Nur busybox-1.00/networking/udhcp/README.udhcpc busybox/networking/udhcp/README.udhcpc | |
34818 | --- busybox-1.00/networking/udhcp/README.udhcpc 2004-03-15 09:29:00.000000000 +0100 | |
34819 | +++ busybox/networking/udhcp/README.udhcpc 2005-06-04 08:20:05.000000000 +0200 | |
34820 | @@ -12,7 +12,8 @@ | |
34821 | ||
34822 | -c, --clientid=CLIENTID Client identifier | |
34823 | -H, --hostname=HOSTNAME Client hostname | |
34824 | --h, Alias for -H | |
34825 | +-h, Alias for -H | |
34826 | +-F, --fqdn=FQDN Client fully qualified domain name | |
34827 | -f, --foreground Do not fork after getting lease | |
34828 | -b, --background Fork to background if lease cannot be | |
34829 | immediately negotiated. | |
34830 | diff -Nur busybox-1.00/networking/udhcp/clientpacket.c busybox/networking/udhcp/clientpacket.c | |
34831 | --- busybox-1.00/networking/udhcp/clientpacket.c 2004-04-14 19:51:25.000000000 +0200 | |
34832 | +++ busybox/networking/udhcp/clientpacket.c 2005-06-04 08:20:05.000000000 +0200 | |
34833 | @@ -78,6 +78,7 @@ | |
34834 | memcpy(packet->chaddr, client_config.arp, 6); | |
34835 | add_option_string(packet->options, client_config.clientid); | |
34836 | if (client_config.hostname) add_option_string(packet->options, client_config.hostname); | |
34837 | + if (client_config.fqdn) add_option_string(packet->options, client_config.fqdn); | |
34838 | add_option_string(packet->options, (uint8_t *) &vendor_id); | |
34839 | } | |
34840 | ||
34841 | diff -Nur busybox-1.00/networking/udhcp/dhcpc.c busybox/networking/udhcp/dhcpc.c | |
34842 | --- busybox-1.00/networking/udhcp/dhcpc.c 2004-05-19 10:29:05.000000000 +0200 | |
34843 | +++ busybox/networking/udhcp/dhcpc.c 2005-06-04 08:20:05.000000000 +0200 | |
34844 | @@ -58,17 +58,18 @@ | |
34845 | ||
34846 | struct client_config_t client_config = { | |
34847 | /* Default options. */ | |
34848 | - abort_if_no_lease: 0, | |
34849 | - foreground: 0, | |
34850 | - quit_after_lease: 0, | |
34851 | - background_if_no_lease: 0, | |
34852 | - interface: "eth0", | |
34853 | - pidfile: NULL, | |
34854 | - script: DEFAULT_SCRIPT, | |
34855 | - clientid: NULL, | |
34856 | - hostname: NULL, | |
34857 | - ifindex: 0, | |
34858 | - arp: "\0\0\0\0\0\0", /* appease gcc-3.0 */ | |
34859 | + .abort_if_no_lease = 0, | |
34860 | + .foreground = 0, | |
34861 | + .quit_after_lease = 0, | |
34862 | + .background_if_no_lease = 0, | |
34863 | + .interface = "eth0", | |
34864 | + .pidfile = NULL, | |
34865 | + .script = DEFAULT_SCRIPT, | |
34866 | + .clientid = NULL, | |
34867 | + .hostname = NULL, | |
34868 | + .fqdn = NULL, | |
34869 | + .ifindex = 0, | |
34870 | + .arp = "\0\0\0\0\0\0", /* appease gcc-3.0 */ | |
34871 | }; | |
34872 | ||
34873 | #ifndef IN_BUSYBOX | |
34874 | @@ -79,6 +80,7 @@ | |
34875 | " -c, --clientid=CLIENTID Client identifier\n" | |
34876 | " -H, --hostname=HOSTNAME Client hostname\n" | |
34877 | " -h Alias for -H\n" | |
34878 | +" -F, --fqdn=FQDN Client fully qualified domain name\n" | |
34879 | " -f, --foreground Do not fork after getting lease\n" | |
34880 | " -b, --background Fork to background if lease cannot be\n" | |
34881 | " immediately negotiated.\n" | |
34882 | @@ -197,7 +199,8 @@ | |
34883 | {"foreground", no_argument, 0, 'f'}, | |
34884 | {"background", no_argument, 0, 'b'}, | |
34885 | {"hostname", required_argument, 0, 'H'}, | |
34886 | - {"hostname", required_argument, 0, 'h'}, | |
34887 | + {"hostname", required_argument, 0, 'h'}, | |
34888 | + {"fqdn", required_argument, 0, 'F'}, | |
34889 | {"interface", required_argument, 0, 'i'}, | |
34890 | {"now", no_argument, 0, 'n'}, | |
34891 | {"pidfile", required_argument, 0, 'p'}, | |
34892 | @@ -211,7 +214,7 @@ | |
34893 | /* get options */ | |
34894 | while (1) { | |
34895 | int option_index = 0; | |
34896 | - c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:v", arg_options, &option_index); | |
34897 | + c = getopt_long(argc, argv, "c:fbH:h:F:i:np:qr:s:v", arg_options, &option_index); | |
34898 | if (c == -1) break; | |
34899 | ||
34900 | switch (c) { | |
34901 | @@ -239,6 +242,23 @@ | |
34902 | client_config.hostname[OPT_LEN] = len; | |
34903 | strncpy(client_config.hostname + 2, optarg, len); | |
34904 | break; | |
34905 | + case 'F': | |
34906 | + len = strlen(optarg) > 255 ? 255 : strlen(optarg); | |
34907 | + if (client_config.fqdn) free(client_config.fqdn); | |
34908 | + client_config.fqdn = xmalloc(len + 5); | |
34909 | + client_config.fqdn[OPT_CODE] = DHCP_FQDN; | |
34910 | + client_config.fqdn[OPT_LEN] = len + 3; | |
34911 | + /* Flags: 0000NEOS | |
34912 | + S: 1 => Client requests Server to update A RR in DNS as well as PTR | |
34913 | + O: 1 => Server indicates to client that DNS has been updated regardless | |
34914 | + E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com" | |
34915 | + N: 1 => Client requests Server to not update DNS | |
34916 | + */ | |
34917 | + client_config.fqdn[OPT_LEN + 1] = 0x1; | |
34918 | + client_config.fqdn[OPT_LEN + 2] = 0; | |
34919 | + client_config.fqdn[OPT_LEN + 3] = 0; | |
34920 | + strncpy(client_config.fqdn + 5, optarg, len); | |
34921 | + break; | |
34922 | case 'i': | |
34923 | client_config.interface = optarg; | |
34924 | break; | |
34925 | @@ -419,6 +439,9 @@ | |
34926 | (unsigned long) packet.xid, xid); | |
34927 | continue; | |
34928 | } | |
34929 | + /* Ignore packets that aren't for us */ | |
34930 | + if (memcmp(client_config.arp,packet.chaddr,6)) | |
34931 | + continue; | |
34932 | ||
34933 | if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { | |
34934 | DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); | |
34935 | diff -Nur busybox-1.00/networking/udhcp/dhcpc.h busybox/networking/udhcp/dhcpc.h | |
34936 | --- busybox-1.00/networking/udhcp/dhcpc.h 2004-01-31 00:45:12.000000000 +0100 | |
34937 | +++ busybox/networking/udhcp/dhcpc.h 2005-06-04 08:20:05.000000000 +0200 | |
34938 | @@ -27,6 +27,7 @@ | |
34939 | char *script; /* User script to run at dhcp events */ | |
34940 | uint8_t *clientid; /* Optional client id to use */ | |
34941 | uint8_t *hostname; /* Optional hostname to use */ | |
34942 | + uint8_t *fqdn; /* Optional fully qualified domain name to use */ | |
34943 | int ifindex; /* Index number of the interface to use */ | |
34944 | uint8_t arp[6]; /* Our arp address */ | |
34945 | }; | |
34946 | diff -Nur busybox-1.00/networking/udhcp/dhcpd.h busybox/networking/udhcp/dhcpd.h | |
34947 | --- busybox-1.00/networking/udhcp/dhcpd.h 2004-10-08 10:49:26.000000000 +0200 | |
34948 | +++ busybox/networking/udhcp/dhcpd.h 2005-06-04 08:20:05.000000000 +0200 | |
34949 | @@ -63,6 +63,7 @@ | |
34950 | #define DHCP_T2 0x3b | |
34951 | #define DHCP_VENDOR 0x3c | |
34952 | #define DHCP_CLIENT_ID 0x3d | |
34953 | +#define DHCP_FQDN 0x51 | |
34954 | ||
34955 | #define DHCP_END 0xFF | |
34956 | ||
34957 | diff -Nur busybox-1.00/networking/udhcp/options.c busybox/networking/udhcp/options.c | |
34958 | --- busybox-1.00/networking/udhcp/options.c 2004-03-15 09:29:01.000000000 +0100 | |
34959 | +++ busybox/networking/udhcp/options.c 2005-06-04 08:20:05.000000000 +0200 | |
34960 | @@ -32,7 +32,9 @@ | |
34961 | {"ipttl", OPTION_U8, 0x17}, | |
34962 | {"mtu", OPTION_U16, 0x1a}, | |
34963 | {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, | |
34964 | - {"ntpsrv", OPTION_IP | OPTION_LIST, 0x2a}, | |
34965 | + {"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, | |
34966 | + {"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, | |
34967 | + {"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, | |
34968 | {"wins", OPTION_IP | OPTION_LIST, 0x2c}, | |
34969 | {"requestip", OPTION_IP, 0x32}, | |
34970 | {"lease", OPTION_U32, 0x33}, | |
34971 | diff -Nur busybox-1.00/networking/udhcp/script.h busybox/networking/udhcp/script.h | |
34972 | --- busybox-1.00/networking/udhcp/script.h 2002-10-14 23:41:27.000000000 +0200 | |
34973 | +++ busybox/networking/udhcp/script.h 2005-06-04 08:20:05.000000000 +0200 | |
34974 | @@ -1,6 +1,6 @@ | |
34975 | #ifndef _SCRIPT_H | |
34976 | #define _SCRIPT_H | |
34977 | ||
34978 | -void run_script(struct dhcpMessage *packet, const char *name); | |
34979 | +extern void run_script(struct dhcpMessage *packet, const char *name); | |
34980 | ||
34981 | #endif | |
34982 | diff -Nur busybox-1.00/networking/wget.c busybox/networking/wget.c | |
34983 | --- busybox-1.00/networking/wget.c 2004-10-08 10:27:40.000000000 +0200 | |
34984 | +++ busybox/networking/wget.c 2005-06-04 08:20:05.000000000 +0200 | |
34985 | @@ -117,9 +117,9 @@ | |
34986 | /* | |
34987 | * Base64-encode character string | |
34988 | * oops... isn't something similar in uuencode.c? | |
34989 | - * It would be better to use already existing code | |
34990 | + * XXX: It would be better to use already existing code | |
34991 | */ | |
34992 | -char *base64enc(unsigned char *p, char *buf, int len) { | |
34993 | +static char *base64enc(unsigned char *p, char *buf, int len) { | |
34994 | ||
34995 | char al[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | |
34996 | "0123456789+/"; | |
34997 | @@ -854,7 +854,7 @@ | |
34998 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34999 | * SUCH DAMAGE. | |
35000 | * | |
35001 | - * $Id$ | |
35002 | + * $Id$ | |
35003 | */ | |
35004 | ||
35005 | ||
35006 | diff -Nur busybox-1.00/networking/zcip.c busybox/networking/zcip.c | |
35007 | --- busybox-1.00/networking/zcip.c 1970-01-01 01:00:00.000000000 +0100 | |
35008 | +++ busybox/networking/zcip.c 2005-06-04 08:20:05.000000000 +0200 | |
35009 | @@ -0,0 +1,550 @@ | |
35010 | +/* | |
35011 | + * RFC3927 ZeroConf IPv4 Link-Local addressing | |
35012 | + * (see <http://www.zeroconf.org/>) | |
35013 | + * | |
35014 | + * Copyright (C) 2003 by Arthur van Hoff (avh@strangeberry.com) | |
35015 | + * Copyright (C) 2004 by David Brownell | |
35016 | + * | |
35017 | + * This program is free software; you can redistribute it and/or modify | |
35018 | + * it under the terms of the GNU General Public License as published by | |
35019 | + * the Free Software Foundation; either version 2 of the License, or | |
35020 | + * (at your option) any later version. | |
35021 | + * | |
35022 | + * This program is distributed in the hope that it will be useful, | |
35023 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
35024 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
35025 | + * General Public License for more details. | |
35026 | + * | |
35027 | + * You should have received a copy of the GNU General Public License | |
35028 | + * along with this program; if not, write to the Free Software | |
35029 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
35030 | + * 02111-1307 USA | |
35031 | + */ | |
35032 | + | |
35033 | +/* | |
35034 | + * This can build as part of BusyBox or by itself: | |
35035 | + * | |
35036 | + * $(CROSS_COMPILE)cc -Os -Wall -DNO_BUSYBOX -DDEBUG -o zcip zcip.c | |
35037 | + * | |
35038 | + * ZCIP just manages the 169.254.*.* addresses. That network is not | |
35039 | + * routed at the IP level, though various proxies or bridges can | |
35040 | + * certainly be used. Its naming is built over multicast DNS. | |
35041 | + */ | |
35042 | + | |
35043 | +// #define DEBUG | |
35044 | + | |
35045 | +// TODO: | |
35046 | +// - more real-world usage/testing, especially daemon mode | |
35047 | +// - kernel packet filters to reduce scheduling noise | |
35048 | +// - avoid silent script failures, especially under load... | |
35049 | +// - link status monitoring (restart on link-up; stop on link-down) | |
35050 | + | |
35051 | +#include <errno.h> | |
35052 | +#include <stdlib.h> | |
35053 | +#include <stdio.h> | |
35054 | +#include <string.h> | |
35055 | +#include <syslog.h> | |
35056 | +#include <poll.h> | |
35057 | +#include <time.h> | |
35058 | +#include <unistd.h> | |
35059 | + | |
35060 | +#include <sys/ioctl.h> | |
35061 | +#include <sys/types.h> | |
35062 | +#include <sys/wait.h> | |
35063 | +#include <sys/time.h> | |
35064 | +#include <sys/socket.h> | |
35065 | + | |
35066 | +#include <arpa/inet.h> | |
35067 | +#include <netinet/in.h> | |
35068 | +#include <netinet/ether.h> | |
35069 | +#include <net/ethernet.h> | |
35070 | +#include <net/if.h> | |
35071 | +#include <net/if_arp.h> | |
35072 | + | |
35073 | +#include <linux/if_packet.h> | |
35074 | +#include <linux/sockios.h> | |
35075 | + | |
35076 | + | |
35077 | +struct arp_packet { | |
35078 | + struct ether_header hdr; | |
35079 | + // FIXME this part is netinet/if_ether.h "struct ether_arp" | |
35080 | + struct arphdr arp; | |
35081 | + struct ether_addr source_addr; | |
35082 | + struct in_addr source_ip; | |
35083 | + struct ether_addr target_addr; | |
35084 | + struct in_addr target_ip; | |
35085 | +} __attribute__ ((__packed__)); | |
35086 | + | |
35087 | +/* 169.254.0.0 */ | |
35088 | +static const uint32_t LINKLOCAL_ADDR = 0xa9fe0000; | |
35089 | + | |
35090 | +/* protocol timeout parameters, specified in seconds */ | |
35091 | +static const unsigned PROBE_WAIT = 1; | |
35092 | +static const unsigned PROBE_MIN = 1; | |
35093 | +static const unsigned PROBE_MAX = 2; | |
35094 | +static const unsigned PROBE_NUM = 3; | |
35095 | +static const unsigned MAX_CONFLICTS = 10; | |
35096 | +static const unsigned RATE_LIMIT_INTERVAL = 60; | |
35097 | +static const unsigned ANNOUNCE_WAIT = 2; | |
35098 | +static const unsigned ANNOUNCE_NUM = 2; | |
35099 | +static const unsigned ANNOUNCE_INTERVAL = 2; | |
35100 | +static const time_t DEFEND_INTERVAL = 10; | |
35101 | + | |
35102 | +static const unsigned char ZCIP_VERSION[] = "0.75 (18 April 2005)"; | |
35103 | +static char *prog; | |
35104 | + | |
35105 | +static const struct in_addr null_ip = { 0 }; | |
35106 | +static const struct ether_addr null_addr = { {0, 0, 0, 0, 0, 0} }; | |
35107 | + | |
35108 | +static int verbose = 0; | |
35109 | + | |
35110 | +#ifdef DEBUG | |
35111 | + | |
35112 | +#define DBG(fmt,args...) \ | |
35113 | + fprintf(stderr, "%s: " fmt , prog , ## args) | |
35114 | +#define VDBG(fmt,args...) do { \ | |
35115 | + if (verbose) fprintf(stderr, "%s: " fmt , prog ,## args); \ | |
35116 | + } while (0) | |
35117 | +#else | |
35118 | + | |
35119 | +#define DBG(fmt,args...) \ | |
35120 | + do { } while (0) | |
35121 | +#define VDBG DBG | |
35122 | +#endif /* DEBUG */ | |
35123 | + | |
35124 | +/** | |
35125 | + * Pick a random link local IP address on 169.254/16, except that | |
35126 | + * the first and last 256 addresses are reserved. | |
35127 | + */ | |
35128 | +static void | |
35129 | +pick(struct in_addr *ip) | |
35130 | +{ | |
35131 | + unsigned tmp; | |
35132 | + | |
35133 | + /* use cheaper math than lrand48() mod N */ | |
35134 | + do { | |
35135 | + tmp = (lrand48() >> 16) & IN_CLASSB_HOST; | |
35136 | + } while (tmp > (IN_CLASSB_HOST - 0x0200)); | |
35137 | + ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp); | |
35138 | +} | |
35139 | + | |
35140 | +/** | |
35141 | + * Broadcast an ARP packet. | |
35142 | + */ | |
35143 | +static int | |
35144 | +arp(int fd, struct sockaddr *saddr, int op, | |
35145 | + const struct ether_addr *source_addr, struct in_addr source_ip, | |
35146 | + const struct ether_addr *target_addr, struct in_addr target_ip) | |
35147 | +{ | |
35148 | + struct arp_packet p; | |
35149 | + | |
35150 | + // ether header | |
35151 | + p.hdr.ether_type = htons(ETHERTYPE_ARP); | |
35152 | + memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN); | |
35153 | + memset(p.hdr.ether_dhost, 0xff, ETH_ALEN); | |
35154 | + | |
35155 | + // arp request | |
35156 | + p.arp.ar_hrd = htons(ARPHRD_ETHER); | |
35157 | + p.arp.ar_pro = htons(ETHERTYPE_IP); | |
35158 | + p.arp.ar_hln = ETH_ALEN; | |
35159 | + p.arp.ar_pln = 4; | |
35160 | + p.arp.ar_op = htons(op); | |
35161 | + memcpy(&p.source_addr, source_addr, ETH_ALEN); | |
35162 | + memcpy(&p.source_ip, &source_ip, sizeof (p.source_ip)); | |
35163 | + memcpy(&p.target_addr, target_addr, ETH_ALEN); | |
35164 | + memcpy(&p.target_ip, &target_ip, sizeof (p.target_ip)); | |
35165 | + | |
35166 | + // send it | |
35167 | + if (sendto(fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0) { | |
35168 | + perror("sendto"); | |
35169 | + return -errno; | |
35170 | + } | |
35171 | + return 0; | |
35172 | +} | |
35173 | + | |
35174 | +/** | |
35175 | + * Run a script. | |
35176 | + */ | |
35177 | +static int | |
35178 | +run(char *script, char *arg, char *intf, struct in_addr *ip) | |
35179 | +{ | |
35180 | + int pid, status; | |
35181 | + char *why; | |
35182 | + | |
35183 | + if (script != NULL) { | |
35184 | + VDBG("%s run %s %s\n", intf, script, arg); | |
35185 | + if (ip != NULL) { | |
35186 | + char *addr = inet_ntoa(*ip); | |
35187 | + setenv("ip", addr, 1); | |
35188 | + syslog(LOG_INFO, "%s %s %s", arg, intf, addr); | |
35189 | + } | |
35190 | + | |
35191 | + pid = vfork(); | |
35192 | + if (pid < 0) { // error | |
35193 | + why = "vfork"; | |
35194 | + goto bad; | |
35195 | + } else if (pid == 0) { // child | |
35196 | + execl(script, script, arg, NULL); | |
35197 | + perror("execl"); | |
35198 | + _exit(EXIT_FAILURE); | |
35199 | + } | |
35200 | + | |
35201 | + if (waitpid(pid, &status, 0) <= 0) { | |
35202 | + why = "waitpid"; | |
35203 | + goto bad; | |
35204 | + } | |
35205 | + if (WEXITSTATUS(status) != 0) { | |
35206 | + fprintf(stderr, "%s: script %s failed, exit=%d\n", | |
35207 | + prog, script, WEXITSTATUS(status)); | |
35208 | + return -errno; | |
35209 | + } | |
35210 | + } | |
35211 | + return 0; | |
35212 | +bad: | |
35213 | + status = -errno; | |
35214 | + syslog(LOG_ERR, "%s %s, %s error: %s", | |
35215 | + arg, intf, why, strerror(errno)); | |
35216 | + return status; | |
35217 | +} | |
35218 | + | |
35219 | +#ifndef NO_BUSYBOX | |
35220 | +#include "busybox.h" | |
35221 | +#endif | |
35222 | + | |
35223 | +/** | |
35224 | + * Print usage information. | |
35225 | + */ | |
35226 | +static void __attribute__ ((noreturn)) | |
35227 | +usage(const char *msg) | |
35228 | +{ | |
35229 | + fprintf(stderr, "%s: %s\n", prog, msg); | |
35230 | +#ifdef NO_BUSYBOX | |
35231 | + fprintf(stderr, "Usage: %s [OPTIONS] ifname script\n" | |
35232 | + "\t-f foreground mode (implied by -v)\n" | |
35233 | + "\t-q quit after address (no daemon)\n" | |
35234 | + "\t-r 169.254.x.x request this address first\n" | |
35235 | + "\t-v verbose; show version\n", | |
35236 | + prog); | |
35237 | + exit(0); | |
35238 | +#else | |
35239 | + bb_show_usage(); | |
35240 | +#endif | |
35241 | +} | |
35242 | + | |
35243 | +/** | |
35244 | + * Return milliseconds of random delay, up to "secs" seconds. | |
35245 | + */ | |
35246 | +static inline unsigned | |
35247 | +ms_rdelay(unsigned secs) | |
35248 | +{ | |
35249 | + return lrand48() % (secs * 1000); | |
35250 | +} | |
35251 | + | |
35252 | +/** | |
35253 | + * main program | |
35254 | + */ | |
35255 | +int | |
35256 | +main(int argc, char *argv[]) | |
35257 | + __attribute__ ((weak, alias ("zcip_main"))); | |
35258 | + | |
35259 | +int zcip_main(int argc, char *argv[]) | |
35260 | +{ | |
35261 | + char *intf = NULL; | |
35262 | + char *script = NULL; | |
35263 | + int quit = 0; | |
35264 | + int foreground = 0; | |
35265 | + | |
35266 | + char *why; | |
35267 | + struct sockaddr saddr; | |
35268 | + struct ether_addr addr; | |
35269 | + struct in_addr ip = { 0 }; | |
35270 | + int fd; | |
35271 | + int ready = 0; | |
35272 | + suseconds_t timeout = 0; // milliseconds | |
35273 | + time_t defend = 0; | |
35274 | + unsigned conflicts = 0; | |
35275 | + unsigned nprobes = 0; | |
35276 | + unsigned nclaims = 0; | |
35277 | + int t; | |
35278 | + | |
35279 | + // parse commandline: prog [options] ifname script | |
35280 | + prog = argv[0]; | |
35281 | + while ((t = getopt(argc, argv, "fqr:v")) != EOF) { | |
35282 | + switch (t) { | |
35283 | + case 'f': | |
35284 | + foreground = 1; | |
35285 | + continue; | |
35286 | + case 'q': | |
35287 | + quit = 1; | |
35288 | + continue; | |
35289 | + case 'r': | |
35290 | + if (inet_aton(optarg, &ip) == 0 | |
35291 | + || (ntohl(ip.s_addr) & IN_CLASSB_NET) | |
35292 | + != LINKLOCAL_ADDR) { | |
35293 | + usage("invalid link address"); | |
35294 | + } | |
35295 | + continue; | |
35296 | + case 'v': | |
35297 | + if (!verbose) | |
35298 | + printf("%s: version %s\n", prog, ZCIP_VERSION); | |
35299 | + verbose++; | |
35300 | + foreground = 1; | |
35301 | + continue; | |
35302 | + default: | |
35303 | + usage("bad option"); | |
35304 | + } | |
35305 | + } | |
35306 | + if (optind < argc - 1) { | |
35307 | + intf = argv[optind++]; | |
35308 | + setenv("interface", intf, 1); | |
35309 | + script = argv[optind++]; | |
35310 | + } | |
35311 | + if (optind != argc || !intf) | |
35312 | + usage("wrong number of arguments"); | |
35313 | + openlog(prog, 0, LOG_DAEMON); | |
35314 | + | |
35315 | + // initialize the interface (modprobe, ifup, etc) | |
35316 | + if (run(script, "init", intf, NULL) < 0) | |
35317 | + return EXIT_FAILURE; | |
35318 | + | |
35319 | + // initialize saddr | |
35320 | + memset(&saddr, 0, sizeof (saddr)); | |
35321 | + strncpy(saddr.sa_data, intf, sizeof (saddr.sa_data)); | |
35322 | + | |
35323 | + // open an ARP socket | |
35324 | + if ((fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) < 0) { | |
35325 | + why = "open"; | |
35326 | +fail: | |
35327 | + foreground = 1; | |
35328 | + goto bad; | |
35329 | + } | |
35330 | + // bind to the interface's ARP socket | |
35331 | + if (bind(fd, &saddr, sizeof (saddr)) < 0) { | |
35332 | + why = "bind"; | |
35333 | + goto fail; | |
35334 | + } else { | |
35335 | + struct ifreq ifr; | |
35336 | + short seed[3]; | |
35337 | + | |
35338 | + // get the interface's ethernet address | |
35339 | + memset(&ifr, 0, sizeof (ifr)); | |
35340 | + strncpy(ifr.ifr_name, intf, sizeof (ifr.ifr_name)); | |
35341 | + if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { | |
35342 | + why = "get ethernet address"; | |
35343 | + goto fail; | |
35344 | + } | |
35345 | + memcpy(&addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); | |
35346 | + | |
35347 | + // start with some stable ip address, either a function of | |
35348 | + // the hardware address or else the last address we used. | |
35349 | + // NOTE: the sequence of addresses we try changes only | |
35350 | + // depending on when we detect conflicts. | |
35351 | + memcpy(seed, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); | |
35352 | + seed48(seed); | |
35353 | + if (ip.s_addr == 0) | |
35354 | + pick(&ip); | |
35355 | + } | |
35356 | + | |
35357 | + // FIXME cases to handle: | |
35358 | + // - zcip already running! | |
35359 | + // - link already has local address... just defend/update | |
35360 | + | |
35361 | + // daemonize now; don't delay system startup | |
35362 | + if (!foreground) { | |
35363 | + if (daemon(0, verbose) < 0) { | |
35364 | + why = "daemon"; | |
35365 | + goto bad; | |
35366 | + } | |
35367 | + syslog(LOG_INFO, "start, interface %s", intf); | |
35368 | + } | |
35369 | + | |
35370 | + // run the dynamic address negotiation protocol, | |
35371 | + // restarting after address conflicts: | |
35372 | + // - start with some address we want to try | |
35373 | + // - short random delay | |
35374 | + // - arp probes to see if another host else uses it | |
35375 | + // - arp announcements that we're claiming it | |
35376 | + // - use it | |
35377 | + // - defend it, within limits | |
35378 | + while (1) { | |
35379 | + struct pollfd fds[1]; | |
35380 | + struct timeval tv1; | |
35381 | + struct arp_packet p; | |
35382 | + | |
35383 | + fds[0].fd = fd; | |
35384 | + fds[0].events = POLLIN; | |
35385 | + fds[0].revents = 0; | |
35386 | + | |
35387 | + // poll, being ready to adjust current timeout | |
35388 | + if (timeout > 0) { | |
35389 | + gettimeofday(&tv1, NULL); | |
35390 | + tv1.tv_usec += (timeout % 1000) * 1000; | |
35391 | + while (tv1.tv_usec > 1000000) { | |
35392 | + tv1.tv_usec -= 1000000; | |
35393 | + tv1.tv_sec++; | |
35394 | + } | |
35395 | + tv1.tv_sec += timeout / 1000; | |
35396 | + } else if (timeout == 0) { | |
35397 | + timeout = ms_rdelay(PROBE_WAIT); | |
35398 | + // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to | |
35399 | + // make the kernel filter out all packets except | |
35400 | + // ones we'd care about. | |
35401 | + } | |
35402 | + VDBG("...wait %ld %s nprobes=%d, nclaims=%d\n", | |
35403 | + timeout, intf, nprobes, nclaims); | |
35404 | + switch (poll(fds, 1, timeout)) { | |
35405 | + | |
35406 | + // timeouts trigger protocol transitions | |
35407 | + case 0: | |
35408 | + // probes | |
35409 | + if (nprobes < PROBE_NUM) { | |
35410 | + nprobes++; | |
35411 | + VDBG("probe/%d %s@%s\n", | |
35412 | + nprobes, intf, inet_ntoa(ip)); | |
35413 | + (void)arp(fd, &saddr, ARPOP_REQUEST, | |
35414 | + &addr, null_ip, | |
35415 | + &null_addr, ip); | |
35416 | + if (nprobes < PROBE_NUM) { | |
35417 | + timeout = PROBE_MIN * 1000; | |
35418 | + timeout += ms_rdelay(PROBE_MAX | |
35419 | + - PROBE_MIN); | |
35420 | + } else | |
35421 | + timeout = ANNOUNCE_WAIT * 1000; | |
35422 | + } | |
35423 | + // then announcements | |
35424 | + else if (nclaims < ANNOUNCE_NUM) { | |
35425 | + nclaims++; | |
35426 | + VDBG("announce/%d %s@%s\n", | |
35427 | + nclaims, intf, inet_ntoa(ip)); | |
35428 | + (void)arp(fd, &saddr, ARPOP_REQUEST, | |
35429 | + &addr, ip, | |
35430 | + &addr, ip); | |
35431 | + if (nclaims < ANNOUNCE_NUM) { | |
35432 | + timeout = ANNOUNCE_INTERVAL * 1000; | |
35433 | + } else { | |
35434 | + // link is ok to use earlier | |
35435 | + run(script, "config", intf, &ip); | |
35436 | + ready = 1; | |
35437 | + conflicts = 0; | |
35438 | + timeout = -1; | |
35439 | + | |
35440 | + // NOTE: all other exit paths | |
35441 | + // should deconfig ... | |
35442 | + if (quit) | |
35443 | + return EXIT_SUCCESS; | |
35444 | + // FIXME update filters | |
35445 | + } | |
35446 | + } | |
35447 | + break; | |
35448 | + | |
35449 | + // packets arriving | |
35450 | + case 1: | |
35451 | + // maybe adjust timeout | |
35452 | + if (timeout > 0) { | |
35453 | + struct timeval tv2; | |
35454 | + | |
35455 | + gettimeofday(&tv2, NULL); | |
35456 | + if (timercmp(&tv1, &tv2, <)) { | |
35457 | + timeout = -1; | |
35458 | + } else { | |
35459 | + timersub(&tv1, &tv2, &tv1); | |
35460 | + timeout = 1000 * tv1.tv_sec | |
35461 | + + tv1.tv_usec / 1000; | |
35462 | + } | |
35463 | + } | |
35464 | + if ((fds[0].revents & POLLIN) == 0) { | |
35465 | + if (fds[0].revents & POLLERR) { | |
35466 | + // FIXME: links routinely go down; | |
35467 | + // this shouldn't necessarily exit. | |
35468 | + fprintf(stderr, "%s %s: poll error\n", | |
35469 | + prog, intf); | |
35470 | + if (ready) { | |
35471 | + run(script, "deconfig", | |
35472 | + intf, &ip); | |
35473 | + } | |
35474 | + return EXIT_FAILURE; | |
35475 | + } | |
35476 | + continue; | |
35477 | + } | |
35478 | + // read ARP packet | |
35479 | + if (recv(fd, &p, sizeof (p), 0) < 0) { | |
35480 | + why = "recv"; | |
35481 | + goto bad; | |
35482 | + } | |
35483 | + if (p.hdr.ether_type != htons(ETHERTYPE_ARP)) | |
35484 | + continue; | |
35485 | + | |
35486 | + VDBG("%s recv arp type=%d, op=%d,\n", | |
35487 | + intf, ntohs(p.hdr.ether_type), | |
35488 | + ntohs(p.arp.ar_op)); | |
35489 | + VDBG("\tsource=%s %s\n", | |
35490 | + ether_ntoa(&p.source_addr), | |
35491 | + inet_ntoa(p.source_ip)); | |
35492 | + VDBG("\ttarget=%s %s\n", | |
35493 | + ether_ntoa(&p.target_addr), | |
35494 | + inet_ntoa(p.target_ip)); | |
35495 | + if (p.arp.ar_op != htons(ARPOP_REQUEST) | |
35496 | + && p.arp.ar_op != htons(ARPOP_REPLY)) | |
35497 | + continue; | |
35498 | + | |
35499 | + // some cases are always conflicts | |
35500 | + if ((p.source_ip.s_addr == ip.s_addr) | |
35501 | + && (memcmp(&addr, &p.source_addr, | |
35502 | + ETH_ALEN) != 0)) { | |
35503 | +collision: | |
35504 | + VDBG("%s ARP conflict from %s\n", intf, | |
35505 | + ether_ntoa(&p.source_addr)); | |
35506 | + if (ready) { | |
35507 | + time_t now = time(0); | |
35508 | + | |
35509 | + if ((defend + DEFEND_INTERVAL) | |
35510 | + < now) { | |
35511 | + defend = now; | |
35512 | + (void)arp(fd, &saddr, | |
35513 | + ARPOP_REQUEST, | |
35514 | + &addr, ip, | |
35515 | + &addr, ip); | |
35516 | + VDBG("%s defend\n", intf); | |
35517 | + timeout = -1; | |
35518 | + continue; | |
35519 | + } | |
35520 | + defend = now; | |
35521 | + ready = 0; | |
35522 | + run(script, "deconfig", intf, &ip); | |
35523 | + // FIXME rm filters: setsockopt(fd, | |
35524 | + // SO_DETACH_FILTER, ...) | |
35525 | + } | |
35526 | + conflicts++; | |
35527 | + if (conflicts >= MAX_CONFLICTS) { | |
35528 | + VDBG("%s ratelimit\n", intf); | |
35529 | + sleep(RATE_LIMIT_INTERVAL); | |
35530 | + } | |
35531 | + // restart the whole protocol | |
35532 | + pick(&ip); | |
35533 | + timeout = 0; | |
35534 | + nprobes = 0; | |
35535 | + nclaims = 0; | |
35536 | + } | |
35537 | + // two hosts probing one address is a collision too | |
35538 | + else if (p.target_ip.s_addr == ip.s_addr | |
35539 | + && nclaims == 0 | |
35540 | + && p.arp.ar_op == htons(ARPOP_REQUEST) | |
35541 | + && memcmp(&addr, &p.target_addr, | |
35542 | + ETH_ALEN) != 0) { | |
35543 | + goto collision; | |
35544 | + } | |
35545 | + break; | |
35546 | + | |
35547 | + default: | |
35548 | + why = "poll"; | |
35549 | + goto bad; | |
35550 | + } | |
35551 | + } | |
35552 | +bad: | |
35553 | + if (foreground) | |
35554 | + perror(why); | |
35555 | + else | |
35556 | + syslog(LOG_ERR, "%s %s, %s error: %s", | |
35557 | + prog, intf, why, strerror(errno)); | |
35558 | + return EXIT_FAILURE; | |
35559 | +} | |
35560 | diff -Nur busybox-1.00/patches/ed.patch busybox/patches/ed.patch | |
35561 | --- busybox-1.00/patches/ed.patch 1970-01-01 01:00:00.000000000 +0100 | |
35562 | +++ busybox/patches/ed.patch 2005-06-04 08:20:03.000000000 +0200 | |
35563 | @@ -0,0 +1,1489 @@ | |
35564 | +Index: editors/Makefile.in | |
35565 | +=================================================================== | |
35566 | +--- editors/Makefile.in (revision 10144) | |
35567 | ++++ editors/Makefile.in (working copy) | |
35568 | +@@ -24,8 +24,9 @@ | |
35569 | + srcdir=$(top_srcdir)/editors | |
35570 | + | |
35571 | + EDITOR-y:= | |
35572 | +-EDITOR-$(CONFIG_AWK) += awk.o | |
35573 | +-EDITOR-$(CONFIG_PATCH) += patch.o | |
35574 | ++EDITOR-$(CONFIG_AWK) += awk.o | |
35575 | ++EDITOR-$(CONFIG_ED) += ed.o | |
35576 | ++EDITOR-$(CONFIG_PATCH) += patch.o | |
35577 | + EDITOR-$(CONFIG_SED) += sed.o | |
35578 | + EDITOR-$(CONFIG_VI) += vi.o | |
35579 | + EDITOR_SRC:= $(EDITOR-y) | |
35580 | +Index: editors/Config.in | |
35581 | +=================================================================== | |
35582 | +--- editors/Config.in (revision 10144) | |
35583 | ++++ editors/Config.in (working copy) | |
35584 | +@@ -20,6 +20,12 @@ | |
35585 | + Enable math functions of the Awk programming language. | |
35586 | + NOTE: This will require libm to be present for linking. | |
35587 | + | |
35588 | ++config CONFIG_ED | |
35589 | ++ bool "ed" | |
35590 | ++ default n | |
35591 | ++ help | |
35592 | ++ ed | |
35593 | ++ | |
35594 | + config CONFIG_PATCH | |
35595 | + bool "patch" | |
35596 | + default n | |
35597 | +Index: include/usage.h | |
35598 | +=================================================================== | |
35599 | +--- include/usage.h (revision 10151) | |
35600 | ++++ include/usage.h (working copy) | |
35601 | +@@ -556,6 +561,9 @@ | |
35602 | + "$ echo \"Erik\\nis\\ncool\"\n" \ | |
35603 | + "Erik\\nis\\ncool\n") | |
35604 | + | |
35605 | ++#define ed_trivial_usage "" | |
35606 | ++#define ed_full_usage "" | |
35607 | ++ | |
35608 | + #define env_trivial_usage \ | |
35609 | + "[-iu] [-] [name=value]... [command]" | |
35610 | + #define env_full_usage \ | |
35611 | +Index: include/applets.h | |
35612 | +=================================================================== | |
35613 | +--- include/applets.h (revision 10151) | |
35614 | ++++ include/applets.h (working copy) | |
35615 | +@@ -179,6 +179,9 @@ | |
35616 | + #ifdef CONFIG_ECHO | |
35617 | + APPLET(echo, echo_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
35618 | + #endif | |
35619 | ++#ifdef CONFIG_ED | |
35620 | ++ APPLET(ed, ed_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
35621 | ++#endif | |
35622 | + #if defined(CONFIG_FEATURE_GREP_EGREP_ALIAS) | |
35623 | + APPLET_NOUSAGE("egrep", grep_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
35624 | + #endif | |
35625 | +--- /dev/null 2005-04-24 01:00:01.350003056 -0400 | |
35626 | ++++ ed.c 2005-04-24 01:38:51.000000000 -0400 | |
35627 | +@@ -0,0 +1,1425 @@ | |
35628 | ++/* | |
35629 | ++ * Copyright (c) 2002 by David I. Bell | |
35630 | ++ * Permission is granted to use, distribute, or modify this source, | |
35631 | ++ * provided that this copyright notice remains intact. | |
35632 | ++ * | |
35633 | ++ * The "ed" built-in command (much simplified) | |
35634 | ++ */ | |
35635 | ++ | |
35636 | ++#include <stdio.h> | |
35637 | ++#include <stdlib.h> | |
35638 | ++#include <unistd.h> | |
35639 | ++#include <fcntl.h> | |
35640 | ++#include <string.h> | |
35641 | ++#include <memory.h> | |
35642 | ++#include <time.h> | |
35643 | ++#include <ctype.h> | |
35644 | ++#include <sys/param.h> | |
35645 | ++#include <malloc.h> | |
35646 | ++#include "busybox.h" | |
35647 | ++ | |
35648 | ++#define USERSIZE 1024 /* max line length typed in by user */ | |
35649 | ++#define INITBUF_SIZE 1024 /* initial buffer size */ | |
35650 | ++ | |
35651 | ++typedef int BOOL; | |
35652 | ++typedef int NUM; | |
35653 | ++typedef int LEN; | |
35654 | ++ | |
35655 | ++typedef struct LINE LINE; | |
35656 | ++struct LINE { | |
35657 | ++ LINE *next; | |
35658 | ++ LINE *prev; | |
35659 | ++ LEN len; | |
35660 | ++ char data[1]; | |
35661 | ++}; | |
35662 | ++ | |
35663 | ++static LINE lines; | |
35664 | ++static LINE *curLine; | |
35665 | ++static NUM curNum; | |
35666 | ++static NUM lastNum; | |
35667 | ++static NUM marks[26]; | |
35668 | ++static BOOL dirty; | |
35669 | ++static char *fileName; | |
35670 | ++static char searchString[USERSIZE]; | |
35671 | ++ | |
35672 | ++static char *bufBase; | |
35673 | ++static char *bufPtr; | |
35674 | ++static LEN bufUsed; | |
35675 | ++static LEN bufSize; | |
35676 | ++ | |
35677 | ++static void doCommands(void); | |
35678 | ++static void subCommand(const char * cmd, NUM num1, NUM num2); | |
35679 | ++static BOOL getNum(const char ** retcp, BOOL * retHaveNum, NUM * retNum); | |
35680 | ++static BOOL setCurNum(NUM num); | |
35681 | ++static BOOL initEdit(void); | |
35682 | ++static void termEdit(void); | |
35683 | ++static void addLines(NUM num); | |
35684 | ++static BOOL insertLine(NUM num, const char * data, LEN len); | |
35685 | ++static BOOL deleteLines(NUM num1, NUM num2); | |
35686 | ++static BOOL printLines(NUM num1, NUM num2, BOOL expandFlag); | |
35687 | ++static BOOL writeLines(const char * file, NUM num1, NUM num2); | |
35688 | ++static BOOL readLines(const char * file, NUM num); | |
35689 | ++static NUM searchLines(const char * str, NUM num1, NUM num2); | |
35690 | ++static LINE * findLine(NUM num); | |
35691 | ++ | |
35692 | ++static LEN findString(const LINE * lp, const char * str, LEN len, LEN offset); | |
35693 | ++ | |
35694 | ++int ed_main(int argc, char **argv) | |
35695 | ++{ | |
35696 | ++ if (!initEdit()) | |
35697 | ++ return EXIT_FAILURE; | |
35698 | ++ | |
35699 | ++ if (argc > 1) { | |
35700 | ++ fileName = strdup(argv[1]); | |
35701 | ++ | |
35702 | ++ if (fileName == NULL) { | |
35703 | ++ bb_error_msg("No memory"); | |
35704 | ++ termEdit(); | |
35705 | ++ return EXIT_SUCCESS; | |
35706 | ++ } | |
35707 | ++ | |
35708 | ++ if (!readLines(fileName, 1)) { | |
35709 | ++ termEdit(); | |
35710 | ++ return EXIT_SUCCESS; | |
35711 | ++ } | |
35712 | ++ | |
35713 | ++ if (lastNum) | |
35714 | ++ setCurNum(1); | |
35715 | ++ | |
35716 | ++ dirty = FALSE; | |
35717 | ++ } | |
35718 | ++ | |
35719 | ++ doCommands(); | |
35720 | ++ | |
35721 | ++ termEdit(); | |
35722 | ++ return EXIT_SUCCESS; | |
35723 | ++} | |
35724 | ++ | |
35725 | ++/* | |
35726 | ++ * Read commands until we are told to stop. | |
35727 | ++ */ | |
35728 | ++static void doCommands(void) | |
35729 | ++{ | |
35730 | ++ const char * cp; | |
35731 | ++ char * endbuf; | |
35732 | ++ char * newname; | |
35733 | ++ int len; | |
35734 | ++ NUM num1; | |
35735 | ++ NUM num2; | |
35736 | ++ BOOL have1; | |
35737 | ++ BOOL have2; | |
35738 | ++ char buf[USERSIZE]; | |
35739 | ++ | |
35740 | ++ while (TRUE) | |
35741 | ++ { | |
35742 | ++ printf(": "); | |
35743 | ++ fflush(stdout); | |
35744 | ++ | |
35745 | ++ if (fgets(buf, sizeof(buf), stdin) == NULL) | |
35746 | ++ return; | |
35747 | ++ | |
35748 | ++ len = strlen(buf); | |
35749 | ++ | |
35750 | ++ if (len == 0) | |
35751 | ++ return; | |
35752 | ++ | |
35753 | ++ endbuf = &buf[len - 1]; | |
35754 | ++ | |
35755 | ++ if (*endbuf != '\n') | |
35756 | ++ { | |
35757 | ++ bb_error_msg("Command line too long"); | |
35758 | ++ | |
35759 | ++ do | |
35760 | ++ { | |
35761 | ++ len = fgetc(stdin); | |
35762 | ++ } | |
35763 | ++ while ((len != EOF) && (len != '\n')); | |
35764 | ++ | |
35765 | ++ continue; | |
35766 | ++ } | |
35767 | ++ | |
35768 | ++ while ((endbuf > buf) && isblank(endbuf[-1])) | |
35769 | ++ endbuf--; | |
35770 | ++ | |
35771 | ++ *endbuf = '\0'; | |
35772 | ++ | |
35773 | ++ cp = buf; | |
35774 | ++ | |
35775 | ++ while (isblank(*cp)) | |
35776 | ++ cp++; | |
35777 | ++ | |
35778 | ++ have1 = FALSE; | |
35779 | ++ have2 = FALSE; | |
35780 | ++ | |
35781 | ++ if ((curNum == 0) && (lastNum > 0)) | |
35782 | ++ { | |
35783 | ++ curNum = 1; | |
35784 | ++ curLine = lines.next; | |
35785 | ++ } | |
35786 | ++ | |
35787 | ++ if (!getNum(&cp, &have1, &num1)) | |
35788 | ++ continue; | |
35789 | ++ | |
35790 | ++ while (isblank(*cp)) | |
35791 | ++ cp++; | |
35792 | ++ | |
35793 | ++ if (*cp == ',') | |
35794 | ++ { | |
35795 | ++ cp++; | |
35796 | ++ | |
35797 | ++ if (!getNum(&cp, &have2, &num2)) | |
35798 | ++ continue; | |
35799 | ++ | |
35800 | ++ if (!have1) | |
35801 | ++ num1 = 1; | |
35802 | ++ | |
35803 | ++ if (!have2) | |
35804 | ++ num2 = lastNum; | |
35805 | ++ | |
35806 | ++ have1 = TRUE; | |
35807 | ++ have2 = TRUE; | |
35808 | ++ } | |
35809 | ++ | |
35810 | ++ if (!have1) | |
35811 | ++ num1 = curNum; | |
35812 | ++ | |
35813 | ++ if (!have2) | |
35814 | ++ num2 = num1; | |
35815 | ++ | |
35816 | ++ switch (*cp++) | |
35817 | ++ { | |
35818 | ++ case 'a': | |
35819 | ++ addLines(num1 + 1); | |
35820 | ++ break; | |
35821 | ++ | |
35822 | ++ case 'c': | |
35823 | ++ deleteLines(num1, num2); | |
35824 | ++ addLines(num1); | |
35825 | ++ break; | |
35826 | ++ | |
35827 | ++ case 'd': | |
35828 | ++ deleteLines(num1, num2); | |
35829 | ++ break; | |
35830 | ++ | |
35831 | ++ case 'f': | |
35832 | ++ if (*cp && !isblank(*cp)) | |
35833 | ++ { | |
35834 | ++ bb_error_msg("Bad file command"); | |
35835 | ++ break; | |
35836 | ++ } | |
35837 | ++ | |
35838 | ++ while (isblank(*cp)) | |
35839 | ++ cp++; | |
35840 | ++ | |
35841 | ++ if (*cp == '\0') | |
35842 | ++ { | |
35843 | ++ if (fileName) | |
35844 | ++ printf("\"%s\"\n", fileName); | |
35845 | ++ else | |
35846 | ++ printf("No file name\n"); | |
35847 | ++ | |
35848 | ++ break; | |
35849 | ++ } | |
35850 | ++ | |
35851 | ++ newname = strdup(cp); | |
35852 | ++ | |
35853 | ++ if (newname == NULL) | |
35854 | ++ { | |
35855 | ++ bb_error_msg("No memory for file name"); | |
35856 | ++ break; | |
35857 | ++ } | |
35858 | ++ | |
35859 | ++ if (fileName) | |
35860 | ++ free(fileName); | |
35861 | ++ | |
35862 | ++ fileName = newname; | |
35863 | ++ break; | |
35864 | ++ | |
35865 | ++ case 'i': | |
35866 | ++ addLines(num1); | |
35867 | ++ break; | |
35868 | ++ | |
35869 | ++ case 'k': | |
35870 | ++ while (isblank(*cp)) | |
35871 | ++ cp++; | |
35872 | ++ | |
35873 | ++ if ((*cp < 'a') || (*cp > 'a') || cp[1]) | |
35874 | ++ { | |
35875 | ++ bb_error_msg("Bad mark name"); | |
35876 | ++ break; | |
35877 | ++ } | |
35878 | ++ | |
35879 | ++ marks[*cp - 'a'] = num2; | |
35880 | ++ break; | |
35881 | ++ | |
35882 | ++ case 'l': | |
35883 | ++ printLines(num1, num2, TRUE); | |
35884 | ++ break; | |
35885 | ++ | |
35886 | ++ case 'p': | |
35887 | ++ printLines(num1, num2, FALSE); | |
35888 | ++ break; | |
35889 | ++ | |
35890 | ++ case 'q': | |
35891 | ++ while (isblank(*cp)) | |
35892 | ++ cp++; | |
35893 | ++ | |
35894 | ++ if (have1 || *cp) | |
35895 | ++ { | |
35896 | ++ bb_error_msg("Bad quit command"); | |
35897 | ++ break; | |
35898 | ++ } | |
35899 | ++ | |
35900 | ++ if (!dirty) | |
35901 | ++ return; | |
35902 | ++ | |
35903 | ++ printf("Really quit? "); | |
35904 | ++ fflush(stdout); | |
35905 | ++ | |
35906 | ++ buf[0] = '\0'; | |
35907 | ++ fgets(buf, sizeof(buf), stdin); | |
35908 | ++ cp = buf; | |
35909 | ++ | |
35910 | ++ while (isblank(*cp)) | |
35911 | ++ cp++; | |
35912 | ++ | |
35913 | ++ if ((*cp == 'y') || (*cp == 'Y')) | |
35914 | ++ return; | |
35915 | ++ | |
35916 | ++ break; | |
35917 | ++ | |
35918 | ++ case 'r': | |
35919 | ++ if (*cp && !isblank(*cp)) | |
35920 | ++ { | |
35921 | ++ bb_error_msg("Bad read command"); | |
35922 | ++ break; | |
35923 | ++ } | |
35924 | ++ | |
35925 | ++ while (isblank(*cp)) | |
35926 | ++ cp++; | |
35927 | ++ | |
35928 | ++ if (*cp == '\0') | |
35929 | ++ { | |
35930 | ++ bb_error_msg("No file name"); | |
35931 | ++ break; | |
35932 | ++ } | |
35933 | ++ | |
35934 | ++ if (!have1) | |
35935 | ++ num1 = lastNum; | |
35936 | ++ | |
35937 | ++ if (readLines(cp, num1 + 1)) | |
35938 | ++ break; | |
35939 | ++ | |
35940 | ++ if (fileName == NULL) | |
35941 | ++ fileName = strdup(cp); | |
35942 | ++ | |
35943 | ++ break; | |
35944 | ++ | |
35945 | ++ case 's': | |
35946 | ++ subCommand(cp, num1, num2); | |
35947 | ++ break; | |
35948 | ++ | |
35949 | ++ case 'w': | |
35950 | ++ if (*cp && !isblank(*cp)) | |
35951 | ++ { | |
35952 | ++ bb_error_msg("Bad write command"); | |
35953 | ++ break; | |
35954 | ++ } | |
35955 | ++ | |
35956 | ++ while (isblank(*cp)) | |
35957 | ++ cp++; | |
35958 | ++ | |
35959 | ++ if (!have1) { | |
35960 | ++ num1 = 1; | |
35961 | ++ num2 = lastNum; | |
35962 | ++ } | |
35963 | ++ | |
35964 | ++ if (*cp == '\0') | |
35965 | ++ cp = fileName; | |
35966 | ++ | |
35967 | ++ if (cp == NULL) | |
35968 | ++ { | |
35969 | ++ bb_error_msg("No file name specified"); | |
35970 | ++ break; | |
35971 | ++ } | |
35972 | ++ | |
35973 | ++ writeLines(cp, num1, num2); | |
35974 | ++ break; | |
35975 | ++ | |
35976 | ++ case 'z': | |
35977 | ++ switch (*cp) | |
35978 | ++ { | |
35979 | ++ case '-': | |
35980 | ++ printLines(curNum-21, curNum, FALSE); | |
35981 | ++ break; | |
35982 | ++ case '.': | |
35983 | ++ printLines(curNum-11, curNum+10, FALSE); | |
35984 | ++ break; | |
35985 | ++ default: | |
35986 | ++ printLines(curNum, curNum+21, FALSE); | |
35987 | ++ break; | |
35988 | ++ } | |
35989 | ++ break; | |
35990 | ++ | |
35991 | ++ case '.': | |
35992 | ++ if (have1) | |
35993 | ++ { | |
35994 | ++ bb_error_msg("No arguments allowed"); | |
35995 | ++ break; | |
35996 | ++ } | |
35997 | ++ | |
35998 | ++ printLines(curNum, curNum, FALSE); | |
35999 | ++ break; | |
36000 | ++ | |
36001 | ++ case '-': | |
36002 | ++ if (setCurNum(curNum - 1)) | |
36003 | ++ printLines(curNum, curNum, FALSE); | |
36004 | ++ | |
36005 | ++ break; | |
36006 | ++ | |
36007 | ++ case '=': | |
36008 | ++ printf("%d\n", num1); | |
36009 | ++ break; | |
36010 | ++ | |
36011 | ++ case '\0': | |
36012 | ++ if (have1) | |
36013 | ++ { | |
36014 | ++ printLines(num2, num2, FALSE); | |
36015 | ++ break; | |
36016 | ++ } | |
36017 | ++ | |
36018 | ++ if (setCurNum(curNum + 1)) | |
36019 | ++ printLines(curNum, curNum, FALSE); | |
36020 | ++ | |
36021 | ++ break; | |
36022 | ++ | |
36023 | ++ default: | |
36024 | ++ bb_error_msg("Unimplemented command"); | |
36025 | ++ break; | |
36026 | ++ } | |
36027 | ++ } | |
36028 | ++} | |
36029 | ++ | |
36030 | ++ | |
36031 | ++/* | |
36032 | ++ * Do the substitute command. | |
36033 | ++ * The current line is set to the last substitution done. | |
36034 | ++ */ | |
36035 | ++static void | |
36036 | ++subCommand(const char * cmd, NUM num1, NUM num2) | |
36037 | ++{ | |
36038 | ++ int delim; | |
36039 | ++ char * cp; | |
36040 | ++ char * oldStr; | |
36041 | ++ char * newStr; | |
36042 | ++ LEN oldLen; | |
36043 | ++ LEN newLen; | |
36044 | ++ LEN deltaLen; | |
36045 | ++ LEN offset; | |
36046 | ++ LINE * lp; | |
36047 | ++ LINE * nlp; | |
36048 | ++ BOOL globalFlag; | |
36049 | ++ BOOL printFlag; | |
36050 | ++ BOOL didSub; | |
36051 | ++ BOOL needPrint; | |
36052 | ++ char buf[USERSIZE]; | |
36053 | ++ | |
36054 | ++ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) | |
36055 | ++ { | |
36056 | ++ bb_error_msg("Bad line range for substitute"); | |
36057 | ++ | |
36058 | ++ return; | |
36059 | ++ } | |
36060 | ++ | |
36061 | ++ globalFlag = FALSE; | |
36062 | ++ printFlag = FALSE; | |
36063 | ++ didSub = FALSE; | |
36064 | ++ needPrint = FALSE; | |
36065 | ++ | |
36066 | ++ /* | |
36067 | ++ * Copy the command so we can modify it. | |
36068 | ++ */ | |
36069 | ++ strcpy(buf, cmd); | |
36070 | ++ cp = buf; | |
36071 | ++ | |
36072 | ++ if (isblank(*cp) || (*cp == '\0')) | |
36073 | ++ { | |
36074 | ++ bb_error_msg("Bad delimiter for substitute"); | |
36075 | ++ | |
36076 | ++ return; | |
36077 | ++ } | |
36078 | ++ | |
36079 | ++ delim = *cp++; | |
36080 | ++ oldStr = cp; | |
36081 | ++ | |
36082 | ++ cp = strchr(cp, delim); | |
36083 | ++ | |
36084 | ++ if (cp == NULL) | |
36085 | ++ { | |
36086 | ++ bb_error_msg("Missing 2nd delimiter for substitute"); | |
36087 | ++ | |
36088 | ++ return; | |
36089 | ++ } | |
36090 | ++ | |
36091 | ++ *cp++ = '\0'; | |
36092 | ++ | |
36093 | ++ newStr = cp; | |
36094 | ++ cp = strchr(cp, delim); | |
36095 | ++ | |
36096 | ++ if (cp) | |
36097 | ++ *cp++ = '\0'; | |
36098 | ++ else | |
36099 | ++ cp = ""; | |
36100 | ++ | |
36101 | ++ while (*cp) switch (*cp++) | |
36102 | ++ { | |
36103 | ++ case 'g': | |
36104 | ++ globalFlag = TRUE; | |
36105 | ++ break; | |
36106 | ++ | |
36107 | ++ case 'p': | |
36108 | ++ printFlag = TRUE; | |
36109 | ++ break; | |
36110 | ++ | |
36111 | ++ default: | |
36112 | ++ bb_error_msg("Unknown option for substitute"); | |
36113 | ++ | |
36114 | ++ return; | |
36115 | ++ } | |
36116 | ++ | |
36117 | ++ if (*oldStr == '\0') | |
36118 | ++ { | |
36119 | ++ if (searchString[0] == '\0') | |
36120 | ++ { | |
36121 | ++ bb_error_msg("No previous search string"); | |
36122 | ++ | |
36123 | ++ return; | |
36124 | ++ } | |
36125 | ++ | |
36126 | ++ oldStr = searchString; | |
36127 | ++ } | |
36128 | ++ | |
36129 | ++ if (oldStr != searchString) | |
36130 | ++ strcpy(searchString, oldStr); | |
36131 | ++ | |
36132 | ++ lp = findLine(num1); | |
36133 | ++ | |
36134 | ++ if (lp == NULL) | |
36135 | ++ return; | |
36136 | ++ | |
36137 | ++ oldLen = strlen(oldStr); | |
36138 | ++ newLen = strlen(newStr); | |
36139 | ++ deltaLen = newLen - oldLen; | |
36140 | ++ offset = 0; | |
36141 | ++ nlp = NULL; | |
36142 | ++ | |
36143 | ++ while (num1 <= num2) | |
36144 | ++ { | |
36145 | ++ offset = findString(lp, oldStr, oldLen, offset); | |
36146 | ++ | |
36147 | ++ if (offset < 0) | |
36148 | ++ { | |
36149 | ++ if (needPrint) | |
36150 | ++ { | |
36151 | ++ printLines(num1, num1, FALSE); | |
36152 | ++ needPrint = FALSE; | |
36153 | ++ } | |
36154 | ++ | |
36155 | ++ offset = 0; | |
36156 | ++ lp = lp->next; | |
36157 | ++ num1++; | |
36158 | ++ | |
36159 | ++ continue; | |
36160 | ++ } | |
36161 | ++ | |
36162 | ++ needPrint = printFlag; | |
36163 | ++ didSub = TRUE; | |
36164 | ++ dirty = TRUE; | |
36165 | ++ | |
36166 | ++ /* | |
36167 | ++ * If the replacement string is the same size or shorter | |
36168 | ++ * than the old string, then the substitution is easy. | |
36169 | ++ */ | |
36170 | ++ if (deltaLen <= 0) | |
36171 | ++ { | |
36172 | ++ memcpy(&lp->data[offset], newStr, newLen); | |
36173 | ++ | |
36174 | ++ if (deltaLen) | |
36175 | ++ { | |
36176 | ++ memcpy(&lp->data[offset + newLen], | |
36177 | ++ &lp->data[offset + oldLen], | |
36178 | ++ lp->len - offset - oldLen); | |
36179 | ++ | |
36180 | ++ lp->len += deltaLen; | |
36181 | ++ } | |
36182 | ++ | |
36183 | ++ offset += newLen; | |
36184 | ++ | |
36185 | ++ if (globalFlag) | |
36186 | ++ continue; | |
36187 | ++ | |
36188 | ++ if (needPrint) | |
36189 | ++ { | |
36190 | ++ printLines(num1, num1, FALSE); | |
36191 | ++ needPrint = FALSE; | |
36192 | ++ } | |
36193 | ++ | |
36194 | ++ lp = lp->next; | |
36195 | ++ num1++; | |
36196 | ++ | |
36197 | ++ continue; | |
36198 | ++ } | |
36199 | ++ | |
36200 | ++ /* | |
36201 | ++ * The new string is larger, so allocate a new line | |
36202 | ++ * structure and use that. Link it in in place of | |
36203 | ++ * the old line structure. | |
36204 | ++ */ | |
36205 | ++ nlp = (LINE *) malloc(sizeof(LINE) + lp->len + deltaLen); | |
36206 | ++ | |
36207 | ++ if (nlp == NULL) | |
36208 | ++ { | |
36209 | ++ bb_error_msg("Cannot get memory for line"); | |
36210 | ++ | |
36211 | ++ return; | |
36212 | ++ } | |
36213 | ++ | |
36214 | ++ nlp->len = lp->len + deltaLen; | |
36215 | ++ | |
36216 | ++ memcpy(nlp->data, lp->data, offset); | |
36217 | ++ | |
36218 | ++ memcpy(&nlp->data[offset], newStr, newLen); | |
36219 | ++ | |
36220 | ++ memcpy(&nlp->data[offset + newLen], | |
36221 | ++ &lp->data[offset + oldLen], | |
36222 | ++ lp->len - offset - oldLen); | |
36223 | ++ | |
36224 | ++ nlp->next = lp->next; | |
36225 | ++ nlp->prev = lp->prev; | |
36226 | ++ nlp->prev->next = nlp; | |
36227 | ++ nlp->next->prev = nlp; | |
36228 | ++ | |
36229 | ++ if (curLine == lp) | |
36230 | ++ curLine = nlp; | |
36231 | ++ | |
36232 | ++ free(lp); | |
36233 | ++ lp = nlp; | |
36234 | ++ | |
36235 | ++ offset += newLen; | |
36236 | ++ | |
36237 | ++ if (globalFlag) | |
36238 | ++ continue; | |
36239 | ++ | |
36240 | ++ if (needPrint) | |
36241 | ++ { | |
36242 | ++ printLines(num1, num1, FALSE); | |
36243 | ++ needPrint = FALSE; | |
36244 | ++ } | |
36245 | ++ | |
36246 | ++ lp = lp->next; | |
36247 | ++ num1++; | |
36248 | ++ } | |
36249 | ++ | |
36250 | ++ if (!didSub) | |
36251 | ++ bb_error_msg("No substitutions found for \"%s\"", oldStr); | |
36252 | ++} | |
36253 | ++ | |
36254 | ++ | |
36255 | ++/* | |
36256 | ++ * Search a line for the specified string starting at the specified | |
36257 | ++ * offset in the line. Returns the offset of the found string, or -1. | |
36258 | ++ */ | |
36259 | ++static LEN | |
36260 | ++findString( const LINE * lp, const char * str, LEN len, LEN offset) | |
36261 | ++{ | |
36262 | ++ LEN left; | |
36263 | ++ const char * cp; | |
36264 | ++ const char * ncp; | |
36265 | ++ | |
36266 | ++ cp = &lp->data[offset]; | |
36267 | ++ left = lp->len - offset; | |
36268 | ++ | |
36269 | ++ while (left >= len) | |
36270 | ++ { | |
36271 | ++ ncp = memchr(cp, *str, left); | |
36272 | ++ | |
36273 | ++ if (ncp == NULL) | |
36274 | ++ return -1; | |
36275 | ++ | |
36276 | ++ left -= (ncp - cp); | |
36277 | ++ | |
36278 | ++ if (left < len) | |
36279 | ++ return -1; | |
36280 | ++ | |
36281 | ++ cp = ncp; | |
36282 | ++ | |
36283 | ++ if (memcmp(cp, str, len) == 0) | |
36284 | ++ return (cp - lp->data); | |
36285 | ++ | |
36286 | ++ cp++; | |
36287 | ++ left--; | |
36288 | ++ } | |
36289 | ++ | |
36290 | ++ return -1; | |
36291 | ++} | |
36292 | ++ | |
36293 | ++ | |
36294 | ++/* | |
36295 | ++ * Add lines which are typed in by the user. | |
36296 | ++ * The lines are inserted just before the specified line number. | |
36297 | ++ * The lines are terminated by a line containing a single dot (ugly!), | |
36298 | ++ * or by an end of file. | |
36299 | ++ */ | |
36300 | ++static void | |
36301 | ++addLines(NUM num) | |
36302 | ++{ | |
36303 | ++ int len; | |
36304 | ++ char buf[USERSIZE + 1]; | |
36305 | ++ | |
36306 | ++ while (fgets(buf, sizeof(buf), stdin)) | |
36307 | ++ { | |
36308 | ++ if ((buf[0] == '.') && (buf[1] == '\n') && (buf[2] == '\0')) | |
36309 | ++ return; | |
36310 | ++ | |
36311 | ++ len = strlen(buf); | |
36312 | ++ | |
36313 | ++ if (len == 0) | |
36314 | ++ return; | |
36315 | ++ | |
36316 | ++ if (buf[len - 1] != '\n') | |
36317 | ++ { | |
36318 | ++ bb_error_msg("Line too long"); | |
36319 | ++ | |
36320 | ++ do | |
36321 | ++ { | |
36322 | ++ len = fgetc(stdin); | |
36323 | ++ } | |
36324 | ++ while ((len != EOF) && (len != '\n')); | |
36325 | ++ | |
36326 | ++ return; | |
36327 | ++ } | |
36328 | ++ | |
36329 | ++ if (!insertLine(num++, buf, len)) | |
36330 | ++ return; | |
36331 | ++ } | |
36332 | ++} | |
36333 | ++ | |
36334 | ++ | |
36335 | ++/* | |
36336 | ++ * Parse a line number argument if it is present. This is a sum | |
36337 | ++ * or difference of numbers, '.', '$', 'x, or a search string. | |
36338 | ++ * Returns TRUE if successful (whether or not there was a number). | |
36339 | ++ * Returns FALSE if there was a parsing error, with a message output. | |
36340 | ++ * Whether there was a number is returned indirectly, as is the number. | |
36341 | ++ * The character pointer which stopped the scan is also returned. | |
36342 | ++ */ | |
36343 | ++static BOOL | |
36344 | ++getNum(const char ** retcp, BOOL * retHaveNum, NUM * retNum) | |
36345 | ++{ | |
36346 | ++ const char * cp; | |
36347 | ++ char * endStr; | |
36348 | ++ char str[USERSIZE]; | |
36349 | ++ BOOL haveNum; | |
36350 | ++ NUM value; | |
36351 | ++ NUM num; | |
36352 | ++ NUM sign; | |
36353 | ++ | |
36354 | ++ cp = *retcp; | |
36355 | ++ haveNum = FALSE; | |
36356 | ++ value = 0; | |
36357 | ++ sign = 1; | |
36358 | ++ | |
36359 | ++ while (TRUE) | |
36360 | ++ { | |
36361 | ++ while (isblank(*cp)) | |
36362 | ++ cp++; | |
36363 | ++ | |
36364 | ++ switch (*cp) | |
36365 | ++ { | |
36366 | ++ case '.': | |
36367 | ++ haveNum = TRUE; | |
36368 | ++ num = curNum; | |
36369 | ++ cp++; | |
36370 | ++ break; | |
36371 | ++ | |
36372 | ++ case '$': | |
36373 | ++ haveNum = TRUE; | |
36374 | ++ num = lastNum; | |
36375 | ++ cp++; | |
36376 | ++ break; | |
36377 | ++ | |
36378 | ++ case '\'': | |
36379 | ++ cp++; | |
36380 | ++ | |
36381 | ++ if ((*cp < 'a') || (*cp > 'z')) | |
36382 | ++ { | |
36383 | ++ bb_error_msg("Bad mark name"); | |
36384 | ++ | |
36385 | ++ return FALSE; | |
36386 | ++ } | |
36387 | ++ | |
36388 | ++ haveNum = TRUE; | |
36389 | ++ num = marks[*cp++ - 'a']; | |
36390 | ++ break; | |
36391 | ++ | |
36392 | ++ case '/': | |
36393 | ++ strcpy(str, ++cp); | |
36394 | ++ endStr = strchr(str, '/'); | |
36395 | ++ | |
36396 | ++ if (endStr) | |
36397 | ++ { | |
36398 | ++ *endStr++ = '\0'; | |
36399 | ++ cp += (endStr - str); | |
36400 | ++ } | |
36401 | ++ else | |
36402 | ++ cp = ""; | |
36403 | ++ | |
36404 | ++ num = searchLines(str, curNum, lastNum); | |
36405 | ++ | |
36406 | ++ if (num == 0) | |
36407 | ++ return FALSE; | |
36408 | ++ | |
36409 | ++ haveNum = TRUE; | |
36410 | ++ break; | |
36411 | ++ | |
36412 | ++ default: | |
36413 | ++ if (!isdigit(*cp)) | |
36414 | ++ { | |
36415 | ++ *retcp = cp; | |
36416 | ++ *retHaveNum = haveNum; | |
36417 | ++ *retNum = value; | |
36418 | ++ | |
36419 | ++ return TRUE; | |
36420 | ++ } | |
36421 | ++ | |
36422 | ++ num = 0; | |
36423 | ++ | |
36424 | ++ while (isdigit(*cp)) | |
36425 | ++ num = num * 10 + *cp++ - '0'; | |
36426 | ++ | |
36427 | ++ haveNum = TRUE; | |
36428 | ++ break; | |
36429 | ++ } | |
36430 | ++ | |
36431 | ++ value += num * sign; | |
36432 | ++ | |
36433 | ++ while (isblank(*cp)) | |
36434 | ++ cp++; | |
36435 | ++ | |
36436 | ++ switch (*cp) | |
36437 | ++ { | |
36438 | ++ case '-': | |
36439 | ++ sign = -1; | |
36440 | ++ cp++; | |
36441 | ++ break; | |
36442 | ++ | |
36443 | ++ case '+': | |
36444 | ++ sign = 1; | |
36445 | ++ cp++; | |
36446 | ++ break; | |
36447 | ++ | |
36448 | ++ default: | |
36449 | ++ *retcp = cp; | |
36450 | ++ *retHaveNum = haveNum; | |
36451 | ++ *retNum = value; | |
36452 | ++ | |
36453 | ++ return TRUE; | |
36454 | ++ } | |
36455 | ++ } | |
36456 | ++} | |
36457 | ++ | |
36458 | ++ | |
36459 | ++/* | |
36460 | ++ * Initialize everything for editing. | |
36461 | ++ */ | |
36462 | ++static BOOL | |
36463 | ++initEdit(void) | |
36464 | ++{ | |
36465 | ++ int i; | |
36466 | ++ | |
36467 | ++ bufSize = INITBUF_SIZE; | |
36468 | ++ bufBase = malloc(bufSize); | |
36469 | ++ | |
36470 | ++ if (bufBase == NULL) | |
36471 | ++ { | |
36472 | ++ bb_error_msg("No memory for buffer"); | |
36473 | ++ | |
36474 | ++ return FALSE; | |
36475 | ++ } | |
36476 | ++ | |
36477 | ++ bufPtr = bufBase; | |
36478 | ++ bufUsed = 0; | |
36479 | ++ | |
36480 | ++ lines.next = &lines; | |
36481 | ++ lines.prev = &lines; | |
36482 | ++ | |
36483 | ++ curLine = NULL; | |
36484 | ++ curNum = 0; | |
36485 | ++ lastNum = 0; | |
36486 | ++ dirty = FALSE; | |
36487 | ++ fileName = NULL; | |
36488 | ++ searchString[0] = '\0'; | |
36489 | ++ | |
36490 | ++ for (i = 0; i < 26; i++) | |
36491 | ++ marks[i] = 0; | |
36492 | ++ | |
36493 | ++ return TRUE; | |
36494 | ++} | |
36495 | ++ | |
36496 | ++ | |
36497 | ++/* | |
36498 | ++ * Finish editing. | |
36499 | ++ */ | |
36500 | ++static void | |
36501 | ++termEdit(void) | |
36502 | ++{ | |
36503 | ++ if (bufBase) | |
36504 | ++ free(bufBase); | |
36505 | ++ | |
36506 | ++ bufBase = NULL; | |
36507 | ++ bufPtr = NULL; | |
36508 | ++ bufSize = 0; | |
36509 | ++ bufUsed = 0; | |
36510 | ++ | |
36511 | ++ if (fileName) | |
36512 | ++ free(fileName); | |
36513 | ++ | |
36514 | ++ fileName = NULL; | |
36515 | ++ | |
36516 | ++ searchString[0] = '\0'; | |
36517 | ++ | |
36518 | ++ if (lastNum) | |
36519 | ++ deleteLines(1, lastNum); | |
36520 | ++ | |
36521 | ++ lastNum = 0; | |
36522 | ++ curNum = 0; | |
36523 | ++ curLine = NULL; | |
36524 | ++} | |
36525 | ++ | |
36526 | ++ | |
36527 | ++/* | |
36528 | ++ * Read lines from a file at the specified line number. | |
36529 | ++ * Returns TRUE if the file was successfully read. | |
36530 | ++ */ | |
36531 | ++static BOOL | |
36532 | ++readLines(const char * file, NUM num) | |
36533 | ++{ | |
36534 | ++ int fd; | |
36535 | ++ int cc; | |
36536 | ++ LEN len; | |
36537 | ++ LEN lineCount; | |
36538 | ++ LEN charCount; | |
36539 | ++ char * cp; | |
36540 | ++ | |
36541 | ++ if ((num < 1) || (num > lastNum + 1)) | |
36542 | ++ { | |
36543 | ++ bb_error_msg("Bad line for read"); | |
36544 | ++ | |
36545 | ++ return FALSE; | |
36546 | ++ } | |
36547 | ++ | |
36548 | ++ fd = open(file, 0); | |
36549 | ++ | |
36550 | ++ if (fd < 0) | |
36551 | ++ { | |
36552 | ++ perror(file); | |
36553 | ++ | |
36554 | ++ return FALSE; | |
36555 | ++ } | |
36556 | ++ | |
36557 | ++ bufPtr = bufBase; | |
36558 | ++ bufUsed = 0; | |
36559 | ++ lineCount = 0; | |
36560 | ++ charCount = 0; | |
36561 | ++ cc = 0; | |
36562 | ++ | |
36563 | ++ printf("\"%s\", ", file); | |
36564 | ++ fflush(stdout); | |
36565 | ++ | |
36566 | ++ do | |
36567 | ++ { | |
36568 | ++ cp = memchr(bufPtr, '\n', bufUsed); | |
36569 | ++ | |
36570 | ++ if (cp) | |
36571 | ++ { | |
36572 | ++ len = (cp - bufPtr) + 1; | |
36573 | ++ | |
36574 | ++ if (!insertLine(num, bufPtr, len)) | |
36575 | ++ { | |
36576 | ++ close(fd); | |
36577 | ++ | |
36578 | ++ return FALSE; | |
36579 | ++ } | |
36580 | ++ | |
36581 | ++ bufPtr += len; | |
36582 | ++ bufUsed -= len; | |
36583 | ++ charCount += len; | |
36584 | ++ lineCount++; | |
36585 | ++ num++; | |
36586 | ++ | |
36587 | ++ continue; | |
36588 | ++ } | |
36589 | ++ | |
36590 | ++ if (bufPtr != bufBase) | |
36591 | ++ { | |
36592 | ++ memcpy(bufBase, bufPtr, bufUsed); | |
36593 | ++ bufPtr = bufBase + bufUsed; | |
36594 | ++ } | |
36595 | ++ | |
36596 | ++ if (bufUsed >= bufSize) | |
36597 | ++ { | |
36598 | ++ len = (bufSize * 3) / 2; | |
36599 | ++ cp = realloc(bufBase, len); | |
36600 | ++ | |
36601 | ++ if (cp == NULL) | |
36602 | ++ { | |
36603 | ++ bb_error_msg("No memory for buffer"); | |
36604 | ++ close(fd); | |
36605 | ++ | |
36606 | ++ return FALSE; | |
36607 | ++ } | |
36608 | ++ | |
36609 | ++ bufBase = cp; | |
36610 | ++ bufPtr = bufBase + bufUsed; | |
36611 | ++ bufSize = len; | |
36612 | ++ } | |
36613 | ++ | |
36614 | ++ cc = read(fd, bufPtr, bufSize - bufUsed); | |
36615 | ++ bufUsed += cc; | |
36616 | ++ bufPtr = bufBase; | |
36617 | ++ | |
36618 | ++ } | |
36619 | ++ while (cc > 0); | |
36620 | ++ | |
36621 | ++ if (cc < 0) | |
36622 | ++ { | |
36623 | ++ perror(file); | |
36624 | ++ close(fd); | |
36625 | ++ | |
36626 | ++ return FALSE; | |
36627 | ++ } | |
36628 | ++ | |
36629 | ++ if (bufUsed) | |
36630 | ++ { | |
36631 | ++ if (!insertLine(num, bufPtr, bufUsed)) | |
36632 | ++ { | |
36633 | ++ close(fd); | |
36634 | ++ | |
36635 | ++ return -1; | |
36636 | ++ } | |
36637 | ++ | |
36638 | ++ lineCount++; | |
36639 | ++ charCount += bufUsed; | |
36640 | ++ } | |
36641 | ++ | |
36642 | ++ close(fd); | |
36643 | ++ | |
36644 | ++ printf("%d lines%s, %d chars\n", lineCount, | |
36645 | ++ (bufUsed ? " (incomplete)" : ""), charCount); | |
36646 | ++ | |
36647 | ++ return TRUE; | |
36648 | ++} | |
36649 | ++ | |
36650 | ++ | |
36651 | ++/* | |
36652 | ++ * Write the specified lines out to the specified file. | |
36653 | ++ * Returns TRUE if successful, or FALSE on an error with a message output. | |
36654 | ++ */ | |
36655 | ++static BOOL | |
36656 | ++writeLines(const char * file, NUM num1, NUM num2) | |
36657 | ++{ | |
36658 | ++ int fd; | |
36659 | ++ LINE * lp; | |
36660 | ++ LEN lineCount; | |
36661 | ++ LEN charCount; | |
36662 | ++ | |
36663 | ++ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) | |
36664 | ++ { | |
36665 | ++ bb_error_msg("Bad line range for write"); | |
36666 | ++ | |
36667 | ++ return FALSE; | |
36668 | ++ } | |
36669 | ++ | |
36670 | ++ lineCount = 0; | |
36671 | ++ charCount = 0; | |
36672 | ++ | |
36673 | ++ fd = creat(file, 0666); | |
36674 | ++ | |
36675 | ++ if (fd < 0) { | |
36676 | ++ perror(file); | |
36677 | ++ | |
36678 | ++ return FALSE; | |
36679 | ++ } | |
36680 | ++ | |
36681 | ++ printf("\"%s\", ", file); | |
36682 | ++ fflush(stdout); | |
36683 | ++ | |
36684 | ++ lp = findLine(num1); | |
36685 | ++ | |
36686 | ++ if (lp == NULL) | |
36687 | ++ { | |
36688 | ++ close(fd); | |
36689 | ++ | |
36690 | ++ return FALSE; | |
36691 | ++ } | |
36692 | ++ | |
36693 | ++ while (num1++ <= num2) | |
36694 | ++ { | |
36695 | ++ if (write(fd, lp->data, lp->len) != lp->len) | |
36696 | ++ { | |
36697 | ++ perror(file); | |
36698 | ++ close(fd); | |
36699 | ++ | |
36700 | ++ return FALSE; | |
36701 | ++ } | |
36702 | ++ | |
36703 | ++ charCount += lp->len; | |
36704 | ++ lineCount++; | |
36705 | ++ lp = lp->next; | |
36706 | ++ } | |
36707 | ++ | |
36708 | ++ if (close(fd) < 0) | |
36709 | ++ { | |
36710 | ++ perror(file); | |
36711 | ++ | |
36712 | ++ return FALSE; | |
36713 | ++ } | |
36714 | ++ | |
36715 | ++ printf("%d lines, %d chars\n", lineCount, charCount); | |
36716 | ++ | |
36717 | ++ return TRUE; | |
36718 | ++} | |
36719 | ++ | |
36720 | ++ | |
36721 | ++/* | |
36722 | ++ * Print lines in a specified range. | |
36723 | ++ * The last line printed becomes the current line. | |
36724 | ++ * If expandFlag is TRUE, then the line is printed specially to | |
36725 | ++ * show magic characters. | |
36726 | ++ */ | |
36727 | ++static BOOL | |
36728 | ++printLines(NUM num1, NUM num2, BOOL expandFlag) | |
36729 | ++{ | |
36730 | ++ const LINE * lp; | |
36731 | ++ const unsigned char * cp; | |
36732 | ++ int ch; | |
36733 | ++ LEN count; | |
36734 | ++ | |
36735 | ++ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) | |
36736 | ++ { | |
36737 | ++ bb_error_msg("Bad line range for print"); | |
36738 | ++ | |
36739 | ++ return FALSE; | |
36740 | ++ } | |
36741 | ++ | |
36742 | ++ lp = findLine(num1); | |
36743 | ++ | |
36744 | ++ if (lp == NULL) | |
36745 | ++ return FALSE; | |
36746 | ++ | |
36747 | ++ while (num1 <= num2) | |
36748 | ++ { | |
36749 | ++ if (!expandFlag) | |
36750 | ++ { | |
36751 | ++ write(1, lp->data, lp->len); | |
36752 | ++ setCurNum(num1++); | |
36753 | ++ lp = lp->next; | |
36754 | ++ | |
36755 | ++ continue; | |
36756 | ++ } | |
36757 | ++ | |
36758 | ++ /* | |
36759 | ++ * Show control characters and characters with the | |
36760 | ++ * high bit set specially. | |
36761 | ++ */ | |
36762 | ++ cp = lp->data; | |
36763 | ++ count = lp->len; | |
36764 | ++ | |
36765 | ++ if ((count > 0) && (cp[count - 1] == '\n')) | |
36766 | ++ count--; | |
36767 | ++ | |
36768 | ++ while (count-- > 0) | |
36769 | ++ { | |
36770 | ++ ch = *cp++; | |
36771 | ++ | |
36772 | ++ if (ch & 0x80) | |
36773 | ++ { | |
36774 | ++ fputs("M-", stdout); | |
36775 | ++ ch &= 0x7f; | |
36776 | ++ } | |
36777 | ++ | |
36778 | ++ if (ch < ' ') | |
36779 | ++ { | |
36780 | ++ fputc('^', stdout); | |
36781 | ++ ch += '@'; | |
36782 | ++ } | |
36783 | ++ | |
36784 | ++ if (ch == 0x7f) | |
36785 | ++ { | |
36786 | ++ fputc('^', stdout); | |
36787 | ++ ch = '?'; | |
36788 | ++ } | |
36789 | ++ | |
36790 | ++ fputc(ch, stdout); | |
36791 | ++ } | |
36792 | ++ | |
36793 | ++ fputs("$\n", stdout); | |
36794 | ++ | |
36795 | ++ setCurNum(num1++); | |
36796 | ++ lp = lp->next; | |
36797 | ++ } | |
36798 | ++ | |
36799 | ++ return TRUE; | |
36800 | ++} | |
36801 | ++ | |
36802 | ++ | |
36803 | ++/* | |
36804 | ++ * Insert a new line with the specified text. | |
36805 | ++ * The line is inserted so as to become the specified line, | |
36806 | ++ * thus pushing any existing and further lines down one. | |
36807 | ++ * The inserted line is also set to become the current line. | |
36808 | ++ * Returns TRUE if successful. | |
36809 | ++ */ | |
36810 | ++static BOOL | |
36811 | ++insertLine(NUM num, const char * data, LEN len) | |
36812 | ++{ | |
36813 | ++ LINE * newLp; | |
36814 | ++ LINE * lp; | |
36815 | ++ | |
36816 | ++ if ((num < 1) || (num > lastNum + 1)) | |
36817 | ++ { | |
36818 | ++ bb_error_msg("Inserting at bad line number"); | |
36819 | ++ | |
36820 | ++ return FALSE; | |
36821 | ++ } | |
36822 | ++ | |
36823 | ++ newLp = (LINE *) malloc(sizeof(LINE) + len - 1); | |
36824 | ++ | |
36825 | ++ if (newLp == NULL) | |
36826 | ++ { | |
36827 | ++ bb_error_msg("Failed to allocate memory for line"); | |
36828 | ++ | |
36829 | ++ return FALSE; | |
36830 | ++ } | |
36831 | ++ | |
36832 | ++ memcpy(newLp->data, data, len); | |
36833 | ++ newLp->len = len; | |
36834 | ++ | |
36835 | ++ if (num > lastNum) | |
36836 | ++ lp = &lines; | |
36837 | ++ else | |
36838 | ++ { | |
36839 | ++ lp = findLine(num); | |
36840 | ++ | |
36841 | ++ if (lp == NULL) | |
36842 | ++ { | |
36843 | ++ free((char *) newLp); | |
36844 | ++ | |
36845 | ++ return FALSE; | |
36846 | ++ } | |
36847 | ++ } | |
36848 | ++ | |
36849 | ++ newLp->next = lp; | |
36850 | ++ newLp->prev = lp->prev; | |
36851 | ++ lp->prev->next = newLp; | |
36852 | ++ lp->prev = newLp; | |
36853 | ++ | |
36854 | ++ lastNum++; | |
36855 | ++ dirty = TRUE; | |
36856 | ++ | |
36857 | ++ return setCurNum(num); | |
36858 | ++} | |
36859 | ++ | |
36860 | ++ | |
36861 | ++/* | |
36862 | ++ * Delete lines from the given range. | |
36863 | ++ */ | |
36864 | ++static BOOL | |
36865 | ++deleteLines(NUM num1, NUM num2) | |
36866 | ++{ | |
36867 | ++ LINE * lp; | |
36868 | ++ LINE * nlp; | |
36869 | ++ LINE * plp; | |
36870 | ++ NUM count; | |
36871 | ++ | |
36872 | ++ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) | |
36873 | ++ { | |
36874 | ++ bb_error_msg("Bad line numbers for delete"); | |
36875 | ++ | |
36876 | ++ return FALSE; | |
36877 | ++ } | |
36878 | ++ | |
36879 | ++ lp = findLine(num1); | |
36880 | ++ | |
36881 | ++ if (lp == NULL) | |
36882 | ++ return FALSE; | |
36883 | ++ | |
36884 | ++ if ((curNum >= num1) && (curNum <= num2)) | |
36885 | ++ { | |
36886 | ++ if (num2 < lastNum) | |
36887 | ++ setCurNum(num2 + 1); | |
36888 | ++ else if (num1 > 1) | |
36889 | ++ setCurNum(num1 - 1); | |
36890 | ++ else | |
36891 | ++ curNum = 0; | |
36892 | ++ } | |
36893 | ++ | |
36894 | ++ count = num2 - num1 + 1; | |
36895 | ++ | |
36896 | ++ if (curNum > num2) | |
36897 | ++ curNum -= count; | |
36898 | ++ | |
36899 | ++ lastNum -= count; | |
36900 | ++ | |
36901 | ++ while (count-- > 0) | |
36902 | ++ { | |
36903 | ++ nlp = lp->next; | |
36904 | ++ plp = lp->prev; | |
36905 | ++ plp->next = nlp; | |
36906 | ++ nlp->prev = plp; | |
36907 | ++ lp->next = NULL; | |
36908 | ++ lp->prev = NULL; | |
36909 | ++ lp->len = 0; | |
36910 | ++ free(lp); | |
36911 | ++ lp = nlp; | |
36912 | ++ } | |
36913 | ++ | |
36914 | ++ dirty = TRUE; | |
36915 | ++ | |
36916 | ++ return TRUE; | |
36917 | ++} | |
36918 | ++ | |
36919 | ++ | |
36920 | ++/* | |
36921 | ++ * Search for a line which contains the specified string. | |
36922 | ++ * If the string is NULL, then the previously searched for string | |
36923 | ++ * is used. The currently searched for string is saved for future use. | |
36924 | ++ * Returns the line number which matches, or 0 if there was no match | |
36925 | ++ * with an error printed. | |
36926 | ++ */ | |
36927 | ++static NUM | |
36928 | ++searchLines(const char * str, NUM num1, NUM num2) | |
36929 | ++{ | |
36930 | ++ const LINE * lp; | |
36931 | ++ int len; | |
36932 | ++ | |
36933 | ++ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) | |
36934 | ++ { | |
36935 | ++ bb_error_msg("Bad line numbers for search"); | |
36936 | ++ | |
36937 | ++ return 0; | |
36938 | ++ } | |
36939 | ++ | |
36940 | ++ if (*str == '\0') | |
36941 | ++ { | |
36942 | ++ if (searchString[0] == '\0') | |
36943 | ++ { | |
36944 | ++ bb_error_msg("No previous search string"); | |
36945 | ++ | |
36946 | ++ return 0; | |
36947 | ++ } | |
36948 | ++ | |
36949 | ++ str = searchString; | |
36950 | ++ } | |
36951 | ++ | |
36952 | ++ if (str != searchString) | |
36953 | ++ strcpy(searchString, str); | |
36954 | ++ | |
36955 | ++ len = strlen(str); | |
36956 | ++ | |
36957 | ++ lp = findLine(num1); | |
36958 | ++ | |
36959 | ++ if (lp == NULL) | |
36960 | ++ return 0; | |
36961 | ++ | |
36962 | ++ while (num1 <= num2) | |
36963 | ++ { | |
36964 | ++ if (findString(lp, str, len, 0) >= 0) | |
36965 | ++ return num1; | |
36966 | ++ | |
36967 | ++ num1++; | |
36968 | ++ lp = lp->next; | |
36969 | ++ } | |
36970 | ++ | |
36971 | ++ bb_error_msg("Cannot find string \"%s\"", str); | |
36972 | ++ | |
36973 | ++ return 0; | |
36974 | ++} | |
36975 | ++ | |
36976 | ++ | |
36977 | ++/* | |
36978 | ++ * Return a pointer to the specified line number. | |
36979 | ++ */ | |
36980 | ++static LINE * | |
36981 | ++findLine(NUM num) | |
36982 | ++{ | |
36983 | ++ LINE * lp; | |
36984 | ++ NUM lnum; | |
36985 | ++ | |
36986 | ++ if ((num < 1) || (num > lastNum)) | |
36987 | ++ { | |
36988 | ++ bb_error_msg("Line number %d does not exist", num); | |
36989 | ++ | |
36990 | ++ return NULL; | |
36991 | ++ } | |
36992 | ++ | |
36993 | ++ if (curNum <= 0) | |
36994 | ++ { | |
36995 | ++ curNum = 1; | |
36996 | ++ curLine = lines.next; | |
36997 | ++ } | |
36998 | ++ | |
36999 | ++ if (num == curNum) | |
37000 | ++ return curLine; | |
37001 | ++ | |
37002 | ++ lp = curLine; | |
37003 | ++ lnum = curNum; | |
37004 | ++ | |
37005 | ++ if (num < (curNum / 2)) | |
37006 | ++ { | |
37007 | ++ lp = lines.next; | |
37008 | ++ lnum = 1; | |
37009 | ++ } | |
37010 | ++ else if (num > ((curNum + lastNum) / 2)) | |
37011 | ++ { | |
37012 | ++ lp = lines.prev; | |
37013 | ++ lnum = lastNum; | |
37014 | ++ } | |
37015 | ++ | |
37016 | ++ while (lnum < num) | |
37017 | ++ { | |
37018 | ++ lp = lp->next; | |
37019 | ++ lnum++; | |
37020 | ++ } | |
37021 | ++ | |
37022 | ++ while (lnum > num) | |
37023 | ++ { | |
37024 | ++ lp = lp->prev; | |
37025 | ++ lnum--; | |
37026 | ++ } | |
37027 | ++ | |
37028 | ++ return lp; | |
37029 | ++} | |
37030 | ++ | |
37031 | ++ | |
37032 | ++/* | |
37033 | ++ * Set the current line number. | |
37034 | ++ * Returns TRUE if successful. | |
37035 | ++ */ | |
37036 | ++static BOOL | |
37037 | ++setCurNum(NUM num) | |
37038 | ++{ | |
37039 | ++ LINE * lp; | |
37040 | ++ | |
37041 | ++ lp = findLine(num); | |
37042 | ++ | |
37043 | ++ if (lp == NULL) | |
37044 | ++ return FALSE; | |
37045 | ++ | |
37046 | ++ curNum = num; | |
37047 | ++ curLine = lp; | |
37048 | ++ | |
37049 | ++ return TRUE; | |
37050 | ++} | |
37051 | ++ | |
37052 | ++/* END CODE */ | |
37053 | diff -Nur busybox-1.00/patches/eject.diff busybox/patches/eject.diff | |
37054 | --- busybox-1.00/patches/eject.diff 2004-03-15 09:29:02.000000000 +0100 | |
37055 | +++ busybox/patches/eject.diff 1970-01-01 01:00:00.000000000 +0100 | |
37056 | @@ -1,164 +0,0 @@ | |
37057 | -Index: AUTHORS | |
37058 | -=================================================================== | |
37059 | -RCS file: /var/cvs/busybox/AUTHORS,v | |
37060 | -retrieving revision 1.40 | |
37061 | -diff -u -r1.40 AUTHORS | |
37062 | ---- a/AUTHORS 9 Oct 2003 21:19:21 -0000 1.40 | |
37063 | -+++ b/AUTHORS 5 Mar 2004 07:23:17 -0000 | |
37064 | -@@ -8,6 +8,9 @@ | |
37065 | - | |
37066 | - ----------- | |
37067 | - | |
37068 | -+Peter Willis <psyphreak@phreaker.net> | |
37069 | -+ eject | |
37070 | -+ | |
37071 | - Emanuele Aina <emanuele.aina@tiscali.it> | |
37072 | - run-parts | |
37073 | - | |
37074 | -Index: coreutils/Config.in | |
37075 | -=================================================================== | |
37076 | -RCS file: /var/cvs/busybox/coreutils/Config.in,v | |
37077 | -retrieving revision 1.23 | |
37078 | -diff -u -r1.23 Config.in | |
37079 | ---- a/coreutils/Config.in 5 Mar 2004 06:47:25 -0000 1.23 | |
37080 | -+++ b/coreutils/Config.in 5 Mar 2004 07:23:18 -0000 | |
37081 | -@@ -164,6 +164,13 @@ | |
37082 | - a command; without options it displays the current | |
37083 | - environment. | |
37084 | - | |
37085 | -+config CONFIG_EJECT | |
37086 | -+ bool "eject" | |
37087 | -+ default n | |
37088 | -+ help | |
37089 | -+ ejects a cdrom drive. | |
37090 | -+ defaults to /dev/cdrom | |
37091 | -+ | |
37092 | - config CONFIG_EXPR | |
37093 | - bool "expr" | |
37094 | - default n | |
37095 | -Index: coreutils/Makefile.in | |
37096 | -=================================================================== | |
37097 | -RCS file: /var/cvs/busybox/coreutils/Makefile.in,v | |
37098 | -retrieving revision 1.8 | |
37099 | -diff -u -r1.8 Makefile.in | |
37100 | ---- a/coreutils/Makefile.in 27 Jan 2004 09:22:20 -0000 1.8 | |
37101 | -+++ b/coreutils/Makefile.in 5 Mar 2004 07:23:18 -0000 | |
37102 | -@@ -41,6 +41,7 @@ | |
37103 | - COREUTILS-$(CONFIG_DU) += du.o | |
37104 | - COREUTILS-$(CONFIG_ECHO) += echo.o | |
37105 | - COREUTILS-$(CONFIG_ENV) += env.o | |
37106 | -+COREUTILS-$(CONFIG_EJECT) += eject.o | |
37107 | - COREUTILS-$(CONFIG_EXPR) += expr.o | |
37108 | - COREUTILS-$(CONFIG_FALSE) += false.o | |
37109 | - COREUTILS-$(CONFIG_FOLD) += fold.o | |
37110 | -Index: coreutils/eject.c | |
37111 | -=================================================================== | |
37112 | -RCS file: coreutils/eject.c | |
37113 | -diff -N coreutils/eject.c | |
37114 | ---- /dev/null 1 Jan 1970 00:00:00 -0000 | |
37115 | -+++ b/coreutils/eject.c 5 Mar 2004 07:23:21 -0000 | |
37116 | -@@ -0,0 +1,66 @@ | |
37117 | -+/* | |
37118 | -+ * eject implementation for busybox | |
37119 | -+ * | |
37120 | -+ * Copyright (C) 2004 Peter Willis <psyphreak@phreaker.net> | |
37121 | -+ * | |
37122 | -+ * This program is free software; you can redistribute it and/or modify | |
37123 | -+ * it under the terms of the GNU General Public License as published by | |
37124 | -+ * the Free Software Foundation; either version 2 of the License, or | |
37125 | -+ * (at your option) any later version. | |
37126 | -+ * | |
37127 | -+ * This program is distributed in the hope that it will be useful, | |
37128 | -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
37129 | -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
37130 | -+ * General Public License for more details. | |
37131 | -+ * | |
37132 | -+ * You should have received a copy of the GNU General Public License | |
37133 | -+ * along with this program; if not, write to the Free Software | |
37134 | -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
37135 | -+ * | |
37136 | -+ */ | |
37137 | -+ | |
37138 | -+/* | |
37139 | -+ * This is a simple hack of eject based on something Erik posted in #uclibc. | |
37140 | -+ * Most of the dirty work blatantly ripped off from cat.c =) | |
37141 | -+ */ | |
37142 | -+ | |
37143 | -+#include <stdio.h> | |
37144 | -+#include <string.h> | |
37145 | -+#include <sys/types.h> | |
37146 | -+#include <sys/stat.h> | |
37147 | -+#include <fcntl.h> | |
37148 | -+#include <sys/ioctl.h> | |
37149 | -+#include "busybox.h" | |
37150 | -+#include <linux/cdrom.h> // needs to be after busybox.h or compile problems arise | |
37151 | -+ | |
37152 | -+#define DEFAULT_CDROM "/dev/cdrom" | |
37153 | -+ | |
37154 | -+extern int eject_main(int argc, char **argv) | |
37155 | -+{ | |
37156 | -+ int fd; | |
37157 | -+ int flag = CDROMEJECT; | |
37158 | -+ int i = 1; | |
37159 | -+ char *device = NULL; | |
37160 | -+ | |
37161 | -+ /* | |
37162 | -+ * i'm too lazy to learn bb_getopt_ulflags and this is obscenely large | |
37163 | -+ * for just some argument parsing so mjn3 can clean it up later. | |
37164 | -+ * sorry, but PlumpOS 7.0-pre2 needs this asap :-/ | |
37165 | -+ */ | |
37166 | -+ while (++i <= argc) { | |
37167 | -+ if ( (! strncmp(argv[i-1],"-t",2)) || (! strncmp(argv[i-1],"--trayclose",11)) ) { | |
37168 | -+ flag = CDROMCLOSETRAY; | |
37169 | -+ } else { | |
37170 | -+ device = argv[i-1]; | |
37171 | -+ } | |
37172 | -+ } | |
37173 | -+ if ( (fd = open(device == NULL ? DEFAULT_CDROM : device, O_RDONLY | O_NONBLOCK) ) < 0 ) { | |
37174 | -+ perror("eject: Can't open device"); | |
37175 | -+ return(EXIT_FAILURE); | |
37176 | -+ } | |
37177 | -+ if (ioctl(fd, flag)) { | |
37178 | -+ perror("eject: Can't eject cdrom"); | |
37179 | -+ return(EXIT_FAILURE); | |
37180 | -+ } | |
37181 | -+ return EXIT_SUCCESS; | |
37182 | -+} | |
37183 | -Index: include/applets.h | |
37184 | -=================================================================== | |
37185 | -RCS file: /var/cvs/busybox/include/applets.h,v | |
37186 | -retrieving revision 1.111 | |
37187 | -diff -u -r1.111 applets.h | |
37188 | ---- a/include/applets.h 27 Jan 2004 09:22:20 -0000 1.111 | |
37189 | -+++ b/include/applets.h 5 Mar 2004 07:23:21 -0000 | |
37190 | -@@ -178,6 +178,9 @@ | |
37191 | - #if defined(CONFIG_FEATURE_GREP_EGREP_ALIAS) | |
37192 | - APPLET_NOUSAGE("egrep", grep_main, _BB_DIR_BIN, _BB_SUID_NEVER) | |
37193 | - #endif | |
37194 | -+#ifdef CONFIG_EJECT | |
37195 | -+ APPLET(eject, eject_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
37196 | -+#endif | |
37197 | - #ifdef CONFIG_ENV | |
37198 | - APPLET(env, env_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | |
37199 | - #endif | |
37200 | -Index: include/usage.h | |
37201 | -=================================================================== | |
37202 | -RCS file: /var/cvs/busybox/include/usage.h,v | |
37203 | -retrieving revision 1.191 | |
37204 | -diff -u -r1.191 usage.h | |
37205 | ---- a/include/usage.h 25 Feb 2004 10:35:55 -0000 1.191 | |
37206 | -+++ b/include/usage.h 5 Mar 2004 07:23:29 -0000 | |
37207 | -@@ -537,6 +537,13 @@ | |
37208 | - "\t-, -i\tstart with an empty environment\n" \ | |
37209 | - "\t-u\tremove variable from the environment\n" | |
37210 | - | |
37211 | -+#define eject_trivial_usage \ | |
37212 | -+ "[-t] [FILE]" | |
37213 | -+#define eject_full_usage \ | |
37214 | -+ "Ejects the specified FILE or /dev/cdrom if FILE is unspecified.\n\n" \ | |
37215 | -+ "Options:\n" \ | |
37216 | -+ "\t-t, --trayclose \tclose tray\n" | |
37217 | -+ | |
37218 | - #define expr_trivial_usage \ | |
37219 | - "EXPRESSION" | |
37220 | - #define expr_full_usage \ | |
37221 | diff -Nur busybox-1.00/procps/ps.c busybox/procps/ps.c | |
37222 | --- busybox-1.00/procps/ps.c 2004-03-15 09:29:03.000000000 +0100 | |
37223 | +++ busybox/procps/ps.c 2005-06-04 08:20:20.000000000 +0200 | |
37224 | @@ -31,9 +31,7 @@ | |
37225 | #include <sys/ioctl.h> | |
37226 | #include "busybox.h" | |
37227 | #ifdef CONFIG_SELINUX | |
37228 | -#include <fs_secure.h> | |
37229 | -#include <ss.h> | |
37230 | -#include <flask_util.h> /* for is_flask_enabled() */ | |
37231 | +#include <selinux/selinux.h> /* for is_selinux_enabled() */ | |
37232 | #endif | |
37233 | ||
37234 | static const int TERMINAL_WIDTH = 79; /* not 80 in case terminal has linefold bug */ | |
37235 | @@ -48,8 +46,8 @@ | |
37236 | ||
37237 | #ifdef CONFIG_SELINUX | |
37238 | int use_selinux = 0; | |
37239 | - security_id_t sid; | |
37240 | - if(is_flask_enabled() && argv[1] && !strcmp(argv[1], "-c") ) | |
37241 | + security_context_t sid=NULL; | |
37242 | + if(is_selinux_enabled() && argv[1] && !strcmp(argv[1], "-c") ) | |
37243 | use_selinux = 1; | |
37244 | #endif | |
37245 | ||
37246 | @@ -58,34 +56,42 @@ | |
37247 | terminal_width--; | |
37248 | ||
37249 | #ifdef CONFIG_SELINUX | |
37250 | - if(use_selinux) | |
37251 | - printf(" PID Context Stat Command\n"); | |
37252 | + if (use_selinux) | |
37253 | + printf(" PID Context Stat Command\n"); | |
37254 | else | |
37255 | #endif | |
37256 | - printf(" PID Uid VmSize Stat Command\n"); | |
37257 | -#ifdef CONFIG_SELINUX | |
37258 | - while ((p = procps_scan(1, use_selinux, &sid)) != 0) { | |
37259 | -#else | |
37260 | - while ((p = procps_scan(1)) != 0) { | |
37261 | -#endif | |
37262 | - char *namecmd = p->cmd; | |
37263 | + printf(" PID Uid VmSize Stat Command\n"); | |
37264 | ||
37265 | + while ((p = procps_scan(1)) != 0) { | |
37266 | + char *namecmd = p->cmd; | |
37267 | #ifdef CONFIG_SELINUX | |
37268 | - if(use_selinux) | |
37269 | - { | |
37270 | + if ( use_selinux ) | |
37271 | + { | |
37272 | char sbuf[128]; | |
37273 | len = sizeof(sbuf); | |
37274 | - if(security_sid_to_context(sid, (security_context_t)&sbuf, &len)) | |
37275 | - strcpy(sbuf, "unknown"); | |
37276 | ||
37277 | + if (is_selinux_enabled()) { | |
37278 | + if (getpidcon(p->pid,&sid)<0) | |
37279 | + sid=NULL; | |
37280 | + } | |
37281 | + | |
37282 | + if (sid) { | |
37283 | + /* I assume sid initilized with NULL */ | |
37284 | + len = strlen(sid)+1; | |
37285 | + safe_strncpy(sbuf, sid, len); | |
37286 | + freecon(sid); | |
37287 | + sid=NULL; | |
37288 | + }else { | |
37289 | + safe_strncpy(sbuf, "unknown",7); | |
37290 | + } | |
37291 | len = printf("%5d %-32s %s ", p->pid, sbuf, p->state); | |
37292 | - } | |
37293 | + } | |
37294 | else | |
37295 | #endif | |
37296 | - if(p->rss == 0) | |
37297 | - len = printf("%5d %-8s %s ", p->pid, p->user, p->state); | |
37298 | - else | |
37299 | - len = printf("%5d %-8s %6ld %s ", p->pid, p->user, p->rss, p->state); | |
37300 | + if(p->rss == 0) | |
37301 | + len = printf("%5d %-8s %s ", p->pid, p->user, p->state); | |
37302 | + else | |
37303 | + len = printf("%5d %-8s %6ld %s ", p->pid, p->user, p->rss, p->state); | |
37304 | i = terminal_width-len; | |
37305 | ||
37306 | if(namecmd != 0 && namecmd[0] != 0) { | |
37307 | diff -Nur busybox-1.00/procps/renice.c busybox/procps/renice.c | |
37308 | --- busybox-1.00/procps/renice.c 2004-03-15 09:29:03.000000000 +0100 | |
37309 | +++ busybox/procps/renice.c 2005-06-04 08:20:20.000000000 +0200 | |
37310 | @@ -1,8 +1,8 @@ | |
37311 | +/* vi: set sw=4 ts=4: */ | |
37312 | /* | |
37313 | - * Mini renice implementation for busybox | |
37314 | + * renice implementation for busybox | |
37315 | * | |
37316 | - * | |
37317 | - * Copyright (C) 2000 Dave 'Kill a Cop' Cinege <dcinege@psychosis.com> | |
37318 | + * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> | |
37319 | * | |
37320 | * This program is free software; you can redistribute it and/or modify | |
37321 | * it under the terms of the GNU General Public License as published by | |
37322 | @@ -20,35 +20,133 @@ | |
37323 | * | |
37324 | */ | |
37325 | ||
37326 | +/* Notes: | |
37327 | + * Setting an absolute priority was obsoleted in SUSv2 and removed | |
37328 | + * in SUSv3. However, the common linux version of renice does | |
37329 | + * absolute and not relative. So we'll continue supporting absolute, | |
37330 | + * although the stdout logging has been removed since both SUSv2 and | |
37331 | + * SUSv3 specify that stdout isn't used. | |
37332 | + * | |
37333 | + * This version is lenient in that it doesn't require any IDs. The | |
37334 | + * options -p, -g, and -u are treated as mode switches for the | |
37335 | + * following IDs (if any). Multiple switches are allowed. | |
37336 | + */ | |
37337 | + | |
37338 | #include <stdio.h> | |
37339 | -#include <errno.h> | |
37340 | #include <stdlib.h> | |
37341 | +#include <string.h> | |
37342 | +#include <limits.h> | |
37343 | +#include <errno.h> | |
37344 | +#include <unistd.h> | |
37345 | #include <sys/time.h> | |
37346 | #include <sys/resource.h> | |
37347 | #include "busybox.h" | |
37348 | ||
37349 | +#if (PRIO_PROCESS < CHAR_MIN) || (PRIO_PROCESS > CHAR_MAX) | |
37350 | +#error Assumption violated : PRIO_PROCESS value | |
37351 | +#endif | |
37352 | +#if (PRIO_PGRP < CHAR_MIN) || (PRIO_PGRP > CHAR_MAX) | |
37353 | +#error Assumption violated : PRIO_PGRP value | |
37354 | +#endif | |
37355 | +#if (PRIO_USER < CHAR_MIN) || (PRIO_USER > CHAR_MAX) | |
37356 | +#error Assumption violated : PRIO_USER value | |
37357 | +#endif | |
37358 | ||
37359 | -extern int renice_main(int argc, char **argv) | |
37360 | +static inline int int_add_no_wrap(int a, int b) | |
37361 | { | |
37362 | - int prio, status = EXIT_SUCCESS; | |
37363 | + int s = a + b; | |
37364 | + | |
37365 | + if (b < 0) { | |
37366 | + if (s > a) s = INT_MIN; | |
37367 | + } else { | |
37368 | + if (s < a) s = INT_MAX; | |
37369 | + } | |
37370 | + | |
37371 | + return s; | |
37372 | +} | |
37373 | ||
37374 | - if (argc < 3) bb_show_usage(); | |
37375 | +int renice_main(int argc, char **argv) | |
37376 | +{ | |
37377 | + static const char Xetpriority_msg[] = "%d : %cetpriority"; | |
37378 | ||
37379 | - prio = atoi(*++argv); | |
37380 | - if (prio > 20) prio = 20; | |
37381 | - if (prio < -20) prio = -20; | |
37382 | + int retval = EXIT_SUCCESS; | |
37383 | + int which = PRIO_PROCESS; /* Default 'which' value. */ | |
37384 | + int use_relative = 0; | |
37385 | + int adjustment, new_priority; | |
37386 | + id_t who; | |
37387 | + | |
37388 | + ++argv; | |
37389 | + | |
37390 | + /* Check if we are using a relative adjustment. */ | |
37391 | + if (argv[0] && (argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) { | |
37392 | + use_relative = 1; | |
37393 | + ++argv; | |
37394 | + } | |
37395 | + | |
37396 | + if (!*argv) { /* No args? Then show usage. */ | |
37397 | + bb_show_usage(); | |
37398 | + } | |
37399 | + | |
37400 | + /* Get the priority adjustment (absolute or relative). */ | |
37401 | + adjustment = bb_xgetlarg(*argv, 10, INT_MIN, INT_MAX); | |
37402 | ||
37403 | while (*++argv) { | |
37404 | - int ps = atoi(*argv); | |
37405 | - int oldp = getpriority(PRIO_PROCESS, ps); | |
37406 | + /* Check for a mode switch. */ | |
37407 | + if ((argv[0][0] == '-') && argv[0][1] && !argv[0][2]) { | |
37408 | + static const char opts[] | |
37409 | + = { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER }; | |
37410 | + const char *p; | |
37411 | + if ((p = strchr(opts, argv[0][1]))) { | |
37412 | + which = p[4]; | |
37413 | + continue; | |
37414 | + } | |
37415 | + } | |
37416 | ||
37417 | - if (setpriority(PRIO_PROCESS, ps, prio) == 0) { | |
37418 | - printf("%d: old priority %d, new priority %d\n", ps, oldp, prio ); | |
37419 | + /* Process an ID arg. */ | |
37420 | + if (which == PRIO_USER) { | |
37421 | + struct passwd *p; | |
37422 | + if (!(p = getpwnam(*argv))) { | |
37423 | + bb_error_msg("unknown user: %s", *argv); | |
37424 | + goto HAD_ERROR; | |
37425 | + } | |
37426 | + who = p->pw_uid; | |
37427 | } else { | |
37428 | - bb_perror_msg("%d: setpriority", ps); | |
37429 | - status = EXIT_FAILURE; | |
37430 | + char *e; | |
37431 | + errno = 0; | |
37432 | + who = strtoul(*argv, &e, 10); | |
37433 | + if (*e || (*argv == e) || errno) { | |
37434 | + bb_error_msg("bad value: %s", *argv); | |
37435 | + goto HAD_ERROR; | |
37436 | + } | |
37437 | } | |
37438 | + | |
37439 | + /* Get priority to use, and set it. */ | |
37440 | + if (use_relative) { | |
37441 | + int old_priority; | |
37442 | + | |
37443 | + errno = 0; /* Needed for getpriority error detection. */ | |
37444 | + old_priority = getpriority(which, who); | |
37445 | + if (errno) { | |
37446 | + bb_perror_msg(Xetpriority_msg, who, 'g'); | |
37447 | + goto HAD_ERROR; | |
37448 | + } | |
37449 | + | |
37450 | + new_priority = int_add_no_wrap(old_priority, adjustment); | |
37451 | + } else { | |
37452 | + new_priority = adjustment; | |
37453 | + } | |
37454 | + | |
37455 | + if (setpriority(which, who, new_priority) == 0) { | |
37456 | + continue; | |
37457 | + } | |
37458 | + | |
37459 | + bb_perror_msg(Xetpriority_msg, who, 's'); | |
37460 | + HAD_ERROR: | |
37461 | + retval = EXIT_FAILURE; | |
37462 | } | |
37463 | ||
37464 | - return status; | |
37465 | + /* No need to check for errors outputing to stderr since, if it | |
37466 | + * was used, the HAD_ERROR label was reached and retval was set. */ | |
37467 | + | |
37468 | + return retval; | |
37469 | } | |
37470 | diff -Nur busybox-1.00/procps/top.c busybox/procps/top.c | |
37471 | --- busybox-1.00/procps/top.c 2004-09-14 21:14:00.000000000 +0200 | |
37472 | +++ busybox/procps/top.c 2005-06-04 08:20:20.000000000 +0200 | |
37473 | @@ -78,7 +78,7 @@ | |
37474 | return (int)((Q->stime + Q->utime) - (P->stime + P->utime)); | |
37475 | } | |
37476 | ||
37477 | -int mult_lvl_cmp(void* a, void* b) { | |
37478 | +static int mult_lvl_cmp(void* a, void* b) { | |
37479 | int i, cmp_val; | |
37480 | ||
37481 | for(i = 0; i < sort_depth; i++) { | |
37482 | @@ -510,11 +510,7 @@ | |
37483 | /* read process IDs & status for all the processes */ | |
37484 | procps_status_t * p; | |
37485 | ||
37486 | -#ifdef CONFIG_SELINUX | |
37487 | - while ((p = procps_scan(0, 0, NULL) ) != 0) { | |
37488 | -#else | |
37489 | while ((p = procps_scan(0)) != 0) { | |
37490 | -#endif | |
37491 | int n = ntop; | |
37492 | ||
37493 | top = xrealloc(top, (++ntop)*sizeof(procps_status_t)); | |
37494 | diff -Nur busybox-1.00/scripts/config/Makefile busybox/scripts/config/Makefile | |
37495 | --- busybox-1.00/scripts/config/Makefile 2004-10-08 09:45:49.000000000 +0200 | |
37496 | +++ busybox/scripts/config/Makefile 2005-06-04 08:20:03.000000000 +0200 | |
37497 | @@ -9,7 +9,11 @@ | |
37498 | ||
37499 | all: ncurses conf mconf | |
37500 | ||
37501 | +ifeq ($(shell uname),SunOS) | |
37502 | +LIBS = -lcurses | |
37503 | +else | |
37504 | LIBS = -lncurses | |
37505 | +endif | |
37506 | ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h)) | |
37507 | HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>" | |
37508 | else | |
37509 | @@ -32,14 +36,17 @@ | |
37510 | endif | |
37511 | endif | |
37512 | ||
37513 | -CONF_SRC =conf.c | |
37514 | -MCONF_SRC =mconf.c checklist.c menubox.c textbox.c yesno.c inputbox.c util.c msgbox.c | |
37515 | -SHARED_SRC=zconf.tab.c | |
37516 | -SHARED_DEPS:=$(srcdir)/lkc.h $(srcdir)/lkc_proto.h \ | |
37517 | - lkc_defs.h $(srcdir)/expr.h zconf.tab.h | |
37518 | -CONF_OBJS =$(patsubst %.c,%.o, $(CONF_SRC)) | |
37519 | -MCONF_OBJS=$(patsubst %.c,%.o, $(MCONF_SRC)) | |
37520 | -SHARED_OBJS=$(patsubst %.c,%.o, $(SHARED_SRC)) | |
37521 | +CONF_SRC = conf.c | |
37522 | +MCONF_SRC = mconf.c | |
37523 | +LXD_SRC = lxdialog/checklist.c lxdialog/menubox.c lxdialog/textbox.c \ | |
37524 | + lxdialog/yesno.c lxdialog/inputbox.c lxdialog/util.c \ | |
37525 | + lxdialog/msgbox.c | |
37526 | +SHARED_SRC = zconf.tab.c | |
37527 | +SHARED_DEPS := $(srcdir)/lkc.h $(srcdir)/lkc_proto.h \ | |
37528 | + lkc_defs.h $(srcdir)/expr.h zconf.tab.h | |
37529 | +CONF_OBJS = $(patsubst %.c,%.o, $(CONF_SRC)) | |
37530 | +MCONF_OBJS = $(patsubst %.c,%.o, $(MCONF_SRC) $(LXD_SRC)) | |
37531 | +SHARED_OBJS = $(patsubst %.c,%.o, $(SHARED_SRC)) | |
37532 | ||
37533 | conf: $(CONF_OBJS) $(SHARED_OBJS) | |
37534 | $(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@ | |
37535 | diff -Nur busybox-1.00/scripts/config/checklist.c busybox/scripts/config/checklist.c | |
37536 | --- busybox-1.00/scripts/config/checklist.c 2004-07-15 08:01:05.000000000 +0200 | |
37537 | +++ busybox/scripts/config/checklist.c 1970-01-01 01:00:00.000000000 +0100 | |
37538 | @@ -1,372 +0,0 @@ | |
37539 | -/* | |
37540 | - * checklist.c -- implements the checklist box | |
37541 | - * | |
37542 | - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
37543 | - * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension | |
37544 | - * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two | |
37545 | - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
37546 | - * | |
37547 | - * This program is free software; you can redistribute it and/or | |
37548 | - * modify it under the terms of the GNU General Public License | |
37549 | - * as published by the Free Software Foundation; either version 2 | |
37550 | - * of the License, or (at your option) any later version. | |
37551 | - * | |
37552 | - * This program is distributed in the hope that it will be useful, | |
37553 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
37554 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
37555 | - * GNU General Public License for more details. | |
37556 | - * | |
37557 | - * You should have received a copy of the GNU General Public License | |
37558 | - * along with this program; if not, write to the Free Software | |
37559 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
37560 | - */ | |
37561 | - | |
37562 | -#include "dialog.h" | |
37563 | - | |
37564 | -static int list_width, check_x, item_x, checkflag; | |
37565 | - | |
37566 | -/* | |
37567 | - * Print list item | |
37568 | - */ | |
37569 | -static void | |
37570 | -print_item (WINDOW * win, const char *item, int status, | |
37571 | - int choice, int selected) | |
37572 | -{ | |
37573 | - int i; | |
37574 | - | |
37575 | - /* Clear 'residue' of last item */ | |
37576 | - wattrset (win, menubox_attr); | |
37577 | - wmove (win, choice, 0); | |
37578 | - for (i = 0; i < list_width; i++) | |
37579 | - waddch (win, ' '); | |
37580 | - | |
37581 | - wmove (win, choice, check_x); | |
37582 | - wattrset (win, selected ? check_selected_attr : check_attr); | |
37583 | - if (checkflag == FLAG_CHECK) | |
37584 | - wprintw (win, "[%c]", status ? 'X' : ' '); | |
37585 | - else | |
37586 | - wprintw (win, "(%c)", status ? 'X' : ' '); | |
37587 | - | |
37588 | - wattrset (win, selected ? tag_selected_attr : tag_attr); | |
37589 | - mvwaddch(win, choice, item_x, item[0]); | |
37590 | - wattrset (win, selected ? item_selected_attr : item_attr); | |
37591 | - waddstr (win, (char *)item+1); | |
37592 | - if (selected) { | |
37593 | - wmove (win, choice, check_x+1); | |
37594 | - wrefresh (win); | |
37595 | - } | |
37596 | -} | |
37597 | - | |
37598 | -/* | |
37599 | - * Print the scroll indicators. | |
37600 | - */ | |
37601 | -static void | |
37602 | -print_arrows (WINDOW * win, int choice, int item_no, int scroll, | |
37603 | - int y, int x, int height) | |
37604 | -{ | |
37605 | - wmove(win, y, x); | |
37606 | - | |
37607 | - if (scroll > 0) { | |
37608 | - wattrset (win, uarrow_attr); | |
37609 | - waddch (win, ACS_UARROW); | |
37610 | - waddstr (win, "(-)"); | |
37611 | - } | |
37612 | - else { | |
37613 | - wattrset (win, menubox_attr); | |
37614 | - waddch (win, ACS_HLINE); | |
37615 | - waddch (win, ACS_HLINE); | |
37616 | - waddch (win, ACS_HLINE); | |
37617 | - waddch (win, ACS_HLINE); | |
37618 | - } | |
37619 | - | |
37620 | - y = y + height + 1; | |
37621 | - wmove(win, y, x); | |
37622 | - | |
37623 | - if ((height < item_no) && (scroll + choice < item_no - 1)) { | |
37624 | - wattrset (win, darrow_attr); | |
37625 | - waddch (win, ACS_DARROW); | |
37626 | - waddstr (win, "(+)"); | |
37627 | - } | |
37628 | - else { | |
37629 | - wattrset (win, menubox_border_attr); | |
37630 | - waddch (win, ACS_HLINE); | |
37631 | - waddch (win, ACS_HLINE); | |
37632 | - waddch (win, ACS_HLINE); | |
37633 | - waddch (win, ACS_HLINE); | |
37634 | - } | |
37635 | -} | |
37636 | - | |
37637 | -/* | |
37638 | - * Display the termination buttons | |
37639 | - */ | |
37640 | -static void | |
37641 | -print_buttons( WINDOW *dialog, int height, int width, int selected) | |
37642 | -{ | |
37643 | - int x = width / 2 - 11; | |
37644 | - int y = height - 2; | |
37645 | - | |
37646 | - print_button (dialog, "Select", y, x, selected == 0); | |
37647 | - print_button (dialog, " Help ", y, x + 14, selected == 1); | |
37648 | - | |
37649 | - wmove(dialog, y, x+1 + 14*selected); | |
37650 | - wrefresh (dialog); | |
37651 | -} | |
37652 | - | |
37653 | -/* | |
37654 | - * Display a dialog box with a list of options that can be turned on or off | |
37655 | - * The `flag' parameter is used to select between radiolist and checklist. | |
37656 | - */ | |
37657 | -int | |
37658 | -dialog_checklist (const char *title, const char *prompt, int height, int width, | |
37659 | - int list_height, int item_no, struct dialog_list_item ** items, | |
37660 | - int flag) | |
37661 | - | |
37662 | -{ | |
37663 | - int i, x, y, box_x, box_y; | |
37664 | - int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; | |
37665 | - WINDOW *dialog, *list; | |
37666 | - | |
37667 | - checkflag = flag; | |
37668 | - | |
37669 | - /* Allocate space for storing item on/off status */ | |
37670 | - if ((status = malloc (sizeof (int) * item_no)) == NULL) { | |
37671 | - endwin (); | |
37672 | - fprintf (stderr, | |
37673 | - "\nCan't allocate memory in dialog_checklist().\n"); | |
37674 | - exit (-1); | |
37675 | - } | |
37676 | - | |
37677 | - /* Initializes status */ | |
37678 | - for (i = 0; i < item_no; i++) { | |
37679 | - status[i] = (items[i]->selected == 1); /* ON */ | |
37680 | - if ((!choice && status[i]) || items[i]->selected == 2) /* SELECTED */ | |
37681 | - choice = i + 1; | |
37682 | - } | |
37683 | - if (choice) | |
37684 | - choice--; | |
37685 | - | |
37686 | - max_choice = MIN (list_height, item_no); | |
37687 | - | |
37688 | - /* center dialog box on screen */ | |
37689 | - x = (COLS - width) / 2; | |
37690 | - y = (LINES - height) / 2; | |
37691 | - | |
37692 | - draw_shadow (stdscr, y, x, height, width); | |
37693 | - | |
37694 | - dialog = newwin (height, width, y, x); | |
37695 | - keypad (dialog, TRUE); | |
37696 | - | |
37697 | - draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
37698 | - wattrset (dialog, border_attr); | |
37699 | - mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
37700 | - for (i = 0; i < width - 2; i++) | |
37701 | - waddch (dialog, ACS_HLINE); | |
37702 | - wattrset (dialog, dialog_attr); | |
37703 | - waddch (dialog, ACS_RTEE); | |
37704 | - | |
37705 | - if (title != NULL && strlen(title) >= width-2 ) { | |
37706 | - /* truncate long title -- mec */ | |
37707 | - char * title2 = malloc(width-2+1); | |
37708 | - memcpy( title2, title, width-2 ); | |
37709 | - title2[width-2] = '\0'; | |
37710 | - title = title2; | |
37711 | - } | |
37712 | - | |
37713 | - if (title != NULL) { | |
37714 | - wattrset (dialog, title_attr); | |
37715 | - mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
37716 | - waddstr (dialog, (char *)title); | |
37717 | - waddch (dialog, ' '); | |
37718 | - } | |
37719 | - | |
37720 | - wattrset (dialog, dialog_attr); | |
37721 | - print_autowrap (dialog, prompt, width - 2, 1, 3); | |
37722 | - | |
37723 | - list_width = width - 6; | |
37724 | - box_y = height - list_height - 5; | |
37725 | - box_x = (width - list_width) / 2 - 1; | |
37726 | - | |
37727 | - /* create new window for the list */ | |
37728 | - list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1); | |
37729 | - | |
37730 | - keypad (list, TRUE); | |
37731 | - | |
37732 | - /* draw a box around the list items */ | |
37733 | - draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2, | |
37734 | - menubox_border_attr, menubox_attr); | |
37735 | - | |
37736 | - /* Find length of longest item in order to center checklist */ | |
37737 | - check_x = 0; | |
37738 | - for (i = 0; i < item_no; i++) | |
37739 | - check_x = MAX (check_x, + strlen (items[i]->name) + 4); | |
37740 | - | |
37741 | - check_x = (list_width - check_x) / 2; | |
37742 | - item_x = check_x + 4; | |
37743 | - | |
37744 | - if (choice >= list_height) { | |
37745 | - scroll = choice - list_height + 1; | |
37746 | - choice -= scroll; | |
37747 | - } | |
37748 | - | |
37749 | - /* Print the list */ | |
37750 | - for (i = 0; i < max_choice; i++) { | |
37751 | - print_item (list, items[scroll + i]->name, | |
37752 | - status[i+scroll], i, i == choice); | |
37753 | - } | |
37754 | - | |
37755 | - print_arrows(dialog, choice, item_no, scroll, | |
37756 | - box_y, box_x + check_x + 5, list_height); | |
37757 | - | |
37758 | - print_buttons(dialog, height, width, 0); | |
37759 | - | |
37760 | - wnoutrefresh (list); | |
37761 | - wnoutrefresh (dialog); | |
37762 | - doupdate (); | |
37763 | - | |
37764 | - while (key != ESC) { | |
37765 | - key = wgetch (dialog); | |
37766 | - | |
37767 | - for (i = 0; i < max_choice; i++) | |
37768 | - if (toupper(key) == toupper(items[scroll + i]->name[0])) | |
37769 | - break; | |
37770 | - | |
37771 | - | |
37772 | - if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || | |
37773 | - key == '+' || key == '-' ) { | |
37774 | - if (key == KEY_UP || key == '-') { | |
37775 | - if (!choice) { | |
37776 | - if (!scroll) | |
37777 | - continue; | |
37778 | - /* Scroll list down */ | |
37779 | - if (list_height > 1) { | |
37780 | - /* De-highlight current first item */ | |
37781 | - print_item (list, items[scroll]->name, | |
37782 | - status[scroll], 0, FALSE); | |
37783 | - scrollok (list, TRUE); | |
37784 | - wscrl (list, -1); | |
37785 | - scrollok (list, FALSE); | |
37786 | - } | |
37787 | - scroll--; | |
37788 | - print_item (list, items[scroll]->name, | |
37789 | - status[scroll], 0, TRUE); | |
37790 | - wnoutrefresh (list); | |
37791 | - | |
37792 | - print_arrows(dialog, choice, item_no, scroll, | |
37793 | - box_y, box_x + check_x + 5, list_height); | |
37794 | - | |
37795 | - wrefresh (dialog); | |
37796 | - | |
37797 | - continue; /* wait for another key press */ | |
37798 | - } else | |
37799 | - i = choice - 1; | |
37800 | - } else if (key == KEY_DOWN || key == '+') { | |
37801 | - if (choice == max_choice - 1) { | |
37802 | - if (scroll + choice >= item_no - 1) | |
37803 | - continue; | |
37804 | - /* Scroll list up */ | |
37805 | - if (list_height > 1) { | |
37806 | - /* De-highlight current last item before scrolling up */ | |
37807 | - print_item (list, items[scroll + max_choice - 1]->name, | |
37808 | - status[scroll + max_choice - 1], | |
37809 | - max_choice - 1, FALSE); | |
37810 | - scrollok (list, TRUE); | |
37811 | - scroll (list); | |
37812 | - scrollok (list, FALSE); | |
37813 | - } | |
37814 | - scroll++; | |
37815 | - print_item (list, items[scroll + max_choice - 1]->name, | |
37816 | - status[scroll + max_choice - 1], | |
37817 | - max_choice - 1, TRUE); | |
37818 | - wnoutrefresh (list); | |
37819 | - | |
37820 | - print_arrows(dialog, choice, item_no, scroll, | |
37821 | - box_y, box_x + check_x + 5, list_height); | |
37822 | - | |
37823 | - wrefresh (dialog); | |
37824 | - | |
37825 | - continue; /* wait for another key press */ | |
37826 | - } else | |
37827 | - i = choice + 1; | |
37828 | - } | |
37829 | - if (i != choice) { | |
37830 | - /* De-highlight current item */ | |
37831 | - print_item (list, items[scroll + choice]->name, | |
37832 | - status[scroll + choice], choice, FALSE); | |
37833 | - /* Highlight new item */ | |
37834 | - choice = i; | |
37835 | - print_item (list, items[scroll + choice]->name, | |
37836 | - status[scroll + choice], choice, TRUE); | |
37837 | - wnoutrefresh (list); | |
37838 | - wrefresh (dialog); | |
37839 | - } | |
37840 | - continue; /* wait for another key press */ | |
37841 | - } | |
37842 | - switch (key) { | |
37843 | - case 'H': | |
37844 | - case 'h': | |
37845 | - case '?': | |
37846 | - for (i = 0; i < item_no; i++) | |
37847 | - items[i]->selected = 0; | |
37848 | - items[scroll + choice]->selected = 1; | |
37849 | - delwin (dialog); | |
37850 | - free (status); | |
37851 | - return 1; | |
37852 | - case TAB: | |
37853 | - case KEY_LEFT: | |
37854 | - case KEY_RIGHT: | |
37855 | - button = ((key == KEY_LEFT ? --button : ++button) < 0) | |
37856 | - ? 1 : (button > 1 ? 0 : button); | |
37857 | - | |
37858 | - print_buttons(dialog, height, width, button); | |
37859 | - wrefresh (dialog); | |
37860 | - break; | |
37861 | - case 'S': | |
37862 | - case 's': | |
37863 | - case ' ': | |
37864 | - case '\n': | |
37865 | - if (!button) { | |
37866 | - if (flag == FLAG_CHECK) { | |
37867 | - status[scroll + choice] = !status[scroll + choice]; | |
37868 | - wmove (list, choice, check_x); | |
37869 | - wattrset (list, check_selected_attr); | |
37870 | - wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' '); | |
37871 | - } else { | |
37872 | - if (!status[scroll + choice]) { | |
37873 | - for (i = 0; i < item_no; i++) | |
37874 | - status[i] = 0; | |
37875 | - status[scroll + choice] = 1; | |
37876 | - for (i = 0; i < max_choice; i++) | |
37877 | - print_item (list, items[scroll + i]->name, | |
37878 | - status[scroll + i], i, i == choice); | |
37879 | - } | |
37880 | - } | |
37881 | - wnoutrefresh (list); | |
37882 | - wrefresh (dialog); | |
37883 | - | |
37884 | - for (i = 0; i < item_no; i++) { | |
37885 | - items[i]->selected = status[i]; | |
37886 | - } | |
37887 | - } else { | |
37888 | - for (i = 0; i < item_no; i++) | |
37889 | - items[i]->selected = 0; | |
37890 | - items[scroll + choice]->selected = 1; | |
37891 | - } | |
37892 | - delwin (dialog); | |
37893 | - free (status); | |
37894 | - return button; | |
37895 | - case 'X': | |
37896 | - case 'x': | |
37897 | - key = ESC; | |
37898 | - case ESC: | |
37899 | - break; | |
37900 | - } | |
37901 | - | |
37902 | - /* Now, update everything... */ | |
37903 | - doupdate (); | |
37904 | - } | |
37905 | - | |
37906 | - | |
37907 | - delwin (dialog); | |
37908 | - free (status); | |
37909 | - return -1; /* ESC pressed */ | |
37910 | -} | |
37911 | diff -Nur busybox-1.00/scripts/config/colors.h busybox/scripts/config/colors.h | |
37912 | --- busybox-1.00/scripts/config/colors.h 2002-12-05 09:41:06.000000000 +0100 | |
37913 | +++ busybox/scripts/config/colors.h 1970-01-01 01:00:00.000000000 +0100 | |
37914 | @@ -1,161 +0,0 @@ | |
37915 | -/* | |
37916 | - * colors.h -- color attribute definitions | |
37917 | - * | |
37918 | - * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
37919 | - * | |
37920 | - * This program is free software; you can redistribute it and/or | |
37921 | - * modify it under the terms of the GNU General Public License | |
37922 | - * as published by the Free Software Foundation; either version 2 | |
37923 | - * of the License, or (at your option) any later version. | |
37924 | - * | |
37925 | - * This program is distributed in the hope that it will be useful, | |
37926 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
37927 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
37928 | - * GNU General Public License for more details. | |
37929 | - * | |
37930 | - * You should have received a copy of the GNU General Public License | |
37931 | - * along with this program; if not, write to the Free Software | |
37932 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
37933 | - */ | |
37934 | - | |
37935 | - | |
37936 | -/* | |
37937 | - * Default color definitions | |
37938 | - * | |
37939 | - * *_FG = foreground | |
37940 | - * *_BG = background | |
37941 | - * *_HL = highlight? | |
37942 | - */ | |
37943 | -#define SCREEN_FG COLOR_CYAN | |
37944 | -#define SCREEN_BG COLOR_BLUE | |
37945 | -#define SCREEN_HL TRUE | |
37946 | - | |
37947 | -#define SHADOW_FG COLOR_BLACK | |
37948 | -#define SHADOW_BG COLOR_BLACK | |
37949 | -#define SHADOW_HL TRUE | |
37950 | - | |
37951 | -#define DIALOG_FG COLOR_BLACK | |
37952 | -#define DIALOG_BG COLOR_WHITE | |
37953 | -#define DIALOG_HL FALSE | |
37954 | - | |
37955 | -#define TITLE_FG COLOR_YELLOW | |
37956 | -#define TITLE_BG COLOR_WHITE | |
37957 | -#define TITLE_HL TRUE | |
37958 | - | |
37959 | -#define BORDER_FG COLOR_WHITE | |
37960 | -#define BORDER_BG COLOR_WHITE | |
37961 | -#define BORDER_HL TRUE | |
37962 | - | |
37963 | -#define BUTTON_ACTIVE_FG COLOR_WHITE | |
37964 | -#define BUTTON_ACTIVE_BG COLOR_BLUE | |
37965 | -#define BUTTON_ACTIVE_HL TRUE | |
37966 | - | |
37967 | -#define BUTTON_INACTIVE_FG COLOR_BLACK | |
37968 | -#define BUTTON_INACTIVE_BG COLOR_WHITE | |
37969 | -#define BUTTON_INACTIVE_HL FALSE | |
37970 | - | |
37971 | -#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE | |
37972 | -#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE | |
37973 | -#define BUTTON_KEY_ACTIVE_HL TRUE | |
37974 | - | |
37975 | -#define BUTTON_KEY_INACTIVE_FG COLOR_RED | |
37976 | -#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE | |
37977 | -#define BUTTON_KEY_INACTIVE_HL FALSE | |
37978 | - | |
37979 | -#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW | |
37980 | -#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE | |
37981 | -#define BUTTON_LABEL_ACTIVE_HL TRUE | |
37982 | - | |
37983 | -#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK | |
37984 | -#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE | |
37985 | -#define BUTTON_LABEL_INACTIVE_HL TRUE | |
37986 | - | |
37987 | -#define INPUTBOX_FG COLOR_BLACK | |
37988 | -#define INPUTBOX_BG COLOR_WHITE | |
37989 | -#define INPUTBOX_HL FALSE | |
37990 | - | |
37991 | -#define INPUTBOX_BORDER_FG COLOR_BLACK | |
37992 | -#define INPUTBOX_BORDER_BG COLOR_WHITE | |
37993 | -#define INPUTBOX_BORDER_HL FALSE | |
37994 | - | |
37995 | -#define SEARCHBOX_FG COLOR_BLACK | |
37996 | -#define SEARCHBOX_BG COLOR_WHITE | |
37997 | -#define SEARCHBOX_HL FALSE | |
37998 | - | |
37999 | -#define SEARCHBOX_TITLE_FG COLOR_YELLOW | |
38000 | -#define SEARCHBOX_TITLE_BG COLOR_WHITE | |
38001 | -#define SEARCHBOX_TITLE_HL TRUE | |
38002 | - | |
38003 | -#define SEARCHBOX_BORDER_FG COLOR_WHITE | |
38004 | -#define SEARCHBOX_BORDER_BG COLOR_WHITE | |
38005 | -#define SEARCHBOX_BORDER_HL TRUE | |
38006 | - | |
38007 | -#define POSITION_INDICATOR_FG COLOR_YELLOW | |
38008 | -#define POSITION_INDICATOR_BG COLOR_WHITE | |
38009 | -#define POSITION_INDICATOR_HL TRUE | |
38010 | - | |
38011 | -#define MENUBOX_FG COLOR_BLACK | |
38012 | -#define MENUBOX_BG COLOR_WHITE | |
38013 | -#define MENUBOX_HL FALSE | |
38014 | - | |
38015 | -#define MENUBOX_BORDER_FG COLOR_WHITE | |
38016 | -#define MENUBOX_BORDER_BG COLOR_WHITE | |
38017 | -#define MENUBOX_BORDER_HL TRUE | |
38018 | - | |
38019 | -#define ITEM_FG COLOR_BLACK | |
38020 | -#define ITEM_BG COLOR_WHITE | |
38021 | -#define ITEM_HL FALSE | |
38022 | - | |
38023 | -#define ITEM_SELECTED_FG COLOR_WHITE | |
38024 | -#define ITEM_SELECTED_BG COLOR_BLUE | |
38025 | -#define ITEM_SELECTED_HL TRUE | |
38026 | - | |
38027 | -#define TAG_FG COLOR_YELLOW | |
38028 | -#define TAG_BG COLOR_WHITE | |
38029 | -#define TAG_HL TRUE | |
38030 | - | |
38031 | -#define TAG_SELECTED_FG COLOR_YELLOW | |
38032 | -#define TAG_SELECTED_BG COLOR_BLUE | |
38033 | -#define TAG_SELECTED_HL TRUE | |
38034 | - | |
38035 | -#define TAG_KEY_FG COLOR_YELLOW | |
38036 | -#define TAG_KEY_BG COLOR_WHITE | |
38037 | -#define TAG_KEY_HL TRUE | |
38038 | - | |
38039 | -#define TAG_KEY_SELECTED_FG COLOR_YELLOW | |
38040 | -#define TAG_KEY_SELECTED_BG COLOR_BLUE | |
38041 | -#define TAG_KEY_SELECTED_HL TRUE | |
38042 | - | |
38043 | -#define CHECK_FG COLOR_BLACK | |
38044 | -#define CHECK_BG COLOR_WHITE | |
38045 | -#define CHECK_HL FALSE | |
38046 | - | |
38047 | -#define CHECK_SELECTED_FG COLOR_WHITE | |
38048 | -#define CHECK_SELECTED_BG COLOR_BLUE | |
38049 | -#define CHECK_SELECTED_HL TRUE | |
38050 | - | |
38051 | -#define UARROW_FG COLOR_GREEN | |
38052 | -#define UARROW_BG COLOR_WHITE | |
38053 | -#define UARROW_HL TRUE | |
38054 | - | |
38055 | -#define DARROW_FG COLOR_GREEN | |
38056 | -#define DARROW_BG COLOR_WHITE | |
38057 | -#define DARROW_HL TRUE | |
38058 | - | |
38059 | -/* End of default color definitions */ | |
38060 | - | |
38061 | -#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y))) | |
38062 | -#define COLOR_NAME_LEN 10 | |
38063 | -#define COLOR_COUNT 8 | |
38064 | - | |
38065 | -/* | |
38066 | - * Global variables | |
38067 | - */ | |
38068 | - | |
38069 | -typedef struct { | |
38070 | - char name[COLOR_NAME_LEN]; | |
38071 | - int value; | |
38072 | -} color_names_st; | |
38073 | - | |
38074 | -extern color_names_st color_names[]; | |
38075 | -extern int color_table[][3]; | |
38076 | diff -Nur busybox-1.00/scripts/config/conf.c busybox/scripts/config/conf.c | |
38077 | --- busybox-1.00/scripts/config/conf.c 2004-01-16 13:48:53.000000000 +0100 | |
38078 | +++ busybox/scripts/config/conf.c 2005-06-04 08:20:03.000000000 +0200 | |
38079 | @@ -31,14 +31,14 @@ | |
38080 | static int indent = 1; | |
38081 | static int valid_stdin = 1; | |
38082 | static int conf_cnt; | |
38083 | -static char line[128]; | |
38084 | +static signed char line[128]; | |
38085 | static struct menu *rootEntry; | |
38086 | ||
38087 | static char nohelp_text[] = "Sorry, no help available for this option yet.\n"; | |
38088 | ||
38089 | -static void strip(char *str) | |
38090 | +static void strip(signed char *str) | |
38091 | { | |
38092 | - char *p = str; | |
38093 | + signed char *p = str; | |
38094 | int l; | |
38095 | ||
38096 | while ((isspace(*p))) | |
38097 | diff -Nur busybox-1.00/scripts/config/confdata.c busybox/scripts/config/confdata.c | |
38098 | --- busybox-1.00/scripts/config/confdata.c 2004-07-15 08:01:05.000000000 +0200 | |
38099 | +++ busybox/scripts/config/confdata.c 2005-06-04 08:20:03.000000000 +0200 | |
38100 | @@ -23,10 +23,10 @@ | |
38101 | NULL, | |
38102 | }; | |
38103 | ||
38104 | -static char *conf_expand_value(const char *in) | |
38105 | +static char *conf_expand_value(const signed char *in) | |
38106 | { | |
38107 | struct symbol *sym; | |
38108 | - const char *src; | |
38109 | + const signed char *src; | |
38110 | static char res_value[SYMBOL_MAXLENGTH]; | |
38111 | char *dst, name[SYMBOL_MAXLENGTH]; | |
38112 | ||
38113 | @@ -287,7 +287,7 @@ | |
38114 | } else | |
38115 | basename = conf_def_filename; | |
38116 | ||
38117 | - sprintf(newname, "%s.tmpconfig.%d", dirname, getpid()); | |
38118 | + sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid()); | |
38119 | out = fopen(newname, "w"); | |
38120 | if (!out) | |
38121 | return 1; | |
38122 | diff -Nur busybox-1.00/scripts/config/dialog.h busybox/scripts/config/dialog.h | |
38123 | --- busybox-1.00/scripts/config/dialog.h 2004-03-15 09:29:08.000000000 +0100 | |
38124 | +++ busybox/scripts/config/dialog.h 1970-01-01 01:00:00.000000000 +0100 | |
38125 | @@ -1,196 +0,0 @@ | |
38126 | - | |
38127 | -/* | |
38128 | - * dialog.h -- common declarations for all dialog modules | |
38129 | - * | |
38130 | - * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
38131 | - * | |
38132 | - * This program is free software; you can redistribute it and/or | |
38133 | - * modify it under the terms of the GNU General Public License | |
38134 | - * as published by the Free Software Foundation; either version 2 | |
38135 | - * of the License, or (at your option) any later version. | |
38136 | - * | |
38137 | - * This program is distributed in the hope that it will be useful, | |
38138 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
38139 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
38140 | - * GNU General Public License for more details. | |
38141 | - * | |
38142 | - * You should have received a copy of the GNU General Public License | |
38143 | - * along with this program; if not, write to the Free Software | |
38144 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
38145 | - */ | |
38146 | - | |
38147 | -#include <sys/types.h> | |
38148 | -#include <fcntl.h> | |
38149 | -#include <unistd.h> | |
38150 | -#include <ctype.h> | |
38151 | -#include <stdlib.h> | |
38152 | -#include <string.h> | |
38153 | - | |
38154 | -#ifdef CURSES_LOC | |
38155 | -#include CURSES_LOC | |
38156 | - | |
38157 | -/* | |
38158 | - * Colors in ncurses 1.9.9e do not work properly since foreground and | |
38159 | - * background colors are OR'd rather than separately masked. This version | |
38160 | - * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible | |
38161 | - * with standard curses. The simplest fix (to make this work with standard | |
38162 | - * curses) uses the wbkgdset() function, not used in the original hack. | |
38163 | - * Turn it off if we're building with 1.9.9e, since it just confuses things. | |
38164 | - */ | |
38165 | -#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) | |
38166 | -#define OLD_NCURSES 1 | |
38167 | -#undef wbkgdset | |
38168 | -#define wbkgdset(w,p) /*nothing*/ | |
38169 | -#else | |
38170 | -#define OLD_NCURSES 0 | |
38171 | -#endif | |
38172 | - | |
38173 | -#define TR(params) _tracef params | |
38174 | - | |
38175 | -#define ESC 27 | |
38176 | -#define TAB 9 | |
38177 | -#define MAX_LEN 2048 | |
38178 | -#define BUF_SIZE (10*1024) | |
38179 | -#define MIN(x,y) (x < y ? x : y) | |
38180 | -#define MAX(x,y) (x > y ? x : y) | |
38181 | - | |
38182 | - | |
38183 | -#ifndef ACS_ULCORNER | |
38184 | -#define ACS_ULCORNER '+' | |
38185 | -#endif | |
38186 | -#ifndef ACS_LLCORNER | |
38187 | -#define ACS_LLCORNER '+' | |
38188 | -#endif | |
38189 | -#ifndef ACS_URCORNER | |
38190 | -#define ACS_URCORNER '+' | |
38191 | -#endif | |
38192 | -#ifndef ACS_LRCORNER | |
38193 | -#define ACS_LRCORNER '+' | |
38194 | -#endif | |
38195 | -#ifndef ACS_HLINE | |
38196 | -#define ACS_HLINE '-' | |
38197 | -#endif | |
38198 | -#ifndef ACS_VLINE | |
38199 | -#define ACS_VLINE '|' | |
38200 | -#endif | |
38201 | -#ifndef ACS_LTEE | |
38202 | -#define ACS_LTEE '+' | |
38203 | -#endif | |
38204 | -#ifndef ACS_RTEE | |
38205 | -#define ACS_RTEE '+' | |
38206 | -#endif | |
38207 | -#ifndef ACS_UARROW | |
38208 | -#define ACS_UARROW '^' | |
38209 | -#endif | |
38210 | -#ifndef ACS_DARROW | |
38211 | -#define ACS_DARROW 'v' | |
38212 | -#endif | |
38213 | - | |
38214 | -/* | |
38215 | - * Attribute names | |
38216 | - */ | |
38217 | -#define screen_attr attributes[0] | |
38218 | -#define shadow_attr attributes[1] | |
38219 | -#define dialog_attr attributes[2] | |
38220 | -#define title_attr attributes[3] | |
38221 | -#define border_attr attributes[4] | |
38222 | -#define button_active_attr attributes[5] | |
38223 | -#define button_inactive_attr attributes[6] | |
38224 | -#define button_key_active_attr attributes[7] | |
38225 | -#define button_key_inactive_attr attributes[8] | |
38226 | -#define button_label_active_attr attributes[9] | |
38227 | -#define button_label_inactive_attr attributes[10] | |
38228 | -#define inputbox_attr attributes[11] | |
38229 | -#define inputbox_border_attr attributes[12] | |
38230 | -#define searchbox_attr attributes[13] | |
38231 | -#define searchbox_title_attr attributes[14] | |
38232 | -#define searchbox_border_attr attributes[15] | |
38233 | -#define position_indicator_attr attributes[16] | |
38234 | -#define menubox_attr attributes[17] | |
38235 | -#define menubox_border_attr attributes[18] | |
38236 | -#define item_attr attributes[19] | |
38237 | -#define item_selected_attr attributes[20] | |
38238 | -#define tag_attr attributes[21] | |
38239 | -#define tag_selected_attr attributes[22] | |
38240 | -#define tag_key_attr attributes[23] | |
38241 | -#define tag_key_selected_attr attributes[24] | |
38242 | -#define check_attr attributes[25] | |
38243 | -#define check_selected_attr attributes[26] | |
38244 | -#define uarrow_attr attributes[27] | |
38245 | -#define darrow_attr attributes[28] | |
38246 | - | |
38247 | -/* number of attributes */ | |
38248 | -#define ATTRIBUTE_COUNT 29 | |
38249 | - | |
38250 | -/* | |
38251 | - * Global variables | |
38252 | - */ | |
38253 | -extern bool use_colors; | |
38254 | - | |
38255 | -extern chtype attributes[]; | |
38256 | -#endif | |
38257 | - | |
38258 | -extern char *backtitle; | |
38259 | - | |
38260 | -struct dialog_list_item { | |
38261 | - char *name; | |
38262 | - int namelen; | |
38263 | - char *tag; | |
38264 | - int selected; /* Set to 1 by dialog_*() function. */ | |
38265 | -}; | |
38266 | - | |
38267 | -/* | |
38268 | - * Function prototypes | |
38269 | - */ | |
38270 | - | |
38271 | -void init_dialog (void); | |
38272 | -void end_dialog (void); | |
38273 | -void dialog_clear (void); | |
38274 | -#ifdef CURSES_LOC | |
38275 | -void attr_clear (WINDOW * win, int height, int width, chtype attr); | |
38276 | -void color_setup (void); | |
38277 | -void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x); | |
38278 | -void print_button (WINDOW * win, const char *label, int y, int x, int selected); | |
38279 | -void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box, | |
38280 | - chtype border); | |
38281 | -void draw_shadow (WINDOW * win, int y, int x, int height, int width); | |
38282 | -#endif | |
38283 | - | |
38284 | -int first_alpha (const char *string, const char *exempt); | |
38285 | -int dialog_yesno (const char *title, const char *prompt, int height, int width); | |
38286 | -int dialog_msgbox (const char *title, const char *prompt, int height, | |
38287 | - int width, int pause); | |
38288 | -int dialog_textbox (const char *title, const char *file, int height, int width); | |
38289 | -int dialog_menu (const char *title, const char *prompt, int height, int width, | |
38290 | - int menu_height, const char *choice, int item_no, | |
38291 | - struct dialog_list_item ** items); | |
38292 | -int dialog_checklist (const char *title, const char *prompt, int height, | |
38293 | - int width, int list_height, int item_no, | |
38294 | - struct dialog_list_item ** items, int flag); | |
38295 | -extern unsigned char dialog_input_result[]; | |
38296 | -int dialog_inputbox (const char *title, const char *prompt, int height, | |
38297 | - int width, const char *init); | |
38298 | - | |
38299 | -struct dialog_list_item *first_sel_item(int item_no, | |
38300 | - struct dialog_list_item ** items); | |
38301 | - | |
38302 | -/* | |
38303 | - * This is the base for fictitious keys, which activate | |
38304 | - * the buttons. | |
38305 | - * | |
38306 | - * Mouse-generated keys are the following: | |
38307 | - * -- the first 32 are used as numbers, in addition to '0'-'9' | |
38308 | - * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') | |
38309 | - * -- uppercase chars are used to invoke the button (M_EVENT + 'O') | |
38310 | - */ | |
38311 | -#ifdef CURSES_LOC | |
38312 | -#define M_EVENT (KEY_MAX+1) | |
38313 | -#endif | |
38314 | - | |
38315 | - | |
38316 | -/* | |
38317 | - * The `flag' parameter in checklist is used to select between | |
38318 | - * radiolist and checklist | |
38319 | - */ | |
38320 | -#define FLAG_CHECK 1 | |
38321 | -#define FLAG_RADIO 0 | |
38322 | diff -Nur busybox-1.00/scripts/config/expr.c busybox/scripts/config/expr.c | |
38323 | --- busybox-1.00/scripts/config/expr.c 2004-07-15 08:01:05.000000000 +0200 | |
38324 | +++ busybox/scripts/config/expr.c 2005-06-04 08:20:03.000000000 +0200 | |
38325 | @@ -1087,3 +1087,13 @@ | |
38326 | { | |
38327 | expr_print(e, expr_print_file_helper, out, E_NONE); | |
38328 | } | |
38329 | + | |
38330 | +static void expr_print_gstr_helper(void *data, const char *str) | |
38331 | +{ | |
38332 | + str_append((struct gstr*)data, str); | |
38333 | +} | |
38334 | + | |
38335 | +void expr_gstr_print(struct expr *e, struct gstr *gs) | |
38336 | +{ | |
38337 | + expr_print(e, expr_print_gstr_helper, gs, E_NONE); | |
38338 | +} | |
38339 | diff -Nur busybox-1.00/scripts/config/expr.h busybox/scripts/config/expr.h | |
38340 | --- busybox-1.00/scripts/config/expr.h 2004-07-15 08:01:05.000000000 +0200 | |
38341 | +++ busybox/scripts/config/expr.h 2005-06-04 08:20:03.000000000 +0200 | |
38342 | @@ -174,6 +174,8 @@ | |
38343 | struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); | |
38344 | ||
38345 | void expr_fprint(struct expr *e, FILE *out); | |
38346 | +struct gstr; /* forward */ | |
38347 | +void expr_gstr_print(struct expr *e, struct gstr *gs); | |
38348 | ||
38349 | static inline int expr_is_yes(struct expr *e) | |
38350 | { | |
38351 | diff -Nur busybox-1.00/scripts/config/inputbox.c busybox/scripts/config/inputbox.c | |
38352 | --- busybox-1.00/scripts/config/inputbox.c 2002-12-05 09:41:07.000000000 +0100 | |
38353 | +++ busybox/scripts/config/inputbox.c 1970-01-01 01:00:00.000000000 +0100 | |
38354 | @@ -1,240 +0,0 @@ | |
38355 | -/* | |
38356 | - * inputbox.c -- implements the input box | |
38357 | - * | |
38358 | - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
38359 | - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
38360 | - * | |
38361 | - * This program is free software; you can redistribute it and/or | |
38362 | - * modify it under the terms of the GNU General Public License | |
38363 | - * as published by the Free Software Foundation; either version 2 | |
38364 | - * of the License, or (at your option) any later version. | |
38365 | - * | |
38366 | - * This program is distributed in the hope that it will be useful, | |
38367 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
38368 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
38369 | - * GNU General Public License for more details. | |
38370 | - * | |
38371 | - * You should have received a copy of the GNU General Public License | |
38372 | - * along with this program; if not, write to the Free Software | |
38373 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
38374 | - */ | |
38375 | - | |
38376 | -#include "dialog.h" | |
38377 | - | |
38378 | -unsigned char dialog_input_result[MAX_LEN + 1]; | |
38379 | - | |
38380 | -/* | |
38381 | - * Print the termination buttons | |
38382 | - */ | |
38383 | -static void | |
38384 | -print_buttons(WINDOW *dialog, int height, int width, int selected) | |
38385 | -{ | |
38386 | - int x = width / 2 - 11; | |
38387 | - int y = height - 2; | |
38388 | - | |
38389 | - print_button (dialog, " Ok ", y, x, selected==0); | |
38390 | - print_button (dialog, " Help ", y, x + 14, selected==1); | |
38391 | - | |
38392 | - wmove(dialog, y, x+1+14*selected); | |
38393 | - wrefresh(dialog); | |
38394 | -} | |
38395 | - | |
38396 | -/* | |
38397 | - * Display a dialog box for inputing a string | |
38398 | - */ | |
38399 | -int | |
38400 | -dialog_inputbox (const char *title, const char *prompt, int height, int width, | |
38401 | - const char *init) | |
38402 | -{ | |
38403 | - int i, x, y, box_y, box_x, box_width; | |
38404 | - int input_x = 0, scroll = 0, key = 0, button = -1; | |
38405 | - unsigned char *instr = dialog_input_result; | |
38406 | - WINDOW *dialog; | |
38407 | - | |
38408 | - /* center dialog box on screen */ | |
38409 | - x = (COLS - width) / 2; | |
38410 | - y = (LINES - height) / 2; | |
38411 | - | |
38412 | - | |
38413 | - draw_shadow (stdscr, y, x, height, width); | |
38414 | - | |
38415 | - dialog = newwin (height, width, y, x); | |
38416 | - keypad (dialog, TRUE); | |
38417 | - | |
38418 | - draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
38419 | - wattrset (dialog, border_attr); | |
38420 | - mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
38421 | - for (i = 0; i < width - 2; i++) | |
38422 | - waddch (dialog, ACS_HLINE); | |
38423 | - wattrset (dialog, dialog_attr); | |
38424 | - waddch (dialog, ACS_RTEE); | |
38425 | - | |
38426 | - if (title != NULL && strlen(title) >= width-2 ) { | |
38427 | - /* truncate long title -- mec */ | |
38428 | - char * title2 = malloc(width-2+1); | |
38429 | - memcpy( title2, title, width-2 ); | |
38430 | - title2[width-2] = '\0'; | |
38431 | - title = title2; | |
38432 | - } | |
38433 | - | |
38434 | - if (title != NULL) { | |
38435 | - wattrset (dialog, title_attr); | |
38436 | - mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
38437 | - waddstr (dialog, (char *)title); | |
38438 | - waddch (dialog, ' '); | |
38439 | - } | |
38440 | - | |
38441 | - wattrset (dialog, dialog_attr); | |
38442 | - print_autowrap (dialog, prompt, width - 2, 1, 3); | |
38443 | - | |
38444 | - /* Draw the input field box */ | |
38445 | - box_width = width - 6; | |
38446 | - getyx (dialog, y, x); | |
38447 | - box_y = y + 2; | |
38448 | - box_x = (width - box_width) / 2; | |
38449 | - draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2, | |
38450 | - border_attr, dialog_attr); | |
38451 | - | |
38452 | - print_buttons(dialog, height, width, 0); | |
38453 | - | |
38454 | - /* Set up the initial value */ | |
38455 | - wmove (dialog, box_y, box_x); | |
38456 | - wattrset (dialog, inputbox_attr); | |
38457 | - | |
38458 | - if (!init) | |
38459 | - instr[0] = '\0'; | |
38460 | - else | |
38461 | - strcpy (instr, init); | |
38462 | - | |
38463 | - input_x = strlen (instr); | |
38464 | - | |
38465 | - if (input_x >= box_width) { | |
38466 | - scroll = input_x - box_width + 1; | |
38467 | - input_x = box_width - 1; | |
38468 | - for (i = 0; i < box_width - 1; i++) | |
38469 | - waddch (dialog, instr[scroll + i]); | |
38470 | - } else | |
38471 | - waddstr (dialog, instr); | |
38472 | - | |
38473 | - wmove (dialog, box_y, box_x + input_x); | |
38474 | - | |
38475 | - wrefresh (dialog); | |
38476 | - | |
38477 | - while (key != ESC) { | |
38478 | - key = wgetch (dialog); | |
38479 | - | |
38480 | - if (button == -1) { /* Input box selected */ | |
38481 | - switch (key) { | |
38482 | - case TAB: | |
38483 | - case KEY_UP: | |
38484 | - case KEY_DOWN: | |
38485 | - break; | |
38486 | - case KEY_LEFT: | |
38487 | - continue; | |
38488 | - case KEY_RIGHT: | |
38489 | - continue; | |
38490 | - case KEY_BACKSPACE: | |
38491 | - case 127: | |
38492 | - if (input_x || scroll) { | |
38493 | - wattrset (dialog, inputbox_attr); | |
38494 | - if (!input_x) { | |
38495 | - scroll = scroll < box_width - 1 ? | |
38496 | - 0 : scroll - (box_width - 1); | |
38497 | - wmove (dialog, box_y, box_x); | |
38498 | - for (i = 0; i < box_width; i++) | |
38499 | - waddch (dialog, instr[scroll + input_x + i] ? | |
38500 | - instr[scroll + input_x + i] : ' '); | |
38501 | - input_x = strlen (instr) - scroll; | |
38502 | - } else | |
38503 | - input_x--; | |
38504 | - instr[scroll + input_x] = '\0'; | |
38505 | - mvwaddch (dialog, box_y, input_x + box_x, ' '); | |
38506 | - wmove (dialog, box_y, input_x + box_x); | |
38507 | - wrefresh (dialog); | |
38508 | - } | |
38509 | - continue; | |
38510 | - default: | |
38511 | - if (key < 0x100 && isprint (key)) { | |
38512 | - if (scroll + input_x < MAX_LEN) { | |
38513 | - wattrset (dialog, inputbox_attr); | |
38514 | - instr[scroll + input_x] = key; | |
38515 | - instr[scroll + input_x + 1] = '\0'; | |
38516 | - if (input_x == box_width - 1) { | |
38517 | - scroll++; | |
38518 | - wmove (dialog, box_y, box_x); | |
38519 | - for (i = 0; i < box_width - 1; i++) | |
38520 | - waddch (dialog, instr[scroll + i]); | |
38521 | - } else { | |
38522 | - wmove (dialog, box_y, input_x++ + box_x); | |
38523 | - waddch (dialog, key); | |
38524 | - } | |
38525 | - wrefresh (dialog); | |
38526 | - } else | |
38527 | - flash (); /* Alarm user about overflow */ | |
38528 | - continue; | |
38529 | - } | |
38530 | - } | |
38531 | - } | |
38532 | - switch (key) { | |
38533 | - case 'O': | |
38534 | - case 'o': | |
38535 | - delwin (dialog); | |
38536 | - return 0; | |
38537 | - case 'H': | |
38538 | - case 'h': | |
38539 | - delwin (dialog); | |
38540 | - return 1; | |
38541 | - case KEY_UP: | |
38542 | - case KEY_LEFT: | |
38543 | - switch (button) { | |
38544 | - case -1: | |
38545 | - button = 1; /* Indicates "Cancel" button is selected */ | |
38546 | - print_buttons(dialog, height, width, 1); | |
38547 | - break; | |
38548 | - case 0: | |
38549 | - button = -1; /* Indicates input box is selected */ | |
38550 | - print_buttons(dialog, height, width, 0); | |
38551 | - wmove (dialog, box_y, box_x + input_x); | |
38552 | - wrefresh (dialog); | |
38553 | - break; | |
38554 | - case 1: | |
38555 | - button = 0; /* Indicates "OK" button is selected */ | |
38556 | - print_buttons(dialog, height, width, 0); | |
38557 | - break; | |
38558 | - } | |
38559 | - break; | |
38560 | - case TAB: | |
38561 | - case KEY_DOWN: | |
38562 | - case KEY_RIGHT: | |
38563 | - switch (button) { | |
38564 | - case -1: | |
38565 | - button = 0; /* Indicates "OK" button is selected */ | |
38566 | - print_buttons(dialog, height, width, 0); | |
38567 | - break; | |
38568 | - case 0: | |
38569 | - button = 1; /* Indicates "Cancel" button is selected */ | |
38570 | - print_buttons(dialog, height, width, 1); | |
38571 | - break; | |
38572 | - case 1: | |
38573 | - button = -1; /* Indicates input box is selected */ | |
38574 | - print_buttons(dialog, height, width, 0); | |
38575 | - wmove (dialog, box_y, box_x + input_x); | |
38576 | - wrefresh (dialog); | |
38577 | - break; | |
38578 | - } | |
38579 | - break; | |
38580 | - case ' ': | |
38581 | - case '\n': | |
38582 | - delwin (dialog); | |
38583 | - return (button == -1 ? 0 : button); | |
38584 | - case 'X': | |
38585 | - case 'x': | |
38586 | - key = ESC; | |
38587 | - case ESC: | |
38588 | - break; | |
38589 | - } | |
38590 | - } | |
38591 | - | |
38592 | - delwin (dialog); | |
38593 | - return -1; /* ESC pressed */ | |
38594 | -} | |
38595 | diff -Nur busybox-1.00/scripts/config/lkc.h busybox/scripts/config/lkc.h | |
38596 | --- busybox-1.00/scripts/config/lkc.h 2003-08-05 04:18:24.000000000 +0200 | |
38597 | +++ busybox/scripts/config/lkc.h 2005-06-04 08:20:03.000000000 +0200 | |
38598 | @@ -56,11 +56,21 @@ | |
38599 | void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); | |
38600 | void menu_finalize(struct menu *parent); | |
38601 | void menu_set_type(int type); | |
38602 | + | |
38603 | +/* util.c */ | |
38604 | struct file *file_lookup(const char *name); | |
38605 | int file_write_dep(const char *name); | |
38606 | ||
38607 | -extern struct menu *current_entry; | |
38608 | -extern struct menu *current_menu; | |
38609 | +struct gstr { | |
38610 | + size_t len; | |
38611 | + char *s; | |
38612 | +}; | |
38613 | +struct gstr str_new(void); | |
38614 | +struct gstr str_assign(const char *s); | |
38615 | +void str_free(struct gstr *gs); | |
38616 | +void str_append(struct gstr *gs, const char *s); | |
38617 | +void str_printf(struct gstr *gs, const char *fmt, ...); | |
38618 | +const char *str_get(struct gstr *gs); | |
38619 | ||
38620 | /* symbol.c */ | |
38621 | void sym_init(void); | |
38622 | diff -Nur busybox-1.00/scripts/config/lkc_proto.h busybox/scripts/config/lkc_proto.h | |
38623 | --- busybox-1.00/scripts/config/lkc_proto.h 2003-08-05 04:18:25.000000000 +0200 | |
38624 | +++ busybox/scripts/config/lkc_proto.h 2005-06-04 08:20:03.000000000 +0200 | |
38625 | @@ -18,6 +18,7 @@ | |
38626 | ||
38627 | P(sym_lookup,struct symbol *,(const char *name, int isconst)); | |
38628 | P(sym_find,struct symbol *,(const char *name)); | |
38629 | +P(sym_re_search,struct symbol **,(const char *pattern)); | |
38630 | P(sym_type_name,const char *,(enum symbol_type type)); | |
38631 | P(sym_calc_value,void,(struct symbol *sym)); | |
38632 | P(sym_get_type,enum symbol_type,(struct symbol *sym)); | |
38633 | diff -Nur busybox-1.00/scripts/config/lxdialog/BIG.FAT.WARNING busybox/scripts/config/lxdialog/BIG.FAT.WARNING | |
38634 | --- busybox-1.00/scripts/config/lxdialog/BIG.FAT.WARNING 1970-01-01 01:00:00.000000000 +0100 | |
38635 | +++ busybox/scripts/config/lxdialog/BIG.FAT.WARNING 2005-06-04 08:20:02.000000000 +0200 | |
38636 | @@ -0,0 +1,4 @@ | |
38637 | +This is NOT the official version of dialog. This version has been | |
38638 | +significantly modified from the original. It is for use by the Linux | |
38639 | +kernel configuration script. Please do not bother Savio Lam with | |
38640 | +questions about this program. | |
38641 | diff -Nur busybox-1.00/scripts/config/lxdialog/checklist.c busybox/scripts/config/lxdialog/checklist.c | |
38642 | --- busybox-1.00/scripts/config/lxdialog/checklist.c 1970-01-01 01:00:00.000000000 +0100 | |
38643 | +++ busybox/scripts/config/lxdialog/checklist.c 2005-06-04 08:20:02.000000000 +0200 | |
38644 | @@ -0,0 +1,372 @@ | |
38645 | +/* | |
38646 | + * checklist.c -- implements the checklist box | |
38647 | + * | |
38648 | + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
38649 | + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension | |
38650 | + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two | |
38651 | + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
38652 | + * | |
38653 | + * This program is free software; you can redistribute it and/or | |
38654 | + * modify it under the terms of the GNU General Public License | |
38655 | + * as published by the Free Software Foundation; either version 2 | |
38656 | + * of the License, or (at your option) any later version. | |
38657 | + * | |
38658 | + * This program is distributed in the hope that it will be useful, | |
38659 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
38660 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
38661 | + * GNU General Public License for more details. | |
38662 | + * | |
38663 | + * You should have received a copy of the GNU General Public License | |
38664 | + * along with this program; if not, write to the Free Software | |
38665 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
38666 | + */ | |
38667 | + | |
38668 | +#include "dialog.h" | |
38669 | + | |
38670 | +static int list_width, check_x, item_x, checkflag; | |
38671 | + | |
38672 | +/* | |
38673 | + * Print list item | |
38674 | + */ | |
38675 | +static void | |
38676 | +print_item (WINDOW * win, const char *item, int status, | |
38677 | + int choice, int selected) | |
38678 | +{ | |
38679 | + int i; | |
38680 | + | |
38681 | + /* Clear 'residue' of last item */ | |
38682 | + wattrset (win, menubox_attr); | |
38683 | + wmove (win, choice, 0); | |
38684 | + for (i = 0; i < list_width; i++) | |
38685 | + waddch (win, ' '); | |
38686 | + | |
38687 | + wmove (win, choice, check_x); | |
38688 | + wattrset (win, selected ? check_selected_attr : check_attr); | |
38689 | + if (checkflag == FLAG_CHECK) | |
38690 | + wprintw (win, "[%c]", status ? 'X' : ' '); | |
38691 | + else | |
38692 | + wprintw (win, "(%c)", status ? 'X' : ' '); | |
38693 | + | |
38694 | + wattrset (win, selected ? tag_selected_attr : tag_attr); | |
38695 | + mvwaddch(win, choice, item_x, item[0]); | |
38696 | + wattrset (win, selected ? item_selected_attr : item_attr); | |
38697 | + waddstr (win, (char *)item+1); | |
38698 | + if (selected) { | |
38699 | + wmove (win, choice, check_x+1); | |
38700 | + wrefresh (win); | |
38701 | + } | |
38702 | +} | |
38703 | + | |
38704 | +/* | |
38705 | + * Print the scroll indicators. | |
38706 | + */ | |
38707 | +static void | |
38708 | +print_arrows (WINDOW * win, int choice, int item_no, int scroll, | |
38709 | + int y, int x, int height) | |
38710 | +{ | |
38711 | + wmove(win, y, x); | |
38712 | + | |
38713 | + if (scroll > 0) { | |
38714 | + wattrset (win, uarrow_attr); | |
38715 | + waddch (win, ACS_UARROW); | |
38716 | + waddstr (win, "(-)"); | |
38717 | + } | |
38718 | + else { | |
38719 | + wattrset (win, menubox_attr); | |
38720 | + waddch (win, ACS_HLINE); | |
38721 | + waddch (win, ACS_HLINE); | |
38722 | + waddch (win, ACS_HLINE); | |
38723 | + waddch (win, ACS_HLINE); | |
38724 | + } | |
38725 | + | |
38726 | + y = y + height + 1; | |
38727 | + wmove(win, y, x); | |
38728 | + | |
38729 | + if ((height < item_no) && (scroll + choice < item_no - 1)) { | |
38730 | + wattrset (win, darrow_attr); | |
38731 | + waddch (win, ACS_DARROW); | |
38732 | + waddstr (win, "(+)"); | |
38733 | + } | |
38734 | + else { | |
38735 | + wattrset (win, menubox_border_attr); | |
38736 | + waddch (win, ACS_HLINE); | |
38737 | + waddch (win, ACS_HLINE); | |
38738 | + waddch (win, ACS_HLINE); | |
38739 | + waddch (win, ACS_HLINE); | |
38740 | + } | |
38741 | +} | |
38742 | + | |
38743 | +/* | |
38744 | + * Display the termination buttons | |
38745 | + */ | |
38746 | +static void | |
38747 | +print_buttons( WINDOW *dialog, int height, int width, int selected) | |
38748 | +{ | |
38749 | + int x = width / 2 - 11; | |
38750 | + int y = height - 2; | |
38751 | + | |
38752 | + print_button (dialog, "Select", y, x, selected == 0); | |
38753 | + print_button (dialog, " Help ", y, x + 14, selected == 1); | |
38754 | + | |
38755 | + wmove(dialog, y, x+1 + 14*selected); | |
38756 | + wrefresh (dialog); | |
38757 | +} | |
38758 | + | |
38759 | +/* | |
38760 | + * Display a dialog box with a list of options that can be turned on or off | |
38761 | + * The `flag' parameter is used to select between radiolist and checklist. | |
38762 | + */ | |
38763 | +int | |
38764 | +dialog_checklist (const char *title, const char *prompt, int height, int width, | |
38765 | + int list_height, int item_no, struct dialog_list_item ** items, | |
38766 | + int flag) | |
38767 | + | |
38768 | +{ | |
38769 | + int i, x, y, box_x, box_y; | |
38770 | + int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; | |
38771 | + WINDOW *dialog, *list; | |
38772 | + | |
38773 | + checkflag = flag; | |
38774 | + | |
38775 | + /* Allocate space for storing item on/off status */ | |
38776 | + if ((status = malloc (sizeof (int) * item_no)) == NULL) { | |
38777 | + endwin (); | |
38778 | + fprintf (stderr, | |
38779 | + "\nCan't allocate memory in dialog_checklist().\n"); | |
38780 | + exit (-1); | |
38781 | + } | |
38782 | + | |
38783 | + /* Initializes status */ | |
38784 | + for (i = 0; i < item_no; i++) { | |
38785 | + status[i] = (items[i]->selected == 1); /* ON */ | |
38786 | + if ((!choice && status[i]) || items[i]->selected == 2) /* SELECTED */ | |
38787 | + choice = i + 1; | |
38788 | + } | |
38789 | + if (choice) | |
38790 | + choice--; | |
38791 | + | |
38792 | + max_choice = MIN (list_height, item_no); | |
38793 | + | |
38794 | + /* center dialog box on screen */ | |
38795 | + x = (COLS - width) / 2; | |
38796 | + y = (LINES - height) / 2; | |
38797 | + | |
38798 | + draw_shadow (stdscr, y, x, height, width); | |
38799 | + | |
38800 | + dialog = newwin (height, width, y, x); | |
38801 | + keypad (dialog, TRUE); | |
38802 | + | |
38803 | + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
38804 | + wattrset (dialog, border_attr); | |
38805 | + mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
38806 | + for (i = 0; i < width - 2; i++) | |
38807 | + waddch (dialog, ACS_HLINE); | |
38808 | + wattrset (dialog, dialog_attr); | |
38809 | + waddch (dialog, ACS_RTEE); | |
38810 | + | |
38811 | + if (title != NULL && strlen(title) >= width-2 ) { | |
38812 | + /* truncate long title -- mec */ | |
38813 | + char * title2 = malloc(width-2+1); | |
38814 | + memcpy( title2, title, width-2 ); | |
38815 | + title2[width-2] = '\0'; | |
38816 | + title = title2; | |
38817 | + } | |
38818 | + | |
38819 | + if (title != NULL) { | |
38820 | + wattrset (dialog, title_attr); | |
38821 | + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
38822 | + waddstr (dialog, (char *)title); | |
38823 | + waddch (dialog, ' '); | |
38824 | + } | |
38825 | + | |
38826 | + wattrset (dialog, dialog_attr); | |
38827 | + print_autowrap (dialog, prompt, width - 2, 1, 3); | |
38828 | + | |
38829 | + list_width = width - 6; | |
38830 | + box_y = height - list_height - 5; | |
38831 | + box_x = (width - list_width) / 2 - 1; | |
38832 | + | |
38833 | + /* create new window for the list */ | |
38834 | + list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1); | |
38835 | + | |
38836 | + keypad (list, TRUE); | |
38837 | + | |
38838 | + /* draw a box around the list items */ | |
38839 | + draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2, | |
38840 | + menubox_border_attr, menubox_attr); | |
38841 | + | |
38842 | + /* Find length of longest item in order to center checklist */ | |
38843 | + check_x = 0; | |
38844 | + for (i = 0; i < item_no; i++) | |
38845 | + check_x = MAX (check_x, + strlen (items[i]->name) + 4); | |
38846 | + | |
38847 | + check_x = (list_width - check_x) / 2; | |
38848 | + item_x = check_x + 4; | |
38849 | + | |
38850 | + if (choice >= list_height) { | |
38851 | + scroll = choice - list_height + 1; | |
38852 | + choice -= scroll; | |
38853 | + } | |
38854 | + | |
38855 | + /* Print the list */ | |
38856 | + for (i = 0; i < max_choice; i++) { | |
38857 | + print_item (list, items[scroll + i]->name, | |
38858 | + status[i+scroll], i, i == choice); | |
38859 | + } | |
38860 | + | |
38861 | + print_arrows(dialog, choice, item_no, scroll, | |
38862 | + box_y, box_x + check_x + 5, list_height); | |
38863 | + | |
38864 | + print_buttons(dialog, height, width, 0); | |
38865 | + | |
38866 | + wnoutrefresh (list); | |
38867 | + wnoutrefresh (dialog); | |
38868 | + doupdate (); | |
38869 | + | |
38870 | + while (key != ESC) { | |
38871 | + key = wgetch (dialog); | |
38872 | + | |
38873 | + for (i = 0; i < max_choice; i++) | |
38874 | + if (toupper(key) == toupper(items[scroll + i]->name[0])) | |
38875 | + break; | |
38876 | + | |
38877 | + | |
38878 | + if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || | |
38879 | + key == '+' || key == '-' ) { | |
38880 | + if (key == KEY_UP || key == '-') { | |
38881 | + if (!choice) { | |
38882 | + if (!scroll) | |
38883 | + continue; | |
38884 | + /* Scroll list down */ | |
38885 | + if (list_height > 1) { | |
38886 | + /* De-highlight current first item */ | |
38887 | + print_item (list, items[scroll]->name, | |
38888 | + status[scroll], 0, FALSE); | |
38889 | + scrollok (list, TRUE); | |
38890 | + wscrl (list, -1); | |
38891 | + scrollok (list, FALSE); | |
38892 | + } | |
38893 | + scroll--; | |
38894 | + print_item (list, items[scroll]->name, | |
38895 | + status[scroll], 0, TRUE); | |
38896 | + wnoutrefresh (list); | |
38897 | + | |
38898 | + print_arrows(dialog, choice, item_no, scroll, | |
38899 | + box_y, box_x + check_x + 5, list_height); | |
38900 | + | |
38901 | + wrefresh (dialog); | |
38902 | + | |
38903 | + continue; /* wait for another key press */ | |
38904 | + } else | |
38905 | + i = choice - 1; | |
38906 | + } else if (key == KEY_DOWN || key == '+') { | |
38907 | + if (choice == max_choice - 1) { | |
38908 | + if (scroll + choice >= item_no - 1) | |
38909 | + continue; | |
38910 | + /* Scroll list up */ | |
38911 | + if (list_height > 1) { | |
38912 | + /* De-highlight current last item before scrolling up */ | |
38913 | + print_item (list, items[scroll + max_choice - 1]->name, | |
38914 | + status[scroll + max_choice - 1], | |
38915 | + max_choice - 1, FALSE); | |
38916 | + scrollok (list, TRUE); | |
38917 | + scroll (list); | |
38918 | + scrollok (list, FALSE); | |
38919 | + } | |
38920 | + scroll++; | |
38921 | + print_item (list, items[scroll + max_choice - 1]->name, | |
38922 | + status[scroll + max_choice - 1], | |
38923 | + max_choice - 1, TRUE); | |
38924 | + wnoutrefresh (list); | |
38925 | + | |
38926 | + print_arrows(dialog, choice, item_no, scroll, | |
38927 | + box_y, box_x + check_x + 5, list_height); | |
38928 | + | |
38929 | + wrefresh (dialog); | |
38930 | + | |
38931 | + continue; /* wait for another key press */ | |
38932 | + } else | |
38933 | + i = choice + 1; | |
38934 | + } | |
38935 | + if (i != choice) { | |
38936 | + /* De-highlight current item */ | |
38937 | + print_item (list, items[scroll + choice]->name, | |
38938 | + status[scroll + choice], choice, FALSE); | |
38939 | + /* Highlight new item */ | |
38940 | + choice = i; | |
38941 | + print_item (list, items[scroll + choice]->name, | |
38942 | + status[scroll + choice], choice, TRUE); | |
38943 | + wnoutrefresh (list); | |
38944 | + wrefresh (dialog); | |
38945 | + } | |
38946 | + continue; /* wait for another key press */ | |
38947 | + } | |
38948 | + switch (key) { | |
38949 | + case 'H': | |
38950 | + case 'h': | |
38951 | + case '?': | |
38952 | + for (i = 0; i < item_no; i++) | |
38953 | + items[i]->selected = 0; | |
38954 | + items[scroll + choice]->selected = 1; | |
38955 | + delwin (dialog); | |
38956 | + free (status); | |
38957 | + return 1; | |
38958 | + case TAB: | |
38959 | + case KEY_LEFT: | |
38960 | + case KEY_RIGHT: | |
38961 | + button = ((key == KEY_LEFT ? --button : ++button) < 0) | |
38962 | + ? 1 : (button > 1 ? 0 : button); | |
38963 | + | |
38964 | + print_buttons(dialog, height, width, button); | |
38965 | + wrefresh (dialog); | |
38966 | + break; | |
38967 | + case 'S': | |
38968 | + case 's': | |
38969 | + case ' ': | |
38970 | + case '\n': | |
38971 | + if (!button) { | |
38972 | + if (flag == FLAG_CHECK) { | |
38973 | + status[scroll + choice] = !status[scroll + choice]; | |
38974 | + wmove (list, choice, check_x); | |
38975 | + wattrset (list, check_selected_attr); | |
38976 | + wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' '); | |
38977 | + } else { | |
38978 | + if (!status[scroll + choice]) { | |
38979 | + for (i = 0; i < item_no; i++) | |
38980 | + status[i] = 0; | |
38981 | + status[scroll + choice] = 1; | |
38982 | + for (i = 0; i < max_choice; i++) | |
38983 | + print_item (list, items[scroll + i]->name, | |
38984 | + status[scroll + i], i, i == choice); | |
38985 | + } | |
38986 | + } | |
38987 | + wnoutrefresh (list); | |
38988 | + wrefresh (dialog); | |
38989 | + | |
38990 | + for (i = 0; i < item_no; i++) { | |
38991 | + items[i]->selected = status[i]; | |
38992 | + } | |
38993 | + } else { | |
38994 | + for (i = 0; i < item_no; i++) | |
38995 | + items[i]->selected = 0; | |
38996 | + items[scroll + choice]->selected = 1; | |
38997 | + } | |
38998 | + delwin (dialog); | |
38999 | + free (status); | |
39000 | + return button; | |
39001 | + case 'X': | |
39002 | + case 'x': | |
39003 | + key = ESC; | |
39004 | + case ESC: | |
39005 | + break; | |
39006 | + } | |
39007 | + | |
39008 | + /* Now, update everything... */ | |
39009 | + doupdate (); | |
39010 | + } | |
39011 | + | |
39012 | + | |
39013 | + delwin (dialog); | |
39014 | + free (status); | |
39015 | + return -1; /* ESC pressed */ | |
39016 | +} | |
39017 | diff -Nur busybox-1.00/scripts/config/lxdialog/colors.h busybox/scripts/config/lxdialog/colors.h | |
39018 | --- busybox-1.00/scripts/config/lxdialog/colors.h 1970-01-01 01:00:00.000000000 +0100 | |
39019 | +++ busybox/scripts/config/lxdialog/colors.h 2005-06-04 08:20:02.000000000 +0200 | |
39020 | @@ -0,0 +1,161 @@ | |
39021 | +/* | |
39022 | + * colors.h -- color attribute definitions | |
39023 | + * | |
39024 | + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
39025 | + * | |
39026 | + * This program is free software; you can redistribute it and/or | |
39027 | + * modify it under the terms of the GNU General Public License | |
39028 | + * as published by the Free Software Foundation; either version 2 | |
39029 | + * of the License, or (at your option) any later version. | |
39030 | + * | |
39031 | + * This program is distributed in the hope that it will be useful, | |
39032 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
39033 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
39034 | + * GNU General Public License for more details. | |
39035 | + * | |
39036 | + * You should have received a copy of the GNU General Public License | |
39037 | + * along with this program; if not, write to the Free Software | |
39038 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
39039 | + */ | |
39040 | + | |
39041 | + | |
39042 | +/* | |
39043 | + * Default color definitions | |
39044 | + * | |
39045 | + * *_FG = foreground | |
39046 | + * *_BG = background | |
39047 | + * *_HL = highlight? | |
39048 | + */ | |
39049 | +#define SCREEN_FG COLOR_CYAN | |
39050 | +#define SCREEN_BG COLOR_BLUE | |
39051 | +#define SCREEN_HL TRUE | |
39052 | + | |
39053 | +#define SHADOW_FG COLOR_BLACK | |
39054 | +#define SHADOW_BG COLOR_BLACK | |
39055 | +#define SHADOW_HL TRUE | |
39056 | + | |
39057 | +#define DIALOG_FG COLOR_BLACK | |
39058 | +#define DIALOG_BG COLOR_WHITE | |
39059 | +#define DIALOG_HL FALSE | |
39060 | + | |
39061 | +#define TITLE_FG COLOR_YELLOW | |
39062 | +#define TITLE_BG COLOR_WHITE | |
39063 | +#define TITLE_HL TRUE | |
39064 | + | |
39065 | +#define BORDER_FG COLOR_WHITE | |
39066 | +#define BORDER_BG COLOR_WHITE | |
39067 | +#define BORDER_HL TRUE | |
39068 | + | |
39069 | +#define BUTTON_ACTIVE_FG COLOR_WHITE | |
39070 | +#define BUTTON_ACTIVE_BG COLOR_BLUE | |
39071 | +#define BUTTON_ACTIVE_HL TRUE | |
39072 | + | |
39073 | +#define BUTTON_INACTIVE_FG COLOR_BLACK | |
39074 | +#define BUTTON_INACTIVE_BG COLOR_WHITE | |
39075 | +#define BUTTON_INACTIVE_HL FALSE | |
39076 | + | |
39077 | +#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE | |
39078 | +#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE | |
39079 | +#define BUTTON_KEY_ACTIVE_HL TRUE | |
39080 | + | |
39081 | +#define BUTTON_KEY_INACTIVE_FG COLOR_RED | |
39082 | +#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE | |
39083 | +#define BUTTON_KEY_INACTIVE_HL FALSE | |
39084 | + | |
39085 | +#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW | |
39086 | +#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE | |
39087 | +#define BUTTON_LABEL_ACTIVE_HL TRUE | |
39088 | + | |
39089 | +#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK | |
39090 | +#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE | |
39091 | +#define BUTTON_LABEL_INACTIVE_HL TRUE | |
39092 | + | |
39093 | +#define INPUTBOX_FG COLOR_BLACK | |
39094 | +#define INPUTBOX_BG COLOR_WHITE | |
39095 | +#define INPUTBOX_HL FALSE | |
39096 | + | |
39097 | +#define INPUTBOX_BORDER_FG COLOR_BLACK | |
39098 | +#define INPUTBOX_BORDER_BG COLOR_WHITE | |
39099 | +#define INPUTBOX_BORDER_HL FALSE | |
39100 | + | |
39101 | +#define SEARCHBOX_FG COLOR_BLACK | |
39102 | +#define SEARCHBOX_BG COLOR_WHITE | |
39103 | +#define SEARCHBOX_HL FALSE | |
39104 | + | |
39105 | +#define SEARCHBOX_TITLE_FG COLOR_YELLOW | |
39106 | +#define SEARCHBOX_TITLE_BG COLOR_WHITE | |
39107 | +#define SEARCHBOX_TITLE_HL TRUE | |
39108 | + | |
39109 | +#define SEARCHBOX_BORDER_FG COLOR_WHITE | |
39110 | +#define SEARCHBOX_BORDER_BG COLOR_WHITE | |
39111 | +#define SEARCHBOX_BORDER_HL TRUE | |
39112 | + | |
39113 | +#define POSITION_INDICATOR_FG COLOR_YELLOW | |
39114 | +#define POSITION_INDICATOR_BG COLOR_WHITE | |
39115 | +#define POSITION_INDICATOR_HL TRUE | |
39116 | + | |
39117 | +#define MENUBOX_FG COLOR_BLACK | |
39118 | +#define MENUBOX_BG COLOR_WHITE | |
39119 | +#define MENUBOX_HL FALSE | |
39120 | + | |
39121 | +#define MENUBOX_BORDER_FG COLOR_WHITE | |
39122 | +#define MENUBOX_BORDER_BG COLOR_WHITE | |
39123 | +#define MENUBOX_BORDER_HL TRUE | |
39124 | + | |
39125 | +#define ITEM_FG COLOR_BLACK | |
39126 | +#define ITEM_BG COLOR_WHITE | |
39127 | +#define ITEM_HL FALSE | |
39128 | + | |
39129 | +#define ITEM_SELECTED_FG COLOR_WHITE | |
39130 | +#define ITEM_SELECTED_BG COLOR_BLUE | |
39131 | +#define ITEM_SELECTED_HL TRUE | |
39132 | + | |
39133 | +#define TAG_FG COLOR_YELLOW | |
39134 | +#define TAG_BG COLOR_WHITE | |
39135 | +#define TAG_HL TRUE | |
39136 | + | |
39137 | +#define TAG_SELECTED_FG COLOR_YELLOW | |
39138 | +#define TAG_SELECTED_BG COLOR_BLUE | |
39139 | +#define TAG_SELECTED_HL TRUE | |
39140 | + | |
39141 | +#define TAG_KEY_FG COLOR_YELLOW | |
39142 | +#define TAG_KEY_BG COLOR_WHITE | |
39143 | +#define TAG_KEY_HL TRUE | |
39144 | + | |
39145 | +#define TAG_KEY_SELECTED_FG COLOR_YELLOW | |
39146 | +#define TAG_KEY_SELECTED_BG COLOR_BLUE | |
39147 | +#define TAG_KEY_SELECTED_HL TRUE | |
39148 | + | |
39149 | +#define CHECK_FG COLOR_BLACK | |
39150 | +#define CHECK_BG COLOR_WHITE | |
39151 | +#define CHECK_HL FALSE | |
39152 | + | |
39153 | +#define CHECK_SELECTED_FG COLOR_WHITE | |
39154 | +#define CHECK_SELECTED_BG COLOR_BLUE | |
39155 | +#define CHECK_SELECTED_HL TRUE | |
39156 | + | |
39157 | +#define UARROW_FG COLOR_GREEN | |
39158 | +#define UARROW_BG COLOR_WHITE | |
39159 | +#define UARROW_HL TRUE | |
39160 | + | |
39161 | +#define DARROW_FG COLOR_GREEN | |
39162 | +#define DARROW_BG COLOR_WHITE | |
39163 | +#define DARROW_HL TRUE | |
39164 | + | |
39165 | +/* End of default color definitions */ | |
39166 | + | |
39167 | +#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y))) | |
39168 | +#define COLOR_NAME_LEN 10 | |
39169 | +#define COLOR_COUNT 8 | |
39170 | + | |
39171 | +/* | |
39172 | + * Global variables | |
39173 | + */ | |
39174 | + | |
39175 | +typedef struct { | |
39176 | + char name[COLOR_NAME_LEN]; | |
39177 | + int value; | |
39178 | +} color_names_st; | |
39179 | + | |
39180 | +extern color_names_st color_names[]; | |
39181 | +extern int color_table[][3]; | |
39182 | diff -Nur busybox-1.00/scripts/config/lxdialog/dialog.h busybox/scripts/config/lxdialog/dialog.h | |
39183 | --- busybox-1.00/scripts/config/lxdialog/dialog.h 1970-01-01 01:00:00.000000000 +0100 | |
39184 | +++ busybox/scripts/config/lxdialog/dialog.h 2005-06-04 08:20:02.000000000 +0200 | |
39185 | @@ -0,0 +1,199 @@ | |
39186 | + | |
39187 | +/* | |
39188 | + * dialog.h -- common declarations for all dialog modules | |
39189 | + * | |
39190 | + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
39191 | + * | |
39192 | + * This program is free software; you can redistribute it and/or | |
39193 | + * modify it under the terms of the GNU General Public License | |
39194 | + * as published by the Free Software Foundation; either version 2 | |
39195 | + * of the License, or (at your option) any later version. | |
39196 | + * | |
39197 | + * This program is distributed in the hope that it will be useful, | |
39198 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
39199 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
39200 | + * GNU General Public License for more details. | |
39201 | + * | |
39202 | + * You should have received a copy of the GNU General Public License | |
39203 | + * along with this program; if not, write to the Free Software | |
39204 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
39205 | + */ | |
39206 | + | |
39207 | +#include <sys/types.h> | |
39208 | +#include <fcntl.h> | |
39209 | +#include <unistd.h> | |
39210 | +#include <ctype.h> | |
39211 | +#include <stdlib.h> | |
39212 | +#include <string.h> | |
39213 | + | |
39214 | +#ifdef CURSES_LOC | |
39215 | +#ifdef __sun__ | |
39216 | +#define CURS_MACROS | |
39217 | +#endif | |
39218 | +#include CURSES_LOC | |
39219 | + | |
39220 | +/* | |
39221 | + * Colors in ncurses 1.9.9e do not work properly since foreground and | |
39222 | + * background colors are OR'd rather than separately masked. This version | |
39223 | + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible | |
39224 | + * with standard curses. The simplest fix (to make this work with standard | |
39225 | + * curses) uses the wbkgdset() function, not used in the original hack. | |
39226 | + * Turn it off if we're building with 1.9.9e, since it just confuses things. | |
39227 | + */ | |
39228 | +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) | |
39229 | +#define OLD_NCURSES 1 | |
39230 | +#undef wbkgdset | |
39231 | +#define wbkgdset(w,p) /*nothing*/ | |
39232 | +#else | |
39233 | +#define OLD_NCURSES 0 | |
39234 | +#endif | |
39235 | + | |
39236 | +#define TR(params) _tracef params | |
39237 | + | |
39238 | +#define ESC 27 | |
39239 | +#define TAB 9 | |
39240 | +#define MAX_LEN 2048 | |
39241 | +#define BUF_SIZE (10*1024) | |
39242 | +#define MIN(x,y) (x < y ? x : y) | |
39243 | +#define MAX(x,y) (x > y ? x : y) | |
39244 | + | |
39245 | + | |
39246 | +#ifndef ACS_ULCORNER | |
39247 | +#define ACS_ULCORNER '+' | |
39248 | +#endif | |
39249 | +#ifndef ACS_LLCORNER | |
39250 | +#define ACS_LLCORNER '+' | |
39251 | +#endif | |
39252 | +#ifndef ACS_URCORNER | |
39253 | +#define ACS_URCORNER '+' | |
39254 | +#endif | |
39255 | +#ifndef ACS_LRCORNER | |
39256 | +#define ACS_LRCORNER '+' | |
39257 | +#endif | |
39258 | +#ifndef ACS_HLINE | |
39259 | +#define ACS_HLINE '-' | |
39260 | +#endif | |
39261 | +#ifndef ACS_VLINE | |
39262 | +#define ACS_VLINE '|' | |
39263 | +#endif | |
39264 | +#ifndef ACS_LTEE | |
39265 | +#define ACS_LTEE '+' | |
39266 | +#endif | |
39267 | +#ifndef ACS_RTEE | |
39268 | +#define ACS_RTEE '+' | |
39269 | +#endif | |
39270 | +#ifndef ACS_UARROW | |
39271 | +#define ACS_UARROW '^' | |
39272 | +#endif | |
39273 | +#ifndef ACS_DARROW | |
39274 | +#define ACS_DARROW 'v' | |
39275 | +#endif | |
39276 | + | |
39277 | +/* | |
39278 | + * Attribute names | |
39279 | + */ | |
39280 | +#define screen_attr attributes[0] | |
39281 | +#define shadow_attr attributes[1] | |
39282 | +#define dialog_attr attributes[2] | |
39283 | +#define title_attr attributes[3] | |
39284 | +#define border_attr attributes[4] | |
39285 | +#define button_active_attr attributes[5] | |
39286 | +#define button_inactive_attr attributes[6] | |
39287 | +#define button_key_active_attr attributes[7] | |
39288 | +#define button_key_inactive_attr attributes[8] | |
39289 | +#define button_label_active_attr attributes[9] | |
39290 | +#define button_label_inactive_attr attributes[10] | |
39291 | +#define inputbox_attr attributes[11] | |
39292 | +#define inputbox_border_attr attributes[12] | |
39293 | +#define searchbox_attr attributes[13] | |
39294 | +#define searchbox_title_attr attributes[14] | |
39295 | +#define searchbox_border_attr attributes[15] | |
39296 | +#define position_indicator_attr attributes[16] | |
39297 | +#define menubox_attr attributes[17] | |
39298 | +#define menubox_border_attr attributes[18] | |
39299 | +#define item_attr attributes[19] | |
39300 | +#define item_selected_attr attributes[20] | |
39301 | +#define tag_attr attributes[21] | |
39302 | +#define tag_selected_attr attributes[22] | |
39303 | +#define tag_key_attr attributes[23] | |
39304 | +#define tag_key_selected_attr attributes[24] | |
39305 | +#define check_attr attributes[25] | |
39306 | +#define check_selected_attr attributes[26] | |
39307 | +#define uarrow_attr attributes[27] | |
39308 | +#define darrow_attr attributes[28] | |
39309 | + | |
39310 | +/* number of attributes */ | |
39311 | +#define ATTRIBUTE_COUNT 29 | |
39312 | + | |
39313 | +/* | |
39314 | + * Global variables | |
39315 | + */ | |
39316 | +extern bool use_colors; | |
39317 | + | |
39318 | +extern chtype attributes[]; | |
39319 | +#endif | |
39320 | + | |
39321 | +extern const char *backtitle; | |
39322 | + | |
39323 | +struct dialog_list_item { | |
39324 | + char *name; | |
39325 | + int namelen; | |
39326 | + char *tag; | |
39327 | + int selected; /* Set to 1 by dialog_*() function. */ | |
39328 | +}; | |
39329 | + | |
39330 | +/* | |
39331 | + * Function prototypes | |
39332 | + */ | |
39333 | + | |
39334 | +void init_dialog (void); | |
39335 | +void end_dialog (void); | |
39336 | +void dialog_clear (void); | |
39337 | +#ifdef CURSES_LOC | |
39338 | +void attr_clear (WINDOW * win, int height, int width, chtype attr); | |
39339 | +void color_setup (void); | |
39340 | +void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x); | |
39341 | +void print_button (WINDOW * win, const char *label, int y, int x, int selected); | |
39342 | +void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box, | |
39343 | + chtype border); | |
39344 | +void draw_shadow (WINDOW * win, int y, int x, int height, int width); | |
39345 | +#endif | |
39346 | + | |
39347 | +int first_alpha (const char *string, const char *exempt); | |
39348 | +int dialog_yesno (const char *title, const char *prompt, int height, int width); | |
39349 | +int dialog_msgbox (const char *title, const char *prompt, int height, | |
39350 | + int width, int pause); | |
39351 | +int dialog_textbox (const char *title, const char *file, int height, int width); | |
39352 | +int dialog_menu (const char *title, const char *prompt, int height, int width, | |
39353 | + int menu_height, const char *choice, int item_no, | |
39354 | + struct dialog_list_item ** items); | |
39355 | +int dialog_checklist (const char *title, const char *prompt, int height, | |
39356 | + int width, int list_height, int item_no, | |
39357 | + struct dialog_list_item ** items, int flag); | |
39358 | +extern unsigned char dialog_input_result[]; | |
39359 | +int dialog_inputbox (const char *title, const char *prompt, int height, | |
39360 | + int width, const char *init); | |
39361 | + | |
39362 | +struct dialog_list_item *first_sel_item(int item_no, | |
39363 | + struct dialog_list_item ** items); | |
39364 | + | |
39365 | +/* | |
39366 | + * This is the base for fictitious keys, which activate | |
39367 | + * the buttons. | |
39368 | + * | |
39369 | + * Mouse-generated keys are the following: | |
39370 | + * -- the first 32 are used as numbers, in addition to '0'-'9' | |
39371 | + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') | |
39372 | + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') | |
39373 | + */ | |
39374 | +#ifdef CURSES_LOC | |
39375 | +#define M_EVENT (KEY_MAX+1) | |
39376 | +#endif | |
39377 | + | |
39378 | + | |
39379 | +/* | |
39380 | + * The `flag' parameter in checklist is used to select between | |
39381 | + * radiolist and checklist | |
39382 | + */ | |
39383 | +#define FLAG_CHECK 1 | |
39384 | +#define FLAG_RADIO 0 | |
39385 | diff -Nur busybox-1.00/scripts/config/lxdialog/inputbox.c busybox/scripts/config/lxdialog/inputbox.c | |
39386 | --- busybox-1.00/scripts/config/lxdialog/inputbox.c 1970-01-01 01:00:00.000000000 +0100 | |
39387 | +++ busybox/scripts/config/lxdialog/inputbox.c 2005-06-04 08:20:02.000000000 +0200 | |
39388 | @@ -0,0 +1,240 @@ | |
39389 | +/* | |
39390 | + * inputbox.c -- implements the input box | |
39391 | + * | |
39392 | + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
39393 | + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
39394 | + * | |
39395 | + * This program is free software; you can redistribute it and/or | |
39396 | + * modify it under the terms of the GNU General Public License | |
39397 | + * as published by the Free Software Foundation; either version 2 | |
39398 | + * of the License, or (at your option) any later version. | |
39399 | + * | |
39400 | + * This program is distributed in the hope that it will be useful, | |
39401 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
39402 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
39403 | + * GNU General Public License for more details. | |
39404 | + * | |
39405 | + * You should have received a copy of the GNU General Public License | |
39406 | + * along with this program; if not, write to the Free Software | |
39407 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
39408 | + */ | |
39409 | + | |
39410 | +#include "dialog.h" | |
39411 | + | |
39412 | +unsigned char dialog_input_result[MAX_LEN + 1]; | |
39413 | + | |
39414 | +/* | |
39415 | + * Print the termination buttons | |
39416 | + */ | |
39417 | +static void | |
39418 | +print_buttons(WINDOW *dialog, int height, int width, int selected) | |
39419 | +{ | |
39420 | + int x = width / 2 - 11; | |
39421 | + int y = height - 2; | |
39422 | + | |
39423 | + print_button (dialog, " Ok ", y, x, selected==0); | |
39424 | + print_button (dialog, " Help ", y, x + 14, selected==1); | |
39425 | + | |
39426 | + wmove(dialog, y, x+1+14*selected); | |
39427 | + wrefresh(dialog); | |
39428 | +} | |
39429 | + | |
39430 | +/* | |
39431 | + * Display a dialog box for inputing a string | |
39432 | + */ | |
39433 | +int | |
39434 | +dialog_inputbox (const char *title, const char *prompt, int height, int width, | |
39435 | + const char *init) | |
39436 | +{ | |
39437 | + int i, x, y, box_y, box_x, box_width; | |
39438 | + int input_x = 0, scroll = 0, key = 0, button = -1; | |
39439 | + unsigned char *instr = dialog_input_result; | |
39440 | + WINDOW *dialog; | |
39441 | + | |
39442 | + /* center dialog box on screen */ | |
39443 | + x = (COLS - width) / 2; | |
39444 | + y = (LINES - height) / 2; | |
39445 | + | |
39446 | + | |
39447 | + draw_shadow (stdscr, y, x, height, width); | |
39448 | + | |
39449 | + dialog = newwin (height, width, y, x); | |
39450 | + keypad (dialog, TRUE); | |
39451 | + | |
39452 | + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
39453 | + wattrset (dialog, border_attr); | |
39454 | + mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
39455 | + for (i = 0; i < width - 2; i++) | |
39456 | + waddch (dialog, ACS_HLINE); | |
39457 | + wattrset (dialog, dialog_attr); | |
39458 | + waddch (dialog, ACS_RTEE); | |
39459 | + | |
39460 | + if (title != NULL && strlen(title) >= width-2 ) { | |
39461 | + /* truncate long title -- mec */ | |
39462 | + char * title2 = malloc(width-2+1); | |
39463 | + memcpy( title2, title, width-2 ); | |
39464 | + title2[width-2] = '\0'; | |
39465 | + title = title2; | |
39466 | + } | |
39467 | + | |
39468 | + if (title != NULL) { | |
39469 | + wattrset (dialog, title_attr); | |
39470 | + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
39471 | + waddstr (dialog, (char *)title); | |
39472 | + waddch (dialog, ' '); | |
39473 | + } | |
39474 | + | |
39475 | + wattrset (dialog, dialog_attr); | |
39476 | + print_autowrap (dialog, prompt, width - 2, 1, 3); | |
39477 | + | |
39478 | + /* Draw the input field box */ | |
39479 | + box_width = width - 6; | |
39480 | + getyx (dialog, y, x); | |
39481 | + box_y = y + 2; | |
39482 | + box_x = (width - box_width) / 2; | |
39483 | + draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2, | |
39484 | + border_attr, dialog_attr); | |
39485 | + | |
39486 | + print_buttons(dialog, height, width, 0); | |
39487 | + | |
39488 | + /* Set up the initial value */ | |
39489 | + wmove (dialog, box_y, box_x); | |
39490 | + wattrset (dialog, inputbox_attr); | |
39491 | + | |
39492 | + if (!init) | |
39493 | + instr[0] = '\0'; | |
39494 | + else | |
39495 | + strcpy (instr, init); | |
39496 | + | |
39497 | + input_x = strlen (instr); | |
39498 | + | |
39499 | + if (input_x >= box_width) { | |
39500 | + scroll = input_x - box_width + 1; | |
39501 | + input_x = box_width - 1; | |
39502 | + for (i = 0; i < box_width - 1; i++) | |
39503 | + waddch (dialog, instr[scroll + i]); | |
39504 | + } else | |
39505 | + waddstr (dialog, instr); | |
39506 | + | |
39507 | + wmove (dialog, box_y, box_x + input_x); | |
39508 | + | |
39509 | + wrefresh (dialog); | |
39510 | + | |
39511 | + while (key != ESC) { | |
39512 | + key = wgetch (dialog); | |
39513 | + | |
39514 | + if (button == -1) { /* Input box selected */ | |
39515 | + switch (key) { | |
39516 | + case TAB: | |
39517 | + case KEY_UP: | |
39518 | + case KEY_DOWN: | |
39519 | + break; | |
39520 | + case KEY_LEFT: | |
39521 | + continue; | |
39522 | + case KEY_RIGHT: | |
39523 | + continue; | |
39524 | + case KEY_BACKSPACE: | |
39525 | + case 127: | |
39526 | + if (input_x || scroll) { | |
39527 | + wattrset (dialog, inputbox_attr); | |
39528 | + if (!input_x) { | |
39529 | + scroll = scroll < box_width - 1 ? | |
39530 | + 0 : scroll - (box_width - 1); | |
39531 | + wmove (dialog, box_y, box_x); | |
39532 | + for (i = 0; i < box_width; i++) | |
39533 | + waddch (dialog, instr[scroll + input_x + i] ? | |
39534 | + instr[scroll + input_x + i] : ' '); | |
39535 | + input_x = strlen (instr) - scroll; | |
39536 | + } else | |
39537 | + input_x--; | |
39538 | + instr[scroll + input_x] = '\0'; | |
39539 | + mvwaddch (dialog, box_y, input_x + box_x, ' '); | |
39540 | + wmove (dialog, box_y, input_x + box_x); | |
39541 | + wrefresh (dialog); | |
39542 | + } | |
39543 | + continue; | |
39544 | + default: | |
39545 | + if (key < 0x100 && isprint (key)) { | |
39546 | + if (scroll + input_x < MAX_LEN) { | |
39547 | + wattrset (dialog, inputbox_attr); | |
39548 | + instr[scroll + input_x] = key; | |
39549 | + instr[scroll + input_x + 1] = '\0'; | |
39550 | + if (input_x == box_width - 1) { | |
39551 | + scroll++; | |
39552 | + wmove (dialog, box_y, box_x); | |
39553 | + for (i = 0; i < box_width - 1; i++) | |
39554 | + waddch (dialog, instr[scroll + i]); | |
39555 | + } else { | |
39556 | + wmove (dialog, box_y, input_x++ + box_x); | |
39557 | + waddch (dialog, key); | |
39558 | + } | |
39559 | + wrefresh (dialog); | |
39560 | + } else | |
39561 | + flash (); /* Alarm user about overflow */ | |
39562 | + continue; | |
39563 | + } | |
39564 | + } | |
39565 | + } | |
39566 | + switch (key) { | |
39567 | + case 'O': | |
39568 | + case 'o': | |
39569 | + delwin (dialog); | |
39570 | + return 0; | |
39571 | + case 'H': | |
39572 | + case 'h': | |
39573 | + delwin (dialog); | |
39574 | + return 1; | |
39575 | + case KEY_UP: | |
39576 | + case KEY_LEFT: | |
39577 | + switch (button) { | |
39578 | + case -1: | |
39579 | + button = 1; /* Indicates "Cancel" button is selected */ | |
39580 | + print_buttons(dialog, height, width, 1); | |
39581 | + break; | |
39582 | + case 0: | |
39583 | + button = -1; /* Indicates input box is selected */ | |
39584 | + print_buttons(dialog, height, width, 0); | |
39585 | + wmove (dialog, box_y, box_x + input_x); | |
39586 | + wrefresh (dialog); | |
39587 | + break; | |
39588 | + case 1: | |
39589 | + button = 0; /* Indicates "OK" button is selected */ | |
39590 | + print_buttons(dialog, height, width, 0); | |
39591 | + break; | |
39592 | + } | |
39593 | + break; | |
39594 | + case TAB: | |
39595 | + case KEY_DOWN: | |
39596 | + case KEY_RIGHT: | |
39597 | + switch (button) { | |
39598 | + case -1: | |
39599 | + button = 0; /* Indicates "OK" button is selected */ | |
39600 | + print_buttons(dialog, height, width, 0); | |
39601 | + break; | |
39602 | + case 0: | |
39603 | + button = 1; /* Indicates "Cancel" button is selected */ | |
39604 | + print_buttons(dialog, height, width, 1); | |
39605 | + break; | |
39606 | + case 1: | |
39607 | + button = -1; /* Indicates input box is selected */ | |
39608 | + print_buttons(dialog, height, width, 0); | |
39609 | + wmove (dialog, box_y, box_x + input_x); | |
39610 | + wrefresh (dialog); | |
39611 | + break; | |
39612 | + } | |
39613 | + break; | |
39614 | + case ' ': | |
39615 | + case '\n': | |
39616 | + delwin (dialog); | |
39617 | + return (button == -1 ? 0 : button); | |
39618 | + case 'X': | |
39619 | + case 'x': | |
39620 | + key = ESC; | |
39621 | + case ESC: | |
39622 | + break; | |
39623 | + } | |
39624 | + } | |
39625 | + | |
39626 | + delwin (dialog); | |
39627 | + return -1; /* ESC pressed */ | |
39628 | +} | |
39629 | diff -Nur busybox-1.00/scripts/config/lxdialog/menubox.c busybox/scripts/config/lxdialog/menubox.c | |
39630 | --- busybox-1.00/scripts/config/lxdialog/menubox.c 1970-01-01 01:00:00.000000000 +0100 | |
39631 | +++ busybox/scripts/config/lxdialog/menubox.c 2005-06-04 08:20:02.000000000 +0200 | |
39632 | @@ -0,0 +1,438 @@ | |
39633 | +/* | |
39634 | + * menubox.c -- implements the menu box | |
39635 | + * | |
39636 | + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
39637 | + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) | |
39638 | + * | |
39639 | + * This program is free software; you can redistribute it and/or | |
39640 | + * modify it under the terms of the GNU General Public License | |
39641 | + * as published by the Free Software Foundation; either version 2 | |
39642 | + * of the License, or (at your option) any later version. | |
39643 | + * | |
39644 | + * This program is distributed in the hope that it will be useful, | |
39645 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
39646 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
39647 | + * GNU General Public License for more details. | |
39648 | + * | |
39649 | + * You should have received a copy of the GNU General Public License | |
39650 | + * along with this program; if not, write to the Free Software | |
39651 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
39652 | + */ | |
39653 | + | |
39654 | +/* | |
39655 | + * Changes by Clifford Wolf (god@clifford.at) | |
39656 | + * | |
39657 | + * [ 1998-06-13 ] | |
39658 | + * | |
39659 | + * *) A bugfix for the Page-Down problem | |
39660 | + * | |
39661 | + * *) Formerly when I used Page Down and Page Up, the cursor would be set | |
39662 | + * to the first position in the menu box. Now lxdialog is a bit | |
39663 | + * smarter and works more like other menu systems (just have a look at | |
39664 | + * it). | |
39665 | + * | |
39666 | + * *) Formerly if I selected something my scrolling would be broken because | |
39667 | + * lxdialog is re-invoked by the Menuconfig shell script, can't | |
39668 | + * remember the last scrolling position, and just sets it so that the | |
39669 | + * cursor is at the bottom of the box. Now it writes the temporary file | |
39670 | + * lxdialog.scrltmp which contains this information. The file is | |
39671 | + * deleted by lxdialog if the user leaves a submenu or enters a new | |
39672 | + * one, but it would be nice if Menuconfig could make another "rm -f" | |
39673 | + * just to be sure. Just try it out - you will recognise a difference! | |
39674 | + * | |
39675 | + * [ 1998-06-14 ] | |
39676 | + * | |
39677 | + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files | |
39678 | + * and menus change their size on the fly. | |
39679 | + * | |
39680 | + * *) If for some reason the last scrolling position is not saved by | |
39681 | + * lxdialog, it sets the scrolling so that the selected item is in the | |
39682 | + * middle of the menu box, not at the bottom. | |
39683 | + * | |
39684 | + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) | |
39685 | + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. | |
39686 | + * This fixes a bug in Menuconfig where using ' ' to descend into menus | |
39687 | + * would leave mis-synchronized lxdialog.scrltmp files lying around, | |
39688 | + * fscanf would read in 'scroll', and eventually that value would get used. | |
39689 | + */ | |
39690 | + | |
39691 | +#include "dialog.h" | |
39692 | + | |
39693 | +static int menu_width, item_x; | |
39694 | + | |
39695 | +/* | |
39696 | + * Print menu item | |
39697 | + */ | |
39698 | +static void | |
39699 | +print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey) | |
39700 | +{ | |
39701 | + int j; | |
39702 | + char menu_item[menu_width+1]; | |
39703 | + | |
39704 | + strncpy(menu_item, item, menu_width); | |
39705 | + menu_item[menu_width] = 0; | |
39706 | + j = first_alpha(menu_item, "YyNnMmHh"); | |
39707 | + | |
39708 | + /* Clear 'residue' of last item */ | |
39709 | + wattrset (win, menubox_attr); | |
39710 | + wmove (win, choice, 0); | |
39711 | +#if OLD_NCURSES | |
39712 | + { | |
39713 | + int i; | |
39714 | + for (i = 0; i < menu_width; i++) | |
39715 | + waddch (win, ' '); | |
39716 | + } | |
39717 | +#else | |
39718 | + wclrtoeol(win); | |
39719 | +#endif | |
39720 | + wattrset (win, selected ? item_selected_attr : item_attr); | |
39721 | + mvwaddstr (win, choice, item_x, menu_item); | |
39722 | + if (hotkey) { | |
39723 | + wattrset (win, selected ? tag_key_selected_attr : tag_key_attr); | |
39724 | + mvwaddch(win, choice, item_x+j, menu_item[j]); | |
39725 | + } | |
39726 | + if (selected) { | |
39727 | + wmove (win, choice, item_x+1); | |
39728 | + wrefresh (win); | |
39729 | + } | |
39730 | +} | |
39731 | + | |
39732 | +/* | |
39733 | + * Print the scroll indicators. | |
39734 | + */ | |
39735 | +static void | |
39736 | +print_arrows (WINDOW * win, int item_no, int scroll, | |
39737 | + int y, int x, int height) | |
39738 | +{ | |
39739 | + int cur_y, cur_x; | |
39740 | + | |
39741 | + getyx(win, cur_y, cur_x); | |
39742 | + | |
39743 | + wmove(win, y, x); | |
39744 | + | |
39745 | + if (scroll > 0) { | |
39746 | + wattrset (win, uarrow_attr); | |
39747 | + waddch (win, ACS_UARROW); | |
39748 | + waddstr (win, "(-)"); | |
39749 | + } | |
39750 | + else { | |
39751 | + wattrset (win, menubox_attr); | |
39752 | + waddch (win, ACS_HLINE); | |
39753 | + waddch (win, ACS_HLINE); | |
39754 | + waddch (win, ACS_HLINE); | |
39755 | + waddch (win, ACS_HLINE); | |
39756 | + } | |
39757 | + | |
39758 | + y = y + height + 1; | |
39759 | + wmove(win, y, x); | |
39760 | + | |
39761 | + if ((height < item_no) && (scroll + height < item_no)) { | |
39762 | + wattrset (win, darrow_attr); | |
39763 | + waddch (win, ACS_DARROW); | |
39764 | + waddstr (win, "(+)"); | |
39765 | + } | |
39766 | + else { | |
39767 | + wattrset (win, menubox_border_attr); | |
39768 | + waddch (win, ACS_HLINE); | |
39769 | + waddch (win, ACS_HLINE); | |
39770 | + waddch (win, ACS_HLINE); | |
39771 | + waddch (win, ACS_HLINE); | |
39772 | + } | |
39773 | + | |
39774 | + wmove(win, cur_y, cur_x); | |
39775 | +} | |
39776 | + | |
39777 | +/* | |
39778 | + * Display the termination buttons. | |
39779 | + */ | |
39780 | +static void | |
39781 | +print_buttons (WINDOW *win, int height, int width, int selected) | |
39782 | +{ | |
39783 | + int x = width / 2 - 16; | |
39784 | + int y = height - 2; | |
39785 | + | |
39786 | + print_button (win, "Select", y, x, selected == 0); | |
39787 | + print_button (win, " Exit ", y, x + 12, selected == 1); | |
39788 | + print_button (win, " Help ", y, x + 24, selected == 2); | |
39789 | + | |
39790 | + wmove(win, y, x+1+12*selected); | |
39791 | + wrefresh (win); | |
39792 | +} | |
39793 | + | |
39794 | +/* | |
39795 | + * Display a menu for choosing among a number of options | |
39796 | + */ | |
39797 | +int | |
39798 | +dialog_menu (const char *title, const char *prompt, int height, int width, | |
39799 | + int menu_height, const char *current, int item_no, | |
39800 | + struct dialog_list_item ** items) | |
39801 | +{ | |
39802 | + int i, j, x, y, box_x, box_y; | |
39803 | + int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice; | |
39804 | + WINDOW *dialog, *menu; | |
39805 | + FILE *f; | |
39806 | + | |
39807 | + max_choice = MIN (menu_height, item_no); | |
39808 | + | |
39809 | + /* center dialog box on screen */ | |
39810 | + x = (COLS - width) / 2; | |
39811 | + y = (LINES - height) / 2; | |
39812 | + | |
39813 | + draw_shadow (stdscr, y, x, height, width); | |
39814 | + | |
39815 | + dialog = newwin (height, width, y, x); | |
39816 | + keypad (dialog, TRUE); | |
39817 | + | |
39818 | + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
39819 | + wattrset (dialog, border_attr); | |
39820 | + mvwaddch (dialog, height - 3, 0, ACS_LTEE); | |
39821 | + for (i = 0; i < width - 2; i++) | |
39822 | + waddch (dialog, ACS_HLINE); | |
39823 | + wattrset (dialog, dialog_attr); | |
39824 | + wbkgdset (dialog, dialog_attr & A_COLOR); | |
39825 | + waddch (dialog, ACS_RTEE); | |
39826 | + | |
39827 | + if (title != NULL && strlen(title) >= width-2 ) { | |
39828 | + /* truncate long title -- mec */ | |
39829 | + char * title2 = malloc(width-2+1); | |
39830 | + memcpy( title2, title, width-2 ); | |
39831 | + title2[width-2] = '\0'; | |
39832 | + title = title2; | |
39833 | + } | |
39834 | + | |
39835 | + if (title != NULL) { | |
39836 | + wattrset (dialog, title_attr); | |
39837 | + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
39838 | + waddstr (dialog, (char *)title); | |
39839 | + waddch (dialog, ' '); | |
39840 | + } | |
39841 | + | |
39842 | + wattrset (dialog, dialog_attr); | |
39843 | + print_autowrap (dialog, prompt, width - 2, 1, 3); | |
39844 | + | |
39845 | + menu_width = width - 6; | |
39846 | + box_y = height - menu_height - 5; | |
39847 | + box_x = (width - menu_width) / 2 - 1; | |
39848 | + | |
39849 | + /* create new window for the menu */ | |
39850 | + menu = subwin (dialog, menu_height, menu_width, | |
39851 | + y + box_y + 1, x + box_x + 1); | |
39852 | + keypad (menu, TRUE); | |
39853 | + | |
39854 | + /* draw a box around the menu items */ | |
39855 | + draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2, | |
39856 | + menubox_border_attr, menubox_attr); | |
39857 | + | |
39858 | + /* | |
39859 | + * Find length of longest item in order to center menu. | |
39860 | + * Set 'choice' to default item. | |
39861 | + */ | |
39862 | + item_x = 0; | |
39863 | + for (i = 0; i < item_no; i++) { | |
39864 | + item_x = MAX (item_x, MIN(menu_width, strlen (items[i]->name) + 2)); | |
39865 | + if (strcmp(current, items[i]->tag) == 0) choice = i; | |
39866 | + } | |
39867 | + | |
39868 | + item_x = (menu_width - item_x) / 2; | |
39869 | + | |
39870 | + /* get the scroll info from the temp file */ | |
39871 | + if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) { | |
39872 | + if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) && | |
39873 | + (scroll+max_choice > choice) && (scroll >= 0) && | |
39874 | + (scroll+max_choice <= item_no) ) { | |
39875 | + first_item = scroll; | |
39876 | + choice = choice - scroll; | |
39877 | + fclose(f); | |
39878 | + } else { | |
39879 | + scroll=0; | |
39880 | + remove("lxdialog.scrltmp"); | |
39881 | + fclose(f); | |
39882 | + f=NULL; | |
39883 | + } | |
39884 | + } | |
39885 | + if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) { | |
39886 | + if (choice >= item_no-max_choice/2) | |
39887 | + scroll = first_item = item_no-max_choice; | |
39888 | + else | |
39889 | + scroll = first_item = choice - max_choice/2; | |
39890 | + choice = choice - scroll; | |
39891 | + } | |
39892 | + | |
39893 | + /* Print the menu */ | |
39894 | + for (i=0; i < max_choice; i++) { | |
39895 | + print_item (menu, items[first_item + i]->name, i, i == choice, | |
39896 | + (items[first_item + i]->tag[0] != ':')); | |
39897 | + } | |
39898 | + | |
39899 | + wnoutrefresh (menu); | |
39900 | + | |
39901 | + print_arrows(dialog, item_no, scroll, | |
39902 | + box_y, box_x+item_x+1, menu_height); | |
39903 | + | |
39904 | + print_buttons (dialog, height, width, 0); | |
39905 | + wmove (menu, choice, item_x+1); | |
39906 | + wrefresh (menu); | |
39907 | + | |
39908 | + while (key != ESC) { | |
39909 | + key = wgetch(menu); | |
39910 | + | |
39911 | + if (key < 256 && isalpha(key)) key = tolower(key); | |
39912 | + | |
39913 | + if (strchr("ynmh", key)) | |
39914 | + i = max_choice; | |
39915 | + else { | |
39916 | + for (i = choice+1; i < max_choice; i++) { | |
39917 | + j = first_alpha(items[scroll + i]->name, "YyNnMmHh"); | |
39918 | + if (key == tolower(items[scroll + i]->name[j])) | |
39919 | + break; | |
39920 | + } | |
39921 | + if (i == max_choice) | |
39922 | + for (i = 0; i < max_choice; i++) { | |
39923 | + j = first_alpha(items[scroll + i]->name, "YyNnMmHh"); | |
39924 | + if (key == tolower(items[scroll + i]->name[j])) | |
39925 | + break; | |
39926 | + } | |
39927 | + } | |
39928 | + | |
39929 | + if (i < max_choice || | |
39930 | + key == KEY_UP || key == KEY_DOWN || | |
39931 | + key == '-' || key == '+' || | |
39932 | + key == KEY_PPAGE || key == KEY_NPAGE) { | |
39933 | + | |
39934 | + print_item (menu, items[scroll + choice]->name, choice, FALSE, | |
39935 | + (items[scroll + choice]->tag[0] != ':')); | |
39936 | + | |
39937 | + if (key == KEY_UP || key == '-') { | |
39938 | + if (choice < 2 && scroll) { | |
39939 | + /* Scroll menu down */ | |
39940 | + scrollok (menu, TRUE); | |
39941 | + wscrl (menu, -1); | |
39942 | + scrollok (menu, FALSE); | |
39943 | + | |
39944 | + scroll--; | |
39945 | + | |
39946 | + print_item (menu, items[scroll]->name, 0, FALSE, | |
39947 | + (items[scroll]->tag[0] != ':')); | |
39948 | + } else | |
39949 | + choice = MAX(choice - 1, 0); | |
39950 | + | |
39951 | + } else if (key == KEY_DOWN || key == '+') { | |
39952 | + | |
39953 | + print_item (menu, items[scroll + choice]->name, choice, FALSE, | |
39954 | + (items[scroll + choice]->tag[0] != ':')); | |
39955 | + | |
39956 | + if ((choice > max_choice-3) && | |
39957 | + (scroll + max_choice < item_no) | |
39958 | + ) { | |
39959 | + /* Scroll menu up */ | |
39960 | + scrollok (menu, TRUE); | |
39961 | + scroll (menu); | |
39962 | + scrollok (menu, FALSE); | |
39963 | + | |
39964 | + scroll++; | |
39965 | + | |
39966 | + print_item (menu, items[scroll + max_choice - 1]->name, | |
39967 | + max_choice-1, FALSE, | |
39968 | + (items[scroll + max_choice - 1]->tag[0] != ':')); | |
39969 | + } else | |
39970 | + choice = MIN(choice+1, max_choice-1); | |
39971 | + | |
39972 | + } else if (key == KEY_PPAGE) { | |
39973 | + scrollok (menu, TRUE); | |
39974 | + for (i=0; (i < max_choice); i++) { | |
39975 | + if (scroll > 0) { | |
39976 | + wscrl (menu, -1); | |
39977 | + scroll--; | |
39978 | + print_item (menu, items[scroll]->name, 0, FALSE, | |
39979 | + (items[scroll]->tag[0] != ':')); | |
39980 | + } else { | |
39981 | + if (choice > 0) | |
39982 | + choice--; | |
39983 | + } | |
39984 | + } | |
39985 | + scrollok (menu, FALSE); | |
39986 | + | |
39987 | + } else if (key == KEY_NPAGE) { | |
39988 | + for (i=0; (i < max_choice); i++) { | |
39989 | + if (scroll+max_choice < item_no) { | |
39990 | + scrollok (menu, TRUE); | |
39991 | + scroll(menu); | |
39992 | + scrollok (menu, FALSE); | |
39993 | + scroll++; | |
39994 | + print_item (menu, items[scroll + max_choice - 1]->name, | |
39995 | + max_choice-1, FALSE, | |
39996 | + (items[scroll + max_choice - 1]->tag[0] != ':')); | |
39997 | + } else { | |
39998 | + if (choice+1 < max_choice) | |
39999 | + choice++; | |
40000 | + } | |
40001 | + } | |
40002 | + | |
40003 | + } else | |
40004 | + choice = i; | |
40005 | + | |
40006 | + print_item (menu, items[scroll + choice]->name, choice, TRUE, | |
40007 | + (items[scroll + choice]->tag[0] != ':')); | |
40008 | + | |
40009 | + print_arrows(dialog, item_no, scroll, | |
40010 | + box_y, box_x+item_x+1, menu_height); | |
40011 | + | |
40012 | + wnoutrefresh (dialog); | |
40013 | + wrefresh (menu); | |
40014 | + | |
40015 | + continue; /* wait for another key press */ | |
40016 | + } | |
40017 | + | |
40018 | + switch (key) { | |
40019 | + case KEY_LEFT: | |
40020 | + case TAB: | |
40021 | + case KEY_RIGHT: | |
40022 | + button = ((key == KEY_LEFT ? --button : ++button) < 0) | |
40023 | + ? 2 : (button > 2 ? 0 : button); | |
40024 | + | |
40025 | + print_buttons(dialog, height, width, button); | |
40026 | + wrefresh (menu); | |
40027 | + break; | |
40028 | + case ' ': | |
40029 | + case 's': | |
40030 | + case 'y': | |
40031 | + case 'n': | |
40032 | + case 'm': | |
40033 | + case '/': | |
40034 | + /* save scroll info */ | |
40035 | + if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) { | |
40036 | + fprintf(f,"%d\n",scroll); | |
40037 | + fclose(f); | |
40038 | + } | |
40039 | + delwin (dialog); | |
40040 | + items[scroll + choice]->selected = 1; | |
40041 | + switch (key) { | |
40042 | + case 's': return 3; | |
40043 | + case 'y': return 3; | |
40044 | + case 'n': return 4; | |
40045 | + case 'm': return 5; | |
40046 | + case ' ': return 6; | |
40047 | + case '/': return 7; | |
40048 | + } | |
40049 | + return 0; | |
40050 | + case 'h': | |
40051 | + case '?': | |
40052 | + button = 2; | |
40053 | + case '\n': | |
40054 | + delwin (dialog); | |
40055 | + items[scroll + choice]->selected = 1; | |
40056 | + | |
40057 | + remove("lxdialog.scrltmp"); | |
40058 | + return button; | |
40059 | + case 'e': | |
40060 | + case 'x': | |
40061 | + key = ESC; | |
40062 | + case ESC: | |
40063 | + break; | |
40064 | + } | |
40065 | + } | |
40066 | + | |
40067 | + delwin (dialog); | |
40068 | + remove("lxdialog.scrltmp"); | |
40069 | + return -1; /* ESC pressed */ | |
40070 | +} | |
40071 | diff -Nur busybox-1.00/scripts/config/lxdialog/msgbox.c busybox/scripts/config/lxdialog/msgbox.c | |
40072 | --- busybox-1.00/scripts/config/lxdialog/msgbox.c 1970-01-01 01:00:00.000000000 +0100 | |
40073 | +++ busybox/scripts/config/lxdialog/msgbox.c 2005-06-04 08:20:02.000000000 +0200 | |
40074 | @@ -0,0 +1,85 @@ | |
40075 | +/* | |
40076 | + * msgbox.c -- implements the message box and info box | |
40077 | + * | |
40078 | + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
40079 | + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) | |
40080 | + * | |
40081 | + * This program is free software; you can redistribute it and/or | |
40082 | + * modify it under the terms of the GNU General Public License | |
40083 | + * as published by the Free Software Foundation; either version 2 | |
40084 | + * of the License, or (at your option) any later version. | |
40085 | + * | |
40086 | + * This program is distributed in the hope that it will be useful, | |
40087 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
40088 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
40089 | + * GNU General Public License for more details. | |
40090 | + * | |
40091 | + * You should have received a copy of the GNU General Public License | |
40092 | + * along with this program; if not, write to the Free Software | |
40093 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
40094 | + */ | |
40095 | + | |
40096 | +#include "dialog.h" | |
40097 | + | |
40098 | +/* | |
40099 | + * Display a message box. Program will pause and display an "OK" button | |
40100 | + * if the parameter 'pause' is non-zero. | |
40101 | + */ | |
40102 | +int | |
40103 | +dialog_msgbox (const char *title, const char *prompt, int height, int width, | |
40104 | + int pause) | |
40105 | +{ | |
40106 | + int i, x, y, key = 0; | |
40107 | + WINDOW *dialog; | |
40108 | + | |
40109 | + /* center dialog box on screen */ | |
40110 | + x = (COLS - width) / 2; | |
40111 | + y = (LINES - height) / 2; | |
40112 | + | |
40113 | + draw_shadow (stdscr, y, x, height, width); | |
40114 | + | |
40115 | + dialog = newwin (height, width, y, x); | |
40116 | + keypad (dialog, TRUE); | |
40117 | + | |
40118 | + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
40119 | + | |
40120 | + if (title != NULL && strlen(title) >= width-2 ) { | |
40121 | + /* truncate long title -- mec */ | |
40122 | + char * title2 = malloc(width-2+1); | |
40123 | + memcpy( title2, title, width-2 ); | |
40124 | + title2[width-2] = '\0'; | |
40125 | + title = title2; | |
40126 | + } | |
40127 | + | |
40128 | + if (title != NULL) { | |
40129 | + wattrset (dialog, title_attr); | |
40130 | + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
40131 | + waddstr (dialog, (char *)title); | |
40132 | + waddch (dialog, ' '); | |
40133 | + } | |
40134 | + wattrset (dialog, dialog_attr); | |
40135 | + print_autowrap (dialog, prompt, width - 2, 1, 2); | |
40136 | + | |
40137 | + if (pause) { | |
40138 | + wattrset (dialog, border_attr); | |
40139 | + mvwaddch (dialog, height - 3, 0, ACS_LTEE); | |
40140 | + for (i = 0; i < width - 2; i++) | |
40141 | + waddch (dialog, ACS_HLINE); | |
40142 | + wattrset (dialog, dialog_attr); | |
40143 | + waddch (dialog, ACS_RTEE); | |
40144 | + | |
40145 | + print_button (dialog, " Ok ", | |
40146 | + height - 2, width / 2 - 4, TRUE); | |
40147 | + | |
40148 | + wrefresh (dialog); | |
40149 | + while (key != ESC && key != '\n' && key != ' ' && | |
40150 | + key != 'O' && key != 'o' && key != 'X' && key != 'x') | |
40151 | + key = wgetch (dialog); | |
40152 | + } else { | |
40153 | + key = '\n'; | |
40154 | + wrefresh (dialog); | |
40155 | + } | |
40156 | + | |
40157 | + delwin (dialog); | |
40158 | + return key == ESC ? -1 : 0; | |
40159 | +} | |
40160 | diff -Nur busybox-1.00/scripts/config/lxdialog/textbox.c busybox/scripts/config/lxdialog/textbox.c | |
40161 | --- busybox-1.00/scripts/config/lxdialog/textbox.c 1970-01-01 01:00:00.000000000 +0100 | |
40162 | +++ busybox/scripts/config/lxdialog/textbox.c 2005-06-04 08:20:02.000000000 +0200 | |
40163 | @@ -0,0 +1,556 @@ | |
40164 | +/* | |
40165 | + * textbox.c -- implements the text box | |
40166 | + * | |
40167 | + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
40168 | + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
40169 | + * | |
40170 | + * This program is free software; you can redistribute it and/or | |
40171 | + * modify it under the terms of the GNU General Public License | |
40172 | + * as published by the Free Software Foundation; either version 2 | |
40173 | + * of the License, or (at your option) any later version. | |
40174 | + * | |
40175 | + * This program is distributed in the hope that it will be useful, | |
40176 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
40177 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
40178 | + * GNU General Public License for more details. | |
40179 | + * | |
40180 | + * You should have received a copy of the GNU General Public License | |
40181 | + * along with this program; if not, write to the Free Software | |
40182 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
40183 | + */ | |
40184 | + | |
40185 | +#include "dialog.h" | |
40186 | + | |
40187 | +static void back_lines (int n); | |
40188 | +static void print_page (WINDOW * win, int height, int width); | |
40189 | +static void print_line (WINDOW * win, int row, int width); | |
40190 | +static char *get_line (void); | |
40191 | +static void print_position (WINDOW * win, int height, int width); | |
40192 | + | |
40193 | +static int hscroll, fd, file_size, bytes_read; | |
40194 | +static int begin_reached = 1, end_reached, page_length; | |
40195 | +static char *buf, *page; | |
40196 | + | |
40197 | +/* | |
40198 | + * Display text from a file in a dialog box. | |
40199 | + */ | |
40200 | +int | |
40201 | +dialog_textbox (const char *title, const char *file, int height, int width) | |
40202 | +{ | |
40203 | + int i, x, y, cur_x, cur_y, fpos, key = 0; | |
40204 | + int passed_end; | |
40205 | + char search_term[MAX_LEN + 1]; | |
40206 | + WINDOW *dialog, *text; | |
40207 | + | |
40208 | + search_term[0] = '\0'; /* no search term entered yet */ | |
40209 | + | |
40210 | + /* Open input file for reading */ | |
40211 | + if ((fd = open (file, O_RDONLY)) == -1) { | |
40212 | + endwin (); | |
40213 | + fprintf (stderr, | |
40214 | + "\nCan't open input file in dialog_textbox().\n"); | |
40215 | + exit (-1); | |
40216 | + } | |
40217 | + /* Get file size. Actually, 'file_size' is the real file size - 1, | |
40218 | + since it's only the last byte offset from the beginning */ | |
40219 | + if ((file_size = lseek (fd, 0, SEEK_END)) == -1) { | |
40220 | + endwin (); | |
40221 | + fprintf (stderr, "\nError getting file size in dialog_textbox().\n"); | |
40222 | + exit (-1); | |
40223 | + } | |
40224 | + /* Restore file pointer to beginning of file after getting file size */ | |
40225 | + if (lseek (fd, 0, SEEK_SET) == -1) { | |
40226 | + endwin (); | |
40227 | + fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n"); | |
40228 | + exit (-1); | |
40229 | + } | |
40230 | + /* Allocate space for read buffer */ | |
40231 | + if ((buf = malloc (BUF_SIZE + 1)) == NULL) { | |
40232 | + endwin (); | |
40233 | + fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n"); | |
40234 | + exit (-1); | |
40235 | + } | |
40236 | + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
40237 | + endwin (); | |
40238 | + fprintf (stderr, "\nError reading file in dialog_textbox().\n"); | |
40239 | + exit (-1); | |
40240 | + } | |
40241 | + buf[bytes_read] = '\0'; /* mark end of valid data */ | |
40242 | + page = buf; /* page is pointer to start of page to be displayed */ | |
40243 | + | |
40244 | + /* center dialog box on screen */ | |
40245 | + x = (COLS - width) / 2; | |
40246 | + y = (LINES - height) / 2; | |
40247 | + | |
40248 | + | |
40249 | + draw_shadow (stdscr, y, x, height, width); | |
40250 | + | |
40251 | + dialog = newwin (height, width, y, x); | |
40252 | + keypad (dialog, TRUE); | |
40253 | + | |
40254 | + /* Create window for text region, used for scrolling text */ | |
40255 | + text = subwin (dialog, height - 4, width - 2, y + 1, x + 1); | |
40256 | + wattrset (text, dialog_attr); | |
40257 | + wbkgdset (text, dialog_attr & A_COLOR); | |
40258 | + | |
40259 | + keypad (text, TRUE); | |
40260 | + | |
40261 | + /* register the new window, along with its borders */ | |
40262 | + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
40263 | + | |
40264 | + wattrset (dialog, border_attr); | |
40265 | + mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
40266 | + for (i = 0; i < width - 2; i++) | |
40267 | + waddch (dialog, ACS_HLINE); | |
40268 | + wattrset (dialog, dialog_attr); | |
40269 | + wbkgdset (dialog, dialog_attr & A_COLOR); | |
40270 | + waddch (dialog, ACS_RTEE); | |
40271 | + | |
40272 | + if (title != NULL && strlen(title) >= width-2 ) { | |
40273 | + /* truncate long title -- mec */ | |
40274 | + char * title2 = malloc(width-2+1); | |
40275 | + memcpy( title2, title, width-2 ); | |
40276 | + title2[width-2] = '\0'; | |
40277 | + title = title2; | |
40278 | + } | |
40279 | + | |
40280 | + if (title != NULL) { | |
40281 | + wattrset (dialog, title_attr); | |
40282 | + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
40283 | + waddstr (dialog, (char *)title); | |
40284 | + waddch (dialog, ' '); | |
40285 | + } | |
40286 | + print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE); | |
40287 | + wnoutrefresh (dialog); | |
40288 | + getyx (dialog, cur_y, cur_x); /* Save cursor position */ | |
40289 | + | |
40290 | + /* Print first page of text */ | |
40291 | + attr_clear (text, height - 4, width - 2, dialog_attr); | |
40292 | + print_page (text, height - 4, width - 2); | |
40293 | + print_position (dialog, height, width); | |
40294 | + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
40295 | + wrefresh (dialog); | |
40296 | + | |
40297 | + while ((key != ESC) && (key != '\n')) { | |
40298 | + key = wgetch (dialog); | |
40299 | + switch (key) { | |
40300 | + case 'E': /* Exit */ | |
40301 | + case 'e': | |
40302 | + case 'X': | |
40303 | + case 'x': | |
40304 | + delwin (dialog); | |
40305 | + free (buf); | |
40306 | + close (fd); | |
40307 | + return 0; | |
40308 | + case 'g': /* First page */ | |
40309 | + case KEY_HOME: | |
40310 | + if (!begin_reached) { | |
40311 | + begin_reached = 1; | |
40312 | + /* First page not in buffer? */ | |
40313 | + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
40314 | + endwin (); | |
40315 | + fprintf (stderr, | |
40316 | + "\nError moving file pointer in dialog_textbox().\n"); | |
40317 | + exit (-1); | |
40318 | + } | |
40319 | + if (fpos > bytes_read) { /* Yes, we have to read it in */ | |
40320 | + if (lseek (fd, 0, SEEK_SET) == -1) { | |
40321 | + endwin (); | |
40322 | + fprintf (stderr, "\nError moving file pointer in " | |
40323 | + "dialog_textbox().\n"); | |
40324 | + exit (-1); | |
40325 | + } | |
40326 | + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
40327 | + endwin (); | |
40328 | + fprintf (stderr, | |
40329 | + "\nError reading file in dialog_textbox().\n"); | |
40330 | + exit (-1); | |
40331 | + } | |
40332 | + buf[bytes_read] = '\0'; | |
40333 | + } | |
40334 | + page = buf; | |
40335 | + print_page (text, height - 4, width - 2); | |
40336 | + print_position (dialog, height, width); | |
40337 | + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
40338 | + wrefresh (dialog); | |
40339 | + } | |
40340 | + break; | |
40341 | + case 'G': /* Last page */ | |
40342 | + case KEY_END: | |
40343 | + | |
40344 | + end_reached = 1; | |
40345 | + /* Last page not in buffer? */ | |
40346 | + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
40347 | + endwin (); | |
40348 | + fprintf (stderr, | |
40349 | + "\nError moving file pointer in dialog_textbox().\n"); | |
40350 | + exit (-1); | |
40351 | + } | |
40352 | + if (fpos < file_size) { /* Yes, we have to read it in */ | |
40353 | + if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) { | |
40354 | + endwin (); | |
40355 | + fprintf (stderr, | |
40356 | + "\nError moving file pointer in dialog_textbox().\n"); | |
40357 | + exit (-1); | |
40358 | + } | |
40359 | + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
40360 | + endwin (); | |
40361 | + fprintf (stderr, | |
40362 | + "\nError reading file in dialog_textbox().\n"); | |
40363 | + exit (-1); | |
40364 | + } | |
40365 | + buf[bytes_read] = '\0'; | |
40366 | + } | |
40367 | + page = buf + bytes_read; | |
40368 | + back_lines (height - 4); | |
40369 | + print_page (text, height - 4, width - 2); | |
40370 | + print_position (dialog, height, width); | |
40371 | + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
40372 | + wrefresh (dialog); | |
40373 | + break; | |
40374 | + case 'K': /* Previous line */ | |
40375 | + case 'k': | |
40376 | + case KEY_UP: | |
40377 | + if (!begin_reached) { | |
40378 | + back_lines (page_length + 1); | |
40379 | + | |
40380 | + /* We don't call print_page() here but use scrolling to ensure | |
40381 | + faster screen update. However, 'end_reached' and | |
40382 | + 'page_length' should still be updated, and 'page' should | |
40383 | + point to start of next page. This is done by calling | |
40384 | + get_line() in the following 'for' loop. */ | |
40385 | + scrollok (text, TRUE); | |
40386 | + wscrl (text, -1); /* Scroll text region down one line */ | |
40387 | + scrollok (text, FALSE); | |
40388 | + page_length = 0; | |
40389 | + passed_end = 0; | |
40390 | + for (i = 0; i < height - 4; i++) { | |
40391 | + if (!i) { | |
40392 | + /* print first line of page */ | |
40393 | + print_line (text, 0, width - 2); | |
40394 | + wnoutrefresh (text); | |
40395 | + } else | |
40396 | + /* Called to update 'end_reached' and 'page' */ | |
40397 | + get_line (); | |
40398 | + if (!passed_end) | |
40399 | + page_length++; | |
40400 | + if (end_reached && !passed_end) | |
40401 | + passed_end = 1; | |
40402 | + } | |
40403 | + | |
40404 | + print_position (dialog, height, width); | |
40405 | + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
40406 | + wrefresh (dialog); | |
40407 | + } | |
40408 | + break; | |
40409 | + case 'B': /* Previous page */ | |
40410 | + case 'b': | |
40411 | + case KEY_PPAGE: | |
40412 | + if (begin_reached) | |
40413 | + break; | |
40414 | + back_lines (page_length + height - 4); | |
40415 | + print_page (text, height - 4, width - 2); | |
40416 | + print_position (dialog, height, width); | |
40417 | + wmove (dialog, cur_y, cur_x); | |
40418 | + wrefresh (dialog); | |
40419 | + break; | |
40420 | + case 'J': /* Next line */ | |
40421 | + case 'j': | |
40422 | + case KEY_DOWN: | |
40423 | + if (!end_reached) { | |
40424 | + begin_reached = 0; | |
40425 | + scrollok (text, TRUE); | |
40426 | + scroll (text); /* Scroll text region up one line */ | |
40427 | + scrollok (text, FALSE); | |
40428 | + print_line (text, height - 5, width - 2); | |
40429 | + wnoutrefresh (text); | |
40430 | + print_position (dialog, height, width); | |
40431 | + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
40432 | + wrefresh (dialog); | |
40433 | + } | |
40434 | + break; | |
40435 | + case KEY_NPAGE: /* Next page */ | |
40436 | + case ' ': | |
40437 | + if (end_reached) | |
40438 | + break; | |
40439 | + | |
40440 | + begin_reached = 0; | |
40441 | + print_page (text, height - 4, width - 2); | |
40442 | + print_position (dialog, height, width); | |
40443 | + wmove (dialog, cur_y, cur_x); | |
40444 | + wrefresh (dialog); | |
40445 | + break; | |
40446 | + case '0': /* Beginning of line */ | |
40447 | + case 'H': /* Scroll left */ | |
40448 | + case 'h': | |
40449 | + case KEY_LEFT: | |
40450 | + if (hscroll <= 0) | |
40451 | + break; | |
40452 | + | |
40453 | + if (key == '0') | |
40454 | + hscroll = 0; | |
40455 | + else | |
40456 | + hscroll--; | |
40457 | + /* Reprint current page to scroll horizontally */ | |
40458 | + back_lines (page_length); | |
40459 | + print_page (text, height - 4, width - 2); | |
40460 | + wmove (dialog, cur_y, cur_x); | |
40461 | + wrefresh (dialog); | |
40462 | + break; | |
40463 | + case 'L': /* Scroll right */ | |
40464 | + case 'l': | |
40465 | + case KEY_RIGHT: | |
40466 | + if (hscroll >= MAX_LEN) | |
40467 | + break; | |
40468 | + hscroll++; | |
40469 | + /* Reprint current page to scroll horizontally */ | |
40470 | + back_lines (page_length); | |
40471 | + print_page (text, height - 4, width - 2); | |
40472 | + wmove (dialog, cur_y, cur_x); | |
40473 | + wrefresh (dialog); | |
40474 | + break; | |
40475 | + case ESC: | |
40476 | + break; | |
40477 | + } | |
40478 | + } | |
40479 | + | |
40480 | + delwin (dialog); | |
40481 | + free (buf); | |
40482 | + close (fd); | |
40483 | + return 1; /* ESC pressed */ | |
40484 | +} | |
40485 | + | |
40486 | +/* | |
40487 | + * Go back 'n' lines in text file. Called by dialog_textbox(). | |
40488 | + * 'page' will be updated to point to the desired line in 'buf'. | |
40489 | + */ | |
40490 | +static void | |
40491 | +back_lines (int n) | |
40492 | +{ | |
40493 | + int i, fpos; | |
40494 | + | |
40495 | + begin_reached = 0; | |
40496 | + /* We have to distinguish between end_reached and !end_reached | |
40497 | + since at end of file, the line is not ended by a '\n'. | |
40498 | + The code inside 'if' basically does a '--page' to move one | |
40499 | + character backward so as to skip '\n' of the previous line */ | |
40500 | + if (!end_reached) { | |
40501 | + /* Either beginning of buffer or beginning of file reached? */ | |
40502 | + if (page == buf) { | |
40503 | + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
40504 | + endwin (); | |
40505 | + fprintf (stderr, "\nError moving file pointer in " | |
40506 | + "back_lines().\n"); | |
40507 | + exit (-1); | |
40508 | + } | |
40509 | + if (fpos > bytes_read) { /* Not beginning of file yet */ | |
40510 | + /* We've reached beginning of buffer, but not beginning of | |
40511 | + file yet, so read previous part of file into buffer. | |
40512 | + Note that we only move backward for BUF_SIZE/2 bytes, | |
40513 | + but not BUF_SIZE bytes to avoid re-reading again in | |
40514 | + print_page() later */ | |
40515 | + /* Really possible to move backward BUF_SIZE/2 bytes? */ | |
40516 | + if (fpos < BUF_SIZE / 2 + bytes_read) { | |
40517 | + /* No, move less then */ | |
40518 | + if (lseek (fd, 0, SEEK_SET) == -1) { | |
40519 | + endwin (); | |
40520 | + fprintf (stderr, "\nError moving file pointer in " | |
40521 | + "back_lines().\n"); | |
40522 | + exit (-1); | |
40523 | + } | |
40524 | + page = buf + fpos - bytes_read; | |
40525 | + } else { /* Move backward BUF_SIZE/2 bytes */ | |
40526 | + if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) | |
40527 | + == -1) { | |
40528 | + endwin (); | |
40529 | + fprintf (stderr, "\nError moving file pointer " | |
40530 | + "in back_lines().\n"); | |
40531 | + exit (-1); | |
40532 | + } | |
40533 | + page = buf + BUF_SIZE / 2; | |
40534 | + } | |
40535 | + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
40536 | + endwin (); | |
40537 | + fprintf (stderr, "\nError reading file in back_lines().\n"); | |
40538 | + exit (-1); | |
40539 | + } | |
40540 | + buf[bytes_read] = '\0'; | |
40541 | + } else { /* Beginning of file reached */ | |
40542 | + begin_reached = 1; | |
40543 | + return; | |
40544 | + } | |
40545 | + } | |
40546 | + if (*(--page) != '\n') { /* '--page' here */ | |
40547 | + /* Something's wrong... */ | |
40548 | + endwin (); | |
40549 | + fprintf (stderr, "\nInternal error in back_lines().\n"); | |
40550 | + exit (-1); | |
40551 | + } | |
40552 | + } | |
40553 | + /* Go back 'n' lines */ | |
40554 | + for (i = 0; i < n; i++) | |
40555 | + do { | |
40556 | + if (page == buf) { | |
40557 | + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
40558 | + endwin (); | |
40559 | + fprintf (stderr, | |
40560 | + "\nError moving file pointer in back_lines().\n"); | |
40561 | + exit (-1); | |
40562 | + } | |
40563 | + if (fpos > bytes_read) { | |
40564 | + /* Really possible to move backward BUF_SIZE/2 bytes? */ | |
40565 | + if (fpos < BUF_SIZE / 2 + bytes_read) { | |
40566 | + /* No, move less then */ | |
40567 | + if (lseek (fd, 0, SEEK_SET) == -1) { | |
40568 | + endwin (); | |
40569 | + fprintf (stderr, "\nError moving file pointer " | |
40570 | + "in back_lines().\n"); | |
40571 | + exit (-1); | |
40572 | + } | |
40573 | + page = buf + fpos - bytes_read; | |
40574 | + } else { /* Move backward BUF_SIZE/2 bytes */ | |
40575 | + if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), | |
40576 | + SEEK_CUR) == -1) { | |
40577 | + endwin (); | |
40578 | + fprintf (stderr, "\nError moving file pointer" | |
40579 | + " in back_lines().\n"); | |
40580 | + exit (-1); | |
40581 | + } | |
40582 | + page = buf + BUF_SIZE / 2; | |
40583 | + } | |
40584 | + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
40585 | + endwin (); | |
40586 | + fprintf (stderr, "\nError reading file in " | |
40587 | + "back_lines().\n"); | |
40588 | + exit (-1); | |
40589 | + } | |
40590 | + buf[bytes_read] = '\0'; | |
40591 | + } else { /* Beginning of file reached */ | |
40592 | + begin_reached = 1; | |
40593 | + return; | |
40594 | + } | |
40595 | + } | |
40596 | + } while (*(--page) != '\n'); | |
40597 | + page++; | |
40598 | +} | |
40599 | + | |
40600 | +/* | |
40601 | + * Print a new page of text. Called by dialog_textbox(). | |
40602 | + */ | |
40603 | +static void | |
40604 | +print_page (WINDOW * win, int height, int width) | |
40605 | +{ | |
40606 | + int i, passed_end = 0; | |
40607 | + | |
40608 | + page_length = 0; | |
40609 | + for (i = 0; i < height; i++) { | |
40610 | + print_line (win, i, width); | |
40611 | + if (!passed_end) | |
40612 | + page_length++; | |
40613 | + if (end_reached && !passed_end) | |
40614 | + passed_end = 1; | |
40615 | + } | |
40616 | + wnoutrefresh (win); | |
40617 | +} | |
40618 | + | |
40619 | +/* | |
40620 | + * Print a new line of text. Called by dialog_textbox() and print_page(). | |
40621 | + */ | |
40622 | +static void | |
40623 | +print_line (WINDOW * win, int row, int width) | |
40624 | +{ | |
40625 | + int y, x; | |
40626 | + char *line; | |
40627 | + | |
40628 | + line = get_line (); | |
40629 | + line += MIN (strlen (line), hscroll); /* Scroll horizontally */ | |
40630 | + wmove (win, row, 0); /* move cursor to correct line */ | |
40631 | + waddch (win, ' '); | |
40632 | + waddnstr (win, line, MIN (strlen (line), width - 2)); | |
40633 | + | |
40634 | + getyx (win, y, x); | |
40635 | + /* Clear 'residue' of previous line */ | |
40636 | +#if OLD_NCURSES | |
40637 | + { | |
40638 | + int i; | |
40639 | + for (i = 0; i < width - x; i++) | |
40640 | + waddch (win, ' '); | |
40641 | + } | |
40642 | +#else | |
40643 | + wclrtoeol(win); | |
40644 | +#endif | |
40645 | +} | |
40646 | + | |
40647 | +/* | |
40648 | + * Return current line of text. Called by dialog_textbox() and print_line(). | |
40649 | + * 'page' should point to start of current line before calling, and will be | |
40650 | + * updated to point to start of next line. | |
40651 | + */ | |
40652 | +static char * | |
40653 | +get_line (void) | |
40654 | +{ | |
40655 | + int i = 0, fpos; | |
40656 | + static char line[MAX_LEN + 1]; | |
40657 | + | |
40658 | + end_reached = 0; | |
40659 | + while (*page != '\n') { | |
40660 | + if (*page == '\0') { | |
40661 | + /* Either end of file or end of buffer reached */ | |
40662 | + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
40663 | + endwin (); | |
40664 | + fprintf (stderr, "\nError moving file pointer in " | |
40665 | + "get_line().\n"); | |
40666 | + exit (-1); | |
40667 | + } | |
40668 | + if (fpos < file_size) { /* Not end of file yet */ | |
40669 | + /* We've reached end of buffer, but not end of file yet, | |
40670 | + so read next part of file into buffer */ | |
40671 | + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
40672 | + endwin (); | |
40673 | + fprintf (stderr, "\nError reading file in get_line().\n"); | |
40674 | + exit (-1); | |
40675 | + } | |
40676 | + buf[bytes_read] = '\0'; | |
40677 | + page = buf; | |
40678 | + } else { | |
40679 | + if (!end_reached) | |
40680 | + end_reached = 1; | |
40681 | + break; | |
40682 | + } | |
40683 | + } else if (i < MAX_LEN) | |
40684 | + line[i++] = *(page++); | |
40685 | + else { | |
40686 | + /* Truncate lines longer than MAX_LEN characters */ | |
40687 | + if (i == MAX_LEN) | |
40688 | + line[i++] = '\0'; | |
40689 | + page++; | |
40690 | + } | |
40691 | + } | |
40692 | + if (i <= MAX_LEN) | |
40693 | + line[i] = '\0'; | |
40694 | + if (!end_reached) | |
40695 | + page++; /* move pass '\n' */ | |
40696 | + | |
40697 | + return line; | |
40698 | +} | |
40699 | + | |
40700 | +/* | |
40701 | + * Print current position | |
40702 | + */ | |
40703 | +static void | |
40704 | +print_position (WINDOW * win, int height, int width) | |
40705 | +{ | |
40706 | + int fpos, percent; | |
40707 | + | |
40708 | + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
40709 | + endwin (); | |
40710 | + fprintf (stderr, "\nError moving file pointer in print_position().\n"); | |
40711 | + exit (-1); | |
40712 | + } | |
40713 | + wattrset (win, position_indicator_attr); | |
40714 | + wbkgdset (win, position_indicator_attr & A_COLOR); | |
40715 | + percent = !file_size ? | |
40716 | + 100 : ((fpos - bytes_read + page - buf) * 100) / file_size; | |
40717 | + wmove (win, height - 3, width - 9); | |
40718 | + wprintw (win, "(%3d%%)", percent); | |
40719 | +} | |
40720 | diff -Nur busybox-1.00/scripts/config/lxdialog/util.c busybox/scripts/config/lxdialog/util.c | |
40721 | --- busybox-1.00/scripts/config/lxdialog/util.c 1970-01-01 01:00:00.000000000 +0100 | |
40722 | +++ busybox/scripts/config/lxdialog/util.c 2005-06-04 08:20:02.000000000 +0200 | |
40723 | @@ -0,0 +1,375 @@ | |
40724 | +/* | |
40725 | + * util.c | |
40726 | + * | |
40727 | + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
40728 | + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
40729 | + * | |
40730 | + * This program is free software; you can redistribute it and/or | |
40731 | + * modify it under the terms of the GNU General Public License | |
40732 | + * as published by the Free Software Foundation; either version 2 | |
40733 | + * of the License, or (at your option) any later version. | |
40734 | + * | |
40735 | + * This program is distributed in the hope that it will be useful, | |
40736 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
40737 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
40738 | + * GNU General Public License for more details. | |
40739 | + * | |
40740 | + * You should have received a copy of the GNU General Public License | |
40741 | + * along with this program; if not, write to the Free Software | |
40742 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
40743 | + */ | |
40744 | + | |
40745 | +#include "dialog.h" | |
40746 | + | |
40747 | + | |
40748 | +/* use colors by default? */ | |
40749 | +bool use_colors = 1; | |
40750 | + | |
40751 | +const char *backtitle = NULL; | |
40752 | + | |
40753 | +const char *dialog_result; | |
40754 | + | |
40755 | +/* | |
40756 | + * Attribute values, default is for mono display | |
40757 | + */ | |
40758 | +chtype attributes[] = | |
40759 | +{ | |
40760 | + A_NORMAL, /* screen_attr */ | |
40761 | + A_NORMAL, /* shadow_attr */ | |
40762 | + A_NORMAL, /* dialog_attr */ | |
40763 | + A_BOLD, /* title_attr */ | |
40764 | + A_NORMAL, /* border_attr */ | |
40765 | + A_REVERSE, /* button_active_attr */ | |
40766 | + A_DIM, /* button_inactive_attr */ | |
40767 | + A_REVERSE, /* button_key_active_attr */ | |
40768 | + A_BOLD, /* button_key_inactive_attr */ | |
40769 | + A_REVERSE, /* button_label_active_attr */ | |
40770 | + A_NORMAL, /* button_label_inactive_attr */ | |
40771 | + A_NORMAL, /* inputbox_attr */ | |
40772 | + A_NORMAL, /* inputbox_border_attr */ | |
40773 | + A_NORMAL, /* searchbox_attr */ | |
40774 | + A_BOLD, /* searchbox_title_attr */ | |
40775 | + A_NORMAL, /* searchbox_border_attr */ | |
40776 | + A_BOLD, /* position_indicator_attr */ | |
40777 | + A_NORMAL, /* menubox_attr */ | |
40778 | + A_NORMAL, /* menubox_border_attr */ | |
40779 | + A_NORMAL, /* item_attr */ | |
40780 | + A_REVERSE, /* item_selected_attr */ | |
40781 | + A_BOLD, /* tag_attr */ | |
40782 | + A_REVERSE, /* tag_selected_attr */ | |
40783 | + A_BOLD, /* tag_key_attr */ | |
40784 | + A_REVERSE, /* tag_key_selected_attr */ | |
40785 | + A_BOLD, /* check_attr */ | |
40786 | + A_REVERSE, /* check_selected_attr */ | |
40787 | + A_BOLD, /* uarrow_attr */ | |
40788 | + A_BOLD /* darrow_attr */ | |
40789 | +}; | |
40790 | + | |
40791 | + | |
40792 | +#include "colors.h" | |
40793 | + | |
40794 | +/* | |
40795 | + * Table of color values | |
40796 | + */ | |
40797 | +int color_table[][3] = | |
40798 | +{ | |
40799 | + {SCREEN_FG, SCREEN_BG, SCREEN_HL}, | |
40800 | + {SHADOW_FG, SHADOW_BG, SHADOW_HL}, | |
40801 | + {DIALOG_FG, DIALOG_BG, DIALOG_HL}, | |
40802 | + {TITLE_FG, TITLE_BG, TITLE_HL}, | |
40803 | + {BORDER_FG, BORDER_BG, BORDER_HL}, | |
40804 | + {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, | |
40805 | + {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, | |
40806 | + {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, | |
40807 | + {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL}, | |
40808 | + {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL}, | |
40809 | + {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG, | |
40810 | + BUTTON_LABEL_INACTIVE_HL}, | |
40811 | + {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL}, | |
40812 | + {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL}, | |
40813 | + {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL}, | |
40814 | + {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL}, | |
40815 | + {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL}, | |
40816 | + {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL}, | |
40817 | + {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL}, | |
40818 | + {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL}, | |
40819 | + {ITEM_FG, ITEM_BG, ITEM_HL}, | |
40820 | + {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL}, | |
40821 | + {TAG_FG, TAG_BG, TAG_HL}, | |
40822 | + {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL}, | |
40823 | + {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL}, | |
40824 | + {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL}, | |
40825 | + {CHECK_FG, CHECK_BG, CHECK_HL}, | |
40826 | + {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL}, | |
40827 | + {UARROW_FG, UARROW_BG, UARROW_HL}, | |
40828 | + {DARROW_FG, DARROW_BG, DARROW_HL}, | |
40829 | +}; /* color_table */ | |
40830 | + | |
40831 | +/* | |
40832 | + * Set window to attribute 'attr' | |
40833 | + */ | |
40834 | +void | |
40835 | +attr_clear (WINDOW * win, int height, int width, chtype attr) | |
40836 | +{ | |
40837 | + int i, j; | |
40838 | + | |
40839 | + wattrset (win, attr); | |
40840 | + for (i = 0; i < height; i++) { | |
40841 | + wmove (win, i, 0); | |
40842 | + for (j = 0; j < width; j++) | |
40843 | + waddch (win, ' '); | |
40844 | + } | |
40845 | + touchwin (win); | |
40846 | +} | |
40847 | + | |
40848 | +void dialog_clear (void) | |
40849 | +{ | |
40850 | + attr_clear (stdscr, LINES, COLS, screen_attr); | |
40851 | + /* Display background title if it exists ... - SLH */ | |
40852 | + if (backtitle != NULL) { | |
40853 | + int i; | |
40854 | + | |
40855 | + wattrset (stdscr, screen_attr); | |
40856 | + mvwaddstr (stdscr, 0, 1, (char *)backtitle); | |
40857 | + wmove (stdscr, 1, 1); | |
40858 | + for (i = 1; i < COLS - 1; i++) | |
40859 | + waddch (stdscr, ACS_HLINE); | |
40860 | + } | |
40861 | + wnoutrefresh (stdscr); | |
40862 | +} | |
40863 | + | |
40864 | +/* | |
40865 | + * Do some initialization for dialog | |
40866 | + */ | |
40867 | +void | |
40868 | +init_dialog (void) | |
40869 | +{ | |
40870 | + initscr (); /* Init curses */ | |
40871 | + keypad (stdscr, TRUE); | |
40872 | + cbreak (); | |
40873 | + noecho (); | |
40874 | + | |
40875 | + | |
40876 | + if (use_colors) /* Set up colors */ | |
40877 | + color_setup (); | |
40878 | + | |
40879 | + | |
40880 | + dialog_clear (); | |
40881 | +} | |
40882 | + | |
40883 | +/* | |
40884 | + * Setup for color display | |
40885 | + */ | |
40886 | +void | |
40887 | +color_setup (void) | |
40888 | +{ | |
40889 | + int i; | |
40890 | + | |
40891 | + if (has_colors ()) { /* Terminal supports color? */ | |
40892 | + start_color (); | |
40893 | + | |
40894 | + /* Initialize color pairs */ | |
40895 | + for (i = 0; i < ATTRIBUTE_COUNT; i++) | |
40896 | + init_pair (i + 1, color_table[i][0], color_table[i][1]); | |
40897 | + | |
40898 | + /* Setup color attributes */ | |
40899 | + for (i = 0; i < ATTRIBUTE_COUNT; i++) | |
40900 | + attributes[i] = C_ATTR (color_table[i][2], i + 1); | |
40901 | + } | |
40902 | +} | |
40903 | + | |
40904 | +/* | |
40905 | + * End using dialog functions. | |
40906 | + */ | |
40907 | +void | |
40908 | +end_dialog (void) | |
40909 | +{ | |
40910 | + endwin (); | |
40911 | +} | |
40912 | + | |
40913 | + | |
40914 | +/* | |
40915 | + * Print a string of text in a window, automatically wrap around to the | |
40916 | + * next line if the string is too long to fit on one line. Newline | |
40917 | + * characters '\n' are replaced by spaces. We start on a new line | |
40918 | + * if there is no room for at least 4 nonblanks following a double-space. | |
40919 | + */ | |
40920 | +void | |
40921 | +print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x) | |
40922 | +{ | |
40923 | + int newl, cur_x, cur_y; | |
40924 | + int i, prompt_len, room, wlen; | |
40925 | + char tempstr[MAX_LEN + 1], *word, *sp, *sp2; | |
40926 | + | |
40927 | + strcpy (tempstr, prompt); | |
40928 | + | |
40929 | + prompt_len = strlen(tempstr); | |
40930 | + | |
40931 | + /* | |
40932 | + * Remove newlines | |
40933 | + */ | |
40934 | + for(i=0; i<prompt_len; i++) { | |
40935 | + if(tempstr[i] == '\n') tempstr[i] = ' '; | |
40936 | + } | |
40937 | + | |
40938 | + if (prompt_len <= width - x * 2) { /* If prompt is short */ | |
40939 | + wmove (win, y, (width - prompt_len) / 2); | |
40940 | + waddstr (win, tempstr); | |
40941 | + } else { | |
40942 | + cur_x = x; | |
40943 | + cur_y = y; | |
40944 | + newl = 1; | |
40945 | + word = tempstr; | |
40946 | + while (word && *word) { | |
40947 | + sp = index(word, ' '); | |
40948 | + if (sp) | |
40949 | + *sp++ = 0; | |
40950 | + | |
40951 | + /* Wrap to next line if either the word does not fit, | |
40952 | + or it is the first word of a new sentence, and it is | |
40953 | + short, and the next word does not fit. */ | |
40954 | + room = width - cur_x; | |
40955 | + wlen = strlen(word); | |
40956 | + if (wlen > room || | |
40957 | + (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room | |
40958 | + && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) { | |
40959 | + cur_y++; | |
40960 | + cur_x = x; | |
40961 | + } | |
40962 | + wmove (win, cur_y, cur_x); | |
40963 | + waddstr (win, word); | |
40964 | + getyx (win, cur_y, cur_x); | |
40965 | + cur_x++; | |
40966 | + if (sp && *sp == ' ') { | |
40967 | + cur_x++; /* double space */ | |
40968 | + while (*++sp == ' '); | |
40969 | + newl = 1; | |
40970 | + } else | |
40971 | + newl = 0; | |
40972 | + word = sp; | |
40973 | + } | |
40974 | + } | |
40975 | +} | |
40976 | + | |
40977 | +/* | |
40978 | + * Print a button | |
40979 | + */ | |
40980 | +void | |
40981 | +print_button (WINDOW * win, const char *label, int y, int x, int selected) | |
40982 | +{ | |
40983 | + int i, temp; | |
40984 | + | |
40985 | + wmove (win, y, x); | |
40986 | + wattrset (win, selected ? button_active_attr : button_inactive_attr); | |
40987 | + waddstr (win, "<"); | |
40988 | + temp = strspn (label, " "); | |
40989 | + label += temp; | |
40990 | + wattrset (win, selected ? button_label_active_attr | |
40991 | + : button_label_inactive_attr); | |
40992 | + for (i = 0; i < temp; i++) | |
40993 | + waddch (win, ' '); | |
40994 | + wattrset (win, selected ? button_key_active_attr | |
40995 | + : button_key_inactive_attr); | |
40996 | + waddch (win, label[0]); | |
40997 | + wattrset (win, selected ? button_label_active_attr | |
40998 | + : button_label_inactive_attr); | |
40999 | + waddstr (win, (char *)label + 1); | |
41000 | + wattrset (win, selected ? button_active_attr : button_inactive_attr); | |
41001 | + waddstr (win, ">"); | |
41002 | + wmove (win, y, x + temp + 1); | |
41003 | +} | |
41004 | + | |
41005 | +/* | |
41006 | + * Draw a rectangular box with line drawing characters | |
41007 | + */ | |
41008 | +void | |
41009 | +draw_box (WINDOW * win, int y, int x, int height, int width, | |
41010 | + chtype box, chtype border) | |
41011 | +{ | |
41012 | + int i, j; | |
41013 | + | |
41014 | + wattrset (win, 0); | |
41015 | + for (i = 0; i < height; i++) { | |
41016 | + wmove (win, y + i, x); | |
41017 | + for (j = 0; j < width; j++) | |
41018 | + if (!i && !j) | |
41019 | + waddch (win, border | ACS_ULCORNER); | |
41020 | + else if (i == height - 1 && !j) | |
41021 | + waddch (win, border | ACS_LLCORNER); | |
41022 | + else if (!i && j == width - 1) | |
41023 | + waddch (win, box | ACS_URCORNER); | |
41024 | + else if (i == height - 1 && j == width - 1) | |
41025 | + waddch (win, box | ACS_LRCORNER); | |
41026 | + else if (!i) | |
41027 | + waddch (win, border | ACS_HLINE); | |
41028 | + else if (i == height - 1) | |
41029 | + waddch (win, box | ACS_HLINE); | |
41030 | + else if (!j) | |
41031 | + waddch (win, border | ACS_VLINE); | |
41032 | + else if (j == width - 1) | |
41033 | + waddch (win, box | ACS_VLINE); | |
41034 | + else | |
41035 | + waddch (win, box | ' '); | |
41036 | + } | |
41037 | +} | |
41038 | + | |
41039 | +/* | |
41040 | + * Draw shadows along the right and bottom edge to give a more 3D look | |
41041 | + * to the boxes | |
41042 | + */ | |
41043 | +void | |
41044 | +draw_shadow (WINDOW * win, int y, int x, int height, int width) | |
41045 | +{ | |
41046 | + int i; | |
41047 | + | |
41048 | + if (has_colors ()) { /* Whether terminal supports color? */ | |
41049 | + wattrset (win, shadow_attr); | |
41050 | + wmove (win, y + height, x + 2); | |
41051 | + for (i = 0; i < width; i++) | |
41052 | + waddch (win, winch (win) & A_CHARTEXT); | |
41053 | + for (i = y + 1; i < y + height + 1; i++) { | |
41054 | + wmove (win, i, x + width); | |
41055 | + waddch (win, winch (win) & A_CHARTEXT); | |
41056 | + waddch (win, winch (win) & A_CHARTEXT); | |
41057 | + } | |
41058 | + wnoutrefresh (win); | |
41059 | + } | |
41060 | +} | |
41061 | + | |
41062 | +/* | |
41063 | + * Return the position of the first alphabetic character in a string. | |
41064 | + */ | |
41065 | +int | |
41066 | +first_alpha(const char *string, const char *exempt) | |
41067 | +{ | |
41068 | + int i, in_paren=0, c; | |
41069 | + | |
41070 | + for (i = 0; i < strlen(string); i++) { | |
41071 | + c = tolower(string[i]); | |
41072 | + | |
41073 | + if (strchr("<[(", c)) ++in_paren; | |
41074 | + if (strchr(">])", c) && in_paren > 0) --in_paren; | |
41075 | + | |
41076 | + if ((! in_paren) && isalpha(c) && | |
41077 | + strchr(exempt, c) == 0) | |
41078 | + return i; | |
41079 | + } | |
41080 | + | |
41081 | + return 0; | |
41082 | +} | |
41083 | + | |
41084 | +/* | |
41085 | + * Get the first selected item in the dialog_list_item list. | |
41086 | + */ | |
41087 | +struct dialog_list_item * | |
41088 | +first_sel_item(int item_no, struct dialog_list_item ** items) | |
41089 | +{ | |
41090 | + int i; | |
41091 | + | |
41092 | + for (i = 0; i < item_no; i++) { | |
41093 | + if (items[i]->selected) | |
41094 | + return items[i]; | |
41095 | + } | |
41096 | + | |
41097 | + return NULL; | |
41098 | +} | |
41099 | diff -Nur busybox-1.00/scripts/config/lxdialog/yesno.c busybox/scripts/config/lxdialog/yesno.c | |
41100 | --- busybox-1.00/scripts/config/lxdialog/yesno.c 1970-01-01 01:00:00.000000000 +0100 | |
41101 | +++ busybox/scripts/config/lxdialog/yesno.c 2005-06-04 08:20:02.000000000 +0200 | |
41102 | @@ -0,0 +1,118 @@ | |
41103 | +/* | |
41104 | + * yesno.c -- implements the yes/no box | |
41105 | + * | |
41106 | + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
41107 | + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
41108 | + * | |
41109 | + * This program is free software; you can redistribute it and/or | |
41110 | + * modify it under the terms of the GNU General Public License | |
41111 | + * as published by the Free Software Foundation; either version 2 | |
41112 | + * of the License, or (at your option) any later version. | |
41113 | + * | |
41114 | + * This program is distributed in the hope that it will be useful, | |
41115 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
41116 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
41117 | + * GNU General Public License for more details. | |
41118 | + * | |
41119 | + * You should have received a copy of the GNU General Public License | |
41120 | + * along with this program; if not, write to the Free Software | |
41121 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
41122 | + */ | |
41123 | + | |
41124 | +#include "dialog.h" | |
41125 | + | |
41126 | +/* | |
41127 | + * Display termination buttons | |
41128 | + */ | |
41129 | +static void | |
41130 | +print_buttons(WINDOW *dialog, int height, int width, int selected) | |
41131 | +{ | |
41132 | + int x = width / 2 - 10; | |
41133 | + int y = height - 2; | |
41134 | + | |
41135 | + print_button (dialog, " Yes ", y, x, selected == 0); | |
41136 | + print_button (dialog, " No ", y, x + 13, selected == 1); | |
41137 | + | |
41138 | + wmove(dialog, y, x+1 + 13*selected ); | |
41139 | + wrefresh (dialog); | |
41140 | +} | |
41141 | + | |
41142 | +/* | |
41143 | + * Display a dialog box with two buttons - Yes and No | |
41144 | + */ | |
41145 | +int | |
41146 | +dialog_yesno (const char *title, const char *prompt, int height, int width) | |
41147 | +{ | |
41148 | + int i, x, y, key = 0, button = 0; | |
41149 | + WINDOW *dialog; | |
41150 | + | |
41151 | + /* center dialog box on screen */ | |
41152 | + x = (COLS - width) / 2; | |
41153 | + y = (LINES - height) / 2; | |
41154 | + | |
41155 | + draw_shadow (stdscr, y, x, height, width); | |
41156 | + | |
41157 | + dialog = newwin (height, width, y, x); | |
41158 | + keypad (dialog, TRUE); | |
41159 | + | |
41160 | + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
41161 | + wattrset (dialog, border_attr); | |
41162 | + mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
41163 | + for (i = 0; i < width - 2; i++) | |
41164 | + waddch (dialog, ACS_HLINE); | |
41165 | + wattrset (dialog, dialog_attr); | |
41166 | + waddch (dialog, ACS_RTEE); | |
41167 | + | |
41168 | + if (title != NULL && strlen(title) >= width-2 ) { | |
41169 | + /* truncate long title -- mec */ | |
41170 | + char * title2 = malloc(width-2+1); | |
41171 | + memcpy( title2, title, width-2 ); | |
41172 | + title2[width-2] = '\0'; | |
41173 | + title = title2; | |
41174 | + } | |
41175 | + | |
41176 | + if (title != NULL) { | |
41177 | + wattrset (dialog, title_attr); | |
41178 | + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
41179 | + waddstr (dialog, (char *)title); | |
41180 | + waddch (dialog, ' '); | |
41181 | + } | |
41182 | + | |
41183 | + wattrset (dialog, dialog_attr); | |
41184 | + print_autowrap (dialog, prompt, width - 2, 1, 3); | |
41185 | + | |
41186 | + print_buttons(dialog, height, width, 0); | |
41187 | + | |
41188 | + while (key != ESC) { | |
41189 | + key = wgetch (dialog); | |
41190 | + switch (key) { | |
41191 | + case 'Y': | |
41192 | + case 'y': | |
41193 | + delwin (dialog); | |
41194 | + return 0; | |
41195 | + case 'N': | |
41196 | + case 'n': | |
41197 | + delwin (dialog); | |
41198 | + return 1; | |
41199 | + | |
41200 | + case TAB: | |
41201 | + case KEY_LEFT: | |
41202 | + case KEY_RIGHT: | |
41203 | + button = ((key == KEY_LEFT ? --button : ++button) < 0) | |
41204 | + ? 1 : (button > 1 ? 0 : button); | |
41205 | + | |
41206 | + print_buttons(dialog, height, width, button); | |
41207 | + wrefresh (dialog); | |
41208 | + break; | |
41209 | + case ' ': | |
41210 | + case '\n': | |
41211 | + delwin (dialog); | |
41212 | + return button; | |
41213 | + case ESC: | |
41214 | + break; | |
41215 | + } | |
41216 | + } | |
41217 | + | |
41218 | + delwin (dialog); | |
41219 | + return -1; /* ESC pressed */ | |
41220 | +} | |
41221 | diff -Nur busybox-1.00/scripts/config/mconf.c busybox/scripts/config/mconf.c | |
41222 | --- busybox-1.00/scripts/config/mconf.c 2004-10-08 09:58:30.000000000 +0200 | |
41223 | +++ busybox/scripts/config/mconf.c 2005-06-04 08:20:03.000000000 +0200 | |
41224 | @@ -23,18 +23,150 @@ | |
41225 | #include <termios.h> | |
41226 | #include <unistd.h> | |
41227 | ||
41228 | -#include "dialog.h" | |
41229 | +#include "lxdialog/dialog.h" | |
41230 | ||
41231 | #define LKC_DIRECT_LINK | |
41232 | #include "lkc.h" | |
41233 | ||
41234 | static char menu_backtitle[128]; | |
41235 | -static const char menu_instructions[] = | |
41236 | +static const char mconf_readme[] = | |
41237 | +"Overview\n" | |
41238 | +"--------\n" | |
41239 | +"Some features may be built directly into BusyBox. Some features\n" | |
41240 | +"may be completely removed altogether. There are also certain\n" | |
41241 | +"parameters which are not really features, but must be\n" | |
41242 | +"entered in as decimal or hexadecimal numbers or possibly text.\n" | |
41243 | +"\n" | |
41244 | +"Menu items beginning with [*] or [ ] represent features\n" | |
41245 | +"configured to be built in or removed respectively.\n" | |
41246 | +"\n" | |
41247 | +"To change any of these features, highlight it with the cursor\n" | |
41248 | +"keys and press <Y> to build it in or <N> to removed it.\n" | |
41249 | +"You may also press the <Space Bar> to cycle\n" | |
41250 | +"through the available options (ie. Y->N->Y).\n" | |
41251 | +"\n" | |
41252 | +"Some additional keyboard hints:\n" | |
41253 | +"\n" | |
41254 | +"Menus\n" | |
41255 | +"----------\n" | |
41256 | +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" | |
41257 | +" you wish to change or submenu wish to select and press <Enter>.\n" | |
41258 | +" Submenus are designated by \"--->\".\n" | |
41259 | +"\n" | |
41260 | +" Shortcut: Press the option's highlighted letter (hotkey).\n" | |
41261 | +" Pressing a hotkey more than once will sequence\n" | |
41262 | +" through all visible items which use that hotkey.\n" | |
41263 | +"\n" | |
41264 | +" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n" | |
41265 | +" unseen options into view.\n" | |
41266 | +"\n" | |
41267 | +"o To exit a menu use the cursor keys to highlight the <Exit> button\n" | |
41268 | +" and press <ENTER>.\n" | |
41269 | +"\n" | |
41270 | +" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n" | |
41271 | +" using those letters. You may press a single <ESC>, but\n" | |
41272 | +" there is a delayed response which you may find annoying.\n" | |
41273 | +"\n" | |
41274 | +" Also, the <TAB> and cursor keys will cycle between <Select>,\n" | |
41275 | +" <Exit> and <Help>\n" | |
41276 | +"\n" | |
41277 | +"o To get help with an item, use the cursor keys to highlight <Help>\n" | |
41278 | +" and Press <ENTER>.\n" | |
41279 | +"\n" | |
41280 | +" Shortcut: Press <H> or <?>.\n" | |
41281 | +"\n" | |
41282 | +"\n" | |
41283 | +"Radiolists (Choice lists)\n" | |
41284 | +"-----------\n" | |
41285 | +"o Use the cursor keys to select the option you wish to set and press\n" | |
41286 | +" <S> or the <SPACE BAR>.\n" | |
41287 | +"\n" | |
41288 | +" Shortcut: Press the first letter of the option you wish to set then\n" | |
41289 | +" press <S> or <SPACE BAR>.\n" | |
41290 | +"\n" | |
41291 | +"o To see available help for the item, use the cursor keys to highlight\n" | |
41292 | +" <Help> and Press <ENTER>.\n" | |
41293 | +"\n" | |
41294 | +" Shortcut: Press <H> or <?>.\n" | |
41295 | +"\n" | |
41296 | +" Also, the <TAB> and cursor keys will cycle between <Select> and\n" | |
41297 | +" <Help>\n" | |
41298 | +"\n" | |
41299 | +"\n" | |
41300 | +"Data Entry\n" | |
41301 | +"-----------\n" | |
41302 | +"o Enter the requested information and press <ENTER>\n" | |
41303 | +" If you are entering hexadecimal values, it is not necessary to\n" | |
41304 | +" add the '0x' prefix to the entry.\n" | |
41305 | +"\n" | |
41306 | +"o For help, use the <TAB> or cursor keys to highlight the help option\n" | |
41307 | +" and press <ENTER>. You can try <TAB><H> as well.\n" | |
41308 | +"\n" | |
41309 | +"\n" | |
41310 | +"Text Box (Help Window)\n" | |
41311 | +"--------\n" | |
41312 | +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" | |
41313 | +" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n" | |
41314 | +" who are familiar with less and lynx.\n" | |
41315 | +"\n" | |
41316 | +"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n" | |
41317 | +"\n" | |
41318 | +"\n" | |
41319 | +"Alternate Configuration Files\n" | |
41320 | +"-----------------------------\n" | |
41321 | +"Menuconfig supports the use of alternate configuration files for\n" | |
41322 | +"those who, for various reasons, find it necessary to switch\n" | |
41323 | +"between different configurations.\n" | |
41324 | +"\n" | |
41325 | +"At the end of the main menu you will find two options. One is\n" | |
41326 | +"for saving the current configuration to a file of your choosing.\n" | |
41327 | +"The other option is for loading a previously saved alternate\n" | |
41328 | +"configuration.\n" | |
41329 | +"\n" | |
41330 | +"Even if you don't use alternate configuration files, but you\n" | |
41331 | +"find during a Menuconfig session that you have completely messed\n" | |
41332 | +"up your settings, you may use the \"Load Alternate...\" option to\n" | |
41333 | +"restore your previously saved settings from \".config\" without\n" | |
41334 | +"restarting Menuconfig.\n" | |
41335 | +"\n" | |
41336 | +"Other information\n" | |
41337 | +"-----------------\n" | |
41338 | +"If you use Menuconfig in an XTERM window make sure you have your\n" | |
41339 | +"$TERM variable set to point to a xterm definition which supports color.\n" | |
41340 | +"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" | |
41341 | +"display correctly in a RXVT window because rxvt displays only one\n" | |
41342 | +"intensity of color, bright.\n" | |
41343 | +"\n" | |
41344 | +"Menuconfig will display larger menus on screens or xterms which are\n" | |
41345 | +"set to display more than the standard 25 row by 80 column geometry.\n" | |
41346 | +"In order for this to work, the \"stty size\" command must be able to\n" | |
41347 | +"display the screen's current row and column geometry. I STRONGLY\n" | |
41348 | +"RECOMMEND that you make sure you do NOT have the shell variables\n" | |
41349 | +"LINES and COLUMNS exported into your environment. Some distributions\n" | |
41350 | +"export those variables via /etc/profile. Some ncurses programs can\n" | |
41351 | +"become confused when those variables (LINES & COLUMNS) don't reflect\n" | |
41352 | +"the true screen size.\n" | |
41353 | +"\n" | |
41354 | +"Optional personality available\n" | |
41355 | +"------------------------------\n" | |
41356 | +"If you prefer to have all of the options listed in a single\n" | |
41357 | +"menu, rather than the default multimenu hierarchy, run the menuconfig\n" | |
41358 | +"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n" | |
41359 | +"\n" | |
41360 | +"make MENUCONFIG_MODE=single_menu menuconfig\n" | |
41361 | +"\n" | |
41362 | +"<Enter> will then unroll the appropriate category, or enfold it if it\n" | |
41363 | +"is already unrolled.\n" | |
41364 | +"\n" | |
41365 | +"Note that this mode can eventually be a little more CPU expensive\n" | |
41366 | +"(especially with a larger number of unrolled categories) than the\n" | |
41367 | +"default mode.\n", | |
41368 | +menu_instructions[] = | |
41369 | "Arrow keys navigate the menu. " | |
41370 | "<Enter> selects submenus --->. " | |
41371 | "Highlighted letters are hotkeys. " | |
41372 | "Pressing <Y> selectes a feature, while <N> will exclude a feature. " | |
41373 | - "Press <Esc><Esc> to exit, <?> for Help. " | |
41374 | + "Press <Esc><Esc> to exit, <?> for Help, </> for Search. " | |
41375 | "Legend: [*] feature is selected [ ] feature is excluded", | |
41376 | radiolist_instructions[] = | |
41377 | "Use the arrow keys to navigate this window or " | |
41378 | @@ -85,23 +217,50 @@ | |
41379 | "\n" | |
41380 | "If you are uncertain what all this means then you should probably\n" | |
41381 | "leave this blank.\n", | |
41382 | -top_menu_help[] = | |
41383 | +search_help[] = | |
41384 | "\n" | |
41385 | - "Use the Up/Down arrow keys (cursor keys) to highlight the item\n" | |
41386 | - "you wish to change or submenu wish to select and press <Enter>.\n" | |
41387 | - "Submenus are designated by \"--->\".\n" | |
41388 | + "Search for CONFIG_ symbols and display their relations.\n" | |
41389 | + "Example: search for \"^FOO\"\n" | |
41390 | + "Result:\n" | |
41391 | + "-----------------------------------------------------------------\n" | |
41392 | + "Symbol: FOO [=m]\n" | |
41393 | + "Prompt: Foo bus is used to drive the bar HW\n" | |
41394 | + "Defined at drivers/pci/Kconfig:47\n" | |
41395 | + "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" | |
41396 | + "Location:\n" | |
41397 | + " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" | |
41398 | + " -> PCI support (PCI [=y])\n" | |
41399 | + " -> PCI access mode (<choice> [=y])\n" | |
41400 | + "Selects: LIBCRC32\n" | |
41401 | + "Selected by: BAR\n" | |
41402 | + "-----------------------------------------------------------------\n" | |
41403 | + "o The line 'Prompt:' shows the text used in the menu structure for\n" | |
41404 | + " this CONFIG_ symbol\n" | |
41405 | + "o The 'Defined at' line tell at what file / line number the symbol\n" | |
41406 | + " is defined\n" | |
41407 | + "o The 'Depends on:' line tell what symbols needs to be defined for\n" | |
41408 | + " this symbol to be visible in the menu (selectable)\n" | |
41409 | + "o The 'Location:' lines tell where in the menu structure this symbol\n" | |
41410 | + " is located\n" | |
41411 | + " A location followed by a [=y] indicate that this is a selectable\n" | |
41412 | + " menu item - and current value is displayed inside brackets.\n" | |
41413 | + "o The 'Selects:' line tell what symbol will be automatically\n" | |
41414 | + " selected if this symbol is selected (y or m)\n" | |
41415 | + "o The 'Selected by' line tell what symbol has selected this symbol\n" | |
41416 | "\n" | |
41417 | - "Shortcut: Press the option's highlighted letter (hotkey).\n" | |
41418 | - "\n" | |
41419 | - "You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n" | |
41420 | - "unseen options into view.\n" | |
41421 | -; | |
41422 | + "Only relevant lines are shown.\n" | |
41423 | + "\n\n" | |
41424 | + "Search examples:\n" | |
41425 | + "Examples: USB => find all CONFIG_ symbols containing USB\n" | |
41426 | + " ^USB => find all CONFIG_ symbols starting with USB\n" | |
41427 | + " USB$ => find all CONFIG_ symbols ending with USB\n" | |
41428 | + "\n"; | |
41429 | ||
41430 | static char filename[PATH_MAX+1] = ".config"; | |
41431 | -static int indent = 0; | |
41432 | +static int indent; | |
41433 | static struct termios ios_org; | |
41434 | -static int rows, cols; | |
41435 | -struct menu *current_menu; | |
41436 | +static int rows = 0, cols = 0; | |
41437 | +static struct menu *current_menu; | |
41438 | static int child_count; | |
41439 | static int single_menu_mode; | |
41440 | ||
41441 | @@ -116,33 +275,31 @@ | |
41442 | static void show_textbox(const char *title, const char *text, int r, int c); | |
41443 | static void show_helptext(const char *title, const char *text); | |
41444 | static void show_help(struct menu *menu); | |
41445 | -static void show_readme(void); | |
41446 | +static void show_file(const char *filename, const char *title, int r, int c); | |
41447 | ||
41448 | static void init_wsize(void) | |
41449 | { | |
41450 | struct winsize ws; | |
41451 | char *env; | |
41452 | ||
41453 | - if (ioctl(1, TIOCGWINSZ, &ws) == -1) { | |
41454 | - rows = 24; | |
41455 | - cols = 80; | |
41456 | - } else { | |
41457 | + if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) { | |
41458 | rows = ws.ws_row; | |
41459 | cols = ws.ws_col; | |
41460 | - if (!rows) { | |
41461 | - env = getenv("LINES"); | |
41462 | - if (env) | |
41463 | - rows = atoi(env); | |
41464 | - if (!rows) | |
41465 | - rows = 24; | |
41466 | - } | |
41467 | - if (!cols) { | |
41468 | - env = getenv("COLUMNS"); | |
41469 | - if (env) | |
41470 | - cols = atoi(env); | |
41471 | - if (!cols) | |
41472 | - cols = 80; | |
41473 | - } | |
41474 | + } | |
41475 | + | |
41476 | + if (!rows) { | |
41477 | + env = getenv("LINES"); | |
41478 | + if (env) | |
41479 | + rows = atoi(env); | |
41480 | + if (!rows) | |
41481 | + rows = 24; | |
41482 | + } | |
41483 | + if (!cols) { | |
41484 | + env = getenv("COLUMNS"); | |
41485 | + if (env) | |
41486 | + cols = atoi(env); | |
41487 | + if (!cols) | |
41488 | + cols = 80; | |
41489 | } | |
41490 | ||
41491 | if (rows < 19 || cols < 80) { | |
41492 | @@ -214,6 +371,103 @@ | |
41493 | item_no = 0; | |
41494 | } | |
41495 | ||
41496 | +static void get_prompt_str(struct gstr *r, struct property *prop) | |
41497 | +{ | |
41498 | + int i, j; | |
41499 | + struct menu *submenu[8], *menu; | |
41500 | + | |
41501 | + str_printf(r, "Prompt: %s\n", prop->text); | |
41502 | + str_printf(r, " Defined at %s:%d\n", prop->menu->file->name, | |
41503 | + prop->menu->lineno); | |
41504 | + if (!expr_is_yes(prop->visible.expr)) { | |
41505 | + str_append(r, " Depends on: "); | |
41506 | + expr_gstr_print(prop->visible.expr, r); | |
41507 | + str_append(r, "\n"); | |
41508 | + } | |
41509 | + menu = prop->menu->parent; | |
41510 | + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) | |
41511 | + submenu[i++] = menu; | |
41512 | + if (i > 0) { | |
41513 | + str_printf(r, " Location:\n"); | |
41514 | + for (j = 4; --i >= 0; j += 2) { | |
41515 | + menu = submenu[i]; | |
41516 | + str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu)); | |
41517 | + if (menu->sym) { | |
41518 | + str_printf(r, " (%s [=%s])", menu->sym->name ? | |
41519 | + menu->sym->name : "<choice>", | |
41520 | + sym_get_string_value(menu->sym)); | |
41521 | + } | |
41522 | + str_append(r, "\n"); | |
41523 | + } | |
41524 | + } | |
41525 | +} | |
41526 | + | |
41527 | +static void get_symbol_str(struct gstr *r, struct symbol *sym) | |
41528 | +{ | |
41529 | + bool hit; | |
41530 | + struct property *prop; | |
41531 | + | |
41532 | + str_printf(r, "Symbol: %s [=%s]\n", sym->name, | |
41533 | + sym_get_string_value(sym)); | |
41534 | + for_all_prompts(sym, prop) | |
41535 | + get_prompt_str(r, prop); | |
41536 | + hit = false; | |
41537 | + for_all_properties(sym, prop, P_SELECT) { | |
41538 | + if (!hit) { | |
41539 | + str_append(r, " Selects: "); | |
41540 | + hit = true; | |
41541 | + } else | |
41542 | + str_printf(r, " && "); | |
41543 | + expr_gstr_print(prop->expr, r); | |
41544 | + } | |
41545 | + if (hit) | |
41546 | + str_append(r, "\n"); | |
41547 | + if (sym->rev_dep.expr) { | |
41548 | + str_append(r, " Selected by: "); | |
41549 | + expr_gstr_print(sym->rev_dep.expr, r); | |
41550 | + str_append(r, "\n"); | |
41551 | + } | |
41552 | + str_append(r, "\n\n"); | |
41553 | +} | |
41554 | + | |
41555 | +static struct gstr get_relations_str(struct symbol **sym_arr) | |
41556 | +{ | |
41557 | + struct symbol *sym; | |
41558 | + struct gstr res = str_new(); | |
41559 | + int i; | |
41560 | + | |
41561 | + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) | |
41562 | + get_symbol_str(&res, sym); | |
41563 | + if (!i) | |
41564 | + str_append(&res, "No matches found.\n"); | |
41565 | + return res; | |
41566 | +} | |
41567 | + | |
41568 | +static void search_conf(void) | |
41569 | +{ | |
41570 | + struct symbol **sym_arr; | |
41571 | + struct gstr res; | |
41572 | + | |
41573 | +again: | |
41574 | + switch (dialog_inputbox("Search Configuration Parameter", | |
41575 | + "Enter Keyword", 10, 75, | |
41576 | + NULL)) { | |
41577 | + case 0: | |
41578 | + break; | |
41579 | + case 1: | |
41580 | + show_helptext("Search Configuration", search_help); | |
41581 | + goto again; | |
41582 | + default: | |
41583 | + return; | |
41584 | + } | |
41585 | + | |
41586 | + sym_arr = sym_re_search(dialog_input_result); | |
41587 | + res = get_relations_str(sym_arr); | |
41588 | + free(sym_arr); | |
41589 | + show_textbox("Search Results", str_get(&res), 0, 0); | |
41590 | + str_free(&res); | |
41591 | +} | |
41592 | + | |
41593 | static void build_conf(struct menu *menu) | |
41594 | { | |
41595 | struct symbol *sym; | |
41596 | @@ -308,6 +562,11 @@ | |
41597 | return; | |
41598 | } | |
41599 | } else { | |
41600 | + if (menu == current_menu) { | |
41601 | + cprint_tag(":%p", menu); | |
41602 | + cprint_name("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); | |
41603 | + goto conf_childs; | |
41604 | + } | |
41605 | child_count++; | |
41606 | val = sym_get_tristate_value(sym); | |
41607 | if (sym_is_choice_value(sym) && val == yes) { | |
41608 | @@ -376,7 +635,7 @@ | |
41609 | while (1) { | |
41610 | indent = 0; | |
41611 | child_count = 0; | |
41612 | - current_menu = menu; | |
41613 | + current_menu = menu; | |
41614 | cdone(); cinit(); | |
41615 | build_conf(menu); | |
41616 | if (!child_count) | |
41617 | @@ -441,7 +700,7 @@ | |
41618 | if (sym) | |
41619 | show_help(submenu); | |
41620 | else | |
41621 | - show_readme(); | |
41622 | + show_helptext("README", mconf_readme); | |
41623 | break; | |
41624 | case 3: | |
41625 | if (type == 't') { | |
41626 | @@ -465,6 +724,9 @@ | |
41627 | else if (type == 'm') | |
41628 | conf(submenu); | |
41629 | break; | |
41630 | + case 7: | |
41631 | + search_conf(); | |
41632 | + break; | |
41633 | } | |
41634 | } | |
41635 | } | |
41636 | @@ -476,37 +738,39 @@ | |
41637 | fd = creat(".help.tmp", 0777); | |
41638 | write(fd, text, strlen(text)); | |
41639 | close(fd); | |
41640 | - while (dialog_textbox(title, ".help.tmp", r, c) < 0) | |
41641 | - ; | |
41642 | + show_file(".help.tmp", title, r, c); | |
41643 | unlink(".help.tmp"); | |
41644 | } | |
41645 | ||
41646 | static void show_helptext(const char *title, const char *text) | |
41647 | { | |
41648 | - show_textbox(title, text, rows, cols); | |
41649 | + show_textbox(title, text, 0, 0); | |
41650 | } | |
41651 | ||
41652 | static void show_help(struct menu *menu) | |
41653 | { | |
41654 | - const char *help; | |
41655 | - char *helptext; | |
41656 | + struct gstr help = str_new(); | |
41657 | struct symbol *sym = menu->sym; | |
41658 | ||
41659 | - help = sym->help; | |
41660 | - if (!help) | |
41661 | - help = nohelp_text; | |
41662 | - if (sym->name) { | |
41663 | - helptext = malloc(strlen(sym->name) + strlen(help) + 16); | |
41664 | - sprintf(helptext, "%s:\n\n%s", sym->name, help); | |
41665 | - show_helptext(menu_get_prompt(menu), helptext); | |
41666 | - free(helptext); | |
41667 | - } else | |
41668 | - show_helptext(menu_get_prompt(menu), help); | |
41669 | + if (sym->help) | |
41670 | + { | |
41671 | + if (sym->name) { | |
41672 | + str_printf(&help, "%s:\n\n", sym->name); | |
41673 | + str_append(&help, sym->help); | |
41674 | + str_append(&help, "\n"); | |
41675 | + } | |
41676 | + } else { | |
41677 | + str_append(&help, nohelp_text); | |
41678 | + } | |
41679 | + get_symbol_str(&help, sym); | |
41680 | + show_helptext(menu_get_prompt(menu), str_get(&help)); | |
41681 | + str_free(&help); | |
41682 | } | |
41683 | ||
41684 | -static void show_readme(void) | |
41685 | +static void show_file(const char *filename, const char *title, int r, int c) | |
41686 | { | |
41687 | - show_helptext("Help", top_menu_help); | |
41688 | + while (dialog_textbox(title, filename, r ? r : rows, c ? c : cols) < 0) | |
41689 | + ; | |
41690 | } | |
41691 | ||
41692 | static void conf_choice(struct menu *menu) | |
41693 | @@ -667,9 +931,9 @@ | |
41694 | ||
41695 | int main(int ac, char **av) | |
41696 | { | |
41697 | - int stat; | |
41698 | - char *mode; | |
41699 | struct symbol *sym; | |
41700 | + char *mode; | |
41701 | + int stat; | |
41702 | ||
41703 | conf_parse(av[1]); | |
41704 | conf_read(NULL); | |
41705 | @@ -697,7 +961,7 @@ | |
41706 | init_dialog(); | |
41707 | do { | |
41708 | stat = dialog_yesno(NULL, | |
41709 | - "Do you wish to save your new BusyBox configuration?", 5, 60); | |
41710 | + "Do you wish to save your new BusyBox configuration?", 5, 60); | |
41711 | } while (stat < 0); | |
41712 | end_dialog(); | |
41713 | ||
41714 | diff -Nur busybox-1.00/scripts/config/menu.c busybox/scripts/config/menu.c | |
41715 | --- busybox-1.00/scripts/config/menu.c 2004-07-15 08:01:05.000000000 +0200 | |
41716 | +++ busybox/scripts/config/menu.c 2005-06-04 08:20:03.000000000 +0200 | |
41717 | @@ -10,7 +10,6 @@ | |
41718 | #include "lkc.h" | |
41719 | ||
41720 | struct menu rootmenu; | |
41721 | -struct menu *current_menu, *current_entry; | |
41722 | static struct menu **last_entry_ptr; | |
41723 | ||
41724 | struct file *file_list; | |
41725 | @@ -389,43 +388,3 @@ | |
41726 | return menu; | |
41727 | } | |
41728 | ||
41729 | -struct file *file_lookup(const char *name) | |
41730 | -{ | |
41731 | - struct file *file; | |
41732 | - | |
41733 | - for (file = file_list; file; file = file->next) { | |
41734 | - if (!strcmp(name, file->name)) | |
41735 | - return file; | |
41736 | - } | |
41737 | - | |
41738 | - file = malloc(sizeof(*file)); | |
41739 | - memset(file, 0, sizeof(*file)); | |
41740 | - file->name = strdup(name); | |
41741 | - file->next = file_list; | |
41742 | - file_list = file; | |
41743 | - return file; | |
41744 | -} | |
41745 | - | |
41746 | -int file_write_dep(const char *name) | |
41747 | -{ | |
41748 | - struct file *file; | |
41749 | - FILE *out; | |
41750 | - | |
41751 | - if (!name) | |
41752 | - name = ".config.cmd"; | |
41753 | - out = fopen(".config.tmp", "w"); | |
41754 | - if (!out) | |
41755 | - return 1; | |
41756 | - fprintf(out, "deps_config := \\\n"); | |
41757 | - for (file = file_list; file; file = file->next) { | |
41758 | - if (file->next) | |
41759 | - fprintf(out, "\t%s \\\n", file->name); | |
41760 | - else | |
41761 | - fprintf(out, "\t%s\n", file->name); | |
41762 | - } | |
41763 | - fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n"); | |
41764 | - fclose(out); | |
41765 | - rename(".config.tmp", name); | |
41766 | - return 0; | |
41767 | -} | |
41768 | - | |
41769 | diff -Nur busybox-1.00/scripts/config/menubox.c busybox/scripts/config/menubox.c | |
41770 | --- busybox-1.00/scripts/config/menubox.c 2004-03-15 09:29:08.000000000 +0100 | |
41771 | +++ busybox/scripts/config/menubox.c 1970-01-01 01:00:00.000000000 +0100 | |
41772 | @@ -1,436 +0,0 @@ | |
41773 | -/* | |
41774 | - * menubox.c -- implements the menu box | |
41775 | - * | |
41776 | - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
41777 | - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) | |
41778 | - * | |
41779 | - * This program is free software; you can redistribute it and/or | |
41780 | - * modify it under the terms of the GNU General Public License | |
41781 | - * as published by the Free Software Foundation; either version 2 | |
41782 | - * of the License, or (at your option) any later version. | |
41783 | - * | |
41784 | - * This program is distributed in the hope that it will be useful, | |
41785 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
41786 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
41787 | - * GNU General Public License for more details. | |
41788 | - * | |
41789 | - * You should have received a copy of the GNU General Public License | |
41790 | - * along with this program; if not, write to the Free Software | |
41791 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
41792 | - */ | |
41793 | - | |
41794 | -/* | |
41795 | - * Changes by Clifford Wolf (god@clifford.at) | |
41796 | - * | |
41797 | - * [ 1998-06-13 ] | |
41798 | - * | |
41799 | - * *) A bugfix for the Page-Down problem | |
41800 | - * | |
41801 | - * *) Formerly when I used Page Down and Page Up, the cursor would be set | |
41802 | - * to the first position in the menu box. Now lxdialog is a bit | |
41803 | - * smarter and works more like other menu systems (just have a look at | |
41804 | - * it). | |
41805 | - * | |
41806 | - * *) Formerly if I selected something my scrolling would be broken because | |
41807 | - * lxdialog is re-invoked by the Menuconfig shell script, can't | |
41808 | - * remember the last scrolling position, and just sets it so that the | |
41809 | - * cursor is at the bottom of the box. Now it writes the temporary file | |
41810 | - * lxdialog.scrltmp which contains this information. The file is | |
41811 | - * deleted by lxdialog if the user leaves a submenu or enters a new | |
41812 | - * one, but it would be nice if Menuconfig could make another "rm -f" | |
41813 | - * just to be sure. Just try it out - you will recognise a difference! | |
41814 | - * | |
41815 | - * [ 1998-06-14 ] | |
41816 | - * | |
41817 | - * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files | |
41818 | - * and menus change their size on the fly. | |
41819 | - * | |
41820 | - * *) If for some reason the last scrolling position is not saved by | |
41821 | - * lxdialog, it sets the scrolling so that the selected item is in the | |
41822 | - * middle of the menu box, not at the bottom. | |
41823 | - * | |
41824 | - * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) | |
41825 | - * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. | |
41826 | - * This fixes a bug in Menuconfig where using ' ' to descend into menus | |
41827 | - * would leave mis-synchronized lxdialog.scrltmp files lying around, | |
41828 | - * fscanf would read in 'scroll', and eventually that value would get used. | |
41829 | - */ | |
41830 | - | |
41831 | -#include "dialog.h" | |
41832 | - | |
41833 | -static int menu_width, item_x; | |
41834 | - | |
41835 | -/* | |
41836 | - * Print menu item | |
41837 | - */ | |
41838 | -static void | |
41839 | -print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey) | |
41840 | -{ | |
41841 | - int j; | |
41842 | - char menu_item[menu_width+1]; | |
41843 | - | |
41844 | - strncpy(menu_item, item, menu_width); | |
41845 | - menu_item[menu_width] = 0; | |
41846 | - j = first_alpha(menu_item, "YyNnMm"); | |
41847 | - | |
41848 | - /* Clear 'residue' of last item */ | |
41849 | - wattrset (win, menubox_attr); | |
41850 | - wmove (win, choice, 0); | |
41851 | -#if OLD_NCURSES | |
41852 | - { | |
41853 | - int i; | |
41854 | - for (i = 0; i < menu_width; i++) | |
41855 | - waddch (win, ' '); | |
41856 | - } | |
41857 | -#else | |
41858 | - wclrtoeol(win); | |
41859 | -#endif | |
41860 | - wattrset (win, selected ? item_selected_attr : item_attr); | |
41861 | - mvwaddstr (win, choice, item_x, menu_item); | |
41862 | - if (hotkey) { | |
41863 | - wattrset (win, selected ? tag_key_selected_attr : tag_key_attr); | |
41864 | - mvwaddch(win, choice, item_x+j, menu_item[j]); | |
41865 | - } | |
41866 | - if (selected) { | |
41867 | - wmove (win, choice, item_x+1); | |
41868 | - wrefresh (win); | |
41869 | - } | |
41870 | -} | |
41871 | - | |
41872 | -/* | |
41873 | - * Print the scroll indicators. | |
41874 | - */ | |
41875 | -static void | |
41876 | -print_arrows (WINDOW * win, int item_no, int scroll, | |
41877 | - int y, int x, int height) | |
41878 | -{ | |
41879 | - int cur_y, cur_x; | |
41880 | - | |
41881 | - getyx(win, cur_y, cur_x); | |
41882 | - | |
41883 | - wmove(win, y, x); | |
41884 | - | |
41885 | - if (scroll > 0) { | |
41886 | - wattrset (win, uarrow_attr); | |
41887 | - waddch (win, ACS_UARROW); | |
41888 | - waddstr (win, "(-)"); | |
41889 | - } | |
41890 | - else { | |
41891 | - wattrset (win, menubox_attr); | |
41892 | - waddch (win, ACS_HLINE); | |
41893 | - waddch (win, ACS_HLINE); | |
41894 | - waddch (win, ACS_HLINE); | |
41895 | - waddch (win, ACS_HLINE); | |
41896 | - } | |
41897 | - | |
41898 | - y = y + height + 1; | |
41899 | - wmove(win, y, x); | |
41900 | - | |
41901 | - if ((height < item_no) && (scroll + height < item_no)) { | |
41902 | - wattrset (win, darrow_attr); | |
41903 | - waddch (win, ACS_DARROW); | |
41904 | - waddstr (win, "(+)"); | |
41905 | - } | |
41906 | - else { | |
41907 | - wattrset (win, menubox_border_attr); | |
41908 | - waddch (win, ACS_HLINE); | |
41909 | - waddch (win, ACS_HLINE); | |
41910 | - waddch (win, ACS_HLINE); | |
41911 | - waddch (win, ACS_HLINE); | |
41912 | - } | |
41913 | - | |
41914 | - wmove(win, cur_y, cur_x); | |
41915 | -} | |
41916 | - | |
41917 | -/* | |
41918 | - * Display the termination buttons. | |
41919 | - */ | |
41920 | -static void | |
41921 | -print_buttons (WINDOW *win, int height, int width, int selected) | |
41922 | -{ | |
41923 | - int x = width / 2 - 16; | |
41924 | - int y = height - 2; | |
41925 | - | |
41926 | - print_button (win, "Select", y, x, selected == 0); | |
41927 | - print_button (win, " Exit ", y, x + 12, selected == 1); | |
41928 | - print_button (win, " Help ", y, x + 24, selected == 2); | |
41929 | - | |
41930 | - wmove(win, y, x+1+12*selected); | |
41931 | - wrefresh (win); | |
41932 | -} | |
41933 | - | |
41934 | -/* | |
41935 | - * Display a menu for choosing among a number of options | |
41936 | - */ | |
41937 | -int | |
41938 | -dialog_menu (const char *title, const char *prompt, int height, int width, | |
41939 | - int menu_height, const char *current, int item_no, | |
41940 | - struct dialog_list_item ** items) | |
41941 | -{ | |
41942 | - int i, j, x, y, box_x, box_y; | |
41943 | - int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice; | |
41944 | - WINDOW *dialog, *menu; | |
41945 | - FILE *f; | |
41946 | - | |
41947 | - max_choice = MIN (menu_height, item_no); | |
41948 | - | |
41949 | - /* center dialog box on screen */ | |
41950 | - x = (COLS - width) / 2; | |
41951 | - y = (LINES - height) / 2; | |
41952 | - | |
41953 | - draw_shadow (stdscr, y, x, height, width); | |
41954 | - | |
41955 | - dialog = newwin (height, width, y, x); | |
41956 | - keypad (dialog, TRUE); | |
41957 | - | |
41958 | - draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
41959 | - wattrset (dialog, border_attr); | |
41960 | - mvwaddch (dialog, height - 3, 0, ACS_LTEE); | |
41961 | - for (i = 0; i < width - 2; i++) | |
41962 | - waddch (dialog, ACS_HLINE); | |
41963 | - wattrset (dialog, dialog_attr); | |
41964 | - wbkgdset (dialog, dialog_attr & A_COLOR); | |
41965 | - waddch (dialog, ACS_RTEE); | |
41966 | - | |
41967 | - if (title != NULL && strlen(title) >= width-2 ) { | |
41968 | - /* truncate long title -- mec */ | |
41969 | - char * title2 = malloc(width-2+1); | |
41970 | - memcpy( title2, title, width-2 ); | |
41971 | - title2[width-2] = '\0'; | |
41972 | - title = title2; | |
41973 | - } | |
41974 | - | |
41975 | - if (title != NULL) { | |
41976 | - wattrset (dialog, title_attr); | |
41977 | - mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
41978 | - waddstr (dialog, (char *)title); | |
41979 | - waddch (dialog, ' '); | |
41980 | - } | |
41981 | - | |
41982 | - wattrset (dialog, dialog_attr); | |
41983 | - print_autowrap (dialog, prompt, width - 2, 1, 3); | |
41984 | - | |
41985 | - menu_width = width - 6; | |
41986 | - box_y = height - menu_height - 5; | |
41987 | - box_x = (width - menu_width) / 2 - 1; | |
41988 | - | |
41989 | - /* create new window for the menu */ | |
41990 | - menu = subwin (dialog, menu_height, menu_width, | |
41991 | - y + box_y + 1, x + box_x + 1); | |
41992 | - keypad (menu, TRUE); | |
41993 | - | |
41994 | - /* draw a box around the menu items */ | |
41995 | - draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2, | |
41996 | - menubox_border_attr, menubox_attr); | |
41997 | - | |
41998 | - /* | |
41999 | - * Find length of longest item in order to center menu. | |
42000 | - * Set 'choice' to default item. | |
42001 | - */ | |
42002 | - item_x = 0; | |
42003 | - for (i = 0; i < item_no; i++) { | |
42004 | - item_x = MAX (item_x, MIN(menu_width, strlen (items[i]->name) + 2)); | |
42005 | - if (strcmp(current, items[i]->tag) == 0) choice = i; | |
42006 | - } | |
42007 | - | |
42008 | - item_x = (menu_width - item_x) / 2; | |
42009 | - | |
42010 | - /* get the scroll info from the temp file */ | |
42011 | - if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) { | |
42012 | - if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) && | |
42013 | - (scroll+max_choice > choice) && (scroll >= 0) && | |
42014 | - (scroll+max_choice <= item_no) ) { | |
42015 | - first_item = scroll; | |
42016 | - choice = choice - scroll; | |
42017 | - fclose(f); | |
42018 | - } else { | |
42019 | - scroll=0; | |
42020 | - remove("lxdialog.scrltmp"); | |
42021 | - fclose(f); | |
42022 | - f=NULL; | |
42023 | - } | |
42024 | - } | |
42025 | - if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) { | |
42026 | - if (choice >= item_no-max_choice/2) | |
42027 | - scroll = first_item = item_no-max_choice; | |
42028 | - else | |
42029 | - scroll = first_item = choice - max_choice/2; | |
42030 | - choice = choice - scroll; | |
42031 | - } | |
42032 | - | |
42033 | - /* Print the menu */ | |
42034 | - for (i=0; i < max_choice; i++) { | |
42035 | - print_item (menu, items[first_item + i]->name, i, i == choice, | |
42036 | - (items[first_item + i]->tag[0] != ':')); | |
42037 | - } | |
42038 | - | |
42039 | - wnoutrefresh (menu); | |
42040 | - | |
42041 | - print_arrows(dialog, item_no, scroll, | |
42042 | - box_y, box_x+item_x+1, menu_height); | |
42043 | - | |
42044 | - print_buttons (dialog, height, width, 0); | |
42045 | - wmove (menu, choice, item_x+1); | |
42046 | - wrefresh (menu); | |
42047 | - | |
42048 | - while (key != ESC) { | |
42049 | - key = wgetch(menu); | |
42050 | - | |
42051 | - if (key < 256 && isalpha(key)) key = tolower(key); | |
42052 | - | |
42053 | - if (strchr("ynm", key)) | |
42054 | - i = max_choice; | |
42055 | - else { | |
42056 | - for (i = choice+1; i < max_choice; i++) { | |
42057 | - j = first_alpha(items[scroll + i]->name, "YyNnMm>"); | |
42058 | - if (key == tolower(items[scroll + i]->name[j])) | |
42059 | - break; | |
42060 | - } | |
42061 | - if (i == max_choice) | |
42062 | - for (i = 0; i < max_choice; i++) { | |
42063 | - j = first_alpha(items[scroll + i]->name, "YyNnMm>"); | |
42064 | - if (key == tolower(items[scroll + i]->name[j])) | |
42065 | - break; | |
42066 | - } | |
42067 | - } | |
42068 | - | |
42069 | - if (i < max_choice || | |
42070 | - key == KEY_UP || key == KEY_DOWN || | |
42071 | - key == '-' || key == '+' || | |
42072 | - key == KEY_PPAGE || key == KEY_NPAGE) { | |
42073 | - | |
42074 | - print_item (menu, items[scroll + choice]->name, choice, FALSE, | |
42075 | - (items[scroll + choice]->tag[0] != ':')); | |
42076 | - | |
42077 | - if (key == KEY_UP || key == '-') { | |
42078 | - if (choice < 2 && scroll) { | |
42079 | - /* Scroll menu down */ | |
42080 | - scrollok (menu, TRUE); | |
42081 | - wscrl (menu, -1); | |
42082 | - scrollok (menu, FALSE); | |
42083 | - | |
42084 | - scroll--; | |
42085 | - | |
42086 | - print_item (menu, items[scroll]->name, 0, FALSE, | |
42087 | - (items[scroll]->tag[0] != ':')); | |
42088 | - } else | |
42089 | - choice = MAX(choice - 1, 0); | |
42090 | - | |
42091 | - } else if (key == KEY_DOWN || key == '+') { | |
42092 | - | |
42093 | - print_item (menu, items[scroll + choice]->name, choice, FALSE, | |
42094 | - (items[scroll + choice]->tag[0] != ':')); | |
42095 | - | |
42096 | - if ((choice > max_choice-3) && | |
42097 | - (scroll + max_choice < item_no) | |
42098 | - ) { | |
42099 | - /* Scroll menu up */ | |
42100 | - scrollok (menu, TRUE); | |
42101 | - scroll (menu); | |
42102 | - scrollok (menu, FALSE); | |
42103 | - | |
42104 | - scroll++; | |
42105 | - | |
42106 | - print_item (menu, items[scroll + max_choice - 1]->name, | |
42107 | - max_choice-1, FALSE, | |
42108 | - (items[scroll + max_choice - 1]->tag[0] != ':')); | |
42109 | - } else | |
42110 | - choice = MIN(choice+1, max_choice-1); | |
42111 | - | |
42112 | - } else if (key == KEY_PPAGE) { | |
42113 | - scrollok (menu, TRUE); | |
42114 | - for (i=0; (i < max_choice); i++) { | |
42115 | - if (scroll > 0) { | |
42116 | - wscrl (menu, -1); | |
42117 | - scroll--; | |
42118 | - print_item (menu, items[scroll]->name, 0, FALSE, | |
42119 | - (items[scroll]->tag[0] != ':')); | |
42120 | - } else { | |
42121 | - if (choice > 0) | |
42122 | - choice--; | |
42123 | - } | |
42124 | - } | |
42125 | - scrollok (menu, FALSE); | |
42126 | - | |
42127 | - } else if (key == KEY_NPAGE) { | |
42128 | - for (i=0; (i < max_choice); i++) { | |
42129 | - if (scroll+max_choice < item_no) { | |
42130 | - scrollok (menu, TRUE); | |
42131 | - scroll(menu); | |
42132 | - scrollok (menu, FALSE); | |
42133 | - scroll++; | |
42134 | - print_item (menu, items[scroll + max_choice - 1]->name, | |
42135 | - max_choice-1, FALSE, | |
42136 | - (items[scroll + max_choice - 1]->tag[0] != ':')); | |
42137 | - } else { | |
42138 | - if (choice+1 < max_choice) | |
42139 | - choice++; | |
42140 | - } | |
42141 | - } | |
42142 | - | |
42143 | - } else | |
42144 | - choice = i; | |
42145 | - | |
42146 | - print_item (menu, items[scroll + choice]->name, choice, TRUE, | |
42147 | - (items[scroll + choice]->tag[0] != ':')); | |
42148 | - | |
42149 | - print_arrows(dialog, item_no, scroll, | |
42150 | - box_y, box_x+item_x+1, menu_height); | |
42151 | - | |
42152 | - wnoutrefresh (dialog); | |
42153 | - wrefresh (menu); | |
42154 | - | |
42155 | - continue; /* wait for another key press */ | |
42156 | - } | |
42157 | - | |
42158 | - switch (key) { | |
42159 | - case KEY_LEFT: | |
42160 | - case TAB: | |
42161 | - case KEY_RIGHT: | |
42162 | - button = ((key == KEY_LEFT ? --button : ++button) < 0) | |
42163 | - ? 2 : (button > 2 ? 0 : button); | |
42164 | - | |
42165 | - print_buttons(dialog, height, width, button); | |
42166 | - wrefresh (menu); | |
42167 | - break; | |
42168 | - case ' ': | |
42169 | - case 's': | |
42170 | - case 'y': | |
42171 | - case 'n': | |
42172 | - case 'm': | |
42173 | - /* save scroll info */ | |
42174 | - if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) { | |
42175 | - fprintf(f,"%d\n",scroll); | |
42176 | - fclose(f); | |
42177 | - } | |
42178 | - delwin (dialog); | |
42179 | - items[scroll + choice]->selected = 1; | |
42180 | - switch (key) { | |
42181 | - case 's': return 3; | |
42182 | - case 'y': return 3; | |
42183 | - case 'n': return 4; | |
42184 | - case 'm': return 5; | |
42185 | - case ' ': return 6; | |
42186 | - } | |
42187 | - return 0; | |
42188 | - case 'h': | |
42189 | - case '?': | |
42190 | - button = 2; | |
42191 | - case '\n': | |
42192 | - delwin (dialog); | |
42193 | - items[scroll + choice]->selected = 1; | |
42194 | - | |
42195 | - remove("lxdialog.scrltmp"); | |
42196 | - return button; | |
42197 | - case 'e': | |
42198 | - case 'x': | |
42199 | - key = ESC; | |
42200 | - case ESC: | |
42201 | - break; | |
42202 | - } | |
42203 | - } | |
42204 | - | |
42205 | - delwin (dialog); | |
42206 | - remove("lxdialog.scrltmp"); | |
42207 | - return -1; /* ESC pressed */ | |
42208 | -} | |
42209 | diff -Nur busybox-1.00/scripts/config/msgbox.c busybox/scripts/config/msgbox.c | |
42210 | --- busybox-1.00/scripts/config/msgbox.c 2002-12-05 09:41:07.000000000 +0100 | |
42211 | +++ busybox/scripts/config/msgbox.c 1970-01-01 01:00:00.000000000 +0100 | |
42212 | @@ -1,85 +0,0 @@ | |
42213 | -/* | |
42214 | - * msgbox.c -- implements the message box and info box | |
42215 | - * | |
42216 | - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
42217 | - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) | |
42218 | - * | |
42219 | - * This program is free software; you can redistribute it and/or | |
42220 | - * modify it under the terms of the GNU General Public License | |
42221 | - * as published by the Free Software Foundation; either version 2 | |
42222 | - * of the License, or (at your option) any later version. | |
42223 | - * | |
42224 | - * This program is distributed in the hope that it will be useful, | |
42225 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
42226 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
42227 | - * GNU General Public License for more details. | |
42228 | - * | |
42229 | - * You should have received a copy of the GNU General Public License | |
42230 | - * along with this program; if not, write to the Free Software | |
42231 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
42232 | - */ | |
42233 | - | |
42234 | -#include "dialog.h" | |
42235 | - | |
42236 | -/* | |
42237 | - * Display a message box. Program will pause and display an "OK" button | |
42238 | - * if the parameter 'pause' is non-zero. | |
42239 | - */ | |
42240 | -int | |
42241 | -dialog_msgbox (const char *title, const char *prompt, int height, int width, | |
42242 | - int pause) | |
42243 | -{ | |
42244 | - int i, x, y, key = 0; | |
42245 | - WINDOW *dialog; | |
42246 | - | |
42247 | - /* center dialog box on screen */ | |
42248 | - x = (COLS - width) / 2; | |
42249 | - y = (LINES - height) / 2; | |
42250 | - | |
42251 | - draw_shadow (stdscr, y, x, height, width); | |
42252 | - | |
42253 | - dialog = newwin (height, width, y, x); | |
42254 | - keypad (dialog, TRUE); | |
42255 | - | |
42256 | - draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
42257 | - | |
42258 | - if (title != NULL && strlen(title) >= width-2 ) { | |
42259 | - /* truncate long title -- mec */ | |
42260 | - char * title2 = malloc(width-2+1); | |
42261 | - memcpy( title2, title, width-2 ); | |
42262 | - title2[width-2] = '\0'; | |
42263 | - title = title2; | |
42264 | - } | |
42265 | - | |
42266 | - if (title != NULL) { | |
42267 | - wattrset (dialog, title_attr); | |
42268 | - mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
42269 | - waddstr (dialog, (char *)title); | |
42270 | - waddch (dialog, ' '); | |
42271 | - } | |
42272 | - wattrset (dialog, dialog_attr); | |
42273 | - print_autowrap (dialog, prompt, width - 2, 1, 2); | |
42274 | - | |
42275 | - if (pause) { | |
42276 | - wattrset (dialog, border_attr); | |
42277 | - mvwaddch (dialog, height - 3, 0, ACS_LTEE); | |
42278 | - for (i = 0; i < width - 2; i++) | |
42279 | - waddch (dialog, ACS_HLINE); | |
42280 | - wattrset (dialog, dialog_attr); | |
42281 | - waddch (dialog, ACS_RTEE); | |
42282 | - | |
42283 | - print_button (dialog, " Ok ", | |
42284 | - height - 2, width / 2 - 4, TRUE); | |
42285 | - | |
42286 | - wrefresh (dialog); | |
42287 | - while (key != ESC && key != '\n' && key != ' ' && | |
42288 | - key != 'O' && key != 'o' && key != 'X' && key != 'x') | |
42289 | - key = wgetch (dialog); | |
42290 | - } else { | |
42291 | - key = '\n'; | |
42292 | - wrefresh (dialog); | |
42293 | - } | |
42294 | - | |
42295 | - delwin (dialog); | |
42296 | - return key == ESC ? -1 : 0; | |
42297 | -} | |
42298 | diff -Nur busybox-1.00/scripts/config/symbol.c busybox/scripts/config/symbol.c | |
42299 | --- busybox-1.00/scripts/config/symbol.c 2004-07-15 08:01:05.000000000 +0200 | |
42300 | +++ busybox/scripts/config/symbol.c 2005-06-04 08:20:03.000000000 +0200 | |
42301 | @@ -6,6 +6,7 @@ | |
42302 | #include <ctype.h> | |
42303 | #include <stdlib.h> | |
42304 | #include <string.h> | |
42305 | +#include <regex.h> | |
42306 | #include <sys/utsname.h> | |
42307 | ||
42308 | #define LKC_DIRECT_LINK | |
42309 | @@ -414,7 +415,7 @@ | |
42310 | ||
42311 | bool sym_string_valid(struct symbol *sym, const char *str) | |
42312 | { | |
42313 | - char ch; | |
42314 | + signed char ch; | |
42315 | ||
42316 | switch (sym->type) { | |
42317 | case S_STRING: | |
42318 | @@ -649,6 +650,43 @@ | |
42319 | return symbol; | |
42320 | } | |
42321 | ||
42322 | +struct symbol **sym_re_search(const char *pattern) | |
42323 | +{ | |
42324 | + struct symbol *sym, **sym_arr = NULL; | |
42325 | + int i, cnt, size; | |
42326 | + regex_t re; | |
42327 | + | |
42328 | + cnt = size = 0; | |
42329 | + /* Skip if empty */ | |
42330 | + if (strlen(pattern) == 0) | |
42331 | + return NULL; | |
42332 | + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) | |
42333 | + return NULL; | |
42334 | + | |
42335 | + for_all_symbols(i, sym) { | |
42336 | + if (sym->flags & SYMBOL_CONST || !sym->name) | |
42337 | + continue; | |
42338 | + if (regexec(&re, sym->name, 0, NULL, 0)) | |
42339 | + continue; | |
42340 | + if (cnt + 1 >= size) { | |
42341 | + void *tmp = sym_arr; | |
42342 | + size += 16; | |
42343 | + sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); | |
42344 | + if (!sym_arr) { | |
42345 | + free(tmp); | |
42346 | + return NULL; | |
42347 | + } | |
42348 | + } | |
42349 | + sym_arr[cnt++] = sym; | |
42350 | + } | |
42351 | + if (sym_arr) | |
42352 | + sym_arr[cnt] = NULL; | |
42353 | + regfree(&re); | |
42354 | + | |
42355 | + return sym_arr; | |
42356 | +} | |
42357 | + | |
42358 | + | |
42359 | struct symbol *sym_check_deps(struct symbol *sym); | |
42360 | ||
42361 | static struct symbol *sym_check_expr_deps(struct expr *e) | |
42362 | diff -Nur busybox-1.00/scripts/config/textbox.c busybox/scripts/config/textbox.c | |
42363 | --- busybox-1.00/scripts/config/textbox.c 2004-07-15 08:01:05.000000000 +0200 | |
42364 | +++ busybox/scripts/config/textbox.c 1970-01-01 01:00:00.000000000 +0100 | |
42365 | @@ -1,556 +0,0 @@ | |
42366 | -/* | |
42367 | - * textbox.c -- implements the text box | |
42368 | - * | |
42369 | - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
42370 | - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
42371 | - * | |
42372 | - * This program is free software; you can redistribute it and/or | |
42373 | - * modify it under the terms of the GNU General Public License | |
42374 | - * as published by the Free Software Foundation; either version 2 | |
42375 | - * of the License, or (at your option) any later version. | |
42376 | - * | |
42377 | - * This program is distributed in the hope that it will be useful, | |
42378 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
42379 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
42380 | - * GNU General Public License for more details. | |
42381 | - * | |
42382 | - * You should have received a copy of the GNU General Public License | |
42383 | - * along with this program; if not, write to the Free Software | |
42384 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
42385 | - */ | |
42386 | - | |
42387 | -#include "dialog.h" | |
42388 | - | |
42389 | -static void back_lines (int n); | |
42390 | -static void print_page (WINDOW * win, int height, int width); | |
42391 | -static void print_line (WINDOW * win, int row, int width); | |
42392 | -static char *get_line (void); | |
42393 | -static void print_position (WINDOW * win, int height, int width); | |
42394 | - | |
42395 | -static int hscroll, fd, file_size, bytes_read; | |
42396 | -static int begin_reached = 1, end_reached, page_length; | |
42397 | -static char *buf, *page; | |
42398 | - | |
42399 | -/* | |
42400 | - * Display text from a file in a dialog box. | |
42401 | - */ | |
42402 | -int | |
42403 | -dialog_textbox (const char *title, const char *file, int height, int width) | |
42404 | -{ | |
42405 | - int i, x, y, cur_x, cur_y, fpos, key = 0; | |
42406 | - int passed_end; | |
42407 | - char search_term[MAX_LEN + 1]; | |
42408 | - WINDOW *dialog, *text; | |
42409 | - | |
42410 | - search_term[0] = '\0'; /* no search term entered yet */ | |
42411 | - | |
42412 | - /* Open input file for reading */ | |
42413 | - if ((fd = open (file, O_RDONLY)) == -1) { | |
42414 | - endwin (); | |
42415 | - fprintf (stderr, | |
42416 | - "\nCan't open input file in dialog_textbox().\n"); | |
42417 | - exit (-1); | |
42418 | - } | |
42419 | - /* Get file size. Actually, 'file_size' is the real file size - 1, | |
42420 | - since it's only the last byte offset from the beginning */ | |
42421 | - if ((file_size = lseek (fd, 0, SEEK_END)) == -1) { | |
42422 | - endwin (); | |
42423 | - fprintf (stderr, "\nError getting file size in dialog_textbox().\n"); | |
42424 | - exit (-1); | |
42425 | - } | |
42426 | - /* Restore file pointer to beginning of file after getting file size */ | |
42427 | - if (lseek (fd, 0, SEEK_SET) == -1) { | |
42428 | - endwin (); | |
42429 | - fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n"); | |
42430 | - exit (-1); | |
42431 | - } | |
42432 | - /* Allocate space for read buffer */ | |
42433 | - if ((buf = malloc (BUF_SIZE + 1)) == NULL) { | |
42434 | - endwin (); | |
42435 | - fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n"); | |
42436 | - exit (-1); | |
42437 | - } | |
42438 | - if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
42439 | - endwin (); | |
42440 | - fprintf (stderr, "\nError reading file in dialog_textbox().\n"); | |
42441 | - exit (-1); | |
42442 | - } | |
42443 | - buf[bytes_read] = '\0'; /* mark end of valid data */ | |
42444 | - page = buf; /* page is pointer to start of page to be displayed */ | |
42445 | - | |
42446 | - /* center dialog box on screen */ | |
42447 | - x = (COLS - width) / 2; | |
42448 | - y = (LINES - height) / 2; | |
42449 | - | |
42450 | - | |
42451 | - draw_shadow (stdscr, y, x, height, width); | |
42452 | - | |
42453 | - dialog = newwin (height, width, y, x); | |
42454 | - keypad (dialog, TRUE); | |
42455 | - | |
42456 | - /* Create window for text region, used for scrolling text */ | |
42457 | - text = subwin (dialog, height - 4, width - 2, y + 1, x + 1); | |
42458 | - wattrset (text, dialog_attr); | |
42459 | - wbkgdset (text, dialog_attr & A_COLOR); | |
42460 | - | |
42461 | - keypad (text, TRUE); | |
42462 | - | |
42463 | - /* register the new window, along with its borders */ | |
42464 | - draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
42465 | - | |
42466 | - wattrset (dialog, border_attr); | |
42467 | - mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
42468 | - for (i = 0; i < width - 2; i++) | |
42469 | - waddch (dialog, ACS_HLINE); | |
42470 | - wattrset (dialog, dialog_attr); | |
42471 | - wbkgdset (dialog, dialog_attr & A_COLOR); | |
42472 | - waddch (dialog, ACS_RTEE); | |
42473 | - | |
42474 | - if (title != NULL && strlen(title) >= width-2 ) { | |
42475 | - /* truncate long title -- mec */ | |
42476 | - char * title2 = malloc(width-2+1); | |
42477 | - memcpy( title2, title, width-2 ); | |
42478 | - title2[width-2] = '\0'; | |
42479 | - title = title2; | |
42480 | - } | |
42481 | - | |
42482 | - if (title != NULL) { | |
42483 | - wattrset (dialog, title_attr); | |
42484 | - mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
42485 | - waddstr (dialog, (char *)title); | |
42486 | - waddch (dialog, ' '); | |
42487 | - } | |
42488 | - print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE); | |
42489 | - wnoutrefresh (dialog); | |
42490 | - getyx (dialog, cur_y, cur_x); /* Save cursor position */ | |
42491 | - | |
42492 | - /* Print first page of text */ | |
42493 | - attr_clear (text, height - 4, width - 2, dialog_attr); | |
42494 | - print_page (text, height - 4, width - 2); | |
42495 | - print_position (dialog, height, width); | |
42496 | - wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
42497 | - wrefresh (dialog); | |
42498 | - | |
42499 | - while ((key != ESC) && (key != '\n')) { | |
42500 | - key = wgetch (dialog); | |
42501 | - switch (key) { | |
42502 | - case 'E': /* Exit */ | |
42503 | - case 'e': | |
42504 | - case 'X': | |
42505 | - case 'x': | |
42506 | - delwin (dialog); | |
42507 | - free (buf); | |
42508 | - close (fd); | |
42509 | - return 0; | |
42510 | - case 'g': /* First page */ | |
42511 | - case KEY_HOME: | |
42512 | - if (!begin_reached) { | |
42513 | - begin_reached = 1; | |
42514 | - /* First page not in buffer? */ | |
42515 | - if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
42516 | - endwin (); | |
42517 | - fprintf (stderr, | |
42518 | - "\nError moving file pointer in dialog_textbox().\n"); | |
42519 | - exit (-1); | |
42520 | - } | |
42521 | - if (fpos > bytes_read) { /* Yes, we have to read it in */ | |
42522 | - if (lseek (fd, 0, SEEK_SET) == -1) { | |
42523 | - endwin (); | |
42524 | - fprintf (stderr, "\nError moving file pointer in " | |
42525 | - "dialog_textbox().\n"); | |
42526 | - exit (-1); | |
42527 | - } | |
42528 | - if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
42529 | - endwin (); | |
42530 | - fprintf (stderr, | |
42531 | - "\nError reading file in dialog_textbox().\n"); | |
42532 | - exit (-1); | |
42533 | - } | |
42534 | - buf[bytes_read] = '\0'; | |
42535 | - } | |
42536 | - page = buf; | |
42537 | - print_page (text, height - 4, width - 2); | |
42538 | - print_position (dialog, height, width); | |
42539 | - wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
42540 | - wrefresh (dialog); | |
42541 | - } | |
42542 | - break; | |
42543 | - case 'G': /* Last page */ | |
42544 | - case KEY_END: | |
42545 | - | |
42546 | - end_reached = 1; | |
42547 | - /* Last page not in buffer? */ | |
42548 | - if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
42549 | - endwin (); | |
42550 | - fprintf (stderr, | |
42551 | - "\nError moving file pointer in dialog_textbox().\n"); | |
42552 | - exit (-1); | |
42553 | - } | |
42554 | - if (fpos < file_size) { /* Yes, we have to read it in */ | |
42555 | - if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) { | |
42556 | - endwin (); | |
42557 | - fprintf (stderr, | |
42558 | - "\nError moving file pointer in dialog_textbox().\n"); | |
42559 | - exit (-1); | |
42560 | - } | |
42561 | - if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
42562 | - endwin (); | |
42563 | - fprintf (stderr, | |
42564 | - "\nError reading file in dialog_textbox().\n"); | |
42565 | - exit (-1); | |
42566 | - } | |
42567 | - buf[bytes_read] = '\0'; | |
42568 | - } | |
42569 | - page = buf + bytes_read; | |
42570 | - back_lines (height - 4); | |
42571 | - print_page (text, height - 4, width - 2); | |
42572 | - print_position (dialog, height, width); | |
42573 | - wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
42574 | - wrefresh (dialog); | |
42575 | - break; | |
42576 | - case 'K': /* Previous line */ | |
42577 | - case 'k': | |
42578 | - case KEY_UP: | |
42579 | - if (!begin_reached) { | |
42580 | - back_lines (page_length + 1); | |
42581 | - | |
42582 | - /* We don't call print_page() here but use scrolling to ensure | |
42583 | - faster screen update. However, 'end_reached' and | |
42584 | - 'page_length' should still be updated, and 'page' should | |
42585 | - point to start of next page. This is done by calling | |
42586 | - get_line() in the following 'for' loop. */ | |
42587 | - scrollok (text, TRUE); | |
42588 | - wscrl (text, -1); /* Scroll text region down one line */ | |
42589 | - scrollok (text, FALSE); | |
42590 | - page_length = 0; | |
42591 | - passed_end = 0; | |
42592 | - for (i = 0; i < height - 4; i++) { | |
42593 | - if (!i) { | |
42594 | - /* print first line of page */ | |
42595 | - print_line (text, 0, width - 2); | |
42596 | - wnoutrefresh (text); | |
42597 | - } else | |
42598 | - /* Called to update 'end_reached' and 'page' */ | |
42599 | - get_line (); | |
42600 | - if (!passed_end) | |
42601 | - page_length++; | |
42602 | - if (end_reached && !passed_end) | |
42603 | - passed_end = 1; | |
42604 | - } | |
42605 | - | |
42606 | - print_position (dialog, height, width); | |
42607 | - wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
42608 | - wrefresh (dialog); | |
42609 | - } | |
42610 | - break; | |
42611 | - case 'B': /* Previous page */ | |
42612 | - case 'b': | |
42613 | - case KEY_PPAGE: | |
42614 | - if (begin_reached) | |
42615 | - break; | |
42616 | - back_lines (page_length + height - 4); | |
42617 | - print_page (text, height - 4, width - 2); | |
42618 | - print_position (dialog, height, width); | |
42619 | - wmove (dialog, cur_y, cur_x); | |
42620 | - wrefresh (dialog); | |
42621 | - break; | |
42622 | - case 'J': /* Next line */ | |
42623 | - case 'j': | |
42624 | - case KEY_DOWN: | |
42625 | - if (!end_reached) { | |
42626 | - begin_reached = 0; | |
42627 | - scrollok (text, TRUE); | |
42628 | - scroll (text); /* Scroll text region up one line */ | |
42629 | - scrollok (text, FALSE); | |
42630 | - print_line (text, height - 5, width - 2); | |
42631 | - wnoutrefresh (text); | |
42632 | - print_position (dialog, height, width); | |
42633 | - wmove (dialog, cur_y, cur_x); /* Restore cursor position */ | |
42634 | - wrefresh (dialog); | |
42635 | - } | |
42636 | - break; | |
42637 | - case KEY_NPAGE: /* Next page */ | |
42638 | - case ' ': | |
42639 | - if (end_reached) | |
42640 | - break; | |
42641 | - | |
42642 | - begin_reached = 0; | |
42643 | - print_page (text, height - 4, width - 2); | |
42644 | - print_position (dialog, height, width); | |
42645 | - wmove (dialog, cur_y, cur_x); | |
42646 | - wrefresh (dialog); | |
42647 | - break; | |
42648 | - case '0': /* Beginning of line */ | |
42649 | - case 'H': /* Scroll left */ | |
42650 | - case 'h': | |
42651 | - case KEY_LEFT: | |
42652 | - if (hscroll <= 0) | |
42653 | - break; | |
42654 | - | |
42655 | - if (key == '0') | |
42656 | - hscroll = 0; | |
42657 | - else | |
42658 | - hscroll--; | |
42659 | - /* Reprint current page to scroll horizontally */ | |
42660 | - back_lines (page_length); | |
42661 | - print_page (text, height - 4, width - 2); | |
42662 | - wmove (dialog, cur_y, cur_x); | |
42663 | - wrefresh (dialog); | |
42664 | - break; | |
42665 | - case 'L': /* Scroll right */ | |
42666 | - case 'l': | |
42667 | - case KEY_RIGHT: | |
42668 | - if (hscroll >= MAX_LEN) | |
42669 | - break; | |
42670 | - hscroll++; | |
42671 | - /* Reprint current page to scroll horizontally */ | |
42672 | - back_lines (page_length); | |
42673 | - print_page (text, height - 4, width - 2); | |
42674 | - wmove (dialog, cur_y, cur_x); | |
42675 | - wrefresh (dialog); | |
42676 | - break; | |
42677 | - case ESC: | |
42678 | - break; | |
42679 | - } | |
42680 | - } | |
42681 | - | |
42682 | - delwin (dialog); | |
42683 | - free (buf); | |
42684 | - close (fd); | |
42685 | - return 1; /* ESC pressed */ | |
42686 | -} | |
42687 | - | |
42688 | -/* | |
42689 | - * Go back 'n' lines in text file. Called by dialog_textbox(). | |
42690 | - * 'page' will be updated to point to the desired line in 'buf'. | |
42691 | - */ | |
42692 | -static void | |
42693 | -back_lines (int n) | |
42694 | -{ | |
42695 | - int i, fpos; | |
42696 | - | |
42697 | - begin_reached = 0; | |
42698 | - /* We have to distinguish between end_reached and !end_reached | |
42699 | - since at end of file, the line is not ended by a '\n'. | |
42700 | - The code inside 'if' basically does a '--page' to move one | |
42701 | - character backward so as to skip '\n' of the previous line */ | |
42702 | - if (!end_reached) { | |
42703 | - /* Either beginning of buffer or beginning of file reached? */ | |
42704 | - if (page == buf) { | |
42705 | - if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
42706 | - endwin (); | |
42707 | - fprintf (stderr, "\nError moving file pointer in " | |
42708 | - "back_lines().\n"); | |
42709 | - exit (-1); | |
42710 | - } | |
42711 | - if (fpos > bytes_read) { /* Not beginning of file yet */ | |
42712 | - /* We've reached beginning of buffer, but not beginning of | |
42713 | - file yet, so read previous part of file into buffer. | |
42714 | - Note that we only move backward for BUF_SIZE/2 bytes, | |
42715 | - but not BUF_SIZE bytes to avoid re-reading again in | |
42716 | - print_page() later */ | |
42717 | - /* Really possible to move backward BUF_SIZE/2 bytes? */ | |
42718 | - if (fpos < BUF_SIZE / 2 + bytes_read) { | |
42719 | - /* No, move less then */ | |
42720 | - if (lseek (fd, 0, SEEK_SET) == -1) { | |
42721 | - endwin (); | |
42722 | - fprintf (stderr, "\nError moving file pointer in " | |
42723 | - "back_lines().\n"); | |
42724 | - exit (-1); | |
42725 | - } | |
42726 | - page = buf + fpos - bytes_read; | |
42727 | - } else { /* Move backward BUF_SIZE/2 bytes */ | |
42728 | - if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) | |
42729 | - == -1) { | |
42730 | - endwin (); | |
42731 | - fprintf (stderr, "\nError moving file pointer " | |
42732 | - "in back_lines().\n"); | |
42733 | - exit (-1); | |
42734 | - } | |
42735 | - page = buf + BUF_SIZE / 2; | |
42736 | - } | |
42737 | - if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
42738 | - endwin (); | |
42739 | - fprintf (stderr, "\nError reading file in back_lines().\n"); | |
42740 | - exit (-1); | |
42741 | - } | |
42742 | - buf[bytes_read] = '\0'; | |
42743 | - } else { /* Beginning of file reached */ | |
42744 | - begin_reached = 1; | |
42745 | - return; | |
42746 | - } | |
42747 | - } | |
42748 | - if (*(--page) != '\n') { /* '--page' here */ | |
42749 | - /* Something's wrong... */ | |
42750 | - endwin (); | |
42751 | - fprintf (stderr, "\nInternal error in back_lines().\n"); | |
42752 | - exit (-1); | |
42753 | - } | |
42754 | - } | |
42755 | - /* Go back 'n' lines */ | |
42756 | - for (i = 0; i < n; i++) | |
42757 | - do { | |
42758 | - if (page == buf) { | |
42759 | - if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
42760 | - endwin (); | |
42761 | - fprintf (stderr, | |
42762 | - "\nError moving file pointer in back_lines().\n"); | |
42763 | - exit (-1); | |
42764 | - } | |
42765 | - if (fpos > bytes_read) { | |
42766 | - /* Really possible to move backward BUF_SIZE/2 bytes? */ | |
42767 | - if (fpos < BUF_SIZE / 2 + bytes_read) { | |
42768 | - /* No, move less then */ | |
42769 | - if (lseek (fd, 0, SEEK_SET) == -1) { | |
42770 | - endwin (); | |
42771 | - fprintf (stderr, "\nError moving file pointer " | |
42772 | - "in back_lines().\n"); | |
42773 | - exit (-1); | |
42774 | - } | |
42775 | - page = buf + fpos - bytes_read; | |
42776 | - } else { /* Move backward BUF_SIZE/2 bytes */ | |
42777 | - if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), | |
42778 | - SEEK_CUR) == -1) { | |
42779 | - endwin (); | |
42780 | - fprintf (stderr, "\nError moving file pointer" | |
42781 | - " in back_lines().\n"); | |
42782 | - exit (-1); | |
42783 | - } | |
42784 | - page = buf + BUF_SIZE / 2; | |
42785 | - } | |
42786 | - if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
42787 | - endwin (); | |
42788 | - fprintf (stderr, "\nError reading file in " | |
42789 | - "back_lines().\n"); | |
42790 | - exit (-1); | |
42791 | - } | |
42792 | - buf[bytes_read] = '\0'; | |
42793 | - } else { /* Beginning of file reached */ | |
42794 | - begin_reached = 1; | |
42795 | - return; | |
42796 | - } | |
42797 | - } | |
42798 | - } while (*(--page) != '\n'); | |
42799 | - page++; | |
42800 | -} | |
42801 | - | |
42802 | -/* | |
42803 | - * Print a new page of text. Called by dialog_textbox(). | |
42804 | - */ | |
42805 | -static void | |
42806 | -print_page (WINDOW * win, int height, int width) | |
42807 | -{ | |
42808 | - int i, passed_end = 0; | |
42809 | - | |
42810 | - page_length = 0; | |
42811 | - for (i = 0; i < height; i++) { | |
42812 | - print_line (win, i, width); | |
42813 | - if (!passed_end) | |
42814 | - page_length++; | |
42815 | - if (end_reached && !passed_end) | |
42816 | - passed_end = 1; | |
42817 | - } | |
42818 | - wnoutrefresh (win); | |
42819 | -} | |
42820 | - | |
42821 | -/* | |
42822 | - * Print a new line of text. Called by dialog_textbox() and print_page(). | |
42823 | - */ | |
42824 | -static void | |
42825 | -print_line (WINDOW * win, int row, int width) | |
42826 | -{ | |
42827 | - int y, x; | |
42828 | - char *line; | |
42829 | - | |
42830 | - line = get_line (); | |
42831 | - line += MIN (strlen (line), hscroll); /* Scroll horizontally */ | |
42832 | - wmove (win, row, 0); /* move cursor to correct line */ | |
42833 | - waddch (win, ' '); | |
42834 | - waddnstr (win, line, MIN (strlen (line), width - 2)); | |
42835 | - | |
42836 | - getyx (win, y, x); | |
42837 | - /* Clear 'residue' of previous line */ | |
42838 | -#if OLD_NCURSES | |
42839 | - { | |
42840 | - int i; | |
42841 | - for (i = 0; i < width - x; i++) | |
42842 | - waddch (win, ' '); | |
42843 | - } | |
42844 | -#else | |
42845 | - wclrtoeol(win); | |
42846 | -#endif | |
42847 | -} | |
42848 | - | |
42849 | -/* | |
42850 | - * Return current line of text. Called by dialog_textbox() and print_line(). | |
42851 | - * 'page' should point to start of current line before calling, and will be | |
42852 | - * updated to point to start of next line. | |
42853 | - */ | |
42854 | -static char * | |
42855 | -get_line (void) | |
42856 | -{ | |
42857 | - int i = 0, fpos; | |
42858 | - static char line[MAX_LEN + 1]; | |
42859 | - | |
42860 | - end_reached = 0; | |
42861 | - while (*page != '\n') { | |
42862 | - if (*page == '\0') { | |
42863 | - /* Either end of file or end of buffer reached */ | |
42864 | - if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
42865 | - endwin (); | |
42866 | - fprintf (stderr, "\nError moving file pointer in " | |
42867 | - "get_line().\n"); | |
42868 | - exit (-1); | |
42869 | - } | |
42870 | - if (fpos < file_size) { /* Not end of file yet */ | |
42871 | - /* We've reached end of buffer, but not end of file yet, | |
42872 | - so read next part of file into buffer */ | |
42873 | - if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { | |
42874 | - endwin (); | |
42875 | - fprintf (stderr, "\nError reading file in get_line().\n"); | |
42876 | - exit (-1); | |
42877 | - } | |
42878 | - buf[bytes_read] = '\0'; | |
42879 | - page = buf; | |
42880 | - } else { | |
42881 | - if (!end_reached) | |
42882 | - end_reached = 1; | |
42883 | - break; | |
42884 | - } | |
42885 | - } else if (i < MAX_LEN) | |
42886 | - line[i++] = *(page++); | |
42887 | - else { | |
42888 | - /* Truncate lines longer than MAX_LEN characters */ | |
42889 | - if (i == MAX_LEN) | |
42890 | - line[i++] = '\0'; | |
42891 | - page++; | |
42892 | - } | |
42893 | - } | |
42894 | - if (i <= MAX_LEN) | |
42895 | - line[i] = '\0'; | |
42896 | - if (!end_reached) | |
42897 | - page++; /* move pass '\n' */ | |
42898 | - | |
42899 | - return line; | |
42900 | -} | |
42901 | - | |
42902 | -/* | |
42903 | - * Print current position | |
42904 | - */ | |
42905 | -static void | |
42906 | -print_position (WINDOW * win, int height, int width) | |
42907 | -{ | |
42908 | - int fpos, percent; | |
42909 | - | |
42910 | - if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { | |
42911 | - endwin (); | |
42912 | - fprintf (stderr, "\nError moving file pointer in print_position().\n"); | |
42913 | - exit (-1); | |
42914 | - } | |
42915 | - wattrset (win, position_indicator_attr); | |
42916 | - wbkgdset (win, position_indicator_attr & A_COLOR); | |
42917 | - percent = !file_size ? | |
42918 | - 100 : ((fpos - bytes_read + page - buf) * 100) / file_size; | |
42919 | - wmove (win, height - 3, width - 9); | |
42920 | - wprintw (win, "(%3d%%)", percent); | |
42921 | -} | |
42922 | diff -Nur busybox-1.00/scripts/config/util.c busybox/scripts/config/util.c | |
42923 | --- busybox-1.00/scripts/config/util.c 2004-07-15 08:01:05.000000000 +0200 | |
42924 | +++ busybox/scripts/config/util.c 2005-06-04 08:20:03.000000000 +0200 | |
42925 | @@ -1,375 +1,109 @@ | |
42926 | /* | |
42927 | - * util.c | |
42928 | + * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org> | |
42929 | + * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org> | |
42930 | * | |
42931 | - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
42932 | - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
42933 | - * | |
42934 | - * This program is free software; you can redistribute it and/or | |
42935 | - * modify it under the terms of the GNU General Public License | |
42936 | - * as published by the Free Software Foundation; either version 2 | |
42937 | - * of the License, or (at your option) any later version. | |
42938 | - * | |
42939 | - * This program is distributed in the hope that it will be useful, | |
42940 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
42941 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
42942 | - * GNU General Public License for more details. | |
42943 | - * | |
42944 | - * You should have received a copy of the GNU General Public License | |
42945 | - * along with this program; if not, write to the Free Software | |
42946 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
42947 | - */ | |
42948 | - | |
42949 | -#include "dialog.h" | |
42950 | - | |
42951 | - | |
42952 | -/* use colors by default? */ | |
42953 | -bool use_colors = 1; | |
42954 | - | |
42955 | -char *backtitle = NULL; | |
42956 | - | |
42957 | -const char *dialog_result; | |
42958 | - | |
42959 | -/* | |
42960 | - * Attribute values, default is for mono display | |
42961 | + * Released under the terms of the GNU GPL v2.0. | |
42962 | */ | |
42963 | -chtype attributes[] = | |
42964 | -{ | |
42965 | - A_NORMAL, /* screen_attr */ | |
42966 | - A_NORMAL, /* shadow_attr */ | |
42967 | - A_NORMAL, /* dialog_attr */ | |
42968 | - A_BOLD, /* title_attr */ | |
42969 | - A_NORMAL, /* border_attr */ | |
42970 | - A_REVERSE, /* button_active_attr */ | |
42971 | - A_DIM, /* button_inactive_attr */ | |
42972 | - A_REVERSE, /* button_key_active_attr */ | |
42973 | - A_BOLD, /* button_key_inactive_attr */ | |
42974 | - A_REVERSE, /* button_label_active_attr */ | |
42975 | - A_NORMAL, /* button_label_inactive_attr */ | |
42976 | - A_NORMAL, /* inputbox_attr */ | |
42977 | - A_NORMAL, /* inputbox_border_attr */ | |
42978 | - A_NORMAL, /* searchbox_attr */ | |
42979 | - A_BOLD, /* searchbox_title_attr */ | |
42980 | - A_NORMAL, /* searchbox_border_attr */ | |
42981 | - A_BOLD, /* position_indicator_attr */ | |
42982 | - A_NORMAL, /* menubox_attr */ | |
42983 | - A_NORMAL, /* menubox_border_attr */ | |
42984 | - A_NORMAL, /* item_attr */ | |
42985 | - A_REVERSE, /* item_selected_attr */ | |
42986 | - A_BOLD, /* tag_attr */ | |
42987 | - A_REVERSE, /* tag_selected_attr */ | |
42988 | - A_BOLD, /* tag_key_attr */ | |
42989 | - A_REVERSE, /* tag_key_selected_attr */ | |
42990 | - A_BOLD, /* check_attr */ | |
42991 | - A_REVERSE, /* check_selected_attr */ | |
42992 | - A_BOLD, /* uarrow_attr */ | |
42993 | - A_BOLD /* darrow_attr */ | |
42994 | -}; | |
42995 | ||
42996 | +#include <string.h> | |
42997 | +#include "lkc.h" | |
42998 | ||
42999 | -#include "colors.h" | |
43000 | - | |
43001 | -/* | |
43002 | - * Table of color values | |
43003 | - */ | |
43004 | -int color_table[][3] = | |
43005 | +/* file already present in list? If not add it */ | |
43006 | +struct file *file_lookup(const char *name) | |
43007 | { | |
43008 | - {SCREEN_FG, SCREEN_BG, SCREEN_HL}, | |
43009 | - {SHADOW_FG, SHADOW_BG, SHADOW_HL}, | |
43010 | - {DIALOG_FG, DIALOG_BG, DIALOG_HL}, | |
43011 | - {TITLE_FG, TITLE_BG, TITLE_HL}, | |
43012 | - {BORDER_FG, BORDER_BG, BORDER_HL}, | |
43013 | - {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, | |
43014 | - {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, | |
43015 | - {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, | |
43016 | - {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL}, | |
43017 | - {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL}, | |
43018 | - {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG, | |
43019 | - BUTTON_LABEL_INACTIVE_HL}, | |
43020 | - {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL}, | |
43021 | - {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL}, | |
43022 | - {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL}, | |
43023 | - {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL}, | |
43024 | - {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL}, | |
43025 | - {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL}, | |
43026 | - {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL}, | |
43027 | - {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL}, | |
43028 | - {ITEM_FG, ITEM_BG, ITEM_HL}, | |
43029 | - {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL}, | |
43030 | - {TAG_FG, TAG_BG, TAG_HL}, | |
43031 | - {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL}, | |
43032 | - {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL}, | |
43033 | - {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL}, | |
43034 | - {CHECK_FG, CHECK_BG, CHECK_HL}, | |
43035 | - {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL}, | |
43036 | - {UARROW_FG, UARROW_BG, UARROW_HL}, | |
43037 | - {DARROW_FG, DARROW_BG, DARROW_HL}, | |
43038 | -}; /* color_table */ | |
43039 | + struct file *file; | |
43040 | ||
43041 | -/* | |
43042 | - * Set window to attribute 'attr' | |
43043 | - */ | |
43044 | -void | |
43045 | -attr_clear (WINDOW * win, int height, int width, chtype attr) | |
43046 | -{ | |
43047 | - int i, j; | |
43048 | + for (file = file_list; file; file = file->next) { | |
43049 | + if (!strcmp(name, file->name)) | |
43050 | + return file; | |
43051 | + } | |
43052 | ||
43053 | - wattrset (win, attr); | |
43054 | - for (i = 0; i < height; i++) { | |
43055 | - wmove (win, i, 0); | |
43056 | - for (j = 0; j < width; j++) | |
43057 | - waddch (win, ' '); | |
43058 | - } | |
43059 | - touchwin (win); | |
43060 | + file = malloc(sizeof(*file)); | |
43061 | + memset(file, 0, sizeof(*file)); | |
43062 | + file->name = strdup(name); | |
43063 | + file->next = file_list; | |
43064 | + file_list = file; | |
43065 | + return file; | |
43066 | +} | |
43067 | + | |
43068 | +/* write a dependency file as used by kbuild to track dependencies */ | |
43069 | +int file_write_dep(const char *name) | |
43070 | +{ | |
43071 | + struct file *file; | |
43072 | + FILE *out; | |
43073 | + | |
43074 | + if (!name) | |
43075 | + name = ".config.cmd"; | |
43076 | + out = fopen(".config.tmp", "w"); | |
43077 | + if (!out) | |
43078 | + return 1; | |
43079 | + fprintf(out, "deps_config := \\\n"); | |
43080 | + for (file = file_list; file; file = file->next) { | |
43081 | + if (file->next) | |
43082 | + fprintf(out, "\t%s \\\n", file->name); | |
43083 | + else | |
43084 | + fprintf(out, "\t%s\n", file->name); | |
43085 | + } | |
43086 | + fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n"); | |
43087 | + fclose(out); | |
43088 | + rename(".config.tmp", name); | |
43089 | + return 0; | |
43090 | } | |
43091 | ||
43092 | -void dialog_clear (void) | |
43093 | -{ | |
43094 | - attr_clear (stdscr, LINES, COLS, screen_attr); | |
43095 | - /* Display background title if it exists ... - SLH */ | |
43096 | - if (backtitle != NULL) { | |
43097 | - int i; | |
43098 | - | |
43099 | - wattrset (stdscr, screen_attr); | |
43100 | - mvwaddstr (stdscr, 0, 1, (char *)backtitle); | |
43101 | - wmove (stdscr, 1, 1); | |
43102 | - for (i = 1; i < COLS - 1; i++) | |
43103 | - waddch (stdscr, ACS_HLINE); | |
43104 | - } | |
43105 | - wnoutrefresh (stdscr); | |
43106 | -} | |
43107 | ||
43108 | -/* | |
43109 | - * Do some initialization for dialog | |
43110 | - */ | |
43111 | -void | |
43112 | -init_dialog (void) | |
43113 | +/* Allocate initial growable sting */ | |
43114 | +struct gstr str_new(void) | |
43115 | { | |
43116 | - initscr (); /* Init curses */ | |
43117 | - keypad (stdscr, TRUE); | |
43118 | - cbreak (); | |
43119 | - noecho (); | |
43120 | - | |
43121 | - | |
43122 | - if (use_colors) /* Set up colors */ | |
43123 | - color_setup (); | |
43124 | - | |
43125 | - | |
43126 | - dialog_clear (); | |
43127 | + struct gstr gs; | |
43128 | + gs.s = malloc(sizeof(char) * 64); | |
43129 | + gs.len = 16; | |
43130 | + strcpy(gs.s, "\0"); | |
43131 | + return gs; | |
43132 | } | |
43133 | ||
43134 | -/* | |
43135 | - * Setup for color display | |
43136 | - */ | |
43137 | -void | |
43138 | -color_setup (void) | |
43139 | +/* Allocate and assign growable string */ | |
43140 | +struct gstr str_assign(const char *s) | |
43141 | { | |
43142 | - int i; | |
43143 | - | |
43144 | - if (has_colors ()) { /* Terminal supports color? */ | |
43145 | - start_color (); | |
43146 | - | |
43147 | - /* Initialize color pairs */ | |
43148 | - for (i = 0; i < ATTRIBUTE_COUNT; i++) | |
43149 | - init_pair (i + 1, color_table[i][0], color_table[i][1]); | |
43150 | - | |
43151 | - /* Setup color attributes */ | |
43152 | - for (i = 0; i < ATTRIBUTE_COUNT; i++) | |
43153 | - attributes[i] = C_ATTR (color_table[i][2], i + 1); | |
43154 | - } | |
43155 | + struct gstr gs; | |
43156 | + gs.s = strdup(s); | |
43157 | + gs.len = strlen(s) + 1; | |
43158 | + return gs; | |
43159 | } | |
43160 | ||
43161 | -/* | |
43162 | - * End using dialog functions. | |
43163 | - */ | |
43164 | -void | |
43165 | -end_dialog (void) | |
43166 | +/* Free storage for growable string */ | |
43167 | +void str_free(struct gstr *gs) | |
43168 | { | |
43169 | - endwin (); | |
43170 | + if (gs->s) | |
43171 | + free(gs->s); | |
43172 | + gs->s = NULL; | |
43173 | + gs->len = 0; | |
43174 | } | |
43175 | ||
43176 | - | |
43177 | -/* | |
43178 | - * Print a string of text in a window, automatically wrap around to the | |
43179 | - * next line if the string is too long to fit on one line. Newline | |
43180 | - * characters '\n' are replaced by spaces. We start on a new line | |
43181 | - * if there is no room for at least 4 nonblanks following a double-space. | |
43182 | - */ | |
43183 | -void | |
43184 | -print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x) | |
43185 | +/* Append to growable string */ | |
43186 | +void str_append(struct gstr *gs, const char *s) | |
43187 | { | |
43188 | - int newl, cur_x, cur_y; | |
43189 | - int i, prompt_len, room, wlen; | |
43190 | - char tempstr[MAX_LEN + 1], *word, *sp, *sp2; | |
43191 | - | |
43192 | - strcpy (tempstr, prompt); | |
43193 | - | |
43194 | - prompt_len = strlen(tempstr); | |
43195 | - | |
43196 | - /* | |
43197 | - * Remove newlines | |
43198 | - */ | |
43199 | - for(i=0; i<prompt_len; i++) { | |
43200 | - if(tempstr[i] == '\n') tempstr[i] = ' '; | |
43201 | - } | |
43202 | - | |
43203 | - if (prompt_len <= width - x * 2) { /* If prompt is short */ | |
43204 | - wmove (win, y, (width - prompt_len) / 2); | |
43205 | - waddstr (win, tempstr); | |
43206 | - } else { | |
43207 | - cur_x = x; | |
43208 | - cur_y = y; | |
43209 | - newl = 1; | |
43210 | - word = tempstr; | |
43211 | - while (word && *word) { | |
43212 | - sp = index(word, ' '); | |
43213 | - if (sp) | |
43214 | - *sp++ = 0; | |
43215 | - | |
43216 | - /* Wrap to next line if either the word does not fit, | |
43217 | - or it is the first word of a new sentence, and it is | |
43218 | - short, and the next word does not fit. */ | |
43219 | - room = width - cur_x; | |
43220 | - wlen = strlen(word); | |
43221 | - if (wlen > room || | |
43222 | - (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room | |
43223 | - && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) { | |
43224 | - cur_y++; | |
43225 | - cur_x = x; | |
43226 | - } | |
43227 | - wmove (win, cur_y, cur_x); | |
43228 | - waddstr (win, word); | |
43229 | - getyx (win, cur_y, cur_x); | |
43230 | - cur_x++; | |
43231 | - if (sp && *sp == ' ') { | |
43232 | - cur_x++; /* double space */ | |
43233 | - while (*++sp == ' '); | |
43234 | - newl = 1; | |
43235 | - } else | |
43236 | - newl = 0; | |
43237 | - word = sp; | |
43238 | + size_t l = strlen(gs->s) + strlen(s) + 1; | |
43239 | + if (l > gs->len) { | |
43240 | + gs->s = realloc(gs->s, l); | |
43241 | + gs->len = l; | |
43242 | } | |
43243 | - } | |
43244 | -} | |
43245 | - | |
43246 | -/* | |
43247 | - * Print a button | |
43248 | - */ | |
43249 | -void | |
43250 | -print_button (WINDOW * win, const char *label, int y, int x, int selected) | |
43251 | -{ | |
43252 | - int i, temp; | |
43253 | - | |
43254 | - wmove (win, y, x); | |
43255 | - wattrset (win, selected ? button_active_attr : button_inactive_attr); | |
43256 | - waddstr (win, "<"); | |
43257 | - temp = strspn (label, " "); | |
43258 | - label += temp; | |
43259 | - wattrset (win, selected ? button_label_active_attr | |
43260 | - : button_label_inactive_attr); | |
43261 | - for (i = 0; i < temp; i++) | |
43262 | - waddch (win, ' '); | |
43263 | - wattrset (win, selected ? button_key_active_attr | |
43264 | - : button_key_inactive_attr); | |
43265 | - waddch (win, label[0]); | |
43266 | - wattrset (win, selected ? button_label_active_attr | |
43267 | - : button_label_inactive_attr); | |
43268 | - waddstr (win, (char *)label + 1); | |
43269 | - wattrset (win, selected ? button_active_attr : button_inactive_attr); | |
43270 | - waddstr (win, ">"); | |
43271 | - wmove (win, y, x + temp + 1); | |
43272 | + strcat(gs->s, s); | |
43273 | } | |
43274 | ||
43275 | -/* | |
43276 | - * Draw a rectangular box with line drawing characters | |
43277 | - */ | |
43278 | -void | |
43279 | -draw_box (WINDOW * win, int y, int x, int height, int width, | |
43280 | - chtype box, chtype border) | |
43281 | -{ | |
43282 | - int i, j; | |
43283 | - | |
43284 | - wattrset (win, 0); | |
43285 | - for (i = 0; i < height; i++) { | |
43286 | - wmove (win, y + i, x); | |
43287 | - for (j = 0; j < width; j++) | |
43288 | - if (!i && !j) | |
43289 | - waddch (win, border | ACS_ULCORNER); | |
43290 | - else if (i == height - 1 && !j) | |
43291 | - waddch (win, border | ACS_LLCORNER); | |
43292 | - else if (!i && j == width - 1) | |
43293 | - waddch (win, box | ACS_URCORNER); | |
43294 | - else if (i == height - 1 && j == width - 1) | |
43295 | - waddch (win, box | ACS_LRCORNER); | |
43296 | - else if (!i) | |
43297 | - waddch (win, border | ACS_HLINE); | |
43298 | - else if (i == height - 1) | |
43299 | - waddch (win, box | ACS_HLINE); | |
43300 | - else if (!j) | |
43301 | - waddch (win, border | ACS_VLINE); | |
43302 | - else if (j == width - 1) | |
43303 | - waddch (win, box | ACS_VLINE); | |
43304 | - else | |
43305 | - waddch (win, box | ' '); | |
43306 | - } | |
43307 | -} | |
43308 | - | |
43309 | -/* | |
43310 | - * Draw shadows along the right and bottom edge to give a more 3D look | |
43311 | - * to the boxes | |
43312 | - */ | |
43313 | -void | |
43314 | -draw_shadow (WINDOW * win, int y, int x, int height, int width) | |
43315 | +/* Append printf formatted string to growable string */ | |
43316 | +void str_printf(struct gstr *gs, const char *fmt, ...) | |
43317 | { | |
43318 | - int i; | |
43319 | - | |
43320 | - if (has_colors ()) { /* Whether terminal supports color? */ | |
43321 | - wattrset (win, shadow_attr); | |
43322 | - wmove (win, y + height, x + 2); | |
43323 | - for (i = 0; i < width; i++) | |
43324 | - waddch (win, winch (win) & A_CHARTEXT); | |
43325 | - for (i = y + 1; i < y + height + 1; i++) { | |
43326 | - wmove (win, i, x + width); | |
43327 | - waddch (win, winch (win) & A_CHARTEXT); | |
43328 | - waddch (win, winch (win) & A_CHARTEXT); | |
43329 | - } | |
43330 | - wnoutrefresh (win); | |
43331 | - } | |
43332 | + va_list ap; | |
43333 | + char s[10000]; /* big enough... */ | |
43334 | + va_start(ap, fmt); | |
43335 | + vsnprintf(s, sizeof(s), fmt, ap); | |
43336 | + str_append(gs, s); | |
43337 | + va_end(ap); | |
43338 | } | |
43339 | ||
43340 | -/* | |
43341 | - * Return the position of the first alphabetic character in a string. | |
43342 | - */ | |
43343 | -int | |
43344 | -first_alpha(const char *string, const char *exempt) | |
43345 | +/* Retreive value of growable string */ | |
43346 | +const char *str_get(struct gstr *gs) | |
43347 | { | |
43348 | - int i, in_paren=0, c; | |
43349 | - | |
43350 | - for (i = 0; i < strlen(string); i++) { | |
43351 | - c = tolower(string[i]); | |
43352 | - | |
43353 | - if (strchr("<[(", c)) ++in_paren; | |
43354 | - if (strchr(">])", c) && in_paren > 0) --in_paren; | |
43355 | - | |
43356 | - if ((! in_paren) && isalpha(c) && | |
43357 | - strchr(exempt, c) == 0) | |
43358 | - return i; | |
43359 | - } | |
43360 | - | |
43361 | - return 0; | |
43362 | + return gs->s; | |
43363 | } | |
43364 | ||
43365 | -/* | |
43366 | - * Get the first selected item in the dialog_list_item list. | |
43367 | - */ | |
43368 | -struct dialog_list_item * | |
43369 | -first_sel_item(int item_no, struct dialog_list_item ** items) | |
43370 | -{ | |
43371 | - int i; | |
43372 | - | |
43373 | - for (i = 0; i < item_no; i++) { | |
43374 | - if (items[i]->selected) | |
43375 | - return items[i]; | |
43376 | - } | |
43377 | - | |
43378 | - return NULL; | |
43379 | -} | |
43380 | diff -Nur busybox-1.00/scripts/config/yesno.c busybox/scripts/config/yesno.c | |
43381 | --- busybox-1.00/scripts/config/yesno.c 2002-12-05 09:41:08.000000000 +0100 | |
43382 | +++ busybox/scripts/config/yesno.c 1970-01-01 01:00:00.000000000 +0100 | |
43383 | @@ -1,118 +0,0 @@ | |
43384 | -/* | |
43385 | - * yesno.c -- implements the yes/no box | |
43386 | - * | |
43387 | - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | |
43388 | - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | |
43389 | - * | |
43390 | - * This program is free software; you can redistribute it and/or | |
43391 | - * modify it under the terms of the GNU General Public License | |
43392 | - * as published by the Free Software Foundation; either version 2 | |
43393 | - * of the License, or (at your option) any later version. | |
43394 | - * | |
43395 | - * This program is distributed in the hope that it will be useful, | |
43396 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
43397 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
43398 | - * GNU General Public License for more details. | |
43399 | - * | |
43400 | - * You should have received a copy of the GNU General Public License | |
43401 | - * along with this program; if not, write to the Free Software | |
43402 | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
43403 | - */ | |
43404 | - | |
43405 | -#include "dialog.h" | |
43406 | - | |
43407 | -/* | |
43408 | - * Display termination buttons | |
43409 | - */ | |
43410 | -static void | |
43411 | -print_buttons(WINDOW *dialog, int height, int width, int selected) | |
43412 | -{ | |
43413 | - int x = width / 2 - 10; | |
43414 | - int y = height - 2; | |
43415 | - | |
43416 | - print_button (dialog, " Yes ", y, x, selected == 0); | |
43417 | - print_button (dialog, " No ", y, x + 13, selected == 1); | |
43418 | - | |
43419 | - wmove(dialog, y, x+1 + 13*selected ); | |
43420 | - wrefresh (dialog); | |
43421 | -} | |
43422 | - | |
43423 | -/* | |
43424 | - * Display a dialog box with two buttons - Yes and No | |
43425 | - */ | |
43426 | -int | |
43427 | -dialog_yesno (const char *title, const char *prompt, int height, int width) | |
43428 | -{ | |
43429 | - int i, x, y, key = 0, button = 0; | |
43430 | - WINDOW *dialog; | |
43431 | - | |
43432 | - /* center dialog box on screen */ | |
43433 | - x = (COLS - width) / 2; | |
43434 | - y = (LINES - height) / 2; | |
43435 | - | |
43436 | - draw_shadow (stdscr, y, x, height, width); | |
43437 | - | |
43438 | - dialog = newwin (height, width, y, x); | |
43439 | - keypad (dialog, TRUE); | |
43440 | - | |
43441 | - draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); | |
43442 | - wattrset (dialog, border_attr); | |
43443 | - mvwaddch (dialog, height-3, 0, ACS_LTEE); | |
43444 | - for (i = 0; i < width - 2; i++) | |
43445 | - waddch (dialog, ACS_HLINE); | |
43446 | - wattrset (dialog, dialog_attr); | |
43447 | - waddch (dialog, ACS_RTEE); | |
43448 | - | |
43449 | - if (title != NULL && strlen(title) >= width-2 ) { | |
43450 | - /* truncate long title -- mec */ | |
43451 | - char * title2 = malloc(width-2+1); | |
43452 | - memcpy( title2, title, width-2 ); | |
43453 | - title2[width-2] = '\0'; | |
43454 | - title = title2; | |
43455 | - } | |
43456 | - | |
43457 | - if (title != NULL) { | |
43458 | - wattrset (dialog, title_attr); | |
43459 | - mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); | |
43460 | - waddstr (dialog, (char *)title); | |
43461 | - waddch (dialog, ' '); | |
43462 | - } | |
43463 | - | |
43464 | - wattrset (dialog, dialog_attr); | |
43465 | - print_autowrap (dialog, prompt, width - 2, 1, 3); | |
43466 | - | |
43467 | - print_buttons(dialog, height, width, 0); | |
43468 | - | |
43469 | - while (key != ESC) { | |
43470 | - key = wgetch (dialog); | |
43471 | - switch (key) { | |
43472 | - case 'Y': | |
43473 | - case 'y': | |
43474 | - delwin (dialog); | |
43475 | - return 0; | |
43476 | - case 'N': | |
43477 | - case 'n': | |
43478 | - delwin (dialog); | |
43479 | - return 1; | |
43480 | - | |
43481 | - case TAB: | |
43482 | - case KEY_LEFT: | |
43483 | - case KEY_RIGHT: | |
43484 | - button = ((key == KEY_LEFT ? --button : ++button) < 0) | |
43485 | - ? 1 : (button > 1 ? 0 : button); | |
43486 | - | |
43487 | - print_buttons(dialog, height, width, button); | |
43488 | - wrefresh (dialog); | |
43489 | - break; | |
43490 | - case ' ': | |
43491 | - case '\n': | |
43492 | - delwin (dialog); | |
43493 | - return button; | |
43494 | - case ESC: | |
43495 | - break; | |
43496 | - } | |
43497 | - } | |
43498 | - | |
43499 | - delwin (dialog); | |
43500 | - return -1; /* ESC pressed */ | |
43501 | -} | |
43502 | diff -Nur busybox-1.00/scripts/config/zconf.tab.c_shipped busybox/scripts/config/zconf.tab.c_shipped | |
43503 | --- busybox-1.00/scripts/config/zconf.tab.c_shipped 2004-03-15 09:29:08.000000000 +0100 | |
43504 | +++ busybox/scripts/config/zconf.tab.c_shipped 2005-06-04 08:20:03.000000000 +0200 | |
43505 | @@ -175,6 +175,8 @@ | |
43506 | ||
43507 | struct symbol *symbol_hash[257]; | |
43508 | ||
43509 | +static struct menu *current_menu, *current_entry; | |
43510 | + | |
43511 | #define YYERROR_VERBOSE | |
43512 | ||
43513 | ||
43514 | @@ -227,7 +229,7 @@ | |
43515 | # define YYSTACK_ALLOC alloca | |
43516 | # else | |
43517 | # ifndef YYSTACK_USE_ALLOCA | |
43518 | -# if defined (alloca) || defined (_ALLOCA_H) | |
43519 | +# if defined (alloca) || (defined (_ALLOCA_H) && defined (__GNUC__)) | |
43520 | # define YYSTACK_ALLOC alloca | |
43521 | # else | |
43522 | # ifdef __GNUC__ | |
43523 | @@ -2119,6 +2121,7 @@ | |
43524 | } | |
43525 | ||
43526 | #include "lex.zconf.c" | |
43527 | +#include "util.c" | |
43528 | #include "confdata.c" | |
43529 | #include "expr.c" | |
43530 | #include "symbol.c" | |
43531 | diff -Nur busybox-1.00/scripts/config/zconf.y busybox/scripts/config/zconf.y | |
43532 | --- busybox-1.00/scripts/config/zconf.y 2003-08-05 07:59:48.000000000 +0200 | |
43533 | +++ busybox/scripts/config/zconf.y 2005-06-04 08:20:03.000000000 +0200 | |
43534 | @@ -25,6 +25,8 @@ | |
43535 | ||
43536 | struct symbol *symbol_hash[257]; | |
43537 | ||
43538 | +static struct menu *current_menu, *current_entry; | |
43539 | + | |
43540 | #define YYERROR_VERBOSE | |
43541 | %} | |
43542 | %expect 40 | |
43543 | @@ -681,6 +683,7 @@ | |
43544 | } | |
43545 | ||
43546 | #include "lex.zconf.c" | |
43547 | +#include "util.c" | |
43548 | #include "confdata.c" | |
43549 | #include "expr.c" | |
43550 | #include "symbol.c" | |
43551 | diff -Nur busybox-1.00/shell/Config.in busybox/shell/Config.in | |
43552 | --- busybox-1.00/shell/Config.in 2004-09-24 11:09:44.000000000 +0200 | |
43553 | +++ busybox/shell/Config.in 2005-06-04 08:20:11.000000000 +0200 | |
43554 | @@ -53,6 +53,17 @@ | |
43555 | help | |
43556 | Enable job control in the ash shell. | |
43557 | ||
43558 | +config CONFIG_ASH_TIMEOUT | |
43559 | + bool " Enable read timeout support." | |
43560 | + default n | |
43561 | + depends on CONFIG_ASH_JOB_CONTROL | |
43562 | + help | |
43563 | + This option provides read -t <seconds> support. | |
43564 | + | |
43565 | + read builtin which allows the function to pass control back | |
43566 | + if no character input is read from the terminal within a set | |
43567 | + number of seconds. | |
43568 | + | |
43569 | config CONFIG_ASH_ALIAS | |
43570 | bool " Enable alias support" | |
43571 | default y | |
43572 | diff -Nur busybox-1.00/shell/ash.c busybox/shell/ash.c | |
43573 | --- busybox-1.00/shell/ash.c 2004-10-08 11:43:34.000000000 +0200 | |
43574 | +++ busybox/shell/ash.c 2005-06-04 08:20:11.000000000 +0200 | |
43575 | @@ -3722,27 +3722,13 @@ | |
43576 | { | |
43577 | int repeated = 0; | |
43578 | #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL | |
43579 | - int flg_bb = 0; | |
43580 | - char *name = cmd; | |
43581 | - | |
43582 | - if(strchr(name, '/') == NULL && find_applet_by_name(name) != NULL) { | |
43583 | - flg_bb = 1; | |
43584 | - } | |
43585 | - if(flg_bb) { | |
43586 | - char **ap; | |
43587 | - char **new; | |
43588 | - | |
43589 | - *argv = name; | |
43590 | - if(strcmp(name, "busybox")) { | |
43591 | - for (ap = argv; *ap; ap++); | |
43592 | - ap = new = xmalloc((ap - argv + 2) * sizeof(char *)); | |
43593 | - *ap++ = cmd = "/bin/busybox"; | |
43594 | - while ((*ap++ = *argv++)); | |
43595 | - argv = new; | |
43596 | - repeated++; | |
43597 | - } else { | |
43598 | - cmd = "/bin/busybox"; | |
43599 | - } | |
43600 | + if(find_applet_by_name(cmd) != NULL) { | |
43601 | + /* re-exec ourselves with the new arguments */ | |
43602 | + execve("/proc/self/exe",argv,envp); | |
43603 | + /* If proc isn't mounted, try hardcoded path to busybox binary*/ | |
43604 | + execve("/bin/busybox",argv,envp); | |
43605 | + /* If they called chroot or otherwise made the binary no longer | |
43606 | + * executable, fall through */ | |
43607 | } | |
43608 | #endif | |
43609 | ||
43610 | @@ -12583,17 +12569,34 @@ | |
43611 | char *prompt; | |
43612 | const char *ifs; | |
43613 | char *p; | |
43614 | +#if defined(CONFIG_ASH_TIMEOUT) | |
43615 | + fd_set set; | |
43616 | + int timeout; | |
43617 | + struct timeval timeout_struct; | |
43618 | + struct termios tty, old_tty; | |
43619 | +#endif | |
43620 | int startword; | |
43621 | int status; | |
43622 | int i; | |
43623 | ||
43624 | rflag = 0; | |
43625 | prompt = NULL; | |
43626 | - while ((i = nextopt("p:r")) != '\0') { | |
43627 | +#if defined(CONFIG_ASH_TIMEOUT) | |
43628 | + timeout = 0; | |
43629 | + | |
43630 | + while ((i = nextopt("p:rt:")) != '\0') | |
43631 | +#else | |
43632 | + while ((i = nextopt("p:r")) != '\0') | |
43633 | +#endif | |
43634 | + { | |
43635 | if (i == 'p') | |
43636 | prompt = optionarg; | |
43637 | - else | |
43638 | + else if (i == 'r') | |
43639 | rflag = 1; | |
43640 | +#if defined(CONFIG_ASH_TIMEOUT) | |
43641 | + else | |
43642 | + timeout = atoi(optionarg); | |
43643 | +#endif | |
43644 | } | |
43645 | if (prompt && isatty(0)) { | |
43646 | out2str(prompt); | |
43647 | @@ -12602,11 +12605,53 @@ | |
43648 | error("arg count"); | |
43649 | if ((ifs = bltinlookup("IFS")) == NULL) | |
43650 | ifs = defifs; | |
43651 | +#if defined(CONFIG_ASH_TIMEOUT) | |
43652 | + c = 0; | |
43653 | +#endif | |
43654 | status = 0; | |
43655 | startword = 1; | |
43656 | backslash = 0; | |
43657 | + | |
43658 | STARTSTACKSTR(p); | |
43659 | - for (;;) { | |
43660 | +#if defined(CONFIG_ASH_TIMEOUT) | |
43661 | + if (timeout > 0) { | |
43662 | + tcgetattr(0, &tty); | |
43663 | + old_tty = tty; | |
43664 | + | |
43665 | + /* cfmakeraw(...) disables too much; we just do this instead. */ | |
43666 | + tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); | |
43667 | + tcsetattr(0, TCSANOW, &tty); | |
43668 | + | |
43669 | + FD_ZERO (&set); | |
43670 | + FD_SET (0, &set); | |
43671 | + | |
43672 | + timeout_struct.tv_sec = timeout; | |
43673 | + timeout_struct.tv_usec = 0; | |
43674 | + | |
43675 | + if ((i = select (FD_SETSIZE, &set, NULL, NULL, &timeout_struct)) == 1) | |
43676 | + { | |
43677 | + read(0, &c, 1); | |
43678 | + if(c == '\n' || c == 4) /* Handle newlines and EOF */ | |
43679 | + i = 0; /* Don't read further... */ | |
43680 | + else | |
43681 | + STPUTC(c, p); /* Keep reading... */ | |
43682 | + } | |
43683 | + tcsetattr(0, TCSANOW, &old_tty); | |
43684 | + | |
43685 | + /* Echo the character so the user knows it was read... | |
43686 | + Yes, this can be done by setting the ECHO flag, but that | |
43687 | + echoes ^D and other control characters at this state */ | |
43688 | + if(c != 0) | |
43689 | + write(1, &c, 1); | |
43690 | + | |
43691 | + } else | |
43692 | + i = 1; | |
43693 | + | |
43694 | + for (;i == 1;) | |
43695 | +#else | |
43696 | + for (;;) | |
43697 | +#endif | |
43698 | + { | |
43699 | if (read(0, &c, 1) != 1) { | |
43700 | status = 1; | |
43701 | break; | |
43702 | diff -Nur busybox-1.00/shell/lash.c busybox/shell/lash.c | |
43703 | --- busybox-1.00/shell/lash.c 2004-08-16 10:38:34.000000000 +0200 | |
43704 | +++ busybox/shell/lash.c 2005-06-04 08:20:11.000000000 +0200 | |
43705 | @@ -1277,11 +1277,17 @@ | |
43706 | name = child->argv[0]; | |
43707 | ||
43708 | { | |
43709 | - char** argv_l=child->argv; | |
43710 | - int argc_l; | |
43711 | - for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++); | |
43712 | - optind = 1; | |
43713 | - run_applet_by_name(name, argc_l, child->argv); | |
43714 | + char** argv_l=child->argv; | |
43715 | + int argc_l; | |
43716 | +#ifdef _NEWLIB_VERSION | |
43717 | + /* newlib uses __getopt_initialized for getopt() in | |
43718 | + * addition to optind, see newlib/libc/sys/linux/getopt.c | |
43719 | + */ | |
43720 | + extern int __getopt_initialized = 0; | |
43721 | +#endif | |
43722 | + for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++); | |
43723 | + optind = 1; | |
43724 | + run_applet_by_name(name, argc_l, child->argv); | |
43725 | } | |
43726 | #endif | |
43727 | ||
43728 | diff -Nur busybox-1.00/sysdeps/linux/Config.in busybox/sysdeps/linux/Config.in | |
43729 | --- busybox-1.00/sysdeps/linux/Config.in 2004-05-25 13:30:22.000000000 +0200 | |
43730 | +++ busybox/sysdeps/linux/Config.in 2005-06-04 08:20:20.000000000 +0200 | |
43731 | @@ -113,6 +113,13 @@ | |
43732 | ||
43733 | cp = --- # disable applet cp for everyone | |
43734 | ||
43735 | + The file has to be owned by user root, group root and has to be | |
43736 | + writeable only by root: | |
43737 | + (chown 0.0 /etc/busybox.conf; chmod 600 /etc/busybox.conf) | |
43738 | + The busybox executable has to be owned by user root, group | |
43739 | + root and has to be setuid root for this to work: | |
43740 | + (chown 0.0 /bin/busybox; chmod 4755 /bin/busybox) | |
43741 | + | |
43742 | Robert 'sandman' Griebl has more information here: | |
43743 | <url: http://www.softforge.de/bb/suid.html >. | |
43744 | ||
43745 | @@ -221,6 +228,7 @@ | |
43746 | source coreutils/Config.in | |
43747 | source console-tools/Config.in | |
43748 | source debianutils/Config.in | |
43749 | +source e2fsprogs/Config.in | |
43750 | source editors/Config.in | |
43751 | source findutils/Config.in | |
43752 | source init/Config.in | |
43753 | @@ -291,4 +299,3 @@ | |
43754 | ||
43755 | ||
43756 | endmenu | |
43757 | - | |
43758 | diff -Nur busybox-1.00/sysklogd/Makefile busybox/sysklogd/Makefile | |
43759 | --- busybox-1.00/sysklogd/Makefile 2004-10-08 09:45:51.000000000 +0200 | |
43760 | +++ busybox/sysklogd/Makefile 2005-06-04 08:20:09.000000000 +0200 | |
43761 | @@ -1,6 +1,6 @@ | |
43762 | # Makefile for busybox | |
43763 | # | |
43764 | -# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | |
43765 | +# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> | |
43766 | # | |
43767 | # This program is free software; you can redistribute it and/or modify | |
43768 | # it under the terms of the GNU General Public License as published by | |
43769 | @@ -18,7 +18,7 @@ | |
43770 | # | |
43771 | ||
43772 | top_srcdir=.. | |
43773 | -top_buildddir=.. | |
43774 | +top_builddir=.. | |
43775 | srcdir=$(top_srcdir)/sysklogd | |
43776 | SYSKLOGD_DIR:=./ | |
43777 | include $(top_builddir)/Rules.mak | |
43778 | @@ -29,4 +29,3 @@ | |
43779 | ||
43780 | clean: | |
43781 | rm -f *.o *.a $(AR_TARGET) | |
43782 | - | |
43783 | diff -Nur busybox-1.00/sysklogd/logger.c busybox/sysklogd/logger.c | |
43784 | --- busybox-1.00/sysklogd/logger.c 2004-08-27 00:18:59.000000000 +0200 | |
43785 | +++ busybox/sysklogd/logger.c 2005-06-04 08:20:09.000000000 +0200 | |
43786 | @@ -127,7 +127,7 @@ | |
43787 | } | |
43788 | } | |
43789 | ||
43790 | - openlog(name, option, (pri | LOG_FACMASK)); | |
43791 | + openlog(name, option, 0); | |
43792 | if (optind == argc) { | |
43793 | do { | |
43794 | /* read from stdin */ | |
43795 | @@ -152,8 +152,8 @@ | |
43796 | message = xrealloc(message, len); | |
43797 | if(!i) | |
43798 | message[0] = 0; | |
43799 | - else | |
43800 | - strcat(message, " "); | |
43801 | + else | |
43802 | + strcat(message, " "); | |
43803 | strcat(message, *argv); | |
43804 | argv++; | |
43805 | } | |
43806 | diff -Nur busybox-1.00/testsuite/sed/sed-branch-conditional-inverted busybox/testsuite/sed/sed-branch-conditional-inverted | |
43807 | --- busybox-1.00/testsuite/sed/sed-branch-conditional-inverted 1970-01-01 01:00:00.000000000 +0100 | |
43808 | +++ busybox/testsuite/sed/sed-branch-conditional-inverted 2005-06-04 08:20:19.000000000 +0200 | |
43809 | @@ -0,0 +1,14 @@ | |
43810 | +busybox sed 's/a/1/;T notone;p;: notone;p'>output <<EOF | |
43811 | +a | |
43812 | +b | |
43813 | +c | |
43814 | +EOF | |
43815 | +cmp -s output - <<EOF | |
43816 | +1 | |
43817 | +1 | |
43818 | +1 | |
43819 | +b | |
43820 | +b | |
43821 | +c | |
43822 | +c | |
43823 | +EOF | |
43824 | diff -Nur busybox-1.00/util-linux/Config.in busybox/util-linux/Config.in | |
43825 | --- busybox-1.00/util-linux/Config.in 2004-05-19 13:06:20.000000000 +0200 | |
43826 | +++ busybox/util-linux/Config.in 2005-06-04 08:20:22.000000000 +0200 | |
43827 | @@ -5,7 +5,6 @@ | |
43828 | ||
43829 | menu "Linux System Utilities" | |
43830 | ||
43831 | - | |
43832 | config CONFIG_DMESG | |
43833 | bool "dmesg" | |
43834 | default n | |
43835 | @@ -27,7 +26,6 @@ | |
43836 | interface to access a graphics display. Enable this option | |
43837 | if you wish to enable the 'fbset' utility. | |
43838 | ||
43839 | - | |
43840 | config CONFIG_FEATURE_FBSET_FANCY | |
43841 | bool " Turn on extra fbset options" | |
43842 | default n | |
43843 | @@ -353,5 +351,11 @@ | |
43844 | value is /etc/mtab, which is where this file is located on most desktop | |
43845 | Linux systems. | |
43846 | ||
43847 | +config CONFIG_READPROFILE | |
43848 | + bool "readprofile" | |
43849 | + default n | |
43850 | + help | |
43851 | + This allows you to parse /proc/profile for basic profiling. | |
43852 | + | |
43853 | endmenu | |
43854 | ||
43855 | diff -Nur busybox-1.00/util-linux/Makefile busybox/util-linux/Makefile | |
43856 | --- busybox-1.00/util-linux/Makefile 2004-10-08 09:46:08.000000000 +0200 | |
43857 | +++ busybox/util-linux/Makefile 2005-06-04 08:20:22.000000000 +0200 | |
43858 | @@ -1,6 +1,6 @@ | |
43859 | # Makefile for busybox | |
43860 | # | |
43861 | -# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | |
43862 | +# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> | |
43863 | # | |
43864 | # This program is free software; you can redistribute it and/or modify | |
43865 | # it under the terms of the GNU General Public License as published by | |
43866 | @@ -18,7 +18,7 @@ | |
43867 | # | |
43868 | ||
43869 | top_srcdir=.. | |
43870 | -top_buildddir=.. | |
43871 | +top_builddir=.. | |
43872 | srcdir=$(top_srcdir)/util-linux | |
43873 | UTILLINUX_DIR:=./ | |
43874 | include $(top_builddir)/Rules.mak | |
43875 | @@ -29,4 +29,3 @@ | |
43876 | ||
43877 | clean: | |
43878 | rm -f *.o *.a $(AR_TARGET) | |
43879 | - | |
43880 | diff -Nur busybox-1.00/util-linux/Makefile.in busybox/util-linux/Makefile.in | |
43881 | --- busybox-1.00/util-linux/Makefile.in 2004-10-08 09:46:08.000000000 +0200 | |
43882 | +++ busybox/util-linux/Makefile.in 2005-06-04 08:20:22.000000000 +0200 | |
43883 | @@ -44,6 +44,7 @@ | |
43884 | UTILLINUX-$(CONFIG_RDATE) +=rdate.o | |
43885 | UTILLINUX-$(CONFIG_SWAPONOFF) +=swaponoff.o | |
43886 | UTILLINUX-$(CONFIG_UMOUNT) +=umount.o | |
43887 | +UTILLINUX-$(CONFIG_READPROFILE) +=readprofile.o | |
43888 | ||
43889 | libraries-y+=$(UTILLINUX_DIR)$(UTILLINUX_AR) | |
43890 | ||
43891 | @@ -63,4 +64,3 @@ | |
43892 | ||
43893 | endif | |
43894 | endif | |
43895 | - | |
43896 | diff -Nur busybox-1.00/util-linux/hwclock.c busybox/util-linux/hwclock.c | |
43897 | --- busybox-1.00/util-linux/hwclock.c 2004-04-14 19:51:38.000000000 +0200 | |
43898 | +++ busybox/util-linux/hwclock.c 2005-06-04 08:20:22.000000000 +0200 | |
43899 | @@ -46,7 +46,7 @@ | |
43900 | int tm_yday; | |
43901 | int tm_isdst; | |
43902 | }; | |
43903 | - | |
43904 | + | |
43905 | #define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time */ | |
43906 | #define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time */ | |
43907 | ||
43908 | @@ -182,11 +182,11 @@ | |
43909 | return utc; | |
43910 | } | |
43911 | ||
43912 | -#define HWCLOCK_OPT_LOCALTIME 1 | |
43913 | -#define HWCLOCK_OPT_UTC 2 | |
43914 | -#define HWCLOCK_OPT_SHOW 4 | |
43915 | -#define HWCLOCK_OPT_HCTOSYS 8 | |
43916 | -#define HWCLOCK_OPT_SYSTOHC 16 | |
43917 | +#define HWCLOCK_OPT_LOCALTIME 0x01 | |
43918 | +#define HWCLOCK_OPT_UTC 0x02 | |
43919 | +#define HWCLOCK_OPT_SHOW 0x04 | |
43920 | +#define HWCLOCK_OPT_HCTOSYS 0x08 | |
43921 | +#define HWCLOCK_OPT_SYSTOHC 0x10 | |
43922 | ||
43923 | extern int hwclock_main ( int argc, char **argv ) | |
43924 | { | |
43925 | @@ -208,16 +208,16 @@ | |
43926 | bb_opt_complementaly = "r~ws:w~rs:s~wr:l~u:u~l"; | |
43927 | opt = bb_getopt_ulflags(argc, argv, "lursw"); | |
43928 | /* Check only one mode was given */ | |
43929 | - if(opt & 0x80000000UL) { | |
43930 | + if(opt & BB_GETOPT_ERROR) { | |
43931 | bb_show_usage(); | |
43932 | } | |
43933 | ||
43934 | /* If -u or -l wasn't given check if we are using utc */ | |
43935 | - if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) | |
43936 | + if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) | |
43937 | utc = opt & HWCLOCK_OPT_UTC; | |
43938 | else | |
43939 | utc = check_utc(); | |
43940 | - | |
43941 | + | |
43942 | if (opt & HWCLOCK_OPT_HCTOSYS) { | |
43943 | return to_sys_clock ( utc ); | |
43944 | } | |
43945 | diff -Nur busybox-1.00/util-linux/readprofile.c busybox/util-linux/readprofile.c | |
43946 | --- busybox-1.00/util-linux/readprofile.c 1970-01-01 01:00:00.000000000 +0100 | |
43947 | +++ busybox/util-linux/readprofile.c 2005-06-04 08:20:22.000000000 +0200 | |
43948 | @@ -0,0 +1,302 @@ | |
43949 | +/* | |
43950 | + * readprofile.c - used to read /proc/profile | |
43951 | + * | |
43952 | + * Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it) | |
43953 | + * | |
43954 | + * This program is free software; you can redistribute it and/or modify | |
43955 | + * it under the terms of the GNU General Public License as published by | |
43956 | + * the Free Software Foundation; either version 2 of the License, or | |
43957 | + * (at your option) any later version. | |
43958 | + * | |
43959 | + * This program is distributed in the hope that it will be useful, | |
43960 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
43961 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
43962 | + * GNU General Public License for more details. | |
43963 | + * | |
43964 | + * You should have received a copy of the GNU General Public License | |
43965 | + * along with this program; if not, write to the Free Software | |
43966 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
43967 | + */ | |
43968 | + | |
43969 | +/* | |
43970 |