rpm: rpm2archive.c Source File

rpm 4.12.0.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

rpm2archive.c
Go to the documentation of this file.
1 /* rpmarchive: spit out the main archive portion of a package */
2
3 #include "system.h"
4 const char *__progname;
5
6 #include <rpm/rpmlib.h> /* rpmReadPackageFile .. */
7 #include <rpm/rpmfi.h>
8 #include <rpm/rpmtag.h>
9 #include <rpm/rpmio.h>
10 #include <rpm/rpmpgp.h>
11
12 #include <rpm/rpmts.h>
13
14 #include <archive.h>
15 #include <archive_entry.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 archive_write_open_fd(a, 1);
125 } else {
126 char * outname = rstrscat(NULL, filename, ".tgz", NULL);
127 archive_write_open_filename(a, outname);
128 _free(outname);
129 // XXX error handling
130 }
131
132 entry = archive_entry_new();
133
134 char * buf = xmalloc(BUFSIZE);
135 char * hardlink = NULL;
136
137 rc = 0;
138 while (rc >= 0) {
139 rc = rpmfiNext(fi);
140 if (rc == RPMERR_ITER_END) {
141 break;
142 }
143
144 rpm_mode_t mode = rpmfiFMode(fi);
145 int nlink = rpmfiFNlink(fi);
146
147 fill_archive_entry(a, entry, fi);
148
149 if (nlink > 1) {
150 if (rpmfiArchiveHasContent(fi)) {
151 _free(hardlink);
152 hardlink = rstrscat(NULL, ".", rpmfiFN(fi), NULL);
153 } else {
154 archive_entry_set_hardlink(entry, hardlink);
155 }
156 }
157
158 archive_write_header(a, entry);
159
160 if (S_ISREG(mode) && (nlink == 1 || rpmfiArchiveHasContent(fi))) {
161 write_file_content(a, buf, fi);
162 }
163 }
164 _free(hardlink);
165
166 Fclose(gzdi); /* XXX gzdi == fdi */
167 archive_entry_free(entry);
168 archive_write_close(a);
169 archive_write_free(a);
170 buf = _free(buf);
171 rpmfilesFree(files);
172 rpmfiFree(fi);
173 headerFree(h);
174 return rc;
175 }
176
177 int main(int argc, char *argv[])
178 {
179 int rc;
180
181 setprogname(argv[0]); /* Retrofit glibc __progname */
182 rpmReadConfigFiles(NULL, NULL);
183 char * filename;
184 if (argc == 1)
185 filename = "-";
186 else {
187 if (rstreq(argv[1], "-h") || rstreq(argv[1], "--help")) {
188 fprintf(stderr, "Usage: rpm2archive file.rpm\n");
189 exit(EXIT_FAILURE);
190 } else {
191 filename = argv[1];
192 }
193 }
194
195 rpmts ts = rpmtsCreate();
196 rpmVSFlags vsflags = 0;
197
198 /* XXX retain the ageless behavior of rpm2cpio */
199 vsflags |= _RPMVSF_NODIGESTS;
200 vsflags |= _RPMVSF_NOSIGNATURES;
201 vsflags |= RPMVSF_NOHDRCHK;
202 (void) rpmtsSetVSFlags(ts, vsflags);
203
204 rc = process_package(ts, filename);
205
206 ts = rpmtsFree(ts);
207
208 return rc;
209 }
setprogname
#define setprogname(pn)
Definition: system.h:97
rpmfiFLink
const char * rpmfiFLink(rpmfi fi)
Return current file linkto (i.e.
xmalloc
#define xmalloc(_size)
Definition: system.h:83
rpmfiArchiveRead
size_t rpmfiArchiveRead(rpmfi fi, void *buf, size_t size)
Read content from current file in archive.
rpmReadPackageFile
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char *fn, Header *hdrp)
Return package header from file handle, verifying digests/signatures.
debug.h
rpmfiFMode
rpm_mode_t rpmfiFMode(rpmfi fi)
Return current file mode from file info set iterator.
rpmtsFree
rpmts rpmtsFree(rpmts ts)
Destroy transaction set, closing the database as well.
BUFSIZE
#define BUFSIZE
Definition: rpm2archive.c:19
headerFree
Header headerFree(Header h)
Dereference a header instance.
rpmts
struct rpmts_s * rpmts
The main types involved in transaction manipulation.
Definition: rpmtypes.h:63
RPMFI_KEEPHEADER
Definition: rpmfiles.h:101
_
#define _(Text)
Definition: system.h:110
rpmfiFRdev
rpm_rdev_t rpmfiFRdev(rpmfi fi)
Return current file rdev from file info set iterator.
rpmtsCreate
rpmts rpmtsCreate(void)
Create an empty transaction set.
RPMRC_NOKEY
Definition: rpmtypes.h:108
rpmfi
struct rpmfi_s * rpmfi
Definition: rpmtypes.h:66
RPMRC_OK
Definition: rpmtypes.h:104
rpmfiFUser
const char * rpmfiFUser(rpmfi fi)
Return current file owner from file info set iterator.
FD_t
struct _FD_s * FD_t
RPM IO file descriptor type.
Definition: rpmtypes.h:98
rpmfiArchiveHasContent
int rpmfiArchiveHasContent(rpmfi fi)
Has current file content stored in the archive.
rpmReadConfigFiles
int rpmReadConfigFiles(const char *file, const char *target)
Read macro configuration file(s) for a target.
rstreq
static int rstreq(const char *s1, const char *s2)
Test for string equality.
Definition: rpmstring.h:113
rpmfiFGroup
const char * rpmfiFGroup(rpmfi fi)
Return current file group from file info set iterator.
rpmfiBN
const char * rpmfiBN(rpmfi fi)
Return current base name from file info set iterator.
rstrscat
char * rstrscat(char **dest, const char *arg,...) RPM_GNUC_NULL_TERMINATED
Concatenate multiple strings with dynamically (re)allocated memory.
Fdopen
FD_t Fdopen(FD_t ofd, const char *fmode)
Header
struct headerToken_s * Header
RPM header and data retrieval types.
Definition: rpmtypes.h:24
rpmfiFN
const char * rpmfiFN(rpmfi fi)
Return current file name from file info set iterator.
rpmfiFSize
rpm_loff_t rpmfiFSize(rpmfi fi)
Return current file size from file info set iterator.
rpmfiFree
rpmfi rpmfiFree(rpmfi fi)
Destroy a file info set iterator.
write_file_content
static void write_file_content(struct archive *a, char *buf, rpmfi fi)
Definition: rpm2archive.c:43
rpmVSFlags
rpmFlags rpmVSFlags
Definition: rpmts.h:110
RPMTAG_PAYLOADCOMPRESSOR
Definition: rpmtag.h:189
main
int main(int argc, char *argv[])
Definition: rpm2archive.c:177
process_package
static int process_package(rpmts ts, char *filename)
Definition: rpm2archive.c:61
rpmtsSetVSFlags
rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
Set verify signatures flag(s).
mode
static int mode
Definition: rpmdb.c:21
rpmfiNewArchiveReader
rpmfi rpmfiNewArchiveReader(FD_t fd, rpmfiles files, int itype)
Get new file iterator for looping over the archive content.
rpmfilesFree
rpmfiles rpmfilesFree(rpmfiles fi)
Destroy a file info set.
rpmfiNext
int rpmfiNext(rpmfi fi)
Return next file iterator index.
_free
#define _free(_ptr)
Definition: system.h:87
_RPMVSF_NOSIGNATURES
#define _RPMVSF_NOSIGNATURES
Definition: rpmts.h:118
Fstrerror
const char * Fstrerror(FD_t fd)
strerror(3) clone.
RPMRC_FAIL
Definition: rpmtypes.h:106
fdDup
FD_t fdDup(int fdno)
RPMERR_ITER_END
Definition: rpmarchive.h:14
system.h
rpmfilesNew
rpmfiles rpmfilesNew(rpmstrPool pool, Header h, rpmTagVal tagN, rpmfiFlags flags)
Create and load a file info set.
rpmfiDN
const char * rpmfiDN(rpmfi fi)
Return current directory name from file info set iterator.
Fopen
FD_t Fopen(const char *path, const char *fmode)
fopen(3) clone.
__progname
#define __progname
Definition: system.h:96
fill_archive_entry
static void fill_archive_entry(struct archive *a, struct archive_entry *entry, rpmfi fi)
Definition: rpm2archive.c:21
_RPMVSF_NODIGESTS
#define _RPMVSF_NODIGESTS
Definition: rpmts.h:112
rpm_mode_t
uint16_t rpm_mode_t
Definition: rpmtypes.h:53
RPMRC_NOTFOUND
Definition: rpmtypes.h:105
rpmfiFNlink
uint32_t rpmfiFNlink(rpmfi fi)
Return (calculated) current file nlink count from file info set iterator.
RPMVSF_NOHDRCHK
Definition: rpmts.h:95
headerGetString
const char * headerGetString(Header h, rpmTagVal tag)
Return a simple string tag from header.
RPMRC_NOTTRUSTED
Definition: rpmtypes.h:107
rpmfiles
struct rpmfiles_s * rpmfiles
Definition: rpmtypes.h:67
rpm_loff_t
uint64_t rpm_loff_t
Definition: rpmtypes.h:51
Ferror
int Ferror(FD_t fd)
ferror(3) clone.
RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST
Definition: rpmfiles.h:144
Fclose
int Fclose(FD_t fd)
fclose(3) clone.
rpmfiFMtime
rpm_time_t rpmfiFMtime(rpmfi fi)
Return current file modify time from file info set iterator.