Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/archival/rpm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1122  
changed lines
  Added in v.1123