aboutsummaryrefslogtreecommitdiff
path: root/archival/rpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/rpm.c')
-rw-r--r--archival/rpm.c115
1 files changed, 44 insertions, 71 deletions
diff --git a/archival/rpm.c b/archival/rpm.c
index 6c1e341cd..38ec20ef5 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -9,8 +9,8 @@
9 9
10#include "libbb.h" 10#include "libbb.h"
11#include "unarchive.h" 11#include "unarchive.h"
12#include "rpm.h"
12 13
13#define RPM_HEADER_MAGIC "\216\255\350"
14#define RPM_CHAR_TYPE 1 14#define RPM_CHAR_TYPE 1
15#define RPM_INT8_TYPE 2 15#define RPM_INT8_TYPE 2
16#define RPM_INT16_TYPE 3 16#define RPM_INT16_TYPE 3
@@ -46,6 +46,7 @@
46#define TAG_DIRINDEXES 1116 46#define TAG_DIRINDEXES 1116
47#define TAG_BASENAMES 1117 47#define TAG_BASENAMES 1117
48#define TAG_DIRNAMES 1118 48#define TAG_DIRNAMES 1118
49
49#define RPMFILE_CONFIG (1 << 0) 50#define RPMFILE_CONFIG (1 << 0)
50#define RPMFILE_DOC (1 << 1) 51#define RPMFILE_DOC (1 << 1)
51 52
@@ -70,7 +71,7 @@ static void *map;
70static rpm_index **mytags; 71static rpm_index **mytags;
71static int tagcount; 72static int tagcount;
72 73
73static void extract_cpio_gz(int fd); 74static void extract_cpio(int fd, const char *source_rpm);
74static rpm_index **rpm_gettags(int fd, int *num_tags); 75static rpm_index **rpm_gettags(int fd, int *num_tags);
75static int bsearch_rpmtag(const void *key, const void *item); 76static int bsearch_rpmtag(const void *key, const void *item);
76static char *rpm_getstr(int tag, int itemindex); 77static char *rpm_getstr(int tag, int itemindex);
@@ -121,6 +122,8 @@ int rpm_main(int argc, char **argv)
121 } 122 }
122 123
123 while (*argv) { 124 while (*argv) {
125 const char *source_rpm;
126
124 rpm_fd = xopen(*argv++, O_RDONLY); 127 rpm_fd = xopen(*argv++, O_RDONLY);
125 mytags = rpm_gettags(rpm_fd, &tagcount); 128 mytags = rpm_gettags(rpm_fd, &tagcount);
126 if (!mytags) 129 if (!mytags)
@@ -129,11 +132,13 @@ int rpm_main(int argc, char **argv)
129 /* Mimimum is one page */ 132 /* Mimimum is one page */
130 map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); 133 map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0);
131 134
135 source_rpm = rpm_getstr(TAG_SOURCERPM, 0);
136
132 if (func & rpm_install) { 137 if (func & rpm_install) {
133 /* Backup any config files */ 138 /* Backup any config files */
134 loop_through_files(TAG_BASENAMES, fileaction_dobackup); 139 loop_through_files(TAG_BASENAMES, fileaction_dobackup);
135 /* Extact the archive */ 140 /* Extact the archive */
136 extract_cpio_gz(rpm_fd); 141 extract_cpio(rpm_fd, source_rpm);
137 /* Set the correct file uid/gid's */ 142 /* Set the correct file uid/gid's */
138 loop_through_files(TAG_BASENAMES, fileaction_setowngrp); 143 loop_through_files(TAG_BASENAMES, fileaction_setowngrp);
139 } 144 }
@@ -147,14 +152,20 @@ int rpm_main(int argc, char **argv)
147 time_t bdate_time; 152 time_t bdate_time;
148 struct tm *bdate_ptm; 153 struct tm *bdate_ptm;
149 char bdatestring[50]; 154 char bdatestring[50];
150 printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_PREFIXS, 0) ? rpm_getstr(TAG_PREFIXS, 0) : "(not relocateable)"); 155 const char *p;
151 printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_VENDOR, 0) ? rpm_getstr(TAG_VENDOR, 0) : "(none)"); 156
157 p = rpm_getstr(TAG_PREFIXS, 0);
158 if (!p) p = "(not relocateable)";
159 printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), p);
160 p = rpm_getstr(TAG_VENDOR, 0);
161 if (!p) p = "(none)";
162 printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), p);
152 bdate_time = rpm_getint(TAG_BUILDTIME, 0); 163 bdate_time = rpm_getint(TAG_BUILDTIME, 0);
153 bdate_ptm = localtime(&bdate_time); 164 bdate_ptm = localtime(&bdate_time);
154 strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); 165 strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm);
155 printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); 166 printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring);
156 printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); 167 printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0));
157 printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), rpm_getstr(TAG_SOURCERPM, 0)); 168 printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm);
158 printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); 169 printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0));
159 printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); 170 printf("URL : %s\n", rpm_getstr(TAG_URL, 0));
160 printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); 171 printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0));
@@ -187,23 +198,23 @@ int rpm_main(int argc, char **argv)
187 return 0; 198 return 0;
188} 199}
189 200
190static void extract_cpio_gz(int fd) 201static void extract_cpio(int fd, const char *source_rpm)
191{ 202{
192 archive_handle_t *archive_handle; 203 archive_handle_t *archive_handle;
193 unsigned char magic[2]; 204
194#if BB_MMU 205 if (source_rpm != NULL) {
195 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); 206 /* Binary rpm (it was built from some SRPM), install to root */
196 enum { xformer_prog = 0 }; 207 xchdir("/");
197#else 208 } /* else: SRPM, install to current dir */
198 enum { xformer = 0 };
199 const char *xformer_prog;
200#endif
201 209
202 /* Initialize */ 210 /* Initialize */
203 archive_handle = init_handle(); 211 archive_handle = init_handle();
204 archive_handle->seek = seek_by_read; 212 archive_handle->seek = seek_by_read;
205 //archive_handle->action_header = header_list;
206 archive_handle->action_data = data_extract_all; 213 archive_handle->action_data = data_extract_all;
214#if 0 /* For testing (rpm -i only lists the files in internal cpio): */
215 archive_handle->action_header = header_list;
216 archive_handle->action_data = data_skip;
217#endif
207 archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS 218 archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS
208 /* compat: overwrite existing files. 219 /* compat: overwrite existing files.
209 * try "rpm -i foo.src.rpm" few times in a row - 220 * try "rpm -i foo.src.rpm" few times in a row -
@@ -213,46 +224,14 @@ static void extract_cpio_gz(int fd)
213 archive_handle->src_fd = fd; 224 archive_handle->src_fd = fd;
214 /*archive_handle->offset = 0; - init_handle() did it */ 225 /*archive_handle->offset = 0; - init_handle() did it */
215 226
216// TODO: open_zipped does the same 227 setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/);
217
218 xread(archive_handle->src_fd, &magic, 2);
219#if BB_MMU
220 xformer = unpack_gz_stream;
221#else
222 xformer_prog = "gunzip";
223#endif
224 if (magic[0] != 0x1f || magic[1] != 0x8b) {
225 if (!ENABLE_FEATURE_SEAMLESS_BZ2
226 || magic[0] != 'B' || magic[1] != 'Z'
227 ) {
228 bb_error_msg_and_die("no gzip"
229 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
230 " magic");
231 }
232#if BB_MMU
233 xformer = unpack_bz2_stream;
234#else
235 xformer_prog = "bunzip2";
236#endif
237 } else {
238#if !BB_MMU
239 /* NOMMU version of open_transformer execs an external unzipper that should
240 * have the file position at the start of the file */
241 xlseek(archive_handle->src_fd, 0, SEEK_SET);
242#endif
243 }
244
245 xchdir("/"); /* Install RPM's to root */
246 open_transformer(archive_handle->src_fd, xformer, xformer_prog);
247 archive_handle->offset = 0;
248 while (get_header_cpio(archive_handle) == EXIT_SUCCESS) 228 while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
249 continue; 229 continue;
250} 230}
251 231
252
253static rpm_index **rpm_gettags(int fd, int *num_tags) 232static rpm_index **rpm_gettags(int fd, int *num_tags)
254{ 233{
255 /* We should never need mode than 200, and realloc later */ 234 /* We should never need more than 200 (shrink via realloc later) */
256 rpm_index **tags = xzalloc(200 * sizeof(tags[0])); 235 rpm_index **tags = xzalloc(200 * sizeof(tags[0]));
257 int pass, tagindex = 0; 236 int pass, tagindex = 0;
258 237
@@ -260,27 +239,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags)
260 239
261 /* 1st pass is the signature headers, 2nd is the main stuff */ 240 /* 1st pass is the signature headers, 2nd is the main stuff */
262 for (pass = 0; pass < 2; pass++) { 241 for (pass = 0; pass < 2; pass++) {
263 struct { 242 struct rpm_header header;
264 char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */
265 uint8_t version; /* 1 byte version number */
266 uint32_t reserved; /* 4 bytes reserved */
267 uint32_t entries; /* Number of entries in header (4 bytes) */
268 uint32_t size; /* Size of store (4 bytes) */
269 } header;
270 struct BUG_header {
271 char BUG_header[sizeof(header) == 16 ? 1 : -1];
272 };
273 rpm_index *tmpindex; 243 rpm_index *tmpindex;
274 int storepos; 244 int storepos;
275 245
276 xread(fd, &header, sizeof(header)); 246 xread(fd, &header, sizeof(header));
277 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) 247 if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER))
278 return NULL; /* Invalid magic */ 248 return NULL; /* Invalid magic, or not version 1 */
279 if (header.version != 1)
280 return NULL; /* This program only supports v1 headers */
281 header.size = ntohl(header.size); 249 header.size = ntohl(header.size);
282 header.entries = ntohl(header.entries); 250 header.entries = ntohl(header.entries);
283 storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; 251 storepos = xlseek(fd, 0, SEEK_CUR) + header.entries * 16;
284 252
285 while (header.entries--) { 253 while (header.entries--) {
286 tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); 254 tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex));
@@ -292,14 +260,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags)
292 if (pass == 0) 260 if (pass == 0)
293 tmpindex->tag -= 743; 261 tmpindex->tag -= 743;
294 } 262 }
295 xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ 263 storepos = xlseek(fd, header.size, SEEK_CUR); /* Seek past store */
296 /* Skip padding to 8 byte boundary after reading signature headers */ 264 /* Skip padding to 8 byte boundary after reading signature headers */
297 if (pass == 0) 265 if (pass == 0)
298 xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); 266 xlseek(fd, (-storepos) & 0x7, SEEK_CUR);
299 } 267 }
300 tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */ 268 /* realloc tags to save space */
269 tags = xrealloc(tags, tagindex * sizeof(tags[0]));
301 *num_tags = tagindex; 270 *num_tags = tagindex;
302 return tags; /* All done, leave the file at the start of the gzipped cpio archive */ 271 /* All done, leave the file at the start of the gzipped cpio archive */
272 return tags;
303} 273}
304 274
305static int bsearch_rpmtag(const void *key, const void *item) 275static int bsearch_rpmtag(const void *key, const void *item)
@@ -324,10 +294,13 @@ static char *rpm_getstr(int tag, int itemindex)
324 found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); 294 found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
325 if (!found || itemindex >= found[0]->count) 295 if (!found || itemindex >= found[0]->count)
326 return NULL; 296 return NULL;
327 if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) { 297 if (found[0]->type == RPM_STRING_TYPE
298 || found[0]->type == RPM_I18NSTRING_TYPE
299 || found[0]->type == RPM_STRING_ARRAY_TYPE
300 ) {
328 int n; 301 int n;
329 char *tmpstr = (char *) map + found[0]->offset; 302 char *tmpstr = (char *) map + found[0]->offset;
330 for (n=0; n < itemindex; n++) 303 for (n = 0; n < itemindex; n++)
331 tmpstr = tmpstr + strlen(tmpstr) + 1; 304 tmpstr = tmpstr + strlen(tmpstr) + 1;
332 return tmpstr; 305 return tmpstr;
333 } 306 }