char get_header_tar_gz(archive_handle_t *archive_handle)
{
#if BB_MMU
	unsigned char magic[2];
#endif

	/* Can't lseek over pipes */
	archive_handle->seek = seek_by_read;

	/* Check gzip magic only if open_transformer will invoke unpack_gz_stream (MMU case).
	 * Otherwise, it will invoke an external helper "gunzip -cf" (NOMMU case) which will
	 * need the header. */
#if BB_MMU
	xread(archive_handle->src_fd, &magic, 2);
	if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
		bb_error_msg_and_die("invalid gzip magic");
	}
#endif

	archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_gz_stream, "gunzip");
	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS)
		continue;

	/* Can only do one file at a time */
	return EXIT_FAILURE;
}
Beispiel #2
0
char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle)
{
#if BB_MMU
    uint16_t magic;
#endif

    /* Can't lseek over pipes */
    archive_handle->seek = seek_by_read;

    /* Check gzip magic only if open_transformer will invoke unpack_gz_stream (MMU case).
     * Otherwise, it will invoke an external helper "gunzip -cf" (NOMMU case) which will
     * need the header. */
#if BB_MMU
    xread(archive_handle->src_fd, &magic, 2);
    /* Can skip this check, but error message will be less clear */
    if (magic != GZIP_MAGIC) {
        bb_error_msg_and_die("invalid gzip magic");
    }
#endif

    open_transformer(archive_handle->src_fd, unpack_gz_stream, "gunzip");
    archive_handle->offset = 0;
    while (get_header_tar(archive_handle) == EXIT_SUCCESS)
        continue;

    /* Can only do one file at a time */
    return EXIT_FAILURE;
}
extern char get_header_tar_bz2(archive_handle_t *archive_handle)
{
	/* Cant lseek over pipe's */
	archive_handle->seek = seek_by_char;

	archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompressStream);
	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS);

	/* Can only do one file at a time */
	return(EXIT_FAILURE);
}
char get_header_tar_lzma(archive_handle_t * archive_handle)
{
	/* Can't lseek over pipes */
	archive_handle->seek = seek_by_read;

	archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_lzma_stream, "unlzma", "unlzma", "-cf", "-", NULL);
	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/;

	/* Can only do one file at a time */
	return EXIT_FAILURE;
}
char get_header_tar_lzma(archive_handle_t * archive_handle)
{
	/* Can't lseek over pipes */
	archive_handle->seek = seek_by_char;

	archive_handle->src_fd = open_transformer(archive_handle->src_fd, unlzma);
	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS);

	/* Can only do one file at a time */
	return EXIT_FAILURE;
}
char FAST_FUNC get_header_tar_bz2(archive_handle_t *archive_handle)
{
	/* Can't lseek over pipes */
	archive_handle->seek = seek_by_read;

	open_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2");
	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS)
		continue;

	/* Can only do one file at a time */
	return EXIT_FAILURE;
}
Beispiel #7
0
extern char get_header_tar_bz2(archive_handle_t *archive_handle)
{
	BZ2_bzReadOpen(archive_handle->src_fd, NULL, 0);

	archive_handle->read = read_bz2;
	archive_handle->seek = seek_by_char;

	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS);

	/* Cleanup */
	BZ2_bzReadClose();
	
	/* Can only do one tar.bz2 per archive */
	return(EXIT_FAILURE);
}
static char get_header_tar_Z(archive_handle_t *archive_handle)
{
	/* Cant lseek over pipe's */
	archive_handle->seek = seek_by_char;

	/* do the decompression, and cleanup */
	if ((bb_xread_char(archive_handle->src_fd) != 0x1f) || (bb_xread_char(archive_handle->src_fd) != 0x9d)) {
		bb_error_msg_and_die("Invalid magic");
	}

	archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress);
	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS);

	/* Can only do one file at a time */
	return(EXIT_FAILURE);
}
Beispiel #9
0
static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle)
{
	/* Can't lseek over pipes */
	archive_handle->seek = seek_by_read;

	/* do the decompression, and cleanup */
	if (xread_char(archive_handle->src_fd) != 0x1f
	 || xread_char(archive_handle->src_fd) != 0x9d
	) {
		bb_error_msg_and_die("invalid magic");
	}

	open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress");
	archive_handle->offset = 0;
	while (get_header_tar(archive_handle) == EXIT_SUCCESS)
		continue;

	/* Can only do one file at a time */
	return EXIT_FAILURE;
}
Beispiel #10
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);
}
Beispiel #11
0
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;
	const char **file_list = NULL;
	char *output_buffer = NULL;
	char *ared_file = NULL;
	struct gzip_handle tar_outer = { }, tar_inner = { };
	file_header_t *tar_header;

	*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);

	tar_outer.file = deb_stream;
	gzip_exec(&tar_outer, NULL);

	/* walk through outer tar file to find ared_file */
	while ((tar_header = get_header_tar(&tar_outer)) != 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) {
			tar_inner.gzip = &tar_outer;
			gzip_exec(&tar_inner, NULL);

			archive_offset = 0;

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

			free_header_tar(tar_header);
			gzip_close(&tar_inner);
			break;
		}

		seek_forward(&tar_outer, tar_header->size);
		free_header_tar(tar_header);
	}

cleanup:
	gzip_close(&tar_outer);

	if (file_list)
		free(file_list);

	return output_buffer;
}
Beispiel #12
0
static file_header_t *get_header_tar(struct gzip_handle *tar_stream)
{
	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;
	file_header_t *tar_entry = NULL;
	long i;
	long sum = 0;

	if (archive_offset % 512 != 0) {
		seek_forward(tar_stream, 512 - (archive_offset % 512));
	}

	if (gzip_read(tar_stream, tar.raw, 512) != 512) {
		/* Unfortunately its common for tar files to have all sorts of
		 * trailing garbage, fail silently */
//              error_msg("Couldnt read header");
		return (NULL);
	}
	archive_offset += 512;

	/* Check header has valid magic, unfortunately some tar files
	 * have empty (0'ed) tar entries at the end, which will
	 * cause this to fail, so fail silently for now
	 */
	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
			return (NULL);
	}

	/* 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)) {
		if (strtol(tar.formated.chksum, NULL, 8) != 0)
			error_msg("Invalid tar header checksum");
		return (NULL);
	}

	/* convert to type'ed variables */
	tar_entry = xcalloc(1, sizeof(file_header_t));

	// tar_entry->name = xstrdup(tar.formated.name);

/*
	parse_mode(tar.formated.mode, &tar_entry->mode);
*/
	tar_entry->mode = 07777 & strtol(tar.formated.mode, NULL, 8);

	tar_entry->uid = strtol(tar.formated.uid, NULL, 8);
	tar_entry->gid = strtol(tar.formated.gid, NULL, 8);
	tar_entry->size = strtol(tar.formated.size, NULL, 8);
	tar_entry->mtime = strtol(tar.formated.mtime, NULL, 8);

	tar_entry->device = (strtol(tar.formated.devmajor, NULL, 8) << 8) +
	    strtol(tar.formated.devminor, NULL, 8);

	/* Fix mode, used by the old format */
	switch (tar.formated.typeflag) {
		/* hard links are detected as regular files with 0 size and a link name */
	case '1':
		tar_entry->mode |= S_IFREG;
		break;
	case 0:
	case '0':

#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
		if (last_char_is(tar_entry->name, '/')) {
			tar_entry->mode |= S_IFDIR;
		} else
#endif
			tar_entry->mode |= S_IFREG;
		break;
	case '2':
		tar_entry->mode |= S_IFLNK;
		break;
	case '3':
		tar_entry->mode |= S_IFCHR;
		break;
	case '4':
		tar_entry->mode |= S_IFBLK;
		break;
	case '5':
		tar_entry->mode |= S_IFDIR;
		break;
	case '6':
		tar_entry->mode |= S_IFIFO;
		break;
#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	case 'L':{
			longname = xmalloc(tar_entry->size + 1);
			if (gzip_read(tar_stream, longname, tar_entry->size) !=
			    tar_entry->size)
				return NULL;
			longname[tar_entry->size] = '\0';
			archive_offset += tar_entry->size;

			return (get_header_tar(tar_stream));
		}
	case 'K':{
			linkname = xmalloc(tar_entry->size + 1);
			if (gzip_read(tar_stream, linkname, tar_entry->size) !=
			    tar_entry->size)
				return NULL;
			linkname[tar_entry->size] = '\0';
			archive_offset += tar_entry->size;

			return (get_header_tar(tar_stream));
		}
	case 'D':
	case 'M':
	case 'N':
	case 'S':
	case 'V':
		perror_msg("Ignoring GNU extension type %c",
			   tar.formated.typeflag);
#endif
	default:
		perror_msg("Unknown typeflag: 0x%x", tar.formated.typeflag);
		break;

	}

#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	if (longname) {
		tar_entry->name = longname;
		longname = NULL;
	} else
#endif
	{
		tar_entry->name = xstrndup(tar.formated.name, 100);

		if (tar.formated.prefix[0]) {
			char *temp = tar_entry->name;
			char *prefixTemp = xstrndup(tar.formated.prefix, 155);
			tar_entry->name = concat_path_file(prefixTemp, temp);
			free(temp);
			free(prefixTemp);
		}
	}

	if (linkname) {
		tar_entry->link_name = linkname;
		linkname = NULL;
	} else {
		tar_entry->link_name = *tar.formated.linkname != '\0' ?
		    xstrndup(tar.formated.linkname, 100) : NULL;
	}

	return (tar_entry);
}
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);
}
Beispiel #14
0
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;
}