void Writer::set_format_helper(struct archive *ar, int format) { std::string error_msg; switch(format) { case Archive::FORMAT_AR_BSD: archive_write_set_format_ar_bsd(ar); break; case Archive::FORMAT_AR_SVR4: archive_write_set_format_ar_svr4(ar); break; case Archive::FORMAT_CPIO: archive_write_set_format_cpio(ar); break; case Archive::FORMAT_CPIO_NEWC: archive_write_set_format_cpio_newc(ar); break; case Archive::FORMAT_MTREE: archive_write_set_format_mtree(ar); break; case Archive::FORMAT_TAR: case Archive::FORMAT_TAR_PAX_RESTRICTED: archive_write_set_format_pax_restricted(ar); break; case Archive::FORMAT_TAR_PAX_INTERCHANGE: archive_write_set_format_pax(ar); break; case Archive::FORMAT_TAR_USTAR: archive_write_set_format_ustar(ar); break; default: error_msg = "unknown or unsupported archive format"; throw Error(error_msg); } }
static int archive_conv_open(struct archive_conv *conv, const struct repo_t *repo) { int r; /* generally, repo files are gzip compressed, but there's no guarantee of * this. in order to be compression-agnostic, use libarchive's reader/writer * methods. this also gives us an opportunity to rewrite the archive as CPIO, * which is marginally faster given our staunch sequential access. */ conv->reponame = repo->name; stpcpy(stpcpy(conv->tmpfile, repo->diskfile), "~"); conv->in = archive_read_new(); conv->out = archive_write_new(); if (conv->in == NULL || conv->out == NULL) { fputs("error: failed to allocate memory for archive objects\n", stderr); return -ENOMEM; } archive_read_support_format_tar(conv->in); archive_read_support_filter_all(conv->in); r = archive_read_open_fd(conv->in, repo->tmpfile.fd, BUFSIZ); if (r != ARCHIVE_OK) { fprintf(stderr, "error: failed to create archive reader for %s: %s\n", repo->name, strerror(archive_errno(conv->in))); r = archive_errno(conv->in); goto open_error; } archive_write_set_format_cpio_newc(conv->out); archive_write_add_filter(conv->out, repo->config->compress); r = archive_write_open_filename(conv->out, conv->tmpfile); if (r != ARCHIVE_OK) { fprintf(stderr, "error: failed to open file for writing: %s: %s\n", conv->tmpfile, strerror(archive_errno(conv->out))); r = archive_errno(conv->out); goto open_error; } return 0; open_error: archive_write_free(conv->out); archive_read_free(conv->in); return -r; }
int main(int argc, char **argv) { int i; unsigned int version = 0, help = 0; char cpiotmpfile[] = CPIOTMPFILE; struct archive *archive; struct archive_entry *entry; struct stat st; char buff[64]; int len, fdfile, fdarchive; DIR * dir; struct dirent * ent; char * filename, * path; off_t pathlength = 0; int8_t rc = EXIT_FAILURE; /* get command line options */ while ((i = getopt_long(argc, argv, optstring, options_long, NULL)) != -1) switch (i) { case 'h': help++; break; case 'V': version++; break; } if (version > 0) printf("%s: %s v%s (compiled: " __DATE__ ", " __TIME__ ")\n", argv[0], PROGNAME, VERSION); if (help > 0) fprintf(stderr, "usage: %s [-h|--help] [-V|--version]\n", argv[0]); if (version > 0 || help > 0) return EXIT_SUCCESS; if ((fdarchive = mkstemp(cpiotmpfile)) < 0) { perror("mkstemp() failed"); goto out10; } if ((archive = archive_write_new()) == NULL) { fprintf(stderr, "archive_write_new() failed.\n"); goto out10; } if (archive_write_set_format_cpio_newc(archive) != ARCHIVE_OK) { fprintf(stderr, "archive_write_set_format_cpio_newc() failed.\n"); goto out10; } if (archive_write_open_fd(archive, fdarchive) != ARCHIVE_OK) { fprintf(stderr, "archive_write_open_fd() failed.\n"); goto out10; } while (1) { path = strdup(CHALLENGEDIR + 1); if (strstr(path + pathlength, "/") == NULL) break; *strstr(path + pathlength, "/") = 0; pathlength = strlen(path) + 1; if (add_dir(archive, path) < 0) { fprintf(stderr, "add_dir() failed"); goto out10; } free(path); } if ((dir = opendir(CHALLENGEDIR)) == NULL) { perror("opendir() failed"); goto out10; } while ((ent = readdir(dir)) != NULL) { filename = malloc(sizeof(CHALLENGEDIR) + strlen(ent->d_name) + 1); sprintf(filename, CHALLENGEDIR "%s", ent->d_name); if (stat(filename, &st) < 0) { perror("stat() failed"); goto out10; } if (S_ISREG(st.st_mode)) { if ((entry = archive_entry_new()) == NULL) { fprintf(stderr, "archive_entry_new() failed.\n"); goto out10; } /* these do not return exit code */ archive_entry_set_pathname(entry, filename + 1); archive_entry_set_size(entry, st.st_size); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_perm(entry, 0644); if (archive_write_header(archive, entry) != ARCHIVE_OK) { fprintf(stderr, "archive_write_header() failed"); goto out10; } if ((fdfile = open(filename, O_RDONLY)) < 0) { perror("open() failed"); goto out10; } if ((len = read(fdfile, buff, sizeof(buff))) < 0) { perror("read() failed"); goto out10; } while (len > 0) { if (archive_write_data(archive, buff, len) < 0) { fprintf(stderr, "archive_write_data() failed"); goto out10; } if ((len = read(fdfile, buff, sizeof(buff))) < 0) { perror("read() failed"); goto out10; } } if (close(fdfile) < 0) { perror("close() failed"); goto out10; } archive_entry_free(entry); } free(filename); } if (closedir(dir) < 0) { perror("closedir() failed"); goto out10; } if (archive_write_close(archive) != ARCHIVE_OK) { fprintf(stderr, "archive_write_close() failed"); goto out10; } if (archive_write_free(archive) != ARCHIVE_OK) { fprintf(stderr, "archive_write_free() failed"); goto out10; } if (access(CPIOFILE, F_OK) == 0 && unlink(CPIOFILE) < 0) { perror("unkink() failed"); goto out10; } if (rename(cpiotmpfile, CPIOFILE) < 0) { perror("rename() failed"); goto out10; } rc = EXIT_SUCCESS; out10: if (access(cpiotmpfile, F_OK) == 0) unlink(cpiotmpfile); return rc; }