Beispiel #1
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;
}
Beispiel #2
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 #3
0
extern int cpio_main(int argc, char **argv)
{
	FILE *src_stream = stdin;
	char **extract_names = NULL;
	int extract_function = 0;
	int num_of_entries = 0;
	int opt = 0;
	mode_t oldmask = 0;

	while ((opt = getopt(argc, argv, "idmuvtF:")) != -1) {
		switch (opt) {
		case 'i': // extract
			extract_function |= extract_all_to_fs;
			break;
		case 'd': // create _leading_ directories
			extract_function |= extract_create_leading_dirs;
			oldmask = umask(077); /* Make make_directory act like GNU cpio */
			break;
		case 'm': // preserve modification time
			extract_function |= extract_preserve_date;
			break;
		case 'v': // verbosly list files
			extract_function |= extract_verbose_list;
			break;
		case 'u': // unconditional
			extract_function |= extract_unconditional;
			break;
		case 't': // list files
			extract_function |= extract_list;
			break;
		case 'F':
			src_stream = xfopen(optarg, "r");
			break;
		default:
			show_usage();
		}
	}

	if ((extract_function & extract_all_to_fs) && (extract_function & extract_list)) {
		extract_function ^= extract_all_to_fs; /* If specify t, don't extract*/
	}

	if ((extract_function & extract_all_to_fs) && (extract_function & extract_verbose_list)) {
		/* The meaning of v changes on extract */
		extract_function ^= extract_verbose_list;
		extract_function |= extract_list;
	}

	while (optind < argc) {
		extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2));
		extract_names[num_of_entries] = xstrdup(argv[optind]);
		num_of_entries++;
		extract_names[num_of_entries] = NULL;
		optind++;
	}

	unarchive(src_stream, stdout, &get_header_cpio, extract_function, "./", extract_names, NULL);
	if (oldmask) {
		umask(oldmask); /* Restore umask if we changed it */
	}
	return EXIT_SUCCESS;
}