Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/archival/cpio.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/archival/cpio.c
r1765 r2725 5 5 * Copyright (C) 2001 by Glenn McGrath 6 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 * 9 9 * Limitations: 10 * 11 * 10 * Doesn't check CRC's 11 * Only supports new ASCII and CRC formats 12 12 * 13 13 */ 14 14 #include "libbb.h" 15 #include "unarchive.h" 16 17 #define CPIO_OPT_EXTRACT 0x01 18 #define CPIO_OPT_TEST 0x02 19 #define CPIO_OPT_UNCONDITIONAL 0x04 20 #define CPIO_OPT_VERBOSE 0x08 21 #define CPIO_OPT_FILE 0x10 22 #define CPIO_OPT_CREATE_LEADING_DIR 0x20 23 #define CPIO_OPT_PRESERVE_MTIME 0x40 24 25 int cpio_main(int argc, char **argv); 26 int cpio_main(int argc, char **argv) 15 #include "archive.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 107 static off_t cpio_pad4(off_t size) 108 { 109 int i; 110 111 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 static NOINLINE int cpio_o(void) 121 { 122 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 line = (option_mask32 & CPIO_OPT_NUL_TERMINATED) 142 ? bb_get_chunk_from_file(stdin, NULL) 143 : xmalloc_fgetline(stdin); 144 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 if ((option_mask32 & CPIO_OPT_DEREF) 157 ? stat(name, &st) 158 : lstat(name, &st) 159 ) { 160 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 fflush_all(); 256 /* 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) 27 278 { 28 279 archive_handle_t *archive_handle; 29 char *cpio_filename = NULL; 280 char *cpio_filename; 281 IF_FEATURE_CPIO_O(const char *cpio_fmt = "";) 30 282 unsigned opt; 31 283 32 /* Initialise */ 284 #if ENABLE_LONG_OPTS 285 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 #if ENABLE_FEATURE_CPIO_P 292 "pass-through\0" No_argument "p" 293 #endif 294 #endif 295 "verbose\0" No_argument "v" 296 "quiet\0" No_argument "\xff" 297 "to-stdout\0" No_argument "\xfe" 298 ; 299 #endif 300 33 301 archive_handle = init_handle(); 34 archive_handle->src_fd = STDIN_FILENO; 35 archive_handle->seek = seek_by_read; 36 archive_handle->flags = ARCHIVE_EXTRACT_NEWER | ARCHIVE_PRESERVE_DATE; 37 38 opt = getopt32(argv, "ituvF:dm", &cpio_filename); 302 /* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */ 303 archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER; 304 305 /* 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 310 #if !ENABLE_FEATURE_CPIO_O 311 opt = getopt32(argv, OPTION_STR, &cpio_filename); 312 argv += optind; 313 if (opt & CPIO_OPT_FILE) { /* -F */ 314 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); 315 } 316 #else 317 opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt); 318 argv += optind; 319 if ((opt & (CPIO_OPT_FILE|CPIO_OPT_CREATE)) == CPIO_OPT_FILE) { /* -F without -o */ 320 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); 321 } 322 if (opt & CPIO_OPT_PASSTHROUGH) { 323 pid_t pid; 324 struct fd_pair pp; 325 326 if (argv[0] == NULL) 327 bb_show_usage(); 328 if (opt & CPIO_OPT_CREATE_LEADING_DIR) 329 mkdir(argv[0], 0777); 330 /* Crude existence check: 331 * close(xopen(argv[0], O_RDONLY | O_DIRECTORY)); 332 * We can also xopen, fstat, IS_DIR, later fchdir. 333 * This would check for existence earlier and cleaner. 334 * As it stands now, if we fail xchdir later, 335 * child dies on EPIPE, unless it caught 336 * a diffrerent problem earlier. 337 * This is good enough for now. 338 */ 339 #if !BB_MMU 340 pp.rd = 3; 341 pp.wr = 4; 342 if (!re_execed) { 343 close(3); 344 close(4); 345 xpiped_pair(pp); 346 } 347 #else 348 xpiped_pair(pp); 349 #endif 350 pid = fork_or_rexec(argv - optind); 351 if (pid == 0) { /* child */ 352 close(pp.rd); 353 xmove_fd(pp.wr, STDOUT_FILENO); 354 goto dump; 355 } 356 /* parent */ 357 xchdir(*argv++); 358 close(pp.wr); 359 xmove_fd(pp.rd, STDIN_FILENO); 360 //opt &= ~CPIO_OPT_PASSTHROUGH; 361 opt |= CPIO_OPT_EXTRACT; 362 goto skip; 363 } 364 /* -o */ 365 if (opt & CPIO_OPT_CREATE) { 366 if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */ 367 bb_show_usage(); 368 if (opt & CPIO_OPT_FILE) { 369 xmove_fd(xopen(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); 370 } 371 dump: 372 return cpio_o(); 373 } 374 skip: 375 #endif 39 376 40 377 /* One of either extract or test options must be given */ … … 45 382 if (opt & CPIO_OPT_TEST) { 46 383 /* if both extract and test options are given, ignore extract option */ 47 if (opt & CPIO_OPT_EXTRACT) { 48 opt &= ~CPIO_OPT_EXTRACT; 49 } 384 opt &= ~CPIO_OPT_EXTRACT; 50 385 archive_handle->action_header = header_list; 51 386 } 52 387 if (opt & CPIO_OPT_EXTRACT) { 53 388 archive_handle->action_data = data_extract_all; 389 if (opt & CPIO_OPT_2STDOUT) 390 archive_handle->action_data = data_extract_to_stdout; 54 391 } 55 392 if (opt & CPIO_OPT_UNCONDITIONAL) { 56 archive_handle-> flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;57 archive_handle-> flags &= ~ARCHIVE_EXTRACT_NEWER;393 archive_handle->ah_flags |= ARCHIVE_UNLINK_OLD; 394 archive_handle->ah_flags &= ~ARCHIVE_EXTRACT_NEWER; 58 395 } 59 396 if (opt & CPIO_OPT_VERBOSE) { … … 64 401 } 65 402 } 66 if (cpio_filename) { /* CPIO_OPT_FILE */67 archive_handle->src_fd = xopen(cpio_filename, O_RDONLY);68 archive_handle->seek = seek_by_jump;69 }70 403 if (opt & CPIO_OPT_CREATE_LEADING_DIR) { 71 archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS; 72 } 73 74 while (optind < argc) { 404 archive_handle->ah_flags |= ARCHIVE_CREATE_LEADING_DIRS; 405 } 406 if (opt & CPIO_OPT_PRESERVE_MTIME) { 407 archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; 408 } 409 410 while (*argv) { 75 411 archive_handle->filter = filter_accept_list; 76 llist_add_to(&(archive_handle->accept), argv[optind]); 77 optind++; 78 } 79 80 while (get_header_cpio(archive_handle) == EXIT_SUCCESS); 412 llist_add_to(&archive_handle->accept, *argv); 413 argv++; 414 } 415 416 /* see get_header_cpio */ 417 archive_handle->cpio__blocks = (off_t)-1; 418 while (get_header_cpio(archive_handle) == EXIT_SUCCESS) 419 continue; 420 421 if (archive_handle->cpio__blocks != (off_t)-1 422 && !(opt & CPIO_OPT_QUIET) 423 ) { 424 fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); 425 } 81 426 82 427 return EXIT_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.