/* These three functions called many times, optimizing for speed.
 * Users reported minute-long delays when they runn iptables repeatedly
 * (iptables use modprobe to install needed kernel modules).
 */
static struct module_entry *helper_get_module(const char *module, int create)
{
	char modname[MODULE_NAME_LEN];
	struct module_entry *e;
	llist_t *l;
	unsigned i;
	unsigned hash;

	filename2modname(module, modname);

	hash = 0;
	for (i = 0; modname[i]; i++)
		hash = ((hash << 5) + hash) + modname[i];
	hash %= DB_HASH_SIZE;

	for (l = G.db[hash]; l; l = l->link) {
		e = (struct module_entry *) l->data;
		if (strcmp(e->modname, modname) == 0)
			return e;
	}
	if (!create)
		return NULL;

	e = xzalloc(sizeof(*e));
	e->modname = xstrdup(modname);
	llist_add_to(&G.db[hash], e);

	return e;
}
Exemple #2
0
int cpio_main(int argc, char **argv)
{
	archive_handle_t *archive_handle;
	char *cpio_filename = NULL;
	unsigned opt;

	/* Initialise */
	archive_handle = init_handle();
	archive_handle->src_fd = STDIN_FILENO;
	archive_handle->seek = seek_by_read;
	archive_handle->flags = ARCHIVE_EXTRACT_NEWER | ARCHIVE_PRESERVE_DATE;

	opt = getopt32(argc, argv, "ituvF:dm", &cpio_filename);

	/* One of either extract or test options must be given */
	if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
		bb_show_usage();
	}

	if (opt & CPIO_OPT_TEST) {
		/* if both extract and test options are given, ignore extract option */
		if (opt & CPIO_OPT_EXTRACT) {
			opt &= ~CPIO_OPT_EXTRACT;
		}
		archive_handle->action_header = header_list;
	}
	if (opt & CPIO_OPT_EXTRACT) {
		archive_handle->action_data = data_extract_all;
	}
	if (opt & CPIO_OPT_UNCONDITIONAL) {
		archive_handle->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
		archive_handle->flags &= ~ARCHIVE_EXTRACT_NEWER;
	}
	if (opt & CPIO_OPT_VERBOSE) {
		if (archive_handle->action_header == header_list) {
			archive_handle->action_header = header_verbose_list;
		} else {
			archive_handle->action_header = header_list;
		}
	}
	if (cpio_filename) { /* CPIO_OPT_FILE */
		archive_handle->src_fd = xopen(cpio_filename, O_RDONLY);
		archive_handle->seek = seek_by_jump;
	}
	if (opt & CPIO_OPT_CREATE_LEADING_DIR) {
		archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS;
	}

	while (optind < argc) {
		archive_handle->filter = filter_accept_list;
		llist_add_to(&(archive_handle->accept), argv[optind]);
		optind++;
	}

	while (get_header_cpio(archive_handle) == EXIT_SUCCESS);

	return EXIT_SUCCESS;
}
Exemple #3
0
int ar_main(int argc, char **argv)
{
	static const char msg_unsupported_err[] ALIGN1 =
		"archive %s is not supported";

	archive_handle_t *archive_handle;
	unsigned opt;
	char magic[8];

	archive_handle = init_handle();

	/* Prepend '-' to the first argument if required */
	opt_complementary = "--:p:t:x:-1:p--tx:t--px:x--pt";
	opt = getopt32(argv, "ptxovcr");

	if (opt & AR_CTX_PRINT) {
		archive_handle->action_data = data_extract_to_stdout;
	}
	if (opt & AR_CTX_LIST) {
		archive_handle->action_header = header_list;
	}
	if (opt & AR_CTX_EXTRACT) {
		archive_handle->action_data = data_extract_all;
	}
	if (opt & AR_OPT_PRESERVE_DATE) {
		archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
	}
	if (opt & AR_OPT_VERBOSE) {
		archive_handle->action_header = header_verbose_list_ar;
	}
	if (opt & AR_OPT_CREATE) {
		bb_error_msg_and_die(msg_unsupported_err, "creation");
	}
	if (opt & AR_OPT_INSERT) {
		bb_error_msg_and_die(msg_unsupported_err, "insertion");
	}

	archive_handle->src_fd = xopen(argv[optind++], O_RDONLY);

	while (optind < argc) {
		archive_handle->filter = filter_accept_list;
		llist_add_to(&(archive_handle->accept), argv[optind++]);
	}

	xread(archive_handle->src_fd, magic, 7);
	if (strncmp(magic, "!<arch>", 7) != 0) {
		bb_error_msg_and_die("invalid ar magic");
	}
	archive_handle->offset += 7;

	while (get_header_ar(archive_handle) == EXIT_SUCCESS)
		continue;

	return EXIT_SUCCESS;
}
Exemple #4
0
static void
add_peers(char *s)
{
	peer_t *p;

	p = xzalloc(sizeof(*p));
	p->p_lsa = xhost2sockaddr(s, 123);
	p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
	p->p_fd = -1;
	p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
	p->p_trustlevel = TRUSTLEVEL_PATHETIC;
	p->next_action_time = time(NULL); /* = set_next(p, 0); */

	llist_add_to(&G.ntp_peers, p);
	G.peer_cnt++;
}
static void load_regexes_from_file(llist_t *fopt)
{
	char *line;
	FILE *f;

	while(fopt) {
		llist_t *cur = fopt;
		char *ffile = cur->data;

		fopt = cur->link;
		free(cur);
		f = bb_xfopen(ffile, "r");
		while ((line = bb_get_chomped_line_from_file(f)) != NULL) {
			pattern_head = llist_add_to(pattern_head, line);
		}
	}
}
Exemple #6
0
static void load_regexes_from_file(llist_t *fopt)
{
	char *line;
	FILE *f;

	while (fopt) {
		llist_t *cur = fopt;
		char *ffile = cur->data;

		fopt = cur->link;
		free(cur);
		f = xfopen(ffile, "r");
		while ((line = xmalloc_getline(f)) != NULL) {
			llist_add_to(&pattern_head,
				new_grep_list_data(line, PATTERN_MEM_A));
		}
	}
}
Exemple #7
0
static llist_t *append_file_list_to_list(llist_t *list)
{
	FILE *src_stream;
	char *line;
	llist_t *newlist = NULL;

	while (list) {
		src_stream = xfopen_for_read(llist_pop(&list));
		while ((line = xmalloc_fgetline(src_stream)) != NULL) {
			/* kill trailing '/' unless the string is just "/" */
			char *cp = last_char_is(line, '/');
			if (cp > line)
				*cp = '\0';
			llist_add_to(&newlist, line);
		}
		fclose(src_stream);
	}
	return newlist;
}
static llist_t *append_file_list_to_list(llist_t *list)
{
	FILE *src_stream;
	llist_t *cur = list;
	llist_t *tmp;
	char *line;
	llist_t *newlist = NULL;

	while(cur) {
		src_stream = bb_xfopen(cur->data, "r");
		tmp = cur;
		cur = cur->link;
		free(tmp);
	while((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
			newlist = llist_add_to(newlist, line);
	}
	fclose(src_stream);
	}
	return newlist;
}
static struct module_entry *helper_get_module(const char *module, int create)
{
	char modname[MODULE_NAME_LEN];
	struct module_entry *e;
	llist_t *l;

	filename2modname(module, modname);
	for (l = G.db; l != NULL; l = l->link) {
		e = (struct module_entry *) l->data;
		if (strcmp(e->modname, modname) == 0)
			return e;
	}
	if (!create)
		return NULL;

	e = xzalloc(sizeof(*e));
	e->modname = xstrdup(modname);
	llist_add_to(&G.db, e);

	return e;
}
Exemple #10
0
static llist_t *append_file_list_to_list(llist_t *list)
{
	FILE *src_stream;
	llist_t *cur = list;
	llist_t *tmp;
	char *line;
	llist_t *newlist = NULL;

	while (cur) {
		src_stream = xfopen(cur->data, "r");
		tmp = cur;
		cur = cur->link;
		free(tmp);
		while ((line = xmalloc_getline(src_stream)) != NULL) {
			/* kill trailing '/' unless the string is just "/" */
			char *cp = last_char_is(line, '/');
			if (cp > line)
				*cp = '\0';
			llist_add_to(&newlist, line);
		}
		fclose(src_stream);
	}
	return newlist;
}
Exemple #11
0
int unzip_main(int argc, char **argv)
{
	enum { O_PROMPT, O_NEVER, O_ALWAYS };

	zip_header_t zip_header;
	smallint quiet = 0;
	IF_NOT_DESKTOP(const) smallint verbose = 0;
	smallint listing = 0;
	smallint overwrite = O_PROMPT;
	smallint x_opt_seen;
#if ENABLE_DESKTOP
	uint32_t cdf_offset;
#endif
	unsigned long total_usize;
	unsigned long total_size;
	unsigned total_entries;
	int dst_fd = -1;
	char *src_fn = NULL;
	char *dst_fn = NULL;
	llist_t *zaccept = NULL;
	llist_t *zreject = NULL;
	char *base_dir = NULL;
	int i, opt;
	char key_buf[80]; /* must match size used by my_fgets80 */
	struct stat stat_buf;

/* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP:
 *
 * # /usr/bin/unzip -qq -v decompress_unlzma.i.zip
 *   204372  Defl:N    35278  83%  09-06-09 14:23  0d056252  decompress_unlzma.i
 * # /usr/bin/unzip -q -v decompress_unlzma.i.zip
 *  Length   Method    Size  Ratio   Date   Time   CRC-32    Name
 * --------  ------  ------- -----   ----   ----   ------    ----
 *   204372  Defl:N    35278  83%  09-06-09 14:23  0d056252  decompress_unlzma.i
 * --------          -------  ---                            -------
 *   204372            35278  83%                            1 file
 * # /usr/bin/unzip -v decompress_unlzma.i.zip
 * Archive:  decompress_unlzma.i.zip
 *  Length   Method    Size  Ratio   Date   Time   CRC-32    Name
 * --------  ------  ------- -----   ----   ----   ------    ----
 *   204372  Defl:N    35278  83%  09-06-09 14:23  0d056252  decompress_unlzma.i
 * --------          -------  ---                            -------
 *   204372            35278  83%                            1 file
 * # unzip -v decompress_unlzma.i.zip
 * Archive:  decompress_unlzma.i.zip
 *   Length     Date   Time    Name
 *  --------    ----   ----    ----
 *    204372  09-06-09 14:23   decompress_unlzma.i
 *  --------                   -------
 *    204372                   1 files
 * # /usr/bin/unzip -l -qq decompress_unlzma.i.zip
 *    204372  09-06-09 14:23   decompress_unlzma.i
 * # /usr/bin/unzip -l -q decompress_unlzma.i.zip
 *   Length     Date   Time    Name
 *  --------    ----   ----    ----
 *    204372  09-06-09 14:23   decompress_unlzma.i
 *  --------                   -------
 *    204372                   1 file
 * # /usr/bin/unzip -l decompress_unlzma.i.zip
 * Archive:  decompress_unlzma.i.zip
 *   Length     Date   Time    Name
 *  --------    ----   ----    ----
 *    204372  09-06-09 14:23   decompress_unlzma.i
 *  --------                   -------
 *    204372                   1 file
 */

	x_opt_seen = 0;
	/* '-' makes getopt return 1 for non-options */
	while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) {
		switch (opt) {
		case 'd':  /* Extract to base directory */
			base_dir = optarg;
			break;

		case 'l': /* List */
			listing = 1;
			break;

		case 'n': /* Never overwrite existing files */
			overwrite = O_NEVER;
			break;

		case 'o': /* Always overwrite existing files */
			overwrite = O_ALWAYS;
			break;

		case 'p': /* Extract files to stdout and fall through to set verbosity */
			dst_fd = STDOUT_FILENO;

		case 'q': /* Be quiet */
			quiet++;
			break;

		case 'v': /* Verbose list */
			IF_DESKTOP(verbose++;)
			listing = 1;
			break;

		case 'x':
			x_opt_seen = 1;
			break;

		case 1:
			if (!src_fn) {
				/* The zip file */
				/* +5: space for ".zip" and NUL */
				src_fn = xmalloc(strlen(optarg) + 5);
				strcpy(src_fn, optarg);
			} else if (!x_opt_seen) {
				/* Include files */
				llist_add_to(&zaccept, optarg);
			} else {
				/* Exclude files */
				llist_add_to(&zreject, optarg);
			}
			break;

		default:
			bb_show_usage();
		}
	}
extern int grep_main(int argc, char **argv)
{
	FILE *file;
	int matched;
	unsigned long opt;
	llist_t *fopt = NULL;

	/* do normal option parsing */
#ifdef CONFIG_FEATURE_GREP_CONTEXT
  {
	char *junk;
	char *slines_after;
	char *slines_before;
	char *Copt;

	bb_opt_complementaly = "H-h:e*:f*:C-AB";
	opt = bb_getopt_ulflags(argc, argv,
		GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP,
		&pattern_head, &fopt,
		&slines_after, &slines_before, &Copt);

	if(opt & GREP_OPT_C) {
		/* C option unseted A and B options, but next -A or -B
		   may be ovewrite own option */
		if(!(opt & GREP_OPT_A))         /* not overwtited */
			slines_after = Copt;
		if(!(opt & GREP_OPT_B))         /* not overwtited */
			slines_before = Copt;
		opt |= GREP_OPT_A|GREP_OPT_B;   /* set for parse now */
	}
	if(opt & GREP_OPT_A) {
		lines_after = strtoul(slines_after, &junk, 10);
				if(*junk != '\0')
					bb_error_msg_and_die("invalid context length argument");
	}
	if(opt & GREP_OPT_B) {
		lines_before = strtoul(slines_before, &junk, 10);
				if(*junk != '\0')
					bb_error_msg_and_die("invalid context length argument");
		}
	/* sanity checks after parse may be invalid numbers ;-) */
	if ((opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L))) {
		opt &= ~GREP_OPT_n;
		lines_before = 0;
		lines_after = 0;
	} else if(lines_before > 0)
		before_buf = (char **)xcalloc(lines_before, sizeof(char *));
	}
#else
	/* with auto sanity checks */
	bb_opt_complementaly = "H-h:e*:f*:c-n:q-n:l-n";
	opt = bb_getopt_ulflags(argc, argv, GREP_OPTS OPT_EGREP,
		&pattern_head, &fopt);

#endif
	print_files_with_matches = opt & GREP_OPT_l;
	print_files_without_matches = (opt & GREP_OPT_L) != 0;
	print_line_num = opt & GREP_OPT_n;
	be_quiet = opt & GREP_OPT_q;
	invert_search = (opt & GREP_OPT_v) != 0;        /* 0 | 1 */
	suppress_err_msgs = opt & GREP_OPT_s;
	print_match_counts = opt & GREP_OPT_c;
	fgrep_flag = opt & GREP_OPT_F;
	if(opt & GREP_OPT_H)
		print_filename++;
	if(opt & GREP_OPT_h)
		print_filename--;
	if(opt & GREP_OPT_f)
		load_regexes_from_file(fopt);

#ifdef CONFIG_FEATURE_GREP_FGREP_ALIAS
	if(bb_applet_name[0] == 'f')
		fgrep_flag = 1;
#endif

#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS
	if(bb_applet_name[0] == 'e' || (opt & GREP_OPT_E))
		reflags = REG_EXTENDED | REG_NOSUB;
	else
#endif
		reflags = REG_NOSUB;

	if(opt & GREP_OPT_i)
		reflags |= REG_ICASE;

	argv += optind;
	argc -= optind;

	/* if we didn't get a pattern from a -e and no command file was specified,
	 * argv[optind] should be the pattern. no pattern, no worky */
	if (pattern_head == NULL) {
		if (*argv == NULL)
			bb_show_usage();
		else {
			pattern_head = llist_add_to(pattern_head, *argv++);
			argc--;
		}
	}

	/* argv[(optind)..(argc-1)] should be names of file to grep through. If
	 * there is more than one file to grep, we will print the filenames */
	if (argc > 1) {
		print_filename++;

	/* If no files were specified, or '-' was specified, take input from
	 * stdin. Otherwise, we grep through all the files specified. */
	} else if (argc == 0) {
		argc++;
	}
	matched = 0;
	while (argc--) {
		cur_file = *argv++;
		if(!cur_file || (*cur_file == '-' && !cur_file[1])) {
			cur_file = "-";
			file = stdin;
		} else {
			file = fopen(cur_file, "r");
		}
			if (file == NULL) {
				if (!suppress_err_msgs)
					bb_perror_msg("%s", cur_file);
		} else {
			matched += grep_file(file);
			if(matched < 0) {
				/* we found a match but were told to be quiet, stop here and
				* return success */
				break;
			}
				fclose(file);
			}
		}

#ifdef CONFIG_FEATURE_CLEAN_UP
	/* destroy all the elments in the pattern list */
	while (pattern_head) {
		llist_t *pattern_head_ptr = pattern_head;

		pattern_head = pattern_head->link;
		free(pattern_head_ptr);
	}
#endif

	return !matched; /* invert return value 0 = success, 1 = failed */
}
Exemple #13
0
int grep_main(int argc, char **argv)
{
	FILE *file;
	int matched;
	llist_t *fopt = NULL;

	/* do normal option parsing */
#if ENABLE_FEATURE_GREP_CONTEXT
	char *slines_after;
	char *slines_before;
	char *Copt;

	opt_complementary = "H-h:e::f::C-AB";
	getopt32(argc, argv,
		GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP,
		&pattern_head, &fopt,
		&slines_after, &slines_before, &Copt);

	if (option_mask32 & GREP_OPT_C) {
		/* -C unsets prev -A and -B, but following -A or -B
		   may override it */
		if (!(option_mask32 & GREP_OPT_A)) /* not overridden */
			slines_after = Copt;
		if (!(option_mask32 & GREP_OPT_B)) /* not overridden */
			slines_before = Copt;
		option_mask32 |= GREP_OPT_A|GREP_OPT_B; /* for parser */
	}
	if (option_mask32 & GREP_OPT_A) {
		lines_after = xatoi_u(slines_after);
	}
	if (option_mask32 & GREP_OPT_B) {
		lines_before = xatoi_u(slines_before);
	}
	/* sanity checks */
	if (option_mask32 & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L)) {
		option_mask32 &= ~GREP_OPT_n;
		lines_before = 0;
		lines_after = 0;
	} else if (lines_before > 0)
		before_buf = xzalloc(lines_before * sizeof(char *));
#else
	/* with auto sanity checks */
	opt_complementary = "H-h:e::f::c-n:q-n:l-n";
	getopt32(argc, argv, GREP_OPTS OPT_EGREP,
		&pattern_head, &fopt);
#endif
	invert_search = ((option_mask32 & GREP_OPT_v) != 0); /* 0 | 1 */

	if (pattern_head != NULL) {
		/* convert char *argv[] to grep_list_data_t */
		llist_t *cur;

		for (cur = pattern_head; cur; cur = cur->link)
			cur->data = new_grep_list_data(cur->data, 0);
	}
	if (option_mask32 & GREP_OPT_f)
		load_regexes_from_file(fopt);

	if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f')
		option_mask32 |= GREP_OPT_F;

	if (!(option_mask32 & GREP_OPT_o))
		reflags = REG_NOSUB;

	if (ENABLE_FEATURE_GREP_EGREP_ALIAS &&
			(applet_name[0] == 'e' || (option_mask32 & GREP_OPT_E)))
		reflags |= REG_EXTENDED;

	if (option_mask32 & GREP_OPT_i)
		reflags |= REG_ICASE;

	argv += optind;
	argc -= optind;

	/* if we didn't get a pattern from a -e and no command file was specified,
	 * argv[optind] should be the pattern. no pattern, no worky */
	if (pattern_head == NULL) {
		if (*argv == NULL)
			bb_show_usage();
		else {
			char *pattern = new_grep_list_data(*argv++, 0);

			llist_add_to(&pattern_head, pattern);
			argc--;
		}
	}

	/* argv[(optind)..(argc-1)] should be names of file to grep through. If
	 * there is more than one file to grep, we will print the filenames. */
	if (argc > 1)
		print_filename = 1;
	/* -H / -h of course override */
	if (option_mask32 & GREP_OPT_H)
		print_filename = 1;
	if (option_mask32 & GREP_OPT_h)
		print_filename = 0;

	/* If no files were specified, or '-' was specified, take input from
	 * stdin. Otherwise, we grep through all the files specified. */
	if (argc == 0)
		argc++;
	matched = 0;
	while (argc--) {
		cur_file = *argv++;
		file = stdin;
		if (!cur_file || (*cur_file == '-' && !cur_file[1])) {
			cur_file = "(standard input)";
		} else {
			if (option_mask32 & GREP_OPT_r) {
				struct stat st;
				if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) {
					if (!(option_mask32 & GREP_OPT_h))
						print_filename = 1;
					matched += grep_dir(cur_file);
					goto grep_done;
				}
			}
			/* else: fopen(dir) will succeed, but reading won't */
			file = fopen(cur_file, "r");
			if (file == NULL) {
				if (!SUPPRESS_ERR_MSGS)
					bb_perror_msg("%s", cur_file);
				open_errors = 1;
				continue;
			}
		}
		matched += grep_file(file);
		fclose_if_not_stdin(file);
 grep_done:
		if (matched < 0) {
			/* we found a match but were told to be quiet, stop here and
			* return success */
			break;
		}
	}

	/* destroy all the elments in the pattern list */
	if (ENABLE_FEATURE_CLEAN_UP) {
		while (pattern_head) {
			llist_t *pattern_head_ptr = pattern_head;
			grep_list_data_t *gl =
				(grep_list_data_t *)pattern_head_ptr->data;

			pattern_head = pattern_head->link;
			if ((gl->flg_mem_alocated_compiled & PATTERN_MEM_A))
				free(gl->pattern);
			if ((gl->flg_mem_alocated_compiled & COMPILED))
				regfree(&(gl->preg));
			free(pattern_head_ptr);
		}
	}
	/* 0 = success, 1 = failed, 2 = error */
	/* If the -q option is specified, the exit status shall be zero
	 * if an input line is selected, even if an error was detected.  */
	if (BE_QUIET && matched)
		return 0;
	if (open_errors)
		return 2;
	return !matched; /* invert return value 0 = success, 1 = failed */
}
char get_header_tar(archive_handle_t *archive_handle)
{
	static int end;

	file_header_t *file_header = archive_handle->file_header;
	struct {
		/* ustar header, Posix 1003.1 */
		char name[100];     /*   0-99 */
		char mode[8];       /* 100-107 */
		char uid[8];        /* 108-115 */
		char gid[8];        /* 116-123 */
		char size[12];      /* 124-135 */
		char mtime[12];     /* 136-147 */
		char chksum[8];     /* 148-155 */
		char typeflag;      /* 156-156 */
		char linkname[100]; /* 157-256 */
		char magic[6];      /* 257-262 */
		char version[2];    /* 263-264 */
		char uname[32];     /* 265-296 */
		char gname[32];     /* 297-328 */
		char devmajor[8];   /* 329-336 */
		char devminor[8];   /* 337-344 */
		char prefix[155];   /* 345-499 */
		char padding[12];   /* 500-512 */
	} tar;
	char *cp;
	int i, sum_u, sum_s, sum;
	int parse_names;

	if (sizeof(tar) != 512)
		BUG_tar_header_size();

#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
 again:
#endif
	/* Align header */
	data_align(archive_handle, 512);

 again_after_align:

	xread(archive_handle->src_fd, &tar, 512);
	archive_handle->offset += 512;

	/* If there is no filename its an empty header */
	if (tar.name[0] == 0) {
		if (end) {
			/* This is the second consecutive empty header! End of archive!
			 * Read until the end to empty the pipe from gz or bz2
			 */
			while (full_read(archive_handle->src_fd, &tar, 512) == 512)
				/* repeat */;
			return EXIT_FAILURE;
		}
		end = 1;
		return EXIT_SUCCESS;
	}
	end = 0;

	/* Check header has valid magic, "ustar" is for the proper tar
	 * 0's are for the old tar format
	 */
	if (strncmp(tar.magic, "ustar", 5) != 0) {
#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
		if (memcmp(tar.magic, "\0\0\0\0", 5) != 0)
#endif
			bb_error_msg_and_die("invalid tar magic");
	}

	/* Do checksum on headers.
	 * POSIX says that checksum is done on unsigned bytes, but
	 * Sun and HP-UX gets it wrong... more details in
	 * GNU tar source. */
	sum_s = sum_u = ' ' * sizeof(tar.chksum);
	for (i = 0; i < 148 ; i++) {
		sum_u += ((unsigned char*)&tar)[i];
		sum_s += ((signed char*)&tar)[i];
	}
	for (i = 156; i < 512 ; i++) {
		sum_u += ((unsigned char*)&tar)[i];
		sum_s += ((signed char*)&tar)[i];
	}
	/* This field does not need special treatment (getOctal) */
	sum = xstrtoul(tar.chksum, 8);
	if (sum_u != sum && sum_s != sum) {
		bb_error_msg_and_die("invalid tar header checksum");
	}

	/* 0 is reserved for high perf file, treat as normal file */
	if (!tar.typeflag) tar.typeflag = '0';
	parse_names = (tar.typeflag >= '0' && tar.typeflag <= '7');

	/* getOctal trashes subsequent field, therefore we call it
	 * on fields in reverse order */
	if (tar.devmajor[0]) {
		unsigned minor = GET_OCTAL(tar.devminor);
		unsigned major = GET_OCTAL(tar.devmajor);
		file_header->device = makedev(major, minor);
	}
	file_header->link_name = NULL;
	if (!linkname && parse_names && tar.linkname[0]) {
		/* we trash magic[0] here, it's ok */
		tar.linkname[sizeof(tar.linkname)] = '\0';
		file_header->link_name = xstrdup(tar.linkname);
		/* FIXME: what if we have non-link object with link_name? */
		/* Will link_name be free()ed? */
	}
	file_header->mtime = GET_OCTAL(tar.mtime);
	file_header->size = GET_OCTAL(tar.size);
	file_header->gid = GET_OCTAL(tar.gid);
	file_header->uid = GET_OCTAL(tar.uid);
	/* Set bits 0-11 of the files mode */
	file_header->mode = 07777 & GET_OCTAL(tar.mode);

	file_header->name = NULL;
	if (!longname && parse_names) {
		/* we trash mode[0] here, it's ok */
		tar.name[sizeof(tar.name)] = '\0';
		if (tar.prefix[0]) {
			/* and padding[0] */
			tar.prefix[sizeof(tar.prefix)] = '\0';
			file_header->name = concat_path_file(tar.prefix, tar.name);
		} else
			file_header->name = xstrdup(tar.name);
	}

	/* Set bits 12-15 of the files mode */
	/* (typeflag was not trashed because chksum does not use getOctal) */
	switch (tar.typeflag) {
	/* busybox identifies hard links as being regular files with 0 size and a link name */
	case '1':
		file_header->mode |= S_IFREG;
		break;
	case '7':
	/* case 0: */
	case '0':
#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
		if (last_char_is(file_header->name, '/')) {
			file_header->mode |= S_IFDIR;
		} else
#endif
		file_header->mode |= S_IFREG;
		break;
	case '2':
		file_header->mode |= S_IFLNK;
		break;
	case '3':
		file_header->mode |= S_IFCHR;
		break;
	case '4':
		file_header->mode |= S_IFBLK;
		break;
	case '5':
		file_header->mode |= S_IFDIR;
		break;
	case '6':
		file_header->mode |= S_IFIFO;
		break;
#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
	case 'L':
		/* free: paranoia: tar with several consecutive longnames */
		free(longname);
		/* For paranoia reasons we allocate extra NUL char */
		longname = xzalloc(file_header->size + 1);
		/* We read ASCIZ string, including NUL */
		xread(archive_handle->src_fd, longname, file_header->size);
		archive_handle->offset += file_header->size;
		/* return get_header_tar(archive_handle); */
		/* gcc 4.1.1 didn't optimize it into jump */
		/* so we will do it ourself, this also saves stack */
		goto again;
	case 'K':
		free(linkname);
		linkname = xzalloc(file_header->size + 1);
		xread(archive_handle->src_fd, linkname, file_header->size);
		archive_handle->offset += file_header->size;
		/* return get_header_tar(archive_handle); */
		goto again;
	case 'D':	/* GNU dump dir */
	case 'M':	/* Continuation of multi volume archive */
	case 'N':	/* Old GNU for names > 100 characters */
	case 'S':	/* Sparse file */
	case 'V':	/* Volume header */
#endif
	case 'g':	/* pax global header */
	case 'x': {	/* pax extended header */
		off_t sz;
		bb_error_msg("warning: skipping header '%c'", tar.typeflag);
		sz = (file_header->size + 511) & ~(off_t)511;
		archive_handle->offset += sz;
		sz >>= 9; /* sz /= 512 but w/o contortions for signed div */
		while (sz--)
			xread(archive_handle->src_fd, &tar, 512);
		/* return get_header_tar(archive_handle); */
		goto again_after_align;
	}
	default:
		bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
	}

#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
	if (longname) {
		file_header->name = longname;
		longname = NULL;
	}
	if (linkname) {
		file_header->link_name = linkname;
		linkname = NULL;
	}
#endif
	if (!strncmp(file_header->name, "/../"+1, 3)
	 || strstr(file_header->name, "/../")
	) {
		bb_error_msg_and_die("name with '..' encountered: '%s'",
				file_header->name);
	}

	/* Strip trailing '/' in directories */
	/* Must be done after mode is set as '/' is used to check if it's a directory */
	cp = last_char_is(file_header->name, '/');

	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
		archive_handle->action_header(archive_handle->file_header);
		/* Note that we kill the '/' only after action_header() */
		/* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */
		if (cp) *cp = '\0';
		archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
		archive_handle->action_data(archive_handle);
		llist_add_to(&(archive_handle->passed), file_header->name);
	} else {
		data_skip(archive_handle);
		free(file_header->name);
	}
	archive_handle->offset += file_header->size;

	free(file_header->link_name);
	/* Do not free(file_header->name)! */

	return EXIT_SUCCESS;
}
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);
}
Exemple #16
0
int unzip_main(int argc, char **argv)
{
	enum { O_PROMPT, O_NEVER, O_ALWAYS };

	zip_header_t zip_header;
	smallint verbose = 1;
	smallint listing = 0;
	smallint overwrite = O_PROMPT;
	unsigned total_size;
	unsigned total_entries;
	int src_fd = -1;
	int dst_fd = -1;
	char *src_fn = NULL;
	char *dst_fn = NULL;
	llist_t *zaccept = NULL;
	llist_t *zreject = NULL;
	char *base_dir = NULL;
	int i, opt;
	int opt_range = 0;
	char key_buf[80];
	struct stat stat_buf;

	/* '-' makes getopt return 1 for non-options */
	while ((opt = getopt(argc, argv, "-d:lnopqx")) != -1) {
		switch (opt_range) {
		case 0: /* Options */
			switch (opt) {
			case 'l': /* List */
				listing = 1;
				break;

			case 'n': /* Never overwrite existing files */
				overwrite = O_NEVER;
				break;

			case 'o': /* Always overwrite existing files */
				overwrite = O_ALWAYS;
				break;

			case 'p': /* Extract files to stdout and fall through to set verbosity */
				dst_fd = STDOUT_FILENO;

			case 'q': /* Be quiet */
				verbose = 0;
				break;

			case 1: /* The zip file */
				/* +5: space for ".zip" and NUL */
				src_fn = xmalloc(strlen(optarg) + 5);
				strcpy(src_fn, optarg);
				opt_range++;
				break;

			default:
				bb_show_usage();

			}
			break;

		case 1: /* Include files */
			if (opt == 1) {
				llist_add_to(&zaccept, optarg);
				break;
			}
			if (opt == 'd') {
				base_dir = optarg;
				opt_range += 2;
				break;
			}
			if (opt == 'x') {
				opt_range++;
				break;
			}
			bb_show_usage();

		case 2 : /* Exclude files */
			if (opt == 1) {
				llist_add_to(&zreject, optarg);
				break;
			}
			if (opt == 'd') { /* Extract to base directory */
				base_dir = optarg;
				opt_range++;
				break;
			}
			/* fall through */

		default:
			bb_show_usage();
		}
	}

	if (src_fn == NULL) {
		bb_show_usage();
	}

	/* Open input file */
	if (LONE_DASH(src_fn)) {
		src_fd = STDIN_FILENO;
		/* Cannot use prompt mode since zip data is arriving on STDIN */
		if (overwrite == O_PROMPT)
			overwrite = O_NEVER;
	} else {
		static const char extn[][5] = {"", ".zip", ".ZIP"};
		int orig_src_fn_len = strlen(src_fn);

		for (i = 0; (i < 3) && (src_fd == -1); i++) {
			strcpy(src_fn + orig_src_fn_len, extn[i]);
			src_fd = open(src_fn, O_RDONLY);
		}
		if (src_fd == -1) {
			src_fn[orig_src_fn_len] = '\0';
			bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn);
		}
	}

	/* Change dir if necessary */
	if (base_dir)
		xchdir(base_dir);

	if (verbose) {
		printf("Archive:  %s\n", src_fn);
		if (listing){
			puts("  Length     Date   Time    Name\n"
			     " --------    ----   ----    ----");
		}
	}

	total_size = 0;
	total_entries = 0;
	while (1) {
		uint32_t magic;

		/* Check magic number */
		xread(src_fd, &magic, 4);
		if (magic == ZIP_CDS_MAGIC)
			break;
		if (magic != ZIP_FILEHEADER_MAGIC)
			bb_error_msg_and_die("invalid zip magic %08X", magic);

		/* Read the file header */
		xread(src_fd, zip_header.raw, ZIP_HEADER_LEN);
		FIX_ENDIANNESS(zip_header);
		if ((zip_header.formatted.method != 0) && (zip_header.formatted.method != 8)) {
			bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method);
		}

		/* Read filename */
		free(dst_fn);
		dst_fn = xzalloc(zip_header.formatted.filename_len + 1);
		xread(src_fd, dst_fn, zip_header.formatted.filename_len);

		/* Skip extra header bytes */
		unzip_skip(src_fd, zip_header.formatted.extra_len);

		/* Filter zip entries */
		if (find_list_entry(zreject, dst_fn)
		 || (zaccept && !find_list_entry(zaccept, dst_fn))
		) { /* Skip entry */
			i = 'n';

		} else { /* Extract entry */
			if (listing) { /* List entry */
				if (verbose) {
					unsigned dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16);
					printf("%9u  %02u-%02u-%02u %02u:%02u   %s\n",
					   zip_header.formatted.ucmpsize,
					   (dostime & 0x01e00000) >> 21,
					   (dostime & 0x001f0000) >> 16,
					   (((dostime & 0xfe000000) >> 25) + 1980) % 100,
					   (dostime & 0x0000f800) >> 11,
					   (dostime & 0x000007e0) >> 5,
					   dst_fn);
					total_size += zip_header.formatted.ucmpsize;
					total_entries++;
				} else {
					/* short listing -- filenames only */
					puts(dst_fn);
				}
				i = 'n';
			} else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */
				i = -1;
			} else if (last_char_is(dst_fn, '/')) { /* Extract directory */
				if (stat(dst_fn, &stat_buf) == -1) {
					if (errno != ENOENT) {
						bb_perror_msg_and_die("cannot stat '%s'",dst_fn);
					}
					if (verbose) {
						printf("   creating: %s\n", dst_fn);
					}
					unzip_create_leading_dirs(dst_fn);
					if (bb_make_directory(dst_fn, 0777, 0)) {
						bb_error_msg_and_die("exiting");
					}
				} else {
					if (!S_ISDIR(stat_buf.st_mode)) {
						bb_error_msg_and_die("'%s' exists but is not directory", dst_fn);
					}
				}
				i = 'n';

			} else {  /* Extract file */
 _check_file:
				if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */
					if (errno != ENOENT) {
						bb_perror_msg_and_die("cannot stat '%s'",dst_fn);
					}
					i = 'y';
				} else { /* File already exists */
					if (overwrite == O_NEVER) {
						i = 'n';
					} else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */
						if (overwrite == O_ALWAYS) {
							i = 'y';
						} else {
							printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn);
							if (!fgets(key_buf, sizeof(key_buf), stdin)) {
								bb_perror_msg_and_die("cannot read input");
							}
							i = key_buf[0];
						}
					} else { /* File is not regular file */
						bb_error_msg_and_die("'%s' exists but is not regular file",dst_fn);
					}
				}
			}
		}
Exemple #17
0
extern int unzip_main(int argc, char **argv)
{
	union {
		unsigned char raw[26];
		struct {
			unsigned short version;	/* 0-1 */
			unsigned short flags;	/* 2-3 */
			unsigned short method;	/* 4-5 */
			unsigned short modtime;	/* 6-7 */
			unsigned short moddate;	/* 8-9 */
			unsigned int crc32 __attribute__ ((packed));		/* 10-13 */
			unsigned int cmpsize __attribute__ ((packed));;	/* 14-17 */
			unsigned int ucmpsize __attribute__ ((packed));;	/* 18-21 */
			unsigned short filename_len;		/* 22-23 */
			unsigned short extra_len;		/* 24-25 */
		} formated __attribute__ ((packed));
	} zip_header;

	archive_handle_t *archive_handle;
	unsigned int total_size = 0;
	unsigned int total_entries = 0;
	char *base_dir = NULL;
	int opt = 0;

	/* Initialise */
	archive_handle = init_handle();
	archive_handle->action_data = NULL;
	archive_handle->action_header = header_list_unzip;

	while ((opt = getopt(argc, argv, "lnopqd:")) != -1) {
		switch (opt) {
			case 'l':	/* list */
				archive_handle->action_header = header_verbose_list_unzip;
				archive_handle->action_data = data_skip;
				break;
			case 'n':	/* never overwright existing files */
				break;
			case 'o':
				archive_handle->flags = ARCHIVE_EXTRACT_UNCONDITIONAL;
				break;
			case 'p':	/* extract files to stdout */
				archive_handle->action_data = data_extract_to_stdout;
				break;
			case 'q':	/* Extract files quietly */
				archive_handle->action_header = header_skip;
				break;
			case 'd':	/* Extract files to specified base directory*/
				base_dir = optarg;
				break;
#if 0
			case 'x':	/* Exclude the specified files */
				archive_handle->filter = filter_accept_reject_list;
				break;
#endif
			default:
				bb_show_usage();
		}
	}

	if (argc == optind) {
		bb_show_usage();
	}

	printf("Archive:  %s\n", argv[optind]);
	if (archive_handle->action_header == header_verbose_list_unzip) {
		printf("  Length     Date   Time    Name\n");
		printf(" --------    ----   ----    ----\n");
	}

	if (*argv[optind] == '-') {
		archive_handle->src_fd = fileno(stdin);
		archive_handle->seek = seek_by_char;
	} else {
		archive_handle->src_fd = bb_xopen(argv[optind++], O_RDONLY);
	}

	if ((base_dir) && (chdir(base_dir))) {
		bb_perror_msg_and_die("Couldnt chdir");
	}

	while (optind < argc) {
		archive_handle->filter = filter_accept_list;
		archive_handle->accept = llist_add_to(archive_handle->accept, argv[optind]);
		optind++;
	}

	while (1) {
		unsigned int magic;
		int dst_fd;

		/* TODO Endian issues */
		archive_xread_all(archive_handle, &magic, 4);
		archive_handle->offset += 4;

		if (magic == ZIP_CDS_MAGIC) {
			break;
		}
		else if (magic != ZIP_FILEHEADER_MAGIC) {
			bb_error_msg_and_die("Invlaide zip magic");
		}

		/* Read the file header */
		archive_xread_all(archive_handle, zip_header.raw, 26);
		archive_handle->offset += 26;
		archive_handle->file_header->mode = S_IFREG | 0777;

		if (zip_header.formated.method != 8) {
			bb_error_msg_and_die("Unsupported compression method %d\n", zip_header.formated.method);
		}

		/* Read filename */
		archive_handle->file_header->name = xmalloc(zip_header.formated.filename_len + 1);
		archive_xread_all(archive_handle, archive_handle->file_header->name, zip_header.formated.filename_len);
		archive_handle->offset += zip_header.formated.filename_len;
		archive_handle->file_header->name[zip_header.formated.filename_len] = '\0';

		/* Skip extra header bits */
		archive_handle->file_header->size = zip_header.formated.extra_len;
		data_skip(archive_handle);
		archive_handle->offset += zip_header.formated.extra_len;

		/* Handle directories */
		archive_handle->file_header->mode = S_IFREG | 0777;
		if (last_char_is(archive_handle->file_header->name, '/')) {
			archive_handle->file_header->mode ^= S_IFREG;
			archive_handle->file_header->mode |= S_IFDIR;
		}

		/* Data section */
		archive_handle->file_header->size = zip_header.formated.cmpsize;
		if (archive_handle->action_data) {
			archive_handle->action_data(archive_handle);
		} else {
			dst_fd = bb_xopen(archive_handle->file_header->name, O_WRONLY | O_CREAT);
			inflate(archive_handle->src_fd, dst_fd);
			close(dst_fd);
			chmod(archive_handle->file_header->name, archive_handle->file_header->mode);

			/* Validate decompression - crc */
			if (zip_header.formated.crc32 != (gunzip_crc ^ 0xffffffffL)) {
				bb_error_msg("Invalid compressed data--crc error");
			}

			/* Validate decompression - size */
			if (gunzip_bytes_out != zip_header.formated.ucmpsize) {
				bb_error_msg("Invalid compressed data--length error");
			}
		}

		/* local file descriptor section */
		archive_handle->offset += zip_header.formated.cmpsize;
		/* This ISNT unix time */
		archive_handle->file_header->mtime = zip_header.formated.modtime | (zip_header.formated.moddate << 16);
		archive_handle->file_header->size = zip_header.formated.ucmpsize;
		total_size += archive_handle->file_header->size;
		total_entries++;

		archive_handle->action_header(archive_handle->file_header);

		/* Data descriptor section */
		if (zip_header.formated.flags & 4) {
			/* skip over duplicate crc, compressed size and uncompressed size */
			unsigned short i;
			for (i = 0; i != 12; i++) {
				archive_xread_char(archive_handle);
			}
			archive_handle->offset += 12;
		}
	}
	/* Central directory section */

	if (archive_handle->action_header == header_verbose_list_unzip) {
		printf(" --------                   -------\n");
		printf("%9d                   %d files\n", total_size, total_entries);
	}

	return(EXIT_SUCCESS);
}
Exemple #18
0
int dpkg_deb_main(int argc, char **argv)
{
	archive_handle_t *ar_archive;
	archive_handle_t *tar_archive;
	llist_t *control_tar_llist = NULL;
	unsigned opt;
	const char *extract_dir;
	int need_args;

	/* Setup the tar archive handle */
	tar_archive = init_handle();

	/* Setup an ar archive handle that refers to the gzip sub archive */
	ar_archive = init_handle();
	ar_archive->dpkg__sub_archive = tar_archive;
	ar_archive->filter = filter_accept_list_reassign;

	llist_add_to(&ar_archive->accept, (char*)"data.tar");
	llist_add_to(&control_tar_llist, (char*)"control.tar");
#if ENABLE_FEATURE_SEAMLESS_GZ
	llist_add_to(&ar_archive->accept, (char*)"data.tar.gz");
	llist_add_to(&control_tar_llist, (char*)"control.tar.gz");
#endif
#if ENABLE_FEATURE_SEAMLESS_BZ2
	llist_add_to(&ar_archive->accept, (char*)"data.tar.bz2");
	llist_add_to(&control_tar_llist, (char*)"control.tar.bz2");
#endif
#if ENABLE_FEATURE_SEAMLESS_LZ
	llist_add_to(&ar_archive->accept, (char*)"data.tar.lz");
	llist_add_to(&control_tar_llist, (char*)"control.tar.lz");
#endif
#if ENABLE_FEATURE_SEAMLESS_LZMA
	llist_add_to(&ar_archive->accept, (char*)"data.tar.lzma");
	llist_add_to(&control_tar_llist, (char*)"control.tar.lzma");
#endif
#if ENABLE_FEATURE_SEAMLESS_XZ
	llist_add_to(&ar_archive->accept, (char*)"data.tar.xz");
	llist_add_to(&control_tar_llist, (char*)"control.tar.xz");
#endif

	opt_complementary = "c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
	opt = getopt32(argv, "cefXx");
	argv += optind;
	argc -= optind;

	if (opt & DPKG_DEB_OPT_CONTENTS) {
		tar_archive->action_header = header_verbose_list;
	}
	extract_dir = NULL;
	need_args = 1;
	if (opt & DPKG_DEB_OPT_CONTROL) {
		ar_archive->accept = control_tar_llist;
		tar_archive->action_data = data_extract_all;
		if (1 == argc) {
			extract_dir = "./DEBIAN";
		} else {
			need_args++;
		}
	}
	if (opt & DPKG_DEB_OPT_FIELD) {
		/* Print the entire control file
		 * it should accept a second argument which specifies a
		 * specific field to print */
		ar_archive->accept = control_tar_llist;
		llist_add_to(&(tar_archive->accept), (char*)"./control");
		tar_archive->filter = filter_accept_list;
		tar_archive->action_data = data_extract_to_stdout;
	}
	if (opt & DPKG_DEB_OPT_EXTRACT) {
		tar_archive->action_header = header_list;
	}
	if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) {
		tar_archive->action_data = data_extract_all;
		need_args = 2;
	}

	if (need_args != argc) {
		bb_show_usage();
	}

	tar_archive->src_fd = ar_archive->src_fd = xopen(argv[0], O_RDONLY);

	/* Work out where to extract the files */
	/* 2nd argument is a dir name */
	if (argv[1]) {
		extract_dir = argv[1];
	}
	if (extract_dir) {
		mkdir(extract_dir, 0777); /* bb_make_directory(extract_dir, 0777, 0) */
		xchdir(extract_dir);
	}

	/* Do it */
	unpack_ar_archive(ar_archive);

	/* Cleanup */
	if (ENABLE_FEATURE_CLEAN_UP)
		close(ar_archive->src_fd);

	return EXIT_SUCCESS;
}
extern char get_header_tar(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	union {
		/* ustar header, Posix 1003.1 */
		unsigned char raw[512];
		struct {
			char name[100];	/*   0-99 */
			char mode[8];	/* 100-107 */
			char uid[8];	/* 108-115 */
			char gid[8];	/* 116-123 */
			char size[12];	/* 124-135 */
			char mtime[12];	/* 136-147 */
			char chksum[8];	/* 148-155 */
			char typeflag;	/* 156-156 */
			char linkname[100];	/* 157-256 */
			char magic[6];	/* 257-262 */
			char version[2];	/* 263-264 */
			char uname[32];	/* 265-296 */
			char gname[32];	/* 297-328 */
			char devmajor[8];	/* 329-336 */
			char devminor[8];	/* 337-344 */
			char prefix[155];	/* 345-499 */
			char padding[12];	/* 500-512 */
		} formated;
	} tar;
	long sum = 0;
	long i;

	/* Align header */
	data_align(archive_handle, 512);

	if (bb_full_read(archive_handle->src_fd, tar.raw, 512) != 512) {
		/* Assume end of file */
		return(EXIT_FAILURE);
	}
	archive_handle->offset += 512;

	/* If there is no filename its an empty header */
	if (tar.formated.name[0] == 0) {
		return(EXIT_SUCCESS);
	}

	/* Check header has valid magic, "ustar" is for the proper tar
	 * 0's are for the old tar format
	 */
	if (strncmp(tar.formated.magic, "ustar", 5) != 0) {
#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
		if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0)
#endif
			bb_error_msg_and_die("Invalid tar magic");
	}
	/* Do checksum on headers */
	for (i =  0; i < 148 ; i++) {
		sum += tar.raw[i];
	}
	sum += ' ' * 8;
	for (i =  156; i < 512 ; i++) {
		sum += tar.raw[i];
	}
	if (sum != strtol(tar.formated.chksum, NULL, 8)) {
		bb_error_msg("Invalid tar header checksum");
		return(EXIT_FAILURE);
	}

#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	if (longname) {
		file_header->name = longname;
		longname = NULL;
	}
	else if (linkname) {
		file_header->name = linkname;
		linkname = NULL;
	} else
#endif
	if (tar.formated.prefix[0] == 0) {
		file_header->name = strdup(tar.formated.name);
	} else {
		file_header->name = concat_path_file(tar.formated.prefix, tar.formated.name);
	}

	file_header->uid = strtol(tar.formated.uid, NULL, 8);
	file_header->gid = strtol(tar.formated.gid, NULL, 8);
	file_header->size = strtol(tar.formated.size, NULL, 8);
	file_header->mtime = strtol(tar.formated.mtime, NULL, 8);
	file_header->link_name = (tar.formated.linkname[0] != '\0') ?
	    bb_xstrdup(tar.formated.linkname) : NULL;
	file_header->device = (dev_t) ((strtol(tar.formated.devmajor, NULL, 8) << 8) +
				 strtol(tar.formated.devminor, NULL, 8));

	/* Set bits 0-11 of the files mode */
	file_header->mode = 07777 & strtol(tar.formated.mode, NULL, 8);

	/* Set bits 12-15 of the files mode */
	switch (tar.formated.typeflag) {
	/* busybox identifies hard links as being regular files with 0 size and a link name */
	case '1':
		file_header->mode |= S_IFREG;
		break;
	case 'x':
	case 'g':
		bb_error_msg_and_die("pax is not tar");
		break;
	case '7':
		/* Reserved for high performance files, treat as normal file */
	case 0:
	case '0':
#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
		if (last_char_is(file_header->name, '/')) {
			file_header->mode |= S_IFDIR;
		} else
#endif
			file_header->mode |= S_IFREG;
		break;
	case '2':
		file_header->mode |= S_IFLNK;
		break;
	case '3':
		file_header->mode |= S_IFCHR;
		break;
	case '4':
		file_header->mode |= S_IFBLK;
		break;
	case '5':
		file_header->mode |= S_IFDIR;
		break;
	case '6':
		file_header->mode |= S_IFIFO;
		break;
#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	case 'L': {
			longname = xmalloc(file_header->size + 1);
			archive_xread_all(archive_handle, longname, file_header->size);
			longname[file_header->size] = '\0';
			archive_handle->offset += file_header->size;

			return(get_header_tar(archive_handle));
		}
	case 'K': {
			linkname = xmalloc(file_header->size + 1);
			archive_xread_all(archive_handle, linkname, file_header->size);
			linkname[file_header->size] = '\0';
			archive_handle->offset += file_header->size;

			file_header->name = linkname;
			return(get_header_tar(archive_handle));
		}
	case 'D':	/* GNU dump dir */
	case 'M':	/* Continuation of multi volume archive*/
	case 'N':	/* Old GNU for names > 100 characters */
	case 'S':	/* Sparse file */
	case 'V':	/* Volume header */
		bb_error_msg("Ignoring GNU extension type %c", tar.formated.typeflag);
#endif
	default:
		bb_error_msg("Unknown typeflag: 0x%x", tar.formated.typeflag);
	}
	{	/* Strip trailing '/' in directories */
		/* Must be done after mode is set as '/' is used to check if its a directory */
		char *tmp = last_char_is(file_header->name, '/');
		if (tmp) {
			*tmp = '\0';
		}
	}

	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
		archive_handle->action_header(archive_handle->file_header);
		archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
		archive_handle->action_data(archive_handle);
		archive_handle->passed = llist_add_to(archive_handle->passed, file_header->name);
	} else {
		data_skip(archive_handle);
	}
	archive_handle->offset += file_header->size;

	free(file_header->link_name);

	return(EXIT_SUCCESS);
}
Exemple #20
0
int last_main(int argc UNUSED_PARAM, char **argv)
{
	struct utmpx ut;
	const char *filename = _PATH_WTMP;
	llist_t *zlist;
	off_t pos;
	time_t start_time;
	time_t boot_time;
	time_t down_time;
	int file;
	smallint going_down;
	smallint boot_down;

	/*opt =*/ getopt32(argv, "Wf:" /* "H" */, &filename);
#ifdef BUT_UTIL_LINUX_LAST_HAS_NO_SUCH_OPT
	if (opt & LAST_OPT_H) {
		/* Print header line */
		if (opt & LAST_OPT_W) {
			printf(HEADER_FORMAT, HEADER_LINE_WIDE);
		} else {
			printf(HEADER_FORMAT, HEADER_LINE);
		}
	}
#endif

	file = xopen(filename, O_RDONLY);
	{
		/* in case the file is empty... */
		struct stat st;
		fstat(file, &st);
		start_time = st.st_ctime;
	}

	time(&down_time);
	going_down = 0;
	boot_down = NORMAL; /* 0 */
	zlist = NULL;
	boot_time = 0;
	/* get file size, rounding down to last full record */
	pos = xlseek(file, 0, SEEK_END) / sizeof(ut) * sizeof(ut);
	for (;;) {
		pos -= (off_t)sizeof(ut);
		if (pos < 0) {
			/* Beyond the beginning of the file boundary =>
			 * the whole file has been read. */
			break;
		}
		xlseek(file, pos, SEEK_SET);
		xread(file, &ut, sizeof(ut));
		/* rewritten by each record, eventially will have
		 * first record's ut_tv.tv_sec: */
		start_time = ut.ut_tv.tv_sec;

		switch (get_ut_type(&ut)) {
		case SHUTDOWN_TIME:
			down_time = ut.ut_tv.tv_sec;
			boot_down = DOWN;
			going_down = 1;
			break;
		case RUN_LVL:
			if (is_runlevel_shutdown(&ut)) {
				down_time = ut.ut_tv.tv_sec;
				going_down = 1;
				boot_down = DOWN;
			}
			break;
		case BOOT_TIME:
			strcpy(ut.ut_line, "system boot");
			show_entry(&ut, REBOOT, down_time);
			boot_down = CRASH;
			going_down = 1;
			break;
		case DEAD_PROCESS:
			if (!ut.ut_line[0]) {
				break;
			}
			/* add_entry */
			llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
			break;
		case USER_PROCESS: {
			int show;

			if (!ut.ut_line[0]) {
				break;
			}
			/* find_entry */
			show = 1;
			{
				llist_t *el, *next;
				for (el = zlist; el; el = next) {
					struct utmpx *up = (struct utmpx *)el->data;
					next = el->link;
					if (strncmp(up->ut_line, ut.ut_line, __UT_LINESIZE) == 0) {
						if (show) {
							show_entry(&ut, NORMAL, up->ut_tv.tv_sec);
							show = 0;
						}
						llist_unlink(&zlist, el);
						free(el->data);
						free(el);
					}
				}
			}

			if (show) {
				int state = boot_down;

				if (boot_time == 0) {
					state = LOGGED;
					/* Check if the process is alive */
					if ((ut.ut_pid > 0)
					 && (kill(ut.ut_pid, 0) != 0)
					 && (errno == ESRCH)) {
						state = GONE;
					}
				}
				show_entry(&ut, state, boot_time);
			}
			/* add_entry */
			llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
			break;
		}
		}

		if (going_down) {
			boot_time = ut.ut_tv.tv_sec;
			llist_free(zlist, free);
			zlist = NULL;
			going_down = 0;
		}
	}

	if (ENABLE_FEATURE_CLEAN_UP) {
		llist_free(zlist, free);
	}

	printf("\nwtmp begins %s", ctime(&start_time));

	if (ENABLE_FEATURE_CLEAN_UP)
		close(file);
	fflush_stdout_and_exit(EXIT_SUCCESS);
}
Exemple #21
0
int dpkg_deb_main(int argc, char **argv)
{
	archive_handle_t *ar_archive;
	archive_handle_t *tar_archive;
	llist_t *control_tar_llist = NULL;
	unsigned long opt;
	char *extract_dir = NULL;
	short argcount = 1;

	/* Setup the tar archive handle */
	tar_archive = init_handle();

	/* Setup an ar archive handle that refers to the gzip sub archive */
	ar_archive = init_handle();
	ar_archive->sub_archive = tar_archive;
	ar_archive->filter = filter_accept_list_reassign;

#ifdef CONFIG_FEATURE_DEB_TAR_GZ
	ar_archive->accept = llist_add_to(NULL, "data.tar.gz");
	control_tar_llist = llist_add_to(NULL, "control.tar.gz");
#endif

#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
	ar_archive->accept = llist_add_to(ar_archive->accept, "data.tar.bz2");
	control_tar_llist = llist_add_to(control_tar_llist, "control.tar.bz2");
#endif

	bb_opt_complementally = "?c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
	opt = bb_getopt_ulflags(argc, argv, "cefXx");

	if (opt & DPKG_DEB_OPT_CONTENTS) {
		tar_archive->action_header = header_verbose_list;
	}
	if (opt & DPKG_DEB_OPT_CONTROL) {
		ar_archive->accept = control_tar_llist;
		tar_archive->action_data = data_extract_all;
		if (optind + 1 == argc) {
			extract_dir = "./DEBIAN";
		} else {
			argcount++;
		}
	}
	if (opt & DPKG_DEB_OPT_FIELD) {
		/* Print the entire control file
		 * it should accept a second argument which specifies a
		 * specific field to print */
		ar_archive->accept = control_tar_llist;
		tar_archive->accept = llist_add_to(NULL, "./control");
		tar_archive->filter = filter_accept_list;
		tar_archive->action_data = data_extract_to_stdout;
	}
	if (opt & DPKG_DEB_OPT_EXTRACT) {
		tar_archive->action_header = header_list;
	}
	if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) {
		tar_archive->action_data = data_extract_all;
		argcount = 2;
	}

	if ((optind + argcount) != argc) {
		bb_show_usage();
	}

	tar_archive->src_fd = ar_archive->src_fd = bb_xopen(argv[optind++], O_RDONLY);

	/* Workout where to extract the files */
	/* 2nd argument is a dir name */
	if (argv[optind]) {
		extract_dir = argv[optind];
	}
	if (extract_dir) {
		mkdir(extract_dir, 0777);
		chdir(extract_dir);
	}
	unpack_ar_archive(ar_archive);

	/* Cleanup */
	close (ar_archive->src_fd);

	return(EXIT_SUCCESS);
}
Exemple #22
0
int dpkg_deb_main(int argc UNUSED_PARAM, char **argv)
{
	archive_handle_t *ar_archive;
	archive_handle_t *tar_archive;
	llist_t *control_tar_llist = NULL;
	unsigned opt;
	const char *extract_dir;

	/* Setup the tar archive handle */
	tar_archive = init_handle();

	/* Setup an ar archive handle that refers to the gzip sub archive */
	ar_archive = init_handle();
	ar_archive->dpkg__sub_archive = tar_archive;
	ar_archive->filter = filter_accept_list_reassign;

	llist_add_to(&ar_archive->accept, (char*)"data.tar");
	llist_add_to(&control_tar_llist, (char*)"control.tar");
#if ENABLE_FEATURE_SEAMLESS_GZ
	llist_add_to(&ar_archive->accept, (char*)"data.tar.gz");
	llist_add_to(&control_tar_llist, (char*)"control.tar.gz");
#endif
#if ENABLE_FEATURE_SEAMLESS_BZ2
	llist_add_to(&ar_archive->accept, (char*)"data.tar.bz2");
	llist_add_to(&control_tar_llist, (char*)"control.tar.bz2");
#endif
#if ENABLE_FEATURE_SEAMLESS_LZMA
	llist_add_to(&ar_archive->accept, (char*)"data.tar.lzma");
	llist_add_to(&control_tar_llist, (char*)"control.tar.lzma");
#endif
#if ENABLE_FEATURE_SEAMLESS_XZ
	llist_add_to(&ar_archive->accept, (char*)"data.tar.xz");
	llist_add_to(&control_tar_llist, (char*)"control.tar.xz");
#endif

	/* Must have 1 or 2 args */
	opt_complementary = "-1:?2:c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
	opt = getopt32(argv, "cefXx");
	argv += optind;
	//argc -= optind;

	extract_dir = argv[1];
	if (opt & DPKG_DEB_OPT_CONTENTS) { // -c
		tar_archive->action_header = header_verbose_list;
		if (extract_dir)
			bb_show_usage();
	}
	if (opt & DPKG_DEB_OPT_FIELD) { // -f
		/* Print the entire control file */
//TODO: standard tool accepts an optional list of fields to print
		ar_archive->accept = control_tar_llist;
		llist_add_to(&(tar_archive->accept), (char*)"./control");
		tar_archive->filter = filter_accept_list;
		tar_archive->action_data = data_extract_to_stdout;
		if (extract_dir)
			bb_show_usage();
	}
	if (opt & DPKG_DEB_OPT_CONTROL) { // -e
		ar_archive->accept = control_tar_llist;
		tar_archive->action_data = data_extract_all;
		if (!extract_dir)
			extract_dir = "./DEBIAN";
	}
	if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) { // -Xx
		if (opt & DPKG_DEB_OPT_EXTRACT_VERBOSE)
			tar_archive->action_header = header_list;
		tar_archive->action_data = data_extract_all;
		if (!extract_dir)
			bb_show_usage();
	}

	/* Standard tool supports "-" */
	tar_archive->src_fd = ar_archive->src_fd = xopen_stdin(argv[0]);

	if (extract_dir) {
		mkdir(extract_dir, 0777); /* bb_make_directory(extract_dir, 0777, 0) */
		xchdir(extract_dir);
	}

	/* Do it */
	unpack_ar_archive(ar_archive);

	/* Cleanup */
	if (ENABLE_FEATURE_CLEAN_UP)
		close(ar_archive->src_fd);

	return EXIT_SUCCESS;
}
Exemple #23
0
extern char get_header_tar(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	union {
		unsigned char raw[512];
		struct {
			char name[100];	/*   0-99 */
			char mode[8];	/* 100-107 */
			char uid[8];	/* 108-115 */
			char gid[8];	/* 116-123 */
			char size[12];	/* 124-135 */
			char mtime[12];	/* 136-147 */
			char chksum[8];	/* 148-155 */
			char typeflag;	/* 156-156 */
			char linkname[100];	/* 157-256 */
			char magic[6];	/* 257-262 */
			char version[2];	/* 263-264 */
			char uname[32];	/* 265-296 */
			char gname[32];	/* 297-328 */
			char devmajor[8];	/* 329-336 */
			char devminor[8];	/* 337-344 */
			char prefix[155];	/* 345-499 */
			char padding[12];	/* 500-512 */
		} formated;
	} tar;
	long sum = 0;
	long i;
	char *tmp;

	/* Align header */
	data_align(archive_handle, 512);

	if (archive_xread(archive_handle, tar.raw, 512) != 512) {
		/* Assume end of file */
		return(EXIT_FAILURE);
	}
	archive_handle->offset += 512;

	/* If there is no filename its an empty header */
	if (tar.formated.name[0] == 0) {
		return(EXIT_SUCCESS);
	}

	/* Check header has valid magic, "ustar" is for the proper tar
	 * 0's are for the old tar format
	 */
	if (strncmp(tar.formated.magic, "ustar", 5) != 0) {
#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
		if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0)
#endif
			bb_error_msg_and_die("Invalid tar magic");
	}
	/* Do checksum on headers */
	for (i =  0; i < 148 ; i++) {
		sum += tar.raw[i];
	}
	sum += ' ' * 8;
	for (i =  156; i < 512 ; i++) {
		sum += tar.raw[i];
	}
	if (sum != strtol(tar.formated.chksum, NULL, 8)) {
		bb_error_msg("Invalid tar header checksum");
		return(EXIT_FAILURE);
	}

#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	if (longname) {
		file_header->name = longname;
		longname = NULL;
	}
	else if (linkname) {
		file_header->name = linkname;
		linkname = NULL;
	} else
#endif
	if (tar.formated.prefix[0] == 0) {
		file_header->name = strdup(tar.formated.name);
	} else {
		file_header->name = concat_path_file(tar.formated.prefix, tar.formated.name);
	}
	tmp = last_char_is(archive_handle->file_header->name, '/');
	if (tmp) {
		*tmp = '\0';
	}

	file_header->mode = strtol(tar.formated.mode, NULL, 8);
	file_header->uid = strtol(tar.formated.uid, NULL, 8);
	file_header->gid = strtol(tar.formated.gid, NULL, 8);
	file_header->size = strtol(tar.formated.size, NULL, 8);
	file_header->mtime = strtol(tar.formated.mtime, NULL, 8);
	file_header->link_name = (tar.formated.linkname[0] != '\0') ? 
	    bb_xstrdup(tar.formated.linkname) : NULL;
	file_header->device = (dev_t) ((strtol(tar.formated.devmajor, NULL, 8) << 8) +
				 strtol(tar.formated.devminor, NULL, 8));

	if (tar.formated.typeflag == '1') {
		bb_error_msg("WARNING: Converting hard link to symlink");
		file_header->mode |= S_IFLNK;
	}
#if defined CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY || defined CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	/* Fix mode, used by the old format */
	switch (tar.formated.typeflag) {
# ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
	case 0:
	case '0':
		file_header->mode |= S_IFREG;
		break;
	case '1':
//		bb_error_msg("Internal hard link not supported");
		break;
	case '2':
		file_header->mode |= S_IFLNK;
		break;
	case '3':
		file_header->mode |= S_IFCHR;
		break;
	case '4':
		file_header->mode |= S_IFBLK;
		break;
	case '5':
		file_header->mode |= S_IFDIR;
		break;
	case '6':
		file_header->mode |= S_IFIFO;
		break;
# endif
# ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	case 'L': {
			longname = xmalloc(file_header->size + 1);
			archive_xread_all(archive_handle, longname, file_header->size);
			longname[file_header->size] = '\0';
			archive_handle->offset += file_header->size;

			return(get_header_tar(archive_handle));
		}
	case 'K': {
			linkname = xmalloc(file_header->size + 1);
			archive_xread_all(archive_handle, linkname, file_header->size);
			linkname[file_header->size] = '\0';
			archive_handle->offset += file_header->size;

			file_header->name = linkname;
			return(get_header_tar(archive_handle));
		}
	case 'D':
	case 'M':
	case 'N':
	case 'S':
	case 'V':
		bb_error_msg("Ignoring GNU extension type %c", tar.formated.typeflag);
# endif
	}
#endif
	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
		archive_handle->action_header(archive_handle->file_header);
		archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
		archive_handle->action_data(archive_handle);
		archive_handle->passed = llist_add_to(archive_handle->passed, archive_handle->file_header->name);
	} else {
		data_skip(archive_handle);			
	}
	archive_handle->offset += file_header->size;

	return(EXIT_SUCCESS);
}
Exemple #24
0
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 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->flags = ARCHIVE_CREATE_LEADING_DIRS
	                  | ARCHIVE_PRESERVE_DATE
	                  | ARCHIVE_EXTRACT_UNCONDITIONAL;

	/* 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
		USE_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
		USE_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
		SKIP_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
	applet_long_options = tar_long_options;
#endif
	opt = getopt32(argc, argv,
		"txC:f:Opvk"
		USE_FEATURE_TAR_CREATE(  "ch"  )
		USE_FEATURE_TAR_BZIP2(   "j"   )
		USE_FEATURE_TAR_LZMA(    "a"   )
		USE_FEATURE_TAR_FROM(    "T:X:")
		USE_FEATURE_TAR_GZIP(    "z"   )
		USE_FEATURE_TAR_COMPRESS("Z"   )
		, &base_dir // -C dir
		, &tar_filename // -f filename
		USE_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
		USE_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
		);

	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->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL;

	if (opt & OPT_NOPRESERVE_OWN)
		tar_handle->flags |= ARCHIVE_NOPRESERVE_OWN;

	if (opt & OPT_NOPRESERVE_PERM)
		tar_handle->flags |= ARCHIVE_NOPRESERVE_PERM;

	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

	/* 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) {
		/* kill trailing '/' unless the string is just "/" */
		char *cp = last_char_is(argv[optind], '/');
		if (cp > argv[optind])
			*cp = '\0';
		llist_add_to(&tar_handle->accept, argv[optind]);
		optind++;
	}
	tar_handle->accept = llist_rev(tar_handle->accept);

	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;
		/* was doing unlink; open(O_WRONLY|O_CREAT|O_EXCL); why? */
		} 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 {
			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) {
		int zipMode = 0;
		if (ENABLE_FEATURE_TAR_GZIP && get_header_ptr == get_header_tar_gz)
			zipMode = 1;
		if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2)
			zipMode = 2;
		/* 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)
		/* nothing */;

	/* 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;
}