void do_tar(int argc, const char ** argv) { const char * options; argc--; argv++; if (argc < 2) { fprintf(stderr, "Too few arguments for tar\n"); return; } extractFlag = FALSE; createFlag = FALSE; listFlag = FALSE; verboseFlag = FALSE; tarName = NULL; tarDev = 0; tarInode = 0; tarFd = -1; /* * Parse the options. */ options = *argv++; argc--; for (; *options; options++) { switch (*options) { case 'f': if (tarName != NULL) { fprintf(stderr, "Only one 'f' option allowed\n"); return; } tarName = *argv++; argc--; break; case 't': listFlag = TRUE; break; case 'x': extractFlag = TRUE; break; case 'c': createFlag = TRUE; break; case 'v': verboseFlag = TRUE; break; default: fprintf(stderr, "Unknown tar flag '%c'\n", *options); return; } } /* * Validate the options. */ if (extractFlag + listFlag + createFlag != 1) { fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n"); return; } if (tarName == NULL) { fprintf(stderr, "The 'f' flag must be specified\n"); return; } /* * Do the correct type of action supplying the rest of the * command line arguments as the list of files to process. */ if (createFlag) writeTarFile(argc, argv); else readTarFile(argc, argv); }
int tar_main(int argc, char **argv) { char (*get_header_ptr)(archive_handle_t *) = get_header_tar; archive_handle_t *tar_handle; char *base_dir = NULL; const char *tar_filename = "-"; unsigned long opt; unsigned long ctx_flag = 0; if (argc < 2) { bb_show_usage(); } /* Prepend '-' to the first argument if required */ if (argv[1][0] != '-') { char *tmp; bb_xasprintf(&tmp, "-%s", argv[1]); argv[1] = tmp; } /* Initialise default values */ tar_handle = init_handle(); tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL; bb_opt_complementaly = "c~tx:t~cx:x~ct:X*:T*"; #ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS bb_applet_long_options = tar_long_options; #endif opt = bb_getopt_ulflags(argc, argv, tar_options, &base_dir, /* Change to dir <optarg> */ &tar_filename /* archive filename */ #ifdef CONFIG_FEATURE_TAR_FROM , NULL, &(tar_handle->reject) #endif ); /* Check one and only one context option was given */ if(opt & 0x80000000UL) { bb_show_usage(); } #ifdef CONFIG_FEATURE_TAR_CREATE ctx_flag = opt & (CTX_CREATE | CTX_TEST | CTX_EXTRACT); #else ctx_flag = opt & (CTX_TEST | CTX_EXTRACT); #endif if (ctx_flag == 0) { bb_show_usage(); } if(ctx_flag & CTX_TEST) { if ((tar_handle->action_header == header_list) || (tar_handle->action_header == header_verbose_list)) { tar_handle->action_header = header_verbose_list; } else { tar_handle->action_header = header_list; } } if(ctx_flag & CTX_EXTRACT) { if (tar_handle->action_data != data_extract_to_stdout) tar_handle->action_data = data_extract_all; } if(opt & TAR_OPT_2STDOUT) { /* To stdout */ tar_handle->action_data = data_extract_to_stdout; } if(opt & TAR_OPT_VERBOSE) { if ((tar_handle->action_header == header_list) || (tar_handle->action_header == header_verbose_list)) { tar_handle->action_header = header_verbose_list; } else { tar_handle->action_header = header_list; } } if (opt & TAR_OPT_KEEP_OLD) { tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL; } #ifdef CONFIG_FEATURE_TAR_GZIP if(opt & TAR_OPT_GZIP) { get_header_ptr = get_header_tar_gz; } #endif #ifdef CONFIG_FEATURE_TAR_BZIP2 if(opt & TAR_OPT_BZIP2) { get_header_ptr = get_header_tar_bz2; } #endif #ifdef CONFIG_FEATURE_TAR_COMPRESS if(opt & TAR_OPT_UNCOMPRESS) { get_header_ptr = get_header_tar_Z; } #endif #ifdef CONFIG_FEATURE_TAR_FROM if(opt & TAR_OPT_EXCLUDE_FROM) { tar_handle->reject = append_file_list_to_list(tar_handle->reject); } #endif /* Check if we are reading from stdin */ if ((argv[optind]) && (*argv[optind] == '-')) { /* Default is to read from stdin, so just skip to next arg */ optind++; } /* Setup an array of filenames to work with */ /* TODO: This is the same as in ar, separate function ? */ while (optind < argc) { char *filename_ptr = last_char_is(argv[optind], '/'); if (filename_ptr) { *filename_ptr = '\0'; } tar_handle->accept = llist_add_to(tar_handle->accept, argv[optind]); optind++; } if ((tar_handle->accept) || (tar_handle->reject)) { tar_handle->filter = filter_accept_reject_list; } /* Open the tar file */ { FILE *tar_stream; int flags; #ifdef CONFIG_FEATURE_TAR_CREATE if (opt & CTX_CREATE) { /* Make sure there is at least one file to tar up. */ if (tar_handle->accept == NULL) { bb_error_msg_and_die("Cowardly refusing to create an empty archive"); } tar_stream = stdout; flags = O_WRONLY | O_CREAT | O_EXCL; unlink(tar_filename); } else #endif { tar_stream = stdin; flags = O_RDONLY; } if ((tar_filename[0] == '-') && (tar_filename[1] == '\0')) { tar_handle->src_fd = fileno(tar_stream); tar_handle->seek = seek_by_char; } else { tar_handle->src_fd = bb_xopen(tar_filename, flags); } } if ((base_dir) && (chdir(base_dir))) { bb_perror_msg_and_die("Couldnt chdir to %s", base_dir); } #ifdef CONFIG_FEATURE_TAR_CREATE /* create an archive */ if (opt & CTX_CREATE) { int verboseFlag = FALSE; int gzipFlag = FALSE; # ifdef CONFIG_FEATURE_TAR_GZIP if (get_header_ptr == get_header_tar_gz) { gzipFlag = TRUE; } # endif /* CONFIG_FEATURE_TAR_GZIP */ # ifdef CONFIG_FEATURE_TAR_BZIP2 if (get_header_ptr == get_header_tar_bz2) { bb_error_msg_and_die("Creating bzip2 compressed archives is not currently supported."); } # endif /* CONFIG_FEATURE_TAR_BZIP2 */ if ((tar_handle->action_header == header_list) || (tar_handle->action_header == header_verbose_list)) { verboseFlag = TRUE; } writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERNCE, tar_handle->accept, tar_handle->reject, gzipFlag); } else #endif /* CONFIG_FEATURE_TAR_CREATE */ { while (get_header_ptr(tar_handle) == EXIT_SUCCESS); /* Ckeck that every file that should have been extracted was */ while (tar_handle->accept) { if (find_list_entry(tar_handle->reject, tar_handle->accept->data) == NULL) { if (find_list_entry(tar_handle->passed, tar_handle->accept->data) == NULL) { bb_error_msg_and_die("%s: Not found in archive\n", tar_handle->accept->data); } } tar_handle->accept = tar_handle->accept->link; } } #ifdef CONFIG_FEATURE_CLEAN_UP if (tar_handle->src_fd != STDIN_FILENO) { close(tar_handle->src_fd); } #endif /* CONFIG_FEATURE_CLEAN_UP */ return(EXIT_SUCCESS); }
int tar_main(int argc UNUSED_PARAM, char **argv) { char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar; archive_handle_t *tar_handle; char *base_dir = NULL; const char *tar_filename = "-"; unsigned opt; int verboseFlag = 0; #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM llist_t *excludes = NULL; #endif /* Initialise default values */ tar_handle = init_handle(); tar_handle->ah_flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL; /* Apparently only root's tar preserves perms (see bug 3844) */ if (getuid() != 0) tar_handle->ah_flags |= ARCHIVE_NOPRESERVE_PERM; /* Prepend '-' to the first argument if required */ opt_complementary = "--:" // first arg is options "tt:vv:" // count -t,-v "?:" // bail out with usage instead of error return "X::T::" // cumulative lists #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM "\xff::" // cumulative lists for --exclude #endif IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive #if ENABLE_FEATURE_TAR_LONG_OPTIONS applet_long_options = tar_longopts; #endif opt = getopt32(argv, "txC:f:Opvk" IF_FEATURE_TAR_CREATE( "ch" ) IF_FEATURE_SEAMLESS_BZ2( "j" ) IF_FEATURE_SEAMLESS_LZMA("a" ) IF_FEATURE_TAR_FROM( "T:X:") IF_FEATURE_SEAMLESS_GZ( "z" ) IF_FEATURE_SEAMLESS_Z( "Z" ) , &base_dir // -C dir , &tar_filename // -f filename IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM , &excludes // --exclude #endif , &verboseFlag // combined count for -t and -v , &verboseFlag // combined count for -t and -v ); argv += optind; if (verboseFlag) tar_handle->action_header = header_verbose_list; if (verboseFlag == 1) tar_handle->action_header = header_list; if (opt & OPT_EXTRACT) tar_handle->action_data = data_extract_all; if (opt & OPT_2STDOUT) tar_handle->action_data = data_extract_to_stdout; if (opt & OPT_KEEP_OLD) tar_handle->ah_flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL; if (opt & OPT_NOPRESERVE_OWN) tar_handle->ah_flags |= ARCHIVE_NOPRESERVE_OWN; if (opt & OPT_NOPRESERVE_PERM) tar_handle->ah_flags |= ARCHIVE_NOPRESERVE_PERM; if (opt & OPT_NUMERIC_OWNER) tar_handle->ah_flags |= ARCHIVE_NUMERIC_OWNER; if (opt & OPT_GZIP) get_header_ptr = get_header_tar_gz; if (opt & OPT_BZIP2) get_header_ptr = get_header_tar_bz2; if (opt & OPT_LZMA) get_header_ptr = get_header_tar_lzma; if (opt & OPT_COMPRESS) get_header_ptr = get_header_tar_Z; #if ENABLE_FEATURE_TAR_FROM tar_handle->reject = append_file_list_to_list(tar_handle->reject); #if ENABLE_FEATURE_TAR_LONG_OPTIONS /* Append excludes to reject */ while (excludes) { llist_t *next = excludes->link; excludes->link = tar_handle->reject; tar_handle->reject = excludes; excludes = next; } #endif tar_handle->accept = append_file_list_to_list(tar_handle->accept); #endif /* Setup an array of filenames to work with */ /* TODO: This is the same as in ar, separate function ? */ while (*argv) { /* kill trailing '/' unless the string is just "/" */ char *cp = last_char_is(*argv, '/'); if (cp > *argv) *cp = '\0'; llist_add_to_end(&tar_handle->accept, *argv); argv++; } if (tar_handle->accept || tar_handle->reject) tar_handle->filter = filter_accept_reject_list; /* Open the tar file */ { FILE *tar_stream; int flags; if (opt & OPT_CREATE) { /* Make sure there is at least one file to tar up. */ if (tar_handle->accept == NULL) bb_error_msg_and_die("empty archive"); tar_stream = stdout; /* Mimicking GNU tar 1.15.1: */ flags = O_WRONLY | O_CREAT | O_TRUNC; } else { tar_stream = stdin; flags = O_RDONLY; } if (LONE_DASH(tar_filename)) { tar_handle->src_fd = fileno(tar_stream); tar_handle->seek = seek_by_read; } else { if (ENABLE_FEATURE_TAR_AUTODETECT && flags == O_RDONLY) { get_header_ptr = get_header_tar; tar_handle->src_fd = open_zipped(tar_filename); if (tar_handle->src_fd < 0) bb_perror_msg_and_die("can't open '%s'", tar_filename); } else { tar_handle->src_fd = xopen(tar_filename, flags); } } } if (base_dir) xchdir(base_dir); #ifdef CHECK_FOR_CHILD_EXITCODE /* We need to know whether child (gzip/bzip/etc) exits abnormally */ signal(SIGCHLD, handle_SIGCHLD); #endif /* create an archive */ if (opt & OPT_CREATE) { #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 int zipMode = 0; if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP)) zipMode = 1; if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2)) zipMode = 2; #endif /* NB: writeTarFile() closes tar_handle->src_fd */ return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, tar_handle->accept, tar_handle->reject, zipMode); } while (get_header_ptr(tar_handle) == EXIT_SUCCESS) continue; /* Check that every file that should have been extracted was */ while (tar_handle->accept) { if (!find_list_entry(tar_handle->reject, tar_handle->accept->data) && !find_list_entry(tar_handle->passed, tar_handle->accept->data) ) { bb_error_msg_and_die("%s: not found in archive", tar_handle->accept->data); } tar_handle->accept = tar_handle->accept->link; } if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */) close(tar_handle->src_fd); return EXIT_SUCCESS; }
extern int tar_main(int argc, char **argv) { char** excludeList=NULL; char** extractList=NULL; const char *tarName="-"; const char *cwd=NULL; #if defined BB_FEATURE_TAR_EXCLUDE int excludeListSize=0; FILE *fileList; char file[256]; #endif #if defined BB_FEATURE_TAR_GZIP FILE *comp_file = NULL; int unzipFlag = FALSE; #endif int listFlag = FALSE; int extractFlag = FALSE; int createFlag = FALSE; int verboseFlag = FALSE; int tostdoutFlag = FALSE; int status = FALSE; int opt; #if defined BB_FEATURE_TAR_GZIP pid_t pid; #endif if (argc <= 1) show_usage(); if (argv[1][0] != '-') { char *tmp = xmalloc(strlen(argv[1]) + 2); tmp[0] = '-'; strcpy(tmp + 1, argv[1]); argv[1] = tmp; } while ( #ifndef BB_FEATURE_TAR_EXCLUDE (opt = getopt(argc, argv, "cxtzvOf:pC:")) #else (opt = getopt_long(argc, argv, "cxtzvOf:X:pC:", longopts, NULL)) #endif > 0) { switch (opt) { case 'c': if (extractFlag == TRUE || listFlag == TRUE) goto flagError; createFlag = TRUE; break; case 'x': if (listFlag == TRUE || createFlag == TRUE) goto flagError; extractFlag = TRUE; break; case 't': if (extractFlag == TRUE || createFlag == TRUE) goto flagError; listFlag = TRUE; break; #ifdef BB_FEATURE_TAR_GZIP case 'z': unzipFlag = TRUE; break; #endif case 'v': verboseFlag = TRUE; break; case 'O': tostdoutFlag = TRUE; break; case 'f': if (*tarName != '-') error_msg_and_die( "Only one 'f' option allowed"); tarName = optarg; break; #if defined BB_FEATURE_TAR_EXCLUDE case 'e': excludeList=xrealloc( excludeList, sizeof(char *) * (excludeListSize+2)); excludeList[excludeListSize] = optarg; /* Tack a NULL onto the end of the list */ excludeList[++excludeListSize] = NULL; case 'X': fileList = xfopen(optarg, "r"); while (fgets(file, sizeof(file), fileList) != NULL) { excludeList = xrealloc(excludeList, sizeof(char *) * (excludeListSize+2)); chomp(file); excludeList[excludeListSize] = xstrdup(file); /* Tack a NULL onto the end of the list */ excludeList[++excludeListSize] = NULL; } fclose(fileList); break; #endif case 'p': break; case 'C': cwd = xgetcwd((char *)cwd); if (chdir(optarg)) { printf("cd: %s: %s\n", optarg, strerror(errno)); return EXIT_FAILURE; } break; default: show_usage(); } } /* * Do the correct type of action supplying the rest of the * command line arguments as the list of files to process. */ if (createFlag == TRUE) { #ifndef BB_FEATURE_TAR_CREATE error_msg_and_die( "This version of tar was not compiled with tar creation support."); #else #ifdef BB_FEATURE_TAR_GZIP if (unzipFlag==TRUE) error_msg_and_die("Creation of compressed not internally support by tar, pipe to busybox gunzip"); #endif status = writeTarFile(tarName, verboseFlag, argv + optind, excludeList); #endif } if (listFlag == TRUE || extractFlag == TRUE) { int tarFd; if (argv[optind]) extractList = argv + optind; /* Open the tar file for reading. */ if (!strcmp(tarName, "-")) tarFd = fileno(stdin); else tarFd = open(tarName, O_RDONLY); if (tarFd < 0) perror_msg_and_die("Error opening '%s'", tarName); #ifdef BB_FEATURE_TAR_GZIP /* unzip tarFd in a seperate process */ if (unzipFlag == TRUE) { comp_file = fdopen(tarFd, "r"); /* set the buffer size */ setvbuf(comp_file, NULL, _IOFBF, 0x8000); if ((tarFd = fileno(gz_open(comp_file, &pid))) == EXIT_FAILURE) { error_msg_and_die("Couldnt unzip file"); } } #endif status = readTarFile(tarFd, extractFlag, listFlag, tostdoutFlag, verboseFlag, extractList, excludeList); close(tarFd); #ifdef BB_FEATURE_TAR_GZIP if (unzipFlag == TRUE) { gz_close(pid); fclose(comp_file); } #endif } if (cwd) chdir(cwd); if (status == TRUE) return EXIT_SUCCESS; else return EXIT_FAILURE; flagError: error_msg_and_die( "Exactly one of 'c', 'x' or 't' must be specified"); }