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