コード例 #1
0
ファイル: ar.c プロジェクト: aYosukeAkatsuka/edimax-br-6528n
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;
}
コード例 #2
0
extern void unpack_ar_archive(archive_handle_t *ar_archive)
{
	char magic[7];

	archive_xread_all(ar_archive, magic, 7);
	if (strncmp(magic, "!<arch>", 7) != 0) {
		bb_error_msg_and_die("Invalid ar magic");
	}
	ar_archive->offset += 7;

	while (get_header_ar(ar_archive) == EXIT_SUCCESS);
}
コード例 #3
0
ファイル: unpack_ar_archive.c プロジェクト: Ayyayay/busybox
void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive)
{
	char magic[7];

	xread(ar_archive->src_fd, magic, AR_MAGIC_LEN);
	if (strncmp(magic, AR_MAGIC, AR_MAGIC_LEN) != 0) {
		bb_error_msg_and_die("invalid ar magic");
	}
	ar_archive->offset += AR_MAGIC_LEN;

	while (get_header_ar(ar_archive) == EXIT_SUCCESS)
		continue;
}
コード例 #4
0
extern char get_header_ar(archive_handle_t *archive_handle)
{
	file_header_t *typed = archive_handle->file_header;
	union {
		char raw[60];
	 	struct {
 			char name[16];
 			char date[12];
 			char uid[6];
 			char gid[6];
 			char mode[8];
 			char size[10];
 			char magic[2];
 		} formated;
	} ar;
#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
	static char *ar_long_names;
	static unsigned int ar_long_name_size;
#endif

	/* dont use bb_xread as we want to handle the error ourself */
	if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
		/* End Of File */
		return(EXIT_FAILURE);
	}

	/* Some ar entries have a trailing '\n' after the previous data entry */
	if (ar.raw[0] == '\n') {
		/* fix up the header, we started reading 1 byte too early */
		memmove(ar.raw, &ar.raw[1], 59);
		ar.raw[59] = bb_xread_char(archive_handle->src_fd);
		archive_handle->offset++;
	}
	archive_handle->offset += 60;

	/* align the headers based on the header magic */
	if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) {
		bb_error_msg_and_die("Invalid ar header");
	}

	typed->mode = strtol(ar.formated.mode, NULL, 8);
	typed->mtime = atoi(ar.formated.date);
	typed->uid = atoi(ar.formated.uid);
	typed->gid = atoi(ar.formated.gid);
	typed->size = atoi(ar.formated.size);

	/* long filenames have '/' as the first character */
	if (ar.formated.name[0] == '/') {
#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
		if (ar.formated.name[1] == '/') {
			/* If the second char is a '/' then this entries data section
			 * stores long filename for multiple entries, they are stored
			 * in static variable long_names for use in future entries */
			ar_long_name_size = typed->size;
			ar_long_names = xmalloc(ar_long_name_size);
			bb_xread_all(archive_handle->src_fd, ar_long_names, ar_long_name_size);
			archive_handle->offset += ar_long_name_size;
			/* This ar entries data section only contained filenames for other records
			 * they are stored in the static ar_long_names for future reference */
			return (get_header_ar(archive_handle)); /* Return next header */
		} else if (ar.formated.name[1] == ' ') {
			/* This is the index of symbols in the file for compilers */
			data_skip(archive_handle);
			archive_handle->offset += typed->size;
			return (get_header_ar(archive_handle)); /* Return next header */
		} else {
			/* The number after the '/' indicates the offset in the ar data section
			(saved in variable long_name) that conatains the real filename */
			const unsigned int long_offset = atoi(&ar.formated.name[1]);
			if (long_offset >= ar_long_name_size) {
				bb_error_msg_and_die("Cant resolve long filename");
			}
			typed->name = bb_xstrdup(ar_long_names + long_offset);
		}
#else
		bb_error_msg_and_die("long filenames not supported");
#endif
	} else {
		/* short filenames */
               typed->name = bb_xstrndup(ar.formated.name, 16);
	}

	typed->name[strcspn(typed->name, " /")] = '\0';

	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
		archive_handle->action_header(typed);
		if (archive_handle->sub_archive) {
			while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS);
		} else {
			archive_handle->action_data(archive_handle);
		}
	} else {
		data_skip(archive_handle);			
	}

	archive_handle->offset += typed->size;
	/* Set the file pointer to the correct spot, we may have been reading a compressed file */
	lseek(archive_handle->src_fd, archive_handle->offset, SEEK_SET);

	return(EXIT_SUCCESS);
}
コード例 #5
0
ファイル: unarchive.c プロジェクト: BashfulBladder/gargoyle
char *
deb_extract(const char *package_filename, FILE *out_stream,
	const int extract_function, const char *prefix,
	const char *filename, int *err)
{
	FILE *deb_stream = NULL;
	file_header_t *ar_header = NULL;
	const char **file_list = NULL;
	char *output_buffer = NULL;
	char *ared_file = NULL;
	char ar_magic[8];
	int gz_err;

	*err = 0;

	if (filename != NULL) {
		file_list = xmalloc(sizeof(char *) * 2);
		file_list[0] = filename;
		file_list[1] = NULL;
	}

	if (extract_function & extract_control_tar_gz) {
		ared_file = "control.tar.gz";
	}
	else if (extract_function & extract_data_tar_gz) {
		ared_file = "data.tar.gz";
	} else {
                error_msg( "Internal error: extract_function=%x\n",
				extract_function);
		*err = -1;
		goto cleanup;
        }

	/* open the debian package to be worked on */
	deb_stream = wfopen(package_filename, "r");
	if (deb_stream == NULL) {
		*err = -1;
		goto cleanup;
	}
	/* set the buffer size */
	setvbuf(deb_stream, NULL, _IOFBF, 0x8000);

	/* check ar magic */
	fread(ar_magic, 1, 8, deb_stream);

	if (strncmp(ar_magic,"!<arch>",7) == 0) {
		archive_offset = 8;

		while ((ar_header = get_header_ar(deb_stream)) != NULL) {
			if (strcmp(ared_file, ar_header->name) == 0) {
				int gunzip_pid = 0;
				FILE *uncompressed_stream;
				/* open a stream of decompressed data */
				uncompressed_stream = gz_open(deb_stream, &gunzip_pid);
				if (uncompressed_stream == NULL) {
					*err = -1;
					goto cleanup;
				}

				archive_offset = 0;
				output_buffer = unarchive(uncompressed_stream,
						out_stream, get_header_tar,
						free_header_tar,
						extract_function, prefix,
						file_list, err);
				fclose(uncompressed_stream);
				gz_err = gz_close(gunzip_pid);
				if (gz_err)
					*err = -1;
				free_header_ar(ar_header);
				break;
			}
			if (fseek(deb_stream, ar_header->size, SEEK_CUR) == -1) {
				perror_msg("Couldn't fseek into %s", package_filename);
				*err = -1;
				free_header_ar(ar_header);
				goto cleanup;
			}
			free_header_ar(ar_header);
		}
		goto cleanup;
	} else if (strncmp(ar_magic, "\037\213", 2) == 0) {
		/* it's a gz file, let's assume it's an opkg */
		int unzipped_opkg_pid;
		FILE *unzipped_opkg_stream;
		file_header_t *tar_header;
		archive_offset = 0;
		if (fseek(deb_stream, 0, SEEK_SET) == -1) {
			perror_msg( "Couldn't fseek into %s", package_filename);
			*err = -1;
			goto cleanup;
		}
		unzipped_opkg_stream = gz_open(deb_stream, &unzipped_opkg_pid);
		if (unzipped_opkg_stream == NULL) {
			*err = -1;
			goto cleanup;
		}

		/* walk through outer tar file to find ared_file */
		while ((tar_header = get_header_tar(unzipped_opkg_stream)) != NULL) {
                        int name_offset = 0;
                        if (strncmp(tar_header->name, "./", 2) == 0)
                                name_offset = 2;
			if (strcmp(ared_file, tar_header->name+name_offset) == 0) {
				int gunzip_pid = 0;
				FILE *uncompressed_stream;
				/* open a stream of decompressed data */
				uncompressed_stream = gz_open(unzipped_opkg_stream, &gunzip_pid);
				if (uncompressed_stream == NULL) {
					*err = -1;
					goto cleanup;
				}
				archive_offset = 0;

				output_buffer = unarchive(uncompressed_stream,
							  out_stream,
							  get_header_tar,
							  free_header_tar,
							  extract_function,
							  prefix,
							  file_list,
							  err);

				free_header_tar(tar_header);
				fclose(uncompressed_stream);
				gz_err = gz_close(gunzip_pid);
				if (gz_err)
					*err = -1;
				break;
			}
			seek_sub_file(unzipped_opkg_stream, tar_header->size);
			free_header_tar(tar_header);
		}
		fclose(unzipped_opkg_stream);
		gz_err = gz_close(unzipped_opkg_pid);
		if (gz_err)
			*err = -1;

		goto cleanup;
	} else {
		*err = -1;
		error_msg("%s: invalid magic", package_filename);
	}

cleanup:
	if (deb_stream)
		fclose(deb_stream);
	if (file_list)
		free(file_list);

	return output_buffer;
}
コード例 #6
0
ファイル: unarchive.c プロジェクト: BashfulBladder/gargoyle
static file_header_t *
get_header_ar(FILE *src_stream)
{
	file_header_t *typed;
	union {
		char raw[60];
	 	struct {
 			char name[16];
 			char date[12];
 			char uid[6];
 			char gid[6];
 			char mode[8];
 			char size[10];
 			char magic[2];
 		} formated;
	} ar;
	static char *ar_long_names;

	if (fread(ar.raw, 1, 60, src_stream) != 60) {
		return(NULL);
	}
	archive_offset += 60;
	/* align the headers based on the header magic */
	if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) {
		/* some version of ar, have an extra '\n' after each data entry,
		 * this puts the next header out by 1 */
		if (ar.formated.magic[1] != '`') {
			error_msg("Invalid magic");
			return(NULL);
		}
		/* read the next char out of what would be the data section,
		 * if its a '\n' then it is a valid header offset by 1*/
		archive_offset++;
		if (fgetc(src_stream) != '\n') {
			error_msg("Invalid magic");
			return(NULL);
		}
		/* fix up the header, we started reading 1 byte too early */
		/* raw_header[60] wont be '\n' as it should, but it doesnt matter */
		memmove(ar.raw, &ar.raw[1], 59);
	}

	typed = (file_header_t *) xcalloc(1, sizeof(file_header_t));

	typed->size = (size_t) atoi(ar.formated.size);
	/* long filenames have '/' as the first character */
	if (ar.formated.name[0] == '/') {
		if (ar.formated.name[1] == '/') {
			/* If the second char is a '/' then this entries data section
			 * stores long filename for multiple entries, they are stored
			 * in static variable long_names for use in future entries */
			ar_long_names = (char *) xrealloc(ar_long_names, typed->size);
			fread(ar_long_names, 1, typed->size, src_stream);
			archive_offset += typed->size;
			/* This ar entries data section only contained filenames for other records
			 * they are stored in the static ar_long_names for future reference */
			return (get_header_ar(src_stream)); /* Return next header */
		} else if (ar.formated.name[1] == ' ') {
			/* This is the index of symbols in the file for compilers */
			seek_sub_file(src_stream, typed->size);
			return (get_header_ar(src_stream)); /* Return next header */
		} else {
			/* The number after the '/' indicates the offset in the ar data section
			(saved in variable long_name) that conatains the real filename */
			if (!ar_long_names) {
				error_msg("Cannot resolve long file name");
				return (NULL);
			}
			typed->name = xstrdup(ar_long_names + atoi(&ar.formated.name[1]));
		}
	} else {
		/* short filenames */
		typed->name = xcalloc(1, 16);
		strncpy(typed->name, ar.formated.name, 16);
	}
	typed->name[strcspn(typed->name, " /")]='\0';

	/* convert the rest of the now valid char header to its typed struct */
	parse_mode(ar.formated.mode, &typed->mode);
	typed->mtime = atoi(ar.formated.date);
	typed->uid = atoi(ar.formated.uid);
	typed->gid = atoi(ar.formated.gid);

	return(typed);
}