1 /* rpmarchive: spit out the main archive portion of a package */
5 #include <rpm/rpmlib.h> /* rpmReadPackageFile .. */
7 #include <rpm/rpmtag.h>
9 #include <rpm/rpmpgp.h>
11 #include <rpm/rpmts.h>
14 #include <archive_entry.h>
19 #define BUFSIZE (128*1024)
21 static void fill_archive_entry(struct archive * a, struct archive_entry * entry, rpmfi fi)
23 archive_entry_clear(entry);
25 char * filename = rstrscat(NULL, ".", rpmfiDN(fi), rpmfiBN(fi), NULL);
26 archive_entry_copy_pathname(entry, filename);
29 archive_entry_set_size(entry, rpmfiFSize(fi));
30 rpm_mode_t mode = rpmfiFMode(fi);
31 archive_entry_set_filetype(entry, mode & S_IFMT);
32 archive_entry_set_perm(entry, mode);
34 archive_entry_set_uname(entry, rpmfiFUser(fi));
35 archive_entry_set_gname(entry, rpmfiFGroup(fi));
36 archive_entry_set_rdev(entry, rpmfiFRdev(fi));
37 archive_entry_set_mtime(entry, rpmfiFMtime(fi), 0);
40 archive_entry_set_symlink(entry, rpmfiFLink(fi));
43 static void write_file_content(struct archive * a, char * buf, rpmfi fi)
45 rpm_loff_t left = rpmfiFSize(fi);
49 len = (left > BUFSIZE ? BUFSIZE : left);
50 read = rpmfiArchiveRead(fi, buf, len);
52 archive_write_data(a, buf, len);
54 fprintf(stderr, "Error reading file from rpm payload\n");
61 static int process_package(rpmts ts, char * filename)
67 char * rpmio_flags = NULL;
69 struct archive_entry *entry;
71 if (!strcmp(filename, "-")) {
72 fdi = fdDup(STDIN_FILENO);
74 fdi = Fopen(filename, "r.ufdio");
78 fprintf(stderr, "rpm2archive: %s: %s\n",
79 filename, Fstrerror(fdi));
83 rc = rpmReadPackageFile(ts, fdi, "rpm2cpio", &h);
88 case RPMRC_NOTTRUSTED:
91 fprintf(stderr, _("argument is not an RPM package\n"));
96 fprintf(stderr, _("error reading header from package\n"));
102 /* Retrieve payload size and compression type. */
103 { const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
104 rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
107 gzdi = Fdopen(fdi, rpmio_flags); /* XXX gzdi == fdi */
111 fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
115 rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
116 rpmfi fi = rpmfiNewArchiveReader(gzdi, files, RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);
119 a = archive_write_new();
120 archive_write_add_filter_gzip(a);
121 archive_write_set_format_pax_restricted(a);
123 if (!strcmp(filename, "-")) {
124 if (isatty(STDOUT_FILENO)) {
125 fprintf(stderr, "Error: refusing to output archive data to a terminal.\n");
128 archive_write_open_fd(a, STDOUT_FILENO);
130 char * outname = rstrscat(NULL, filename, ".tgz", NULL);
131 archive_write_open_filename(a, outname);
133 // XXX error handling
136 entry = archive_entry_new();
138 char * buf = xmalloc(BUFSIZE);
139 char * hardlink = NULL;
144 if (rc == RPMERR_ITER_END) {
148 rpm_mode_t mode = rpmfiFMode(fi);
149 int nlink = rpmfiFNlink(fi);
151 fill_archive_entry(a, entry, fi);
154 if (rpmfiArchiveHasContent(fi)) {
156 hardlink = rstrscat(NULL, ".", rpmfiFN(fi), NULL);
158 archive_entry_set_hardlink(entry, hardlink);
162 archive_write_header(a, entry);
164 if (S_ISREG(mode) && (nlink == 1 || rpmfiArchiveHasContent(fi))) {
165 write_file_content(a, buf, fi);
168 /* End of iteration is not an error */
169 if (rc == RPMERR_ITER_END) {
175 Fclose(gzdi); /* XXX gzdi == fdi */
176 archive_entry_free(entry);
177 archive_write_close(a);
178 archive_write_free(a);
186 int main(int argc, char *argv[])
190 xsetprogname(argv[0]); /* Portability call -- see system.h */
191 rpmReadConfigFiles(NULL, NULL);
196 if (rstreq(argv[1], "-h") || rstreq(argv[1], "--help")) {
197 fprintf(stderr, "Usage: rpm2archive file.rpm\n");
204 rpmts ts = rpmtsCreate();
205 rpmVSFlags vsflags = 0;
207 /* XXX retain the ageless behavior of rpm2cpio */
208 vsflags |= _RPMVSF_NODIGESTS;
209 vsflags |= _RPMVSF_NOSIGNATURES;
210 vsflags |= RPMVSF_NOHDRCHK;
211 (void) rpmtsSetVSFlags(ts, vsflags);
213 rc = process_package(ts, filename);