tizen: Do not generate nor use ksyms Requires/Provides for kernel & modules package(s)
[platform/upstream/rpm.git] / rpm2archive.c
1 /* rpmarchive: spit out the main archive portion of a package */
2
3 #include "system.h"
4
5 #include <rpm/rpmlib.h>         /* rpmReadPackageFile .. */
6 #include <rpm/rpmfi.h>
7 #include <rpm/rpmtag.h>
8 #include <rpm/rpmio.h>
9 #include <rpm/rpmpgp.h>
10
11 #include <rpm/rpmts.h>
12
13 #include <archive.h>
14 #include <archive_entry.h>
15 #include <unistd.h>
16
17 #include "debug.h"
18
19 #define BUFSIZE (128*1024)
20
21 static void fill_archive_entry(struct archive * a, struct archive_entry * entry, rpmfi fi)
22 {
23     archive_entry_clear(entry);
24
25     char * filename = rstrscat(NULL, ".", rpmfiDN(fi), rpmfiBN(fi), NULL);
26     archive_entry_copy_pathname(entry, filename);
27     _free(filename);
28
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);
33
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);
38
39     if (S_ISLNK(mode))
40         archive_entry_set_symlink(entry, rpmfiFLink(fi));
41 }
42
43 static void write_file_content(struct archive * a, char * buf, rpmfi fi)
44 {
45     rpm_loff_t left = rpmfiFSize(fi);
46     size_t len, read;
47
48     while (left) {
49         len = (left > BUFSIZE ? BUFSIZE : left);
50         read = rpmfiArchiveRead(fi, buf, len);
51         if (read==len) {
52             archive_write_data(a, buf, len);
53         } else {
54             fprintf(stderr, "Error reading file from rpm payload\n");
55             break;
56         }
57         left -= len;
58     }
59 }
60
61 static int process_package(rpmts ts, char * filename)
62 {
63     FD_t fdi;
64     FD_t gzdi;
65     Header h;
66     int rc = 0;
67     char * rpmio_flags = NULL;
68     struct archive *a;
69     struct archive_entry *entry;
70
71     if (!strcmp(filename, "-")) {
72         fdi = fdDup(STDIN_FILENO);
73     } else {
74         fdi = Fopen(filename, "r.ufdio");
75     }
76
77     if (Ferror(fdi)) {
78         fprintf(stderr, "rpm2archive: %s: %s\n",
79                 filename, Fstrerror(fdi));
80         exit(EXIT_FAILURE);
81     }
82
83     rc = rpmReadPackageFile(ts, fdi, "rpm2cpio", &h);
84
85     switch (rc) {
86     case RPMRC_OK:
87     case RPMRC_NOKEY:
88     case RPMRC_NOTTRUSTED:
89         break;
90     case RPMRC_NOTFOUND:
91         fprintf(stderr, _("argument is not an RPM package\n"));
92         exit(EXIT_FAILURE);
93         break;
94     case RPMRC_FAIL:
95     default:
96         fprintf(stderr, _("error reading header from package\n"));
97         exit(EXIT_FAILURE);
98         break;
99     }
100
101
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);
105     }
106
107     gzdi = Fdopen(fdi, rpmio_flags);    /* XXX gzdi == fdi */
108     free(rpmio_flags);
109
110     if (gzdi == NULL) {
111         fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
112         exit(EXIT_FAILURE);
113     }
114
115     rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
116     rpmfi fi = rpmfiNewArchiveReader(gzdi, files, RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);
117
118     /* create archive */
119     a = archive_write_new();
120     archive_write_add_filter_gzip(a);
121     archive_write_set_format_pax_restricted(a);
122
123     if (!strcmp(filename, "-")) {
124         if (isatty(STDOUT_FILENO)) {
125             fprintf(stderr, "Error: refusing to output archive data to a terminal.\n");
126             exit(EXIT_FAILURE);
127         }
128         archive_write_open_fd(a, STDOUT_FILENO);
129     } else {
130         char * outname = rstrscat(NULL, filename, ".tgz", NULL);
131         archive_write_open_filename(a, outname);
132         _free(outname);
133         // XXX error handling
134     }
135
136     entry = archive_entry_new();
137
138     char * buf = xmalloc(BUFSIZE);
139     char * hardlink = NULL;
140
141     rc = 0;
142     while (rc >= 0) {
143         rc = rpmfiNext(fi);
144         if (rc == RPMERR_ITER_END) {
145             break;
146         }
147
148         rpm_mode_t mode = rpmfiFMode(fi);
149         int nlink = rpmfiFNlink(fi);
150
151         fill_archive_entry(a, entry, fi);
152
153         if (nlink > 1) {
154             if (rpmfiArchiveHasContent(fi)) {
155                 _free(hardlink);
156                 hardlink = rstrscat(NULL, ".", rpmfiFN(fi), NULL);
157             } else {
158                 archive_entry_set_hardlink(entry, hardlink);
159             }
160         }
161
162         archive_write_header(a, entry);
163
164         if (S_ISREG(mode) && (nlink == 1 || rpmfiArchiveHasContent(fi))) {
165             write_file_content(a, buf, fi);
166         }
167     }
168     /* End of iteration is not an error */
169     if (rc == RPMERR_ITER_END) {
170         rc = 0;
171     }
172
173     _free(hardlink);
174
175     Fclose(gzdi);       /* XXX gzdi == fdi */
176     archive_entry_free(entry);
177     archive_write_close(a);
178     archive_write_free(a);
179     buf = _free(buf);
180     rpmfilesFree(files);
181     rpmfiFree(fi);
182     headerFree(h);
183     return rc;
184 }
185
186 int main(int argc, char *argv[])
187 {
188     int rc;
189     
190     xsetprogname(argv[0]);      /* Portability call -- see system.h */
191     rpmReadConfigFiles(NULL, NULL);
192     char * filename;
193     if (argc == 1)
194         filename = "-";
195     else {
196         if (rstreq(argv[1], "-h") || rstreq(argv[1], "--help")) {
197             fprintf(stderr, "Usage: rpm2archive file.rpm\n");
198             exit(EXIT_FAILURE);
199         } else {
200             filename = argv[1];
201         }
202     }
203
204     rpmts ts = rpmtsCreate();
205     rpmVSFlags vsflags = 0;
206
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);
212
213     rc = process_package(ts, filename);
214
215     ts = rpmtsFree(ts);
216
217     return rc;
218 }