Bug#1107203: unblock: initramfs-tools/0.148.1 (5/5)
From
Ben Hutchings@1:229/2 to
All on Tue Jun 3 00:20:01 2025
[continued from previous message]
+ argv[argc] = NULL;
+
+ if (pipe(pipe_fds)) {
+ warn("pipe");
+ return false;
+ }
+ pid = fork();
+ if (pid < 0) {
+ warn("fork");
+ return false;
+ }
+
+ /* Child */
+ if (pid == 0) {
+ /*
+ * Close write end of the pipe; make the read end
+ * stdout.
+ */
+ close(pipe_fds[1]);
+ dup2(pipe_fds[0], 0);
+ close(pipe_fds[0]);
+
+ execvp("cpio", (char **)argv);
+ _exit(127);
+ }
+
+ /*
+ * Parent: close read end of the pipe; return child pid and
+ * write end of pipe.
+ */
+ close(pipe_fds[0]);
+ proc->pid = pid;
+ proc->pipe = pipe_fds[1];
+ return true;
+}
+
+static bool end_cpio(const struct cpio_proc *proc, bool ok)
+{
+ int wstatus;
+
+ close(proc->pipe);
+
+ if (ok) {
+ if (waitpid(proc->pid, &wstatus, 0) != proc->pid ||
+ !WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) {
+ warnx("cpio failed");
+ return false;
+ }
+ } else {
+ kill(proc->pid, SIGTERM);
+ }
+
+ return true;
+}
+
+static const struct option long_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "list", no_argument, NULL, 'l' },
+ { "verbose", no_argument, NULL, 'v' },
+ { NULL }
+};
+
+static void usage(FILE *stream)
+{
+ fprintf(stream, "\
+\n\
+Usage: unmkinitramfs [-v|--verbose] INITRAMFS-FILE DIRECTORY\n\
+\n\
+Options:\n\
+ -v | --verbose Display verbose messages about extraction\n\
+\n\
+See unmkinitramfs(8) for further details.\n\
+\n"
+ );
+}
+
+int main(int argc, char **argv)
+{
+ int opt;
+ bool do_list = false;
+ bool verbose = false;
+ const char *in_filename;
+ FILE *in_file;
+ const char *out_dirname = NULL;
+ char *out_subdirname = NULL;
+ const char *cpio_optv[3];
+ int cpio_optc;
+ struct cpio_proc cpio_proc = { 0 };
+ unsigned int early_count = 0;
+ bool ok;
+
+ /* Parse options */
+ opterr = 0;
+ while ((opt = getopt_long(argc, argv, "hv", long_opts, NULL)) >= 0) {
+ switch (opt) {
+ case '?':
+ usage(stderr);
+ return 2;
+ case 'h':
+ usage(stdout);
+ return 0;
+ case 'l':
+ do_list = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ }
+ }
+
+ /* Check number of non-option arguments */
+ if (argc - optind != (do_list ? 1 : 2)) {
+ usage(stderr);
+ return 2;
+ }
+
+ /* Set up input file and output directory */
+ in_filename = argv[optind];
+ in_file = fopen(in_filename, "rb");
+ if (!in_file)
+ err(1, "%s", in_filename);
+ if (!do_list) {
+ out_dirname = argv[optind + 1];
+ if (!mkdir_allow_exist(out_dirname, 0777))
+ err(1, "%s", out_dirname);
+ out_subdirname = malloc(strlen(out_dirname) + 20);
+ if (!out_subdirname)
+ err(1, "malloc");
+ }
+
+ /* Set up extra options for cpio */
+ cpio_optc = 0;
+ if (do_list) {
+ cpio_optv[cpio_optc++] = "--list";
+ } else {
+ cpio_optv[cpio_optc++] = "-D";
+ cpio_optv[cpio_optc++] = out_subdirname;
+ }
+ if (verbose)
+ cpio_optv[cpio_optc++] = "-v";
+
+ /* Iterate over archives within the initramfs */
+ for (;;) {
+ unsigned char magic_buf[MAX_MAGIC_LEN];
+ size_t read_len;
+ const struct magic_entry *me;
+
+ /* Peek at first bytes of next archive; handle EOF */
+ read_len = fread(magic_buf, 1, sizeof(magic_buf), in_file);
+ if (read_len == 0) {
+ /*
+ * EOF with no compresed archive. Add back a
+ * trailer to keep cpio happy.
+ */
+ if (ferror(in_file)) {
+ warn("%s", in_filename);
+ ok = false;
+ }
+ if (cpio_proc.pid && !write_trailer(cpio_proc.pipe))
+ ok = false;
+ break;
+ }
+ fseek(in_file, -(long)read_len, SEEK_CUR);
+
+ /* Identify format */
+ for (me = magic_table; me->magic_len; ++me)
+ if (read_len >= me->magic_len &&
+ memcmp(magic_buf, me->magic, me->magic_len) == 0)
+ break;
+ if (me->magic_len == 0) {
+ warnx("%s: unrecognised compression or corrupted file", + in_filename);
+ ok = false;
+ break;
+ }
+
+ /*
+ * Extract the archive to an "early" or "early<n>"
+ * subdirectory if:
+ * - We have not already started the main cpio process
+ * - We are not listing
+ * - This looks like an early initramfs (uncompressed
+ * and contains files under kernel/)
+ */
+ if (!cpio_proc.pid && !do_list &&
+ me->format == FORMAT_CPIO_NEW &&
+ detect_early_initramfs(in_file, in_filename)) {
+ struct cpio_proc early_cpio_proc;
+
+ if (++early_count == 1)
+ sprintf(out_subdirname, "%s/early",
+ out_dirname);
+ else
+ sprintf(out_subdirname, "%s/early%u",
+ out_dirname, early_count);
+ if (!mkdir_allow_exist(out_subdirname, 0777)) {
+ warn("%s", out_subdirname);
+ ok = false;
+ break;
+ }
+ if (!spawn_cpio(cpio_optc, cpio_optv,
+ &early_cpio_proc)) {
+ ok = false;
+ break;
+ }
+ ok = handle_uncompressed(in_file, in_filename,
+ early_cpio_proc.pipe)
+ && write_trailer(early_cpio_proc.pipe);
+ if (!end_cpio(&early_cpio_proc, ok))
+ ok = false;
+ if (!ok)
+ break;
+ } else {
+ /*
+ * Otherwise, extract to either the base
+ * output directory or a "main" subdirectory,
+ * depending on whether we already created
+ * subdirectories.
+ */
+ if (!cpio_proc.pid) {
+ if (do_list) {
+ ;
+ } else if (early_count) {
+ sprintf(out_subdirname, "%s/main",
+ out_dirname);
+ if (!mkdir_allow_exist(out_subdirname, + 0777)) {
+ warn("%s", out_subdirname);
+ ok = false;
+ break;
+ }
+ } else {
+ strcpy(out_subdirname, out_dirname);
+ }
+ if (!spawn_cpio(cpio_optc, cpio_optv,
+ &cpio_proc)) {
+ ok = false;
+ break;
+ }
+ }
+ if (me->format == FORMAT_CPIO_NEW) {
+ ok = handle_uncompressed(in_file, in_filename, + cpio_proc.pipe);
+ if (!ok)
+ break;
+ } else {
+ ok = handle_compressed(in_file, me->format,
+ cpio_proc.pipe);
+ break;
+ }
+ }
+ }
+
+ fclose(in_file);
+
+ if (cpio_proc.pid && !end_cpio(&cpio_proc, ok))
+ ok = false;
+
+ return !ok;
+}
--- SoupGate-Win32 v1.05
* Origin: you cannot sedate... all the things you hate (1:229/2)