Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 14  Line 14 
14  #include "libbb.h"  #include "libbb.h"
15  #include "unarchive.h"  #include "unarchive.h"
16    
17    /* 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  #if ENABLE_FEATURE_CPIO_O  #if ENABLE_FEATURE_CPIO_O
107  static off_t cpio_pad4(off_t size)  static off_t cpio_pad4(off_t size)
108  {  {
# Line 28  static off_t cpio_pad4(off_t size) Line 117  static off_t cpio_pad4(off_t size)
117    
118  /* Return value will become exit code.  /* Return value will become exit code.
119   * It's ok to exit instead of return. */   * It's ok to exit instead of return. */
120  static int cpio_o(void)  static NOINLINE int cpio_o(void)
121  {  {
122   static const char trailer[] ALIGN1 = "TRAILER!!!";   static const char trailer[] ALIGN1 = "TRAILER!!!";
123   struct name_s {   struct name_s {
# Line 49  static int cpio_o(void) Line 138  static int cpio_o(void)
138   char *line;   char *line;
139   struct stat st;   struct stat st;
140    
141   line = xmalloc_fgetline(stdin);   line = (option_mask32 & CPIO_OPT_NUL_TERMINATED)
142     ? bb_get_chunk_from_file(stdin, NULL)
143     : xmalloc_fgetline(stdin);
144    
145   if (line) {   if (line) {
146   /* Strip leading "./[./]..." from the filename */   /* Strip leading "./[./]..." from the filename */
# Line 62  static int cpio_o(void) Line 153  static int cpio_o(void)
153   free(line);   free(line);
154   continue;   continue;
155   }   }
156   if (lstat(name, &st)) {   if ((option_mask32 & CPIO_OPT_DEREF)
157     ? stat(name, &st)
158     : lstat(name, &st)
159     ) {
160   abort_cpio_o:   abort_cpio_o:
161   bb_simple_perror_msg_and_die(name);   bb_simple_perror_msg_and_die(name);
162   }   }
# Line 158  static int cpio_o(void) Line 252  static int cpio_o(void)
252   free(lpath);   free(lpath);
253   } else { /* S_ISREG */   } else { /* S_ISREG */
254   int fd = xopen(name, O_RDONLY);   int fd = xopen(name, O_RDONLY);
255   fflush(stdout);   fflush_all();
256   /* We must abort if file got shorter too! */   /* We must abort if file got shorter too! */
257   bb_copyfd_exact_size(fd, STDOUT_FILENO, st.st_size);   bb_copyfd_exact_size(fd, STDOUT_FILENO, st.st_size);
258   bytes += st.st_size;   bytes += st.st_size;
# Line 179  static int cpio_o(void) Line 273  static int cpio_o(void)
273  }  }
274  #endif  #endif
275    
 /* GNU cpio 2.9 --help (abridged):  
   
  Modes:  
   -i, --extract              Extract files from an archive  
   -o, --create               Create the archive  
   -p, --pass-through         Copy-pass mode [was ist das?!]  
   -t, --list                 List the archive  
   
  Options valid in any mode:  
       --block-size=SIZE      I/O block size = SIZE * 512 bytes  
   -B                         I/O block size = 5120 bytes  
   -c                         Use the old portable (ASCII) archive format  
   -C, --io-size=NUMBER       I/O block size in bytes  
   -f, --nonmatching          Only copy files that do not match given pattern  
   -F, --file=FILE            Use FILE instead of standard input or output  
   -H, --format=FORMAT        Use given archive FORMAT  
   -M, --message=STRING       Print STRING when the end of a volume of the  
                              backup media is reached  
   -n, --numeric-uid-gid      If -v, show numeric UID and GID  
       --quiet                Do not print the number of blocks copied  
       --rsh-command=COMMAND  Use remote COMMAND instead of rsh  
   -v, --verbose              Verbosely list the files processed  
   -V, --dot                  Print a "." for each file processed  
   -W, --warning=FLAG         Control warning display: 'none','truncate','all';  
                              multiple options accumulate  
   
  Options valid only in --extract mode:  
   -b, --swap                 Swap both halfwords of words and bytes of  
                              halfwords in the data (equivalent to -sS)  
   -r, --rename               Interactively rename files  
   -s, --swap-bytes           Swap the bytes of each halfword in the files  
   -S, --swap-halfwords       Swap the halfwords of each word (4 bytes)  
       --to-stdout            Extract files to standard output  
   -E, --pattern-file=FILE    Read additional patterns specifying filenames to  
                              extract or list from FILE  
       --only-verify-crc      Verify CRC's, don't actually extract the files  
   
  Options valid only in --create mode:  
   -A, --append               Append to an existing archive  
   -O FILE                    File to use instead of standard output  
   
  Options valid only in --pass-through mode:  
   -l, --link                 Link files instead of copying them, when possible  
   
  Options valid in --extract and --create modes:  
       --absolute-filenames   Do not strip file system prefix components from  
                              the file names  
       --no-absolute-filenames Create all files relative to the current dir  
   
  Options valid in --create and --pass-through modes:  
   -0, --null                 A list of filenames is terminated by a NUL  
   -a, --reset-access-time    Reset the access times of files after reading them  
   -I FILE                    File to use instead of standard input  
   -L, --dereference          Dereference symbolic links (copy the files  
                              that they point to instead of copying the links)  
   -R, --owner=[USER][:.][GROUP] Set owner of created files  
   
  Options valid in --extract and --pass-through modes:  
   -d, --make-directories     Create leading directories where needed  
   -m, --preserve-modification-time  Retain mtime when creating files  
       --no-preserve-owner    Do not change the ownership of the files  
       --sparse               Write files with blocks of zeros as sparse files  
   -u, --unconditional        Replace all files unconditionally  
  */  
   
276  int cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;  int cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
277  int cpio_main(int argc UNUSED_PARAM, char **argv)  int cpio_main(int argc UNUSED_PARAM, char **argv)
278  {  {
279   archive_handle_t *archive_handle;   archive_handle_t *archive_handle;
280   char *cpio_filename;   char *cpio_filename;
281   USE_FEATURE_CPIO_O(const char *cpio_fmt = "";)   IF_FEATURE_CPIO_O(const char *cpio_fmt = "";)
282   unsigned opt;   unsigned opt;
  enum {  
  CPIO_OPT_EXTRACT            = (1 << 0),  
  CPIO_OPT_TEST               = (1 << 1),  
  CPIO_OPT_UNCONDITIONAL      = (1 << 2),  
  CPIO_OPT_VERBOSE            = (1 << 3),  
  CPIO_OPT_FILE               = (1 << 4),  
  CPIO_OPT_CREATE_LEADING_DIR = (1 << 5),  
  CPIO_OPT_PRESERVE_MTIME     = (1 << 6),  
  CPIO_OPT_CREATE             = (1 << 7),  
  CPIO_OPT_FORMAT             = (1 << 8),  
  };  
283    
284  #if ENABLE_GETOPT_LONG  #if ENABLE_LONG_OPTS
285   applet_long_options =   applet_long_options =
286   "extract\0"      No_argument       "i"   "extract\0"      No_argument       "i"
287   "list\0"         No_argument       "t"   "list\0"         No_argument       "t"
288  #if ENABLE_FEATURE_CPIO_O  #if ENABLE_FEATURE_CPIO_O
289   "create\0"       No_argument       "o"   "create\0"       No_argument       "o"
290   "format\0"       Required_argument "H"   "format\0"       Required_argument "H"
291    #if ENABLE_FEATURE_CPIO_P
292     "pass-through\0" No_argument       "p"
293    #endif
294  #endif  #endif
295     "verbose\0"      No_argument       "v"
296     "quiet\0"        No_argument       "\xff"
297     "to-stdout\0"    No_argument       "\xfe"
298   ;   ;
299  #endif  #endif
300    
  /* Initialize */  
301   archive_handle = init_handle();   archive_handle = init_handle();
302   archive_handle->src_fd = STDIN_FILENO;   /* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */
  archive_handle->seek = seek_by_read;  
303   archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;   archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
304    
305  #if ENABLE_FEATURE_CPIO_O   /* As of now we do not enforce this: */
306   opt = getopt32(argv, "ituvF:dmoH:", &cpio_filename, &cpio_fmt);   /* -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    
310    #if !ENABLE_FEATURE_CPIO_O
311     /* no parameters */
312     opt_complementary = "=0";
313     opt = getopt32(argv, OPTION_STR, &cpio_filename);
314     if (opt & CPIO_OPT_FILE) { /* -F */
315     xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
316     }
317    #else
318     /* _exactly_ one parameter for -p, thus <= 1 param if -p is allowed */
319     opt_complementary = ENABLE_FEATURE_CPIO_P ? "?1" : "=0";
320     opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt);
321     argv += optind;
322     if ((opt & (CPIO_OPT_FILE|CPIO_OPT_CREATE)) == CPIO_OPT_FILE) { /* -F without -o */
323     xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
324     }
325     if (opt & CPIO_OPT_PASSTHROUGH) {
326     pid_t pid;
327     struct fd_pair pp;
328    
329     if (argv[0] == NULL)
330     bb_show_usage();
331     if (opt & CPIO_OPT_CREATE_LEADING_DIR)
332     mkdir(argv[0], 0777);
333     /* Crude existence check:
334     * close(xopen(argv[0], O_RDONLY | O_DIRECTORY));
335     * We can also xopen, fstat, IS_DIR, later fchdir.
336     * This would check for existence earlier and cleaner.
337     * As it stands now, if we fail xchdir later,
338     * child dies on EPIPE, unless it caught
339     * a diffrerent problem earlier.
340     * This is good enough for now.
341     */
342    #if !BB_MMU
343     pp.rd = 3;
344     pp.wr = 4;
345     if (!re_execed) {
346     close(3);
347     close(4);
348     xpiped_pair(pp);
349     }
350    #else
351     xpiped_pair(pp);
352    #endif
353     pid = fork_or_rexec(argv - optind);
354     if (pid == 0) { /* child */
355     close(pp.rd);
356     xmove_fd(pp.wr, STDOUT_FILENO);
357     goto dump;
358     }
359     /* parent */
360     xchdir(*argv++);
361     close(pp.wr);
362     xmove_fd(pp.rd, STDIN_FILENO);
363     //opt &= ~CPIO_OPT_PASSTHROUGH;
364     opt |= CPIO_OPT_EXTRACT;
365     goto skip;
366     }
367     /* -o */
368   if (opt & CPIO_OPT_CREATE) {   if (opt & CPIO_OPT_CREATE) {
369   if (*cpio_fmt != 'n')   if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */
370   bb_show_usage();   bb_show_usage();
371   if (opt & CPIO_OPT_FILE) {   if (opt & CPIO_OPT_FILE) {
372   fclose(stdout);   xmove_fd(xopen3(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666), STDOUT_FILENO);
  stdout = fopen_for_write(cpio_filename);  
  /* Paranoia: I don't trust libc that much */  
  xdup2(fileno(stdout), STDOUT_FILENO);  
373   }   }
374     dump:
375   return cpio_o();   return cpio_o();
376   }   }
377  #else   skip:
  opt = getopt32(argv, "ituvF:dm", &cpio_filename);  
378  #endif  #endif
  argv += optind;  
379    
380   /* One of either extract or test options must be given */   /* One of either extract or test options must be given */
381   if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {   if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
# Line 306  int cpio_main(int argc UNUSED_PARAM, cha Line 384  int cpio_main(int argc UNUSED_PARAM, cha
384    
385   if (opt & CPIO_OPT_TEST) {   if (opt & CPIO_OPT_TEST) {
386   /* if both extract and test options are given, ignore extract option */   /* if both extract and test options are given, ignore extract option */
387   if (opt & CPIO_OPT_EXTRACT) {   opt &= ~CPIO_OPT_EXTRACT;
  opt &= ~CPIO_OPT_EXTRACT;  
  }  
388   archive_handle->action_header = header_list;   archive_handle->action_header = header_list;
389   }   }
390   if (opt & CPIO_OPT_EXTRACT) {   if (opt & CPIO_OPT_EXTRACT) {
391   archive_handle->action_data = data_extract_all;   archive_handle->action_data = data_extract_all;
392     if (opt & CPIO_OPT_2STDOUT)
393     archive_handle->action_data = data_extract_to_stdout;
394   }   }
395   if (opt & CPIO_OPT_UNCONDITIONAL) {   if (opt & CPIO_OPT_UNCONDITIONAL) {
396   archive_handle->ah_flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;   archive_handle->ah_flags |= ARCHIVE_UNLINK_OLD;
397   archive_handle->ah_flags &= ~ARCHIVE_EXTRACT_NEWER;   archive_handle->ah_flags &= ~ARCHIVE_EXTRACT_NEWER;
398   }   }
399   if (opt & CPIO_OPT_VERBOSE) {   if (opt & CPIO_OPT_VERBOSE) {
# Line 325  int cpio_main(int argc UNUSED_PARAM, cha Line 403  int cpio_main(int argc UNUSED_PARAM, cha
403   archive_handle->action_header = header_list;   archive_handle->action_header = header_list;
404   }   }
405   }   }
  if (opt & CPIO_OPT_FILE) { /* -F */  
  archive_handle->src_fd = xopen(cpio_filename, O_RDONLY);  
  archive_handle->seek = seek_by_jump;  
  }  
406   if (opt & CPIO_OPT_CREATE_LEADING_DIR) {   if (opt & CPIO_OPT_CREATE_LEADING_DIR) {
407   archive_handle->ah_flags |= ARCHIVE_CREATE_LEADING_DIRS;   archive_handle->ah_flags |= ARCHIVE_CREATE_LEADING_DIRS;
408   }   }
409   if (opt & CPIO_OPT_PRESERVE_MTIME) {   if (opt & CPIO_OPT_PRESERVE_MTIME) {
410   archive_handle->ah_flags |= ARCHIVE_PRESERVE_DATE;   archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE;
411   }   }
412    
413   while (*argv) {   while (*argv) {
414   archive_handle->filter = filter_accept_list;   archive_handle->filter = filter_accept_list;
415   llist_add_to(&(archive_handle->accept), *argv);   llist_add_to(&archive_handle->accept, *argv);
416   argv++;   argv++;
417   }   }
418    
419   /* see get_header_cpio */   /* see get_header_cpio */
420   archive_handle->ah_priv[2] = (void*) ~(ptrdiff_t)0;   archive_handle->cpio__blocks = (off_t)-1;
421   while (get_header_cpio(archive_handle) == EXIT_SUCCESS)   while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
422   continue;   continue;
423    
424   if (archive_handle->ah_priv[2] != (void*) ~(ptrdiff_t)0)   if (archive_handle->cpio__blocks != (off_t)-1
425   printf("%lu blocks\n", (unsigned long)(ptrdiff_t)(archive_handle->ah_priv[2]));   && !(opt & CPIO_OPT_QUIET)
426     ) {
427     printf("%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks);
428     }
429    
430   return EXIT_SUCCESS;   return EXIT_SUCCESS;
431  }  }

Legend:
Removed from v.983  
changed lines
  Added in v.984