Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/archival/cpio.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1123 - (hide annotations) (download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 9 months ago) by niro
File MIME type: text/plain
File size: 13482 byte(s)
-updated to busybox-1.17.1
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * Mini cpio implementation for busybox
4     *
5     * Copyright (C) 2001 by Glenn McGrath
6     *
7     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8     *
9     * Limitations:
10 niro 816 * Doesn't check CRC's
11     * Only supports new ASCII and CRC formats
12 niro 532 *
13     */
14 niro 816 #include "libbb.h"
15 niro 532 #include "unarchive.h"
16    
17 niro 984 /* GNU cpio 2.9 --help (abridged):
18    
19     Modes:
20     -t, --list List the archive
21     -i, --extract Extract files from an archive
22     -o, --create Create the archive
23     -p, --pass-through Copy-pass mode [was ist das?!]
24    
25     Options valid in any mode:
26     --block-size=SIZE I/O block size = SIZE * 512 bytes
27     -B I/O block size = 5120 bytes
28     -c Use the old portable (ASCII) archive format
29     -C, --io-size=NUMBER I/O block size in bytes
30     -f, --nonmatching Only copy files that do not match given pattern
31     -F, --file=FILE Use FILE instead of standard input or output
32     -H, --format=FORMAT Use given archive FORMAT
33     -M, --message=STRING Print STRING when the end of a volume of the
34     backup media is reached
35     -n, --numeric-uid-gid If -v, show numeric UID and GID
36     --quiet Do not print the number of blocks copied
37     --rsh-command=COMMAND Use remote COMMAND instead of rsh
38     -v, --verbose Verbosely list the files processed
39     -V, --dot Print a "." for each file processed
40     -W, --warning=FLAG Control warning display: 'none','truncate','all';
41     multiple options accumulate
42    
43     Options valid only in --extract mode:
44     -b, --swap Swap both halfwords of words and bytes of
45     halfwords in the data (equivalent to -sS)
46     -r, --rename Interactively rename files
47     -s, --swap-bytes Swap the bytes of each halfword in the files
48     -S, --swap-halfwords Swap the halfwords of each word (4 bytes)
49     --to-stdout Extract files to standard output
50     -E, --pattern-file=FILE Read additional patterns specifying filenames to
51     extract or list from FILE
52     --only-verify-crc Verify CRC's, don't actually extract the files
53    
54     Options valid only in --create mode:
55     -A, --append Append to an existing archive
56     -O FILE File to use instead of standard output
57    
58     Options valid only in --pass-through mode:
59     -l, --link Link files instead of copying them, when possible
60    
61     Options valid in --extract and --create modes:
62     --absolute-filenames Do not strip file system prefix components from
63     the file names
64     --no-absolute-filenames Create all files relative to the current dir
65    
66     Options valid in --create and --pass-through modes:
67     -0, --null A list of filenames is terminated by a NUL
68     -a, --reset-access-time Reset the access times of files after reading them
69     -I FILE File to use instead of standard input
70     -L, --dereference Dereference symbolic links (copy the files
71     that they point to instead of copying the links)
72     -R, --owner=[USER][:.][GROUP] Set owner of created files
73    
74     Options valid in --extract and --pass-through modes:
75     -d, --make-directories Create leading directories where needed
76     -m, --preserve-modification-time Retain mtime when creating files
77     --no-preserve-owner Do not change the ownership of the files
78     --sparse Write files with blocks of zeros as sparse files
79     -u, --unconditional Replace all files unconditionally
80     */
81     enum {
82     CPIO_OPT_EXTRACT = (1 << 0),
83     CPIO_OPT_TEST = (1 << 1),
84     CPIO_OPT_NUL_TERMINATED = (1 << 2),
85     CPIO_OPT_UNCONDITIONAL = (1 << 3),
86     CPIO_OPT_VERBOSE = (1 << 4),
87     CPIO_OPT_CREATE_LEADING_DIR = (1 << 5),
88     CPIO_OPT_PRESERVE_MTIME = (1 << 6),
89     CPIO_OPT_DEREF = (1 << 7),
90     CPIO_OPT_FILE = (1 << 8),
91     OPTBIT_FILE = 8,
92     IF_FEATURE_CPIO_O(OPTBIT_CREATE ,)
93     IF_FEATURE_CPIO_O(OPTBIT_FORMAT ,)
94     IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,)
95     IF_LONG_OPTS( OPTBIT_QUIET ,)
96     IF_LONG_OPTS( OPTBIT_2STDOUT ,)
97     CPIO_OPT_CREATE = IF_FEATURE_CPIO_O((1 << OPTBIT_CREATE )) + 0,
98     CPIO_OPT_FORMAT = IF_FEATURE_CPIO_O((1 << OPTBIT_FORMAT )) + 0,
99     CPIO_OPT_PASSTHROUGH = IF_FEATURE_CPIO_P((1 << OPTBIT_PASSTHROUGH)) + 0,
100     CPIO_OPT_QUIET = IF_LONG_OPTS( (1 << OPTBIT_QUIET )) + 0,
101     CPIO_OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0,
102     };
103    
104     #define OPTION_STR "it0uvdmLF:"
105    
106 niro 816 #if ENABLE_FEATURE_CPIO_O
107     static off_t cpio_pad4(off_t size)
108     {
109     int i;
110 niro 532
111 niro 816 i = (- size) & 3;
112     size += i;
113     while (--i >= 0)
114     bb_putchar('\0');
115     return size;
116     }
117    
118     /* Return value will become exit code.
119     * It's ok to exit instead of return. */
120 niro 984 static NOINLINE int cpio_o(void)
121 niro 532 {
122 niro 816 static const char trailer[] ALIGN1 = "TRAILER!!!";
123     struct name_s {
124     struct name_s *next;
125     char name[1];
126     };
127     struct inodes_s {
128     struct inodes_s *next;
129     struct name_s *names;
130     struct stat st;
131     };
132    
133     struct inodes_s *links = NULL;
134     off_t bytes = 0; /* output bytes count */
135    
136     while (1) {
137     const char *name;
138     char *line;
139     struct stat st;
140    
141 niro 984 line = (option_mask32 & CPIO_OPT_NUL_TERMINATED)
142     ? bb_get_chunk_from_file(stdin, NULL)
143     : xmalloc_fgetline(stdin);
144 niro 816
145     if (line) {
146     /* Strip leading "./[./]..." from the filename */
147     name = line;
148     while (name[0] == '.' && name[1] == '/') {
149     while (*++name == '/')
150     continue;
151     }
152     if (!*name) { /* line is empty */
153     free(line);
154     continue;
155     }
156 niro 984 if ((option_mask32 & CPIO_OPT_DEREF)
157     ? stat(name, &st)
158     : lstat(name, &st)
159     ) {
160 niro 816 abort_cpio_o:
161     bb_simple_perror_msg_and_die(name);
162     }
163    
164     if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode)))
165     st.st_size = 0; /* paranoia */
166    
167     /* Store hardlinks for later processing, dont output them */
168     if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) {
169     struct name_s *n;
170     struct inodes_s *l;
171    
172     /* Do we have this hardlink remembered? */
173     l = links;
174     while (1) {
175     if (l == NULL) {
176     /* Not found: add new item to "links" list */
177     l = xzalloc(sizeof(*l));
178     l->st = st;
179     l->next = links;
180     links = l;
181     break;
182     }
183     if (l->st.st_ino == st.st_ino) {
184     /* found */
185     break;
186     }
187     l = l->next;
188     }
189     /* Add new name to "l->names" list */
190     n = xmalloc(sizeof(*n) + strlen(name));
191     strcpy(n->name, name);
192     n->next = l->names;
193     l->names = n;
194    
195     free(line);
196     continue;
197     }
198    
199     } else { /* line == NULL: EOF */
200     next_link:
201     if (links) {
202     /* Output hardlink's data */
203     st = links->st;
204     name = links->names->name;
205     links->names = links->names->next;
206     /* GNU cpio is reported to emit file data
207     * only for the last instance. Mimic that. */
208     if (links->names == NULL)
209     links = links->next;
210     else
211     st.st_size = 0;
212     /* NB: we leak links->names and/or links,
213     * this is intended (we exit soon anyway) */
214     } else {
215     /* If no (more) hardlinks to output,
216     * output "trailer" entry */
217     name = trailer;
218     /* st.st_size == 0 is a must, but for uniformity
219     * in the output, we zero out everything */
220     memset(&st, 0, sizeof(st));
221     /* st.st_nlink = 1; - GNU cpio does this */
222     }
223     }
224    
225     bytes += printf("070701"
226     "%08X%08X%08X%08X%08X%08X%08X"
227     "%08X%08X%08X%08X" /* GNU cpio uses uppercase hex */
228     /* strlen+1: */ "%08X"
229     /* chksum: */ "00000000" /* (only for "070702" files) */
230     /* name,NUL: */ "%s%c",
231     (unsigned)(uint32_t) st.st_ino,
232     (unsigned)(uint32_t) st.st_mode,
233     (unsigned)(uint32_t) st.st_uid,
234     (unsigned)(uint32_t) st.st_gid,
235     (unsigned)(uint32_t) st.st_nlink,
236     (unsigned)(uint32_t) st.st_mtime,
237     (unsigned)(uint32_t) st.st_size,
238     (unsigned)(uint32_t) major(st.st_dev),
239     (unsigned)(uint32_t) minor(st.st_dev),
240     (unsigned)(uint32_t) major(st.st_rdev),
241     (unsigned)(uint32_t) minor(st.st_rdev),
242     (unsigned)(strlen(name) + 1),
243     name, '\0');
244     bytes = cpio_pad4(bytes);
245    
246     if (st.st_size) {
247     if (S_ISLNK(st.st_mode)) {
248     char *lpath = xmalloc_readlink_or_warn(name);
249     if (!lpath)
250     goto abort_cpio_o;
251     bytes += printf("%s", lpath);
252     free(lpath);
253     } else { /* S_ISREG */
254     int fd = xopen(name, O_RDONLY);
255 niro 984 fflush_all();
256 niro 816 /* We must abort if file got shorter too! */
257     bb_copyfd_exact_size(fd, STDOUT_FILENO, st.st_size);
258     bytes += st.st_size;
259     close(fd);
260     }
261     bytes = cpio_pad4(bytes);
262     }
263    
264     if (!line) {
265     if (name != trailer)
266     goto next_link;
267     /* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */
268     return EXIT_SUCCESS;
269     }
270    
271     free(line);
272     } /* end of "while (1)" */
273     }
274     #endif
275    
276     int cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
277     int cpio_main(int argc UNUSED_PARAM, char **argv)
278     {
279 niro 532 archive_handle_t *archive_handle;
280 niro 816 char *cpio_filename;
281 niro 984 IF_FEATURE_CPIO_O(const char *cpio_fmt = "";)
282 niro 532 unsigned opt;
283    
284 niro 984 #if ENABLE_LONG_OPTS
285 niro 816 applet_long_options =
286     "extract\0" No_argument "i"
287     "list\0" No_argument "t"
288     #if ENABLE_FEATURE_CPIO_O
289     "create\0" No_argument "o"
290     "format\0" Required_argument "H"
291 niro 984 #if ENABLE_FEATURE_CPIO_P
292     "pass-through\0" No_argument "p"
293 niro 816 #endif
294 niro 984 #endif
295     "verbose\0" No_argument "v"
296     "quiet\0" No_argument "\xff"
297     "to-stdout\0" No_argument "\xfe"
298 niro 816 ;
299     #endif
300    
301 niro 532 archive_handle = init_handle();
302 niro 984 /* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */
303 niro 816 archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
304 niro 532
305 niro 984 /* As of now we do not enforce this: */
306     /* -i,-t,-o,-p are mutually exclusive */
307     /* -u,-d,-m make sense only with -i or -p */
308     /* -L makes sense only with -o or -p */
309 niro 532
310 niro 984 #if !ENABLE_FEATURE_CPIO_O
311     /* no parameters */
312     opt_complementary = "=0";
313     opt = getopt32(argv, OPTION_STR, &cpio_filename);
314 niro 1123 argv += optind;
315 niro 984 if (opt & CPIO_OPT_FILE) { /* -F */
316     xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
317     }
318     #else
319     /* _exactly_ one parameter for -p, thus <= 1 param if -p is allowed */
320     opt_complementary = ENABLE_FEATURE_CPIO_P ? "?1" : "=0";
321     opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt);
322     argv += optind;
323     if ((opt & (CPIO_OPT_FILE|CPIO_OPT_CREATE)) == CPIO_OPT_FILE) { /* -F without -o */
324     xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
325     }
326     if (opt & CPIO_OPT_PASSTHROUGH) {
327     pid_t pid;
328     struct fd_pair pp;
329    
330     if (argv[0] == NULL)
331     bb_show_usage();
332     if (opt & CPIO_OPT_CREATE_LEADING_DIR)
333     mkdir(argv[0], 0777);
334     /* Crude existence check:
335     * close(xopen(argv[0], O_RDONLY | O_DIRECTORY));
336     * We can also xopen, fstat, IS_DIR, later fchdir.
337     * This would check for existence earlier and cleaner.
338     * As it stands now, if we fail xchdir later,
339     * child dies on EPIPE, unless it caught
340     * a diffrerent problem earlier.
341     * This is good enough for now.
342     */
343     #if !BB_MMU
344     pp.rd = 3;
345     pp.wr = 4;
346     if (!re_execed) {
347     close(3);
348     close(4);
349     xpiped_pair(pp);
350     }
351     #else
352     xpiped_pair(pp);
353     #endif
354     pid = fork_or_rexec(argv - optind);
355     if (pid == 0) { /* child */
356     close(pp.rd);
357     xmove_fd(pp.wr, STDOUT_FILENO);
358     goto dump;
359     }
360     /* parent */
361     xchdir(*argv++);
362     close(pp.wr);
363     xmove_fd(pp.rd, STDIN_FILENO);
364     //opt &= ~CPIO_OPT_PASSTHROUGH;
365     opt |= CPIO_OPT_EXTRACT;
366     goto skip;
367     }
368     /* -o */
369 niro 816 if (opt & CPIO_OPT_CREATE) {
370 niro 984 if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */
371 niro 816 bb_show_usage();
372     if (opt & CPIO_OPT_FILE) {
373 niro 984 xmove_fd(xopen3(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666), STDOUT_FILENO);
374 niro 816 }
375 niro 984 dump:
376 niro 816 return cpio_o();
377     }
378 niro 984 skip:
379 niro 816 #endif
380    
381 niro 532 /* One of either extract or test options must be given */
382     if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
383     bb_show_usage();
384     }
385    
386     if (opt & CPIO_OPT_TEST) {
387     /* if both extract and test options are given, ignore extract option */
388 niro 984 opt &= ~CPIO_OPT_EXTRACT;
389 niro 532 archive_handle->action_header = header_list;
390     }
391     if (opt & CPIO_OPT_EXTRACT) {
392     archive_handle->action_data = data_extract_all;
393 niro 984 if (opt & CPIO_OPT_2STDOUT)
394     archive_handle->action_data = data_extract_to_stdout;
395 niro 532 }
396     if (opt & CPIO_OPT_UNCONDITIONAL) {
397 niro 984 archive_handle->ah_flags |= ARCHIVE_UNLINK_OLD;
398 niro 816 archive_handle->ah_flags &= ~ARCHIVE_EXTRACT_NEWER;
399 niro 532 }
400     if (opt & CPIO_OPT_VERBOSE) {
401     if (archive_handle->action_header == header_list) {
402     archive_handle->action_header = header_verbose_list;
403     } else {
404     archive_handle->action_header = header_list;
405     }
406     }
407     if (opt & CPIO_OPT_CREATE_LEADING_DIR) {
408 niro 816 archive_handle->ah_flags |= ARCHIVE_CREATE_LEADING_DIRS;
409 niro 532 }
410 niro 816 if (opt & CPIO_OPT_PRESERVE_MTIME) {
411 niro 984 archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE;
412 niro 816 }
413 niro 532
414 niro 816 while (*argv) {
415 niro 532 archive_handle->filter = filter_accept_list;
416 niro 984 llist_add_to(&archive_handle->accept, *argv);
417 niro 816 argv++;
418 niro 532 }
419    
420 niro 816 /* see get_header_cpio */
421 niro 984 archive_handle->cpio__blocks = (off_t)-1;
422 niro 816 while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
423     continue;
424 niro 532
425 niro 984 if (archive_handle->cpio__blocks != (off_t)-1
426     && !(opt & CPIO_OPT_QUIET)
427     ) {
428 niro 986 fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks);
429 niro 984 }
430 niro 816
431 niro 532 return EXIT_SUCCESS;
432     }