Magellan Linux

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

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

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 6  Line 6 
6   *  written by glenn mcgrath with the help of others   *  written by glenn mcgrath with the help of others
7   *  copyright (c) 2001 by glenn mcgrath   *  copyright (c) 2001 by glenn mcgrath
8   *   *
9     *  parts of the version comparison code is plucked from the real dpkg
10     *  application which is licensed GPLv2 and
11     *  copyright (c) 1995 Ian Jackson <ian@chiark.greenend.org.uk>
12     *
13   *  started life as a busybox implementation of udpkg   *  started life as a busybox implementation of udpkg
14   *   *
15   * licensed under gplv2 or later, see file license in this tarball for details.   * licensed under gplv2 or later, see file license in this tarball for details.
# Line 135  static void make_hash(const char *key, u Line 139  static void make_hash(const char *key, u
139   /* shifts the ascii based value and adds it to previous value   /* shifts the ascii based value and adds it to previous value
140   * shift amount is mod 24 because long int is 32 bit and data   * shift amount is mod 24 because long int is 32 bit and data
141   * to be shifted is 8, don't want to shift data to where it has   * to be shifted is 8, don't want to shift data to where it has
142   * no effect*/   * no effect */
143   hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24);   hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24);
144   }   }
145   *start = (unsigned) hash_num % hash_prime;   *start = (unsigned) hash_num % hash_prime;
# Line 183  static unsigned search_status_hashtable( Line 187  static unsigned search_status_hashtable(
187   return probe_address;   return probe_address;
188  }  }
189    
190  /* Need to rethink version comparison, maybe the official dpkg has something i can use ? */  static int order(char x)
 static int version_compare_part(const char *version1, const char *version2)  
191  {  {
192   int upstream_len1 = 0;   return (x == '~' ? -1
193   int upstream_len2 = 0;   : x == '\0' ? 0
194   char *name1_char;   : isdigit(x) ? 0
195   char *name2_char;   : isalpha(x) ? x
196   int len1 = 0;   : (unsigned char)x + 256
197   int len2 = 0;   );
198   int tmp_int;  }
199   int ver_num1;  
200   int ver_num2;  /* This code is taken from dpkg and modified slightly to work with busybox */
201    static int version_compare_part(const char *val, const char *ref)
202   if (version1 == NULL) {  {
203   version1 = xstrdup("");   if (!val) val = "";
204   }   if (!ref) ref = "";
205   if (version2 == NULL) {  
206   version2 = xstrdup("");   while (*val || *ref) {
207   }   int first_diff;
208   upstream_len1 = strlen(version1);  
209   upstream_len2 = strlen(version2);   while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) {
210     int vc = order(*val);
211   while ((len1 < upstream_len1) || (len2 < upstream_len2)) {   int rc = order(*ref);
212   /* Compare non-digit section */   if (vc != rc)
213   tmp_int = strcspn(&version1[len1], "0123456789");   return vc - rc;
214   name1_char = xstrndup(&version1[len1], tmp_int);   val++;
215   len1 += tmp_int;   ref++;
216   tmp_int = strcspn(&version2[len2], "0123456789");   }
217   name2_char = xstrndup(&version2[len2], tmp_int);  
218   len2 += tmp_int;   while (*val == '0')
219   tmp_int = strcmp(name1_char, name2_char);   val++;
220   free(name1_char);   while (*ref == '0')
221   free(name2_char);   ref++;
222   if (tmp_int != 0) {  
223   return tmp_int;   first_diff = 0;
224   }   while (isdigit(*val) && isdigit(*ref)) {
225     if (first_diff == 0)
226   /* Compare digits */   first_diff = *val - *ref;
227   tmp_int = strspn(&version1[len1], "0123456789");   val++;
228   name1_char = xstrndup(&version1[len1], tmp_int);   ref++;
  len1 += tmp_int;  
  tmp_int = strspn(&version2[len2], "0123456789");  
  name2_char = xstrndup(&version2[len2], tmp_int);  
  len2 += tmp_int;  
  ver_num1 = atoi(name1_char);  
  ver_num2 = atoi(name2_char);  
  free(name1_char);  
  free(name2_char);  
  if (ver_num1 < ver_num2) {  
  return -1;  
229   }   }
230   if (ver_num1 > ver_num2) {   if (isdigit(*val))
231   return 1;   return 1;
232   }   if (isdigit(*ref))
233     return -1;
234     if (first_diff)
235     return first_diff;
236   }   }
237   return 0;   return 0;
238  }  }
# Line 249  static int version_compare(const unsigne Line 245  static int version_compare(const unsigne
245  {  {
246   char *ch_ver1 = name_hashtable[ver1];   char *ch_ver1 = name_hashtable[ver1];
247   char *ch_ver2 = name_hashtable[ver2];   char *ch_ver2 = name_hashtable[ver2];
248     unsigned long epoch1 = 0, epoch2 = 0;
249   char epoch1, epoch2;   char *colon;
250   char *deb_ver1, *deb_ver2;   char *deb_ver1, *deb_ver2;
  char *ver1_ptr, *ver2_ptr;  
251   char *upstream_ver1;   char *upstream_ver1;
252   char *upstream_ver2;   char *upstream_ver2;
253   int result;   int result;
254    
255   /* Compare epoch */   /* Compare epoch */
256   if (ch_ver1[1] == ':') {   colon = strchr(ch_ver1, ':');
257   epoch1 = ch_ver1[0];   if (colon) {
258   ver1_ptr = strchr(ch_ver1, ':') + 1;   epoch1 = atoi(ch_ver1);
259   } else {   ch_ver1 = colon + 1;
260   epoch1 = '0';   }
261   ver1_ptr = ch_ver1;   colon = strchr(ch_ver2, ':');
262   }   if (colon) {
263   if (ch_ver2[1] == ':') {   epoch2 = atoi(ch_ver2);
264   epoch2 = ch_ver2[0];   ch_ver2 = colon + 1;
  ver2_ptr = strchr(ch_ver2, ':') + 1;  
  } else {  
  epoch2 = '0';  
  ver2_ptr = ch_ver2;  
265   }   }
266   if (epoch1 < epoch2) {   if (epoch1 < epoch2) {
267   return -1;   return -1;
268   }   }
269   else if (epoch1 > epoch2) {   if (epoch1 > epoch2) {
270   return 1;   return 1;
271   }   }
272    
273   /* Compare upstream version */   /* Compare upstream version */
274   upstream_ver1 = xstrdup(ver1_ptr);   upstream_ver1 = xstrdup(ch_ver1);
275   upstream_ver2 = xstrdup(ver2_ptr);   upstream_ver2 = xstrdup(ch_ver2);
276    
277   /* Chop off debian version, and store for later use */   /* Chop off debian version, and store for later use */
278   deb_ver1 = strrchr(upstream_ver1, '-');   deb_ver1 = strrchr(upstream_ver1, '-');
# Line 502  static void free_package(common_node_t * Line 493  static void free_package(common_node_t *
493  }  }
494    
495  /*  /*
496   * Gets the next package field from package_buffer, seperated into the field name   * Gets the next package field from package_buffer, separated into the field name
497   * and field value, it returns the int offset to the first character of the next field   * and field value, it returns the int offset to the first character of the next field
498   */   */
499  static int read_package_field(const char *package_buffer, char **field_name, char **field_value)  static int read_package_field(const char *package_buffer, char **field_name, char **field_value)
# Line 815  static void write_status_file(deb_file_t Line 806  static void write_status_file(deb_file_t
806   write_flag = FALSE;   write_flag = FALSE;
807   tmp_string = strstr(control_buffer, "Status:");   tmp_string = strstr(control_buffer, "Status:");
808   if (tmp_string != NULL) {   if (tmp_string != NULL) {
809   /* Seperate the status value from the control buffer */   /* Separate the status value from the control buffer */
810   tmp_string += 7;   tmp_string += 7;
811   tmp_string += strspn(tmp_string, " \n\t");   tmp_string += strspn(tmp_string, " \n\t");
812   status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n"));   status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
# Line 921  static void write_status_file(deb_file_t Line 912  static void write_status_file(deb_file_t
912   /* Create a separate backfile to dpkg */   /* Create a separate backfile to dpkg */
913   if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) {   if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) {
914   if (errno != ENOENT)   if (errno != ENOENT)
915   bb_error_msg_and_die("cannot create backup status file");   bb_error_msg_and_die("can't create backup status file");
916   /* Its ok if renaming the status file fails because status   /* Its ok if renaming the status file fails because status
917   * file doesnt exist, maybe we are starting from scratch */   * file doesnt exist, maybe we are starting from scratch */
918   bb_error_msg("no status file found, creating new one");   bb_error_msg("no status file found, creating new one");
# Line 1363  static void remove_package(const unsigne Line 1354  static void remove_package(const unsigne
1354   free_array(exclude_files);   free_array(exclude_files);
1355   free_array(remove_files);   free_array(remove_files);
1356    
1357   /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep  */   /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep */
1358   exclude_files = xzalloc(sizeof(char*) * 3);   exclude_files = xzalloc(sizeof(exclude_files[0]) * 3);
1359   exclude_files[0] = xstrdup(conffile_name);   exclude_files[0] = xstrdup(conffile_name);
1360   exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");   exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");
1361    
# Line 1402  static void purge_package(const unsigned Line 1393  static void purge_package(const unsigned
1393   sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");   sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");
1394   remove_files = create_list(list_name);   remove_files = create_list(list_name);
1395    
  exclude_files = xzalloc(sizeof(char*));  
   
1396   /* Some directories cant be removed straight away, so do multiple passes */   /* Some directories cant be removed straight away, so do multiple passes */
1397   while (remove_file_array(remove_files, exclude_files)) /* repeat */;   while (remove_file_array(remove_files, NULL))
1398     continue;
1399   free_array(remove_files);   free_array(remove_files);
1400    
1401   /* Create a list of all /var/lib/dpkg/info/<package> files */   /* Create a list of all /var/lib/dpkg/info/<package> files */
1402   remove_files = all_control_list(package_name);   remove_files = all_control_list(package_name);
1403    
1404     /* Delete all of them except the postrm script */
1405     exclude_files = xzalloc(sizeof(exclude_files[0]) * 2);
1406     exclude_files[0] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");
1407   remove_file_array(remove_files, exclude_files);   remove_file_array(remove_files, exclude_files);
1408   free_array(remove_files);   free_array(exclude_files);
  free(exclude_files);  
1409    
1410   /* Run postrm script */   /* Run and remove postrm script */
1411   run_package_script_or_die(package_name, "postrm");   run_package_script_or_die(package_name, "postrm");
1412     remove_file_array(remove_files, NULL);
1413    
1414     free_array(remove_files);
1415    
1416   /* Change package status */   /* Change package status */
1417   set_status(status_num, "not-installed", 3);   set_status(status_num, "not-installed", 3);
# Line 1450  static void init_archive_deb_control(arc Line 1446  static void init_archive_deb_control(arc
1446  #endif  #endif
1447    
1448   /* Assign the tar handle as a subarchive of the ar handle */   /* Assign the tar handle as a subarchive of the ar handle */
1449   ar_handle->sub_archive = tar_handle;   ar_handle->dpkg__sub_archive = tar_handle;
1450  }  }
1451    
1452  static void init_archive_deb_data(archive_handle_t *ar_handle)  static void init_archive_deb_data(archive_handle_t *ar_handle)
# Line 1470  static void init_archive_deb_data(archiv Line 1466  static void init_archive_deb_data(archiv
1466  #endif  #endif
1467    
1468   /* Assign the tar handle as a subarchive of the ar handle */   /* Assign the tar handle as a subarchive of the ar handle */
1469   ar_handle->sub_archive = tar_handle;   ar_handle->dpkg__sub_archive = tar_handle;
1470    }
1471    
1472    static void FAST_FUNC data_extract_to_buffer(archive_handle_t *archive_handle)
1473    {
1474     unsigned size = archive_handle->file_header->size;
1475    
1476     archive_handle->dpkg__buffer = xzalloc(size + 1);
1477     xread(archive_handle->src_fd, archive_handle->dpkg__buffer, size);
1478  }  }
1479    
1480  static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept)  static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept)
1481  {  {
1482   ar_handle->sub_archive->action_data = data_extract_to_buffer;   ar_handle->dpkg__sub_archive->action_data = data_extract_to_buffer;
1483   ar_handle->sub_archive->accept = myaccept;   ar_handle->dpkg__sub_archive->accept = myaccept;
1484   ar_handle->sub_archive->filter = filter_accept_list;   ar_handle->dpkg__sub_archive->filter = filter_accept_list;
1485    
1486   unpack_ar_archive(ar_handle);   unpack_ar_archive(ar_handle);
1487   close(ar_handle->src_fd);   close(ar_handle->src_fd);
1488    
1489   return ar_handle->sub_archive->buffer;   return ar_handle->dpkg__sub_archive->dpkg__buffer;
1490  }  }
1491    
1492  static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)  static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)
1493  {  {
1494   char *name_ptr = archive_handle->file_header->name;   char *name_ptr = archive_handle->file_header->name;
1495    
1496   name_ptr += strspn(name_ptr, "./");   /* Skip all leading "/" */
1497     while (*name_ptr == '/')
1498     name_ptr++;
1499     /* Skip all leading "./" and "../" */
1500     while (name_ptr[0] == '.') {
1501     if (name_ptr[1] == '.' && name_ptr[2] == '/')
1502     name_ptr++;
1503     if (name_ptr[1] != '/')
1504     break;
1505     name_ptr += 2;
1506     }
1507    
1508   if (name_ptr[0] != '\0') {   if (name_ptr[0] != '\0') {
1509   archive_handle->file_header->name = xasprintf("%s%s", archive_handle->buffer, name_ptr);   archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr);
1510   data_extract_all(archive_handle);   data_extract_all(archive_handle);
1511   }   }
1512  }  }
# Line 1531  static void unpack_package(deb_file_t *d Line 1546  static void unpack_package(deb_file_t *d
1546   llist_add_to(&accept_list, c);   llist_add_to(&accept_list, c);
1547   i++;   i++;
1548   }   }
1549   archive_handle->sub_archive->accept = accept_list;   archive_handle->dpkg__sub_archive->accept = accept_list;
1550   archive_handle->sub_archive->filter = filter_accept_list;   archive_handle->dpkg__sub_archive->filter = filter_accept_list;
1551   archive_handle->sub_archive->action_data = data_extract_all_prefix;   archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
1552   archive_handle->sub_archive->buffer = info_prefix;   archive_handle->dpkg__sub_archive->dpkg__buffer = info_prefix;
1553   archive_handle->sub_archive->ah_flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;   archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD;
1554   unpack_ar_archive(archive_handle);   unpack_ar_archive(archive_handle);
1555    
1556   /* Run the preinst prior to extracting */   /* Run the preinst prior to extracting */
# Line 1544  static void unpack_package(deb_file_t *d Line 1559  static void unpack_package(deb_file_t *d
1559   /* Extract data.tar.gz to the root directory */   /* Extract data.tar.gz to the root directory */
1560   archive_handle = init_archive_deb_ar(deb_file->filename);   archive_handle = init_archive_deb_ar(deb_file->filename);
1561   init_archive_deb_data(archive_handle);   init_archive_deb_data(archive_handle);
1562   archive_handle->sub_archive->action_data = data_extract_all_prefix;   archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
1563   archive_handle->sub_archive->buffer = (char*)"/"; /* huh? */   archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */
1564   archive_handle->sub_archive->ah_flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;   archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD;
1565   unpack_ar_archive(archive_handle);   unpack_ar_archive(archive_handle);
1566    
1567   /* Create the list file */   /* Create the list file */
1568   list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list");   list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list");
1569   out_stream = xfopen_for_write(list_filename);   out_stream = xfopen_for_write(list_filename);
1570   while (archive_handle->sub_archive->passed) {   while (archive_handle->dpkg__sub_archive->passed) {
1571   /* the leading . has been stripped by data_extract_all_prefix already */   /* the leading . has been stripped by data_extract_all_prefix already */
1572   fputs(archive_handle->sub_archive->passed->data, out_stream);   fputs(archive_handle->dpkg__sub_archive->passed->data, out_stream);
1573   fputc('\n', out_stream);   fputc('\n', out_stream);
1574   archive_handle->sub_archive->passed = archive_handle->sub_archive->passed->link;   archive_handle->dpkg__sub_archive->passed = archive_handle->dpkg__sub_archive->passed->link;
1575   }   }
1576   fclose(out_stream);   fclose(out_stream);
1577    
# Line 1650  int dpkg_main(int argc UNUSED_PARAM, cha Line 1665  int dpkg_main(int argc UNUSED_PARAM, cha
1665   init_archive_deb_control(archive_handle);   init_archive_deb_control(archive_handle);
1666   deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);   deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
1667   if (deb_file[deb_count]->control_file == NULL) {   if (deb_file[deb_count]->control_file == NULL) {
1668   bb_error_msg_and_die("cannot extract control file");   bb_error_msg_and_die("can't extract control file");
1669   }   }
1670   deb_file[deb_count]->filename = xstrdup(argv[0]);   deb_file[deb_count]->filename = xstrdup(argv[0]);
1671   package_num = fill_package_struct(deb_file[deb_count]->control_file);   package_num = fill_package_struct(deb_file[deb_count]->control_file);

Legend:
Removed from v.983  
changed lines
  Added in v.984