Magellan Linux

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

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

revision 815 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 24  Line 24 
24   *   *
25   */   */
26    
27  #include "busybox.h"  #include "libbb.h"
28    #include <fnmatch.h>
29  #include "unarchive.h"  #include "unarchive.h"
30    
31  /* note: if you vary hash_prime sizes be aware,  /* note: if you vary hash_prime sizes be aware,
# Line 53  Line 54 
54   *      and available file */   *      and available file */
55  #define PACKAGE_HASH_PRIME 10007  #define PACKAGE_HASH_PRIME 10007
56  typedef struct edge_s {  typedef struct edge_s {
57   unsigned operator:3;   unsigned operator:4; /* was:3 */
58   unsigned type:4;   unsigned type:4;
59   unsigned name:14;   unsigned name:16; /* was:14 */
60   unsigned version:14;   unsigned version:16; /* was:14 */
61  } edge_t;  } edge_t;
62    
63  typedef struct common_node_s {  typedef struct common_node_s {
64   unsigned name:14;   unsigned name:16; /* was:14 */
65   unsigned version:14;   unsigned version:16; /* was:14 */
66   unsigned num_of_edges:14;   unsigned num_of_edges:16; /* was:14 */
67   edge_t **edge;   edge_t **edge;
68  } common_node_t;  } common_node_t;
69    
# Line 71  typedef struct common_node_s { Line 72  typedef struct common_node_s {
72   * likely to be installed at any one time, so there is a bit of leeway here */   * likely to be installed at any one time, so there is a bit of leeway here */
73  #define STATUS_HASH_PRIME 8191  #define STATUS_HASH_PRIME 8191
74  typedef struct status_node_s {  typedef struct status_node_s {
75   unsigned package:14; /* has to fit PACKAGE_HASH_PRIME */   unsigned package:16; /* was:14 */       /* has to fit PACKAGE_HASH_PRIME */
76   unsigned status:14; /* has to fit STATUS_HASH_PRIME */   unsigned status:16; /* was:14 */        /* has to fit STATUS_HASH_PRIME */
77  } status_node_t;  } status_node_t;
78    
79  /* Were statically declared here, but such a big bss is nommu-unfriendly */  
80  static char **name_hashtable;             /* [NAME_HASH_PRIME + 1] */  /* Globals */
81  static common_node_t **package_hashtable; /* [PACKAGE_HASH_PRIME + 1] */  struct globals {
82  static status_node_t **status_hashtable;  /* [STATUS_HASH_PRIME + 1] */   char          *name_hashtable[NAME_HASH_PRIME + 1];
83     common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1];
84     status_node_t *status_hashtable[STATUS_HASH_PRIME + 1];
85    };
86    #define G (*ptr_to_globals)
87    #define name_hashtable    (G.name_hashtable   )
88    #define package_hashtable (G.package_hashtable)
89    #define status_hashtable  (G.status_hashtable )
90    #define INIT_G() do { \
91     SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
92    } while (0)
93    
94    
95  /* Even numbers are for 'extras', like ored dependencies or null */  /* Even numbers are for 'extras', like ored dependencies or null */
96  enum edge_type_e {  enum edge_type_e {
# Line 107  enum operator_e { Line 119  enum operator_e {
119  typedef struct deb_file_s {  typedef struct deb_file_s {
120   char *control_file;   char *control_file;
121   char *filename;   char *filename;
122   unsigned package:14;   unsigned package:16; /* was:14 */
123  } deb_file_t;  } deb_file_t;
124    
125    
126  static void make_hash(const char *key, unsigned *start, unsigned *decrement, const int hash_prime)  static void make_hash(const char *key, unsigned *start, unsigned *decrement, const int hash_prime)
127  {  {
128   unsigned long int hash_num = key[0];   unsigned long hash_num = key[0];
129   int len = strlen(key);   int len = strlen(key);
130   int i;   int i;
131    
# Line 124  static void make_hash(const char *key, u Line 136  static void make_hash(const char *key, u
136   * 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
137   * 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
138   * no effect*/   * no effect*/
139   hash_num += ((key[i] + key[i-1]) << ((key[i] * i) % 24));   hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24);
140   }   }
141   *start = (unsigned) hash_num % hash_prime;   *start = (unsigned) hash_num % hash_prime;
142   *decrement = (unsigned) 1 + (hash_num % (hash_prime - 1));   *decrement = (unsigned) 1 + (hash_num % (hash_prime - 1));
# Line 133  static void make_hash(const char *key, u Line 145  static void make_hash(const char *key, u
145  /* this adds the key to the hash table */  /* this adds the key to the hash table */
146  static int search_name_hashtable(const char *key)  static int search_name_hashtable(const char *key)
147  {  {
148   unsigned probe_address = 0;   unsigned probe_address;
149   unsigned probe_decrement = 0;   unsigned probe_decrement;
150    
151   make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME);   make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME);
152   while (name_hashtable[probe_address] != NULL) {   while (name_hashtable[probe_address] != NULL) {
# Line 155  static int search_name_hashtable(const c Line 167  static int search_name_hashtable(const c
167   */   */
168  static unsigned search_status_hashtable(const char *key)  static unsigned search_status_hashtable(const char *key)
169  {  {
170   unsigned probe_address = 0;   unsigned probe_address;
171   unsigned probe_decrement = 0;   unsigned probe_decrement;
172    
173   make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME);   make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME);
174   while (status_hashtable[probe_address] != NULL) {   while (status_hashtable[probe_address] != NULL) {
# Line 312  static int test_version(const unsigned v Line 324  static int test_version(const unsigned v
324   return FALSE;   return FALSE;
325  }  }
326    
   
327  static int search_package_hashtable(const unsigned name, const unsigned version, const unsigned operator)  static int search_package_hashtable(const unsigned name, const unsigned version, const unsigned operator)
328  {  {
329   unsigned probe_address = 0;   unsigned probe_address;
330   unsigned probe_decrement = 0;   unsigned probe_decrement;
331    
332   make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME);   make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME);
333   while (package_hashtable[probe_address] != NULL) {   while (package_hashtable[probe_address] != NULL) {
# Line 352  static int search_package_hashtable(cons Line 363  static int search_package_hashtable(cons
363   * FIXME: I don't think this is very efficient, but I thought I'd keep   * FIXME: I don't think this is very efficient, but I thought I'd keep
364   * it simple for now until it proves to be a problem.   * it simple for now until it proves to be a problem.
365   */   */
366  static int search_for_provides(int needle, int start_at) {  static int search_for_provides(int needle, int start_at)
367    {
368   int i, j;   int i, j;
369   common_node_t *p;   common_node_t *p;
370   for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) {   for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) {
# Line 371  static int search_for_provides(int needl Line 383  static int search_for_provides(int needl
383   */   */
384  static void add_edge_to_node(common_node_t *node, edge_t *edge)  static void add_edge_to_node(common_node_t *node, edge_t *edge)
385  {  {
386   node->num_of_edges++;   node->edge = xrealloc_vector(node->edge, 2, node->num_of_edges);
387   node->edge = xrealloc(node->edge, sizeof(edge_t) * (node->num_of_edges + 1));   node->edge[node->num_of_edges++] = edge;
  node->edge[node->num_of_edges - 1] = edge;  
388  }  }
389    
390  /*  /*
# Line 409  static void add_split_dependencies(commo Line 420  static void add_split_dependencies(commo
420   if ((edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS)   if ((edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS)
421   && (strcmp(field, field2) != 0)   && (strcmp(field, field2) != 0)
422   ) {   ) {
423   or_edge = xmalloc(sizeof(edge_t));   or_edge = xzalloc(sizeof(edge_t));
424   or_edge->type = edge_type + 1;   or_edge->type = edge_type + 1;
425   or_edge->name = search_name_hashtable(field);   or_edge->name = search_name_hashtable(field);
426   or_edge->version = 0; // tracks the number of altenatives   //or_edge->version = 0; // tracks the number of alternatives
427   add_edge_to_node(parent_node, or_edge);   add_edge_to_node(parent_node, or_edge);
428   }   }
429    
# Line 431  static void add_split_dependencies(commo Line 442  static void add_split_dependencies(commo
442   edge->version = search_name_hashtable("ANY");   edge->version = search_name_hashtable("ANY");
443   } else {   } else {
444   /* Skip leading ' ' or '(' */   /* Skip leading ' ' or '(' */
445   version += strspn(field2, " (");   version += strspn(version, " (");
446   /* Calculate length of any operator characters */   /* Calculate length of any operator characters */
447   offset_ch = strspn(version, "<=>");   offset_ch = strspn(version, "<=>");
448   /* Determine operator */   /* Determine operator */
449   if (offset_ch > 0) {   if (offset_ch > 0) {
450   if (strncmp(version, "=", offset_ch) == 0) {   if (strncmp(version, "=", offset_ch) == 0) {
451   edge->operator = VER_EQUAL;   edge->operator = VER_EQUAL;
452   }   } else if (strncmp(version, "<<", offset_ch) == 0) {
  else if (strncmp(version, "<<", offset_ch) == 0) {  
453   edge->operator = VER_LESS;   edge->operator = VER_LESS;
454   }   } else if (strncmp(version, "<=", offset_ch) == 0) {
  else if (strncmp(version, "<=", offset_ch) == 0) {  
455   edge->operator = VER_LESS_EQUAL;   edge->operator = VER_LESS_EQUAL;
456   }   } else if (strncmp(version, ">>", offset_ch) == 0) {
  else if (strncmp(version, ">>", offset_ch) == 0) {  
457   edge->operator = VER_MORE;   edge->operator = VER_MORE;
458   }   } else if (strncmp(version, ">=", offset_ch) == 0) {
  else if (strncmp(version, ">=", offset_ch) == 0) {  
459   edge->operator = VER_MORE_EQUAL;   edge->operator = VER_MORE_EQUAL;
460   } else {   } else {
461   bb_error_msg_and_die("illegal operator");   bb_error_msg_and_die("illegal operator");
# Line 472  static void add_split_dependencies(commo Line 479  static void add_split_dependencies(commo
479   or_edge->version++;   or_edge->version++;
480    
481   add_edge_to_node(parent_node, edge);   add_edge_to_node(parent_node, edge);
482   } while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL);   field2 = strtok_r(NULL, "|", &line_ptr2);
483     } while (field2 != NULL);
484    
485   free(line2);   free(line2);
486   } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL);   field = strtok_r(NULL, ",", &line_ptr1);
487     } while (field != NULL);
488    
489   free(line);   free(line);
490  }  }
491    
# Line 577  static int read_package_field(const char Line 588  static int read_package_field(const char
588    
589  static unsigned fill_package_struct(char *control_buffer)  static unsigned fill_package_struct(char *control_buffer)
590  {  {
591   static const char *const field_names[] = { "Package", "Version",   static const char field_names[] ALIGN1 =
592   "Pre-Depends", "Depends","Replaces", "Provides",   "Package\0""Version\0"
593   "Conflicts", "Suggests", "Recommends", "Enhances", 0   "Pre-Depends\0""Depends\0""Replaces\0""Provides\0"
594   };   "Conflicts\0""Suggests\0""Recommends\0""Enhances\0";
595    
596   common_node_t *new_node = xzalloc(sizeof(common_node_t));   common_node_t *new_node = xzalloc(sizeof(common_node_t));
597   char *field_name;   char *field_name;
# Line 597  static unsigned fill_package_struct(char Line 608  static unsigned fill_package_struct(char
608   &field_name, &field_value);   &field_name, &field_value);
609    
610   if (field_name == NULL) {   if (field_name == NULL) {
611   goto fill_package_struct_cleanup; /* Oh no, the dreaded goto statement ! */   goto fill_package_struct_cleanup;
612   }   }
613    
614   field_num = index_in_str_array(field_names, field_name);   field_num = index_in_strings(field_names, field_name);
615   switch (field_num) {   switch (field_num) {
616   case 0: /* Package */   case 0: /* Package */
617   new_node->name = search_name_hashtable(field_value);   new_node->name = search_name_hashtable(field_value);
# Line 643  static unsigned fill_package_struct(char Line 654  static unsigned fill_package_struct(char
654   return -1;   return -1;
655   }   }
656   num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL);   num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL);
657   if (package_hashtable[num] == NULL) {   free_package(package_hashtable[num]);
658   package_hashtable[num] = new_node;   package_hashtable[num] = new_node;
  } else {  
  free_package(new_node);  
  }  
659   return num;   return num;
660  }  }
661    
# Line 706  static void set_status(const unsigned st Line 714  static void set_status(const unsigned st
714   new_status = xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);   new_status = xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
715   status_hashtable[status_node_num]->status = search_name_hashtable(new_status);   status_hashtable[status_node_num]->status = search_name_hashtable(new_status);
716   free(new_status);   free(new_status);
  return;  
717  }  }
718    
719  static const char *describe_status(int status_num) {  static const char *describe_status(int status_num)
720   int status_want, status_state ;  {
721     int status_want, status_state;
722   if (status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0)   if (status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0)
723   return "is not installed or flagged to be installed\n";   return "is not installed or flagged to be installed";
724    
725   status_want = get_status(status_num, 1);   status_want = get_status(status_num, 1);
726   status_state = get_status(status_num, 3);   status_state = get_status(status_num, 3);
# Line 725  static const char *describe_status(int s Line 733  static const char *describe_status(int s
733   if (status_want == search_name_hashtable("purge"))   if (status_want == search_name_hashtable("purge"))
734   return "is marked to be purged";   return "is marked to be purged";
735   }   }
736   if (status_want ==  search_name_hashtable("unknown"))   if (status_want == search_name_hashtable("unknown"))
737   return "is in an indeterminate state";   return "is in an indeterminate state";
738   if (status_want == search_name_hashtable("install"))   if (status_want == search_name_hashtable("install"))
739   return "is marked to be installed";   return "is marked to be installed";
# Line 733  static const char *describe_status(int s Line 741  static const char *describe_status(int s
741   return "is not installed or flagged to be installed";   return "is not installed or flagged to be installed";
742  }  }
743    
   
744  static void index_status_file(const char *filename)  static void index_status_file(const char *filename)
745  {  {
746   FILE *status_file;   FILE *status_file;
# Line 742  static void index_status_file(const char Line 749  static void index_status_file(const char
749   status_node_t *status_node = NULL;   status_node_t *status_node = NULL;
750   unsigned status_num;   unsigned status_num;
751    
752   status_file = xfopen(filename, "r");   status_file = xfopen_for_read(filename);
753   while ((control_buffer = xmalloc_fgets_str(status_file, "\n\n")) != NULL) {   while ((control_buffer = xmalloc_fgetline_str(status_file, "\n\n")) != NULL) {
754   const unsigned package_num = fill_package_struct(control_buffer);   const unsigned package_num = fill_package_struct(control_buffer);
755   if (package_num != -1) {   if (package_num != -1) {
756   status_node = xmalloc(sizeof(status_node_t));   status_node = xmalloc(sizeof(status_node_t));
# Line 763  static void index_status_file(const char Line 770  static void index_status_file(const char
770   free(control_buffer);   free(control_buffer);
771   }   }
772   fclose(status_file);   fclose(status_file);
  return;  
773  }  }
774    
775  static void write_buffer_no_status(FILE *new_status_file, const char *control_buffer)  static void write_buffer_no_status(FILE *new_status_file, const char *control_buffer)
# Line 780  static void write_buffer_no_status(FILE Line 786  static void write_buffer_no_status(FILE
786   fprintf(new_status_file, "%s: %s\n", name, value);   fprintf(new_status_file, "%s: %s\n", name, value);
787   }   }
788   }   }
  return;  
789  }  }
790    
791  /* This could do with a cleanup */  /* This could do with a cleanup */
792  static void write_status_file(deb_file_t **deb_file)  static void write_status_file(deb_file_t **deb_file)
793  {  {
794   FILE *old_status_file = xfopen("/var/lib/dpkg/status", "r");   FILE *old_status_file = xfopen_for_read("/var/lib/dpkg/status");
795   FILE *new_status_file = xfopen("/var/lib/dpkg/status.udeb", "w");   FILE *new_status_file = xfopen_for_write("/var/lib/dpkg/status.udeb");
796   char *package_name;   char *package_name;
797   char *status_from_file;   char *status_from_file;
798   char *control_buffer = NULL;   char *control_buffer = NULL;
# Line 798  static void write_status_file(deb_file_t Line 803  static void write_status_file(deb_file_t
803   int i = 0;   int i = 0;
804    
805   /* Update previously known packages */   /* Update previously known packages */
806   while ((control_buffer = xmalloc_fgets_str(old_status_file, "\n\n")) != NULL) {   while ((control_buffer = xmalloc_fgetline_str(old_status_file, "\n\n")) != NULL) {
807   if ((tmp_string = strstr(control_buffer, "Package:")) == NULL) {   tmp_string = strstr(control_buffer, "Package:");
808     if (tmp_string == NULL) {
809   continue;   continue;
810   }   }
811    
# Line 824  static void write_status_file(deb_file_t Line 830  static void write_status_file(deb_file_t
830   if (strcmp(status_from_file, status_from_hashtable) != 0) {   if (strcmp(status_from_file, status_from_hashtable) != 0) {
831   /* New status isnt exactly the same as old status */   /* New status isnt exactly the same as old status */
832   const int state_status = get_status(status_num, 3);   const int state_status = get_status(status_num, 3);
833   if ((strcmp("installed", name_hashtable[state_status]) == 0) ||   if ((strcmp("installed", name_hashtable[state_status]) == 0)
834   (strcmp("unpacked", name_hashtable[state_status]) == 0)) {   || (strcmp("unpacked", name_hashtable[state_status]) == 0)
835     ) {
836   /* We need to add the control file from the package */   /* We need to add the control file from the package */
837   i = 0;   i = 0;
838   while (deb_file[i] != NULL) {   while (deb_file[i] != NULL) {
# Line 890  static void write_status_file(deb_file_t Line 897  static void write_status_file(deb_file_t
897   }   }
898   }   }
899   /* If the package from the status file wasnt handle above, do it now*/   /* If the package from the status file wasnt handle above, do it now*/
900   if (! write_flag) {   if (!write_flag) {
901   fprintf(new_status_file, "%s\n\n", control_buffer);   fprintf(new_status_file, "%s\n\n", control_buffer);
902   }   }
903    
# Line 911  static void write_status_file(deb_file_t Line 918  static void write_status_file(deb_file_t
918   fclose(old_status_file);   fclose(old_status_file);
919   fclose(new_status_file);   fclose(new_status_file);
920    
   
921   /* Create a separate backfile to dpkg */   /* Create a separate backfile to dpkg */
922   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) {
923   struct stat stat_buf;   if (errno != ENOENT)
924   xstat("/var/lib/dpkg/status", &stat_buf);   bb_error_msg_and_die("cannot create backup status file");
925   /* Its ok if renaming the status file fails because status   /* Its ok if renaming the status file fails because status
926   * file doesnt exist, maybe we are starting from scratch */   * file doesnt exist, maybe we are starting from scratch */
927   bb_error_msg("no status file found, creating new one");   bb_error_msg("no status file found, creating new one");
928   }   }
929    
930   if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) {   xrename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status");
  bb_error_msg_and_die("DANGER: cannot create status file, "  
  "you need to manually repair your status file");  
  }  
931  }  }
932    
933  /* This function returns TRUE if the given package can satisfy a  /* This function returns TRUE if the given package can satisfy a
# Line 951  static int package_satisfies_dependency( Line 954  static int package_satisfies_dependency(
954   return 0;   return 0;
955  }  }
956    
957  static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)  static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count - ?? */)
958  {  {
959   int *conflicts = NULL;   int *conflicts = NULL;
960   int conflicts_num = 0;   int conflicts_num = 0;
# Line 969  static int check_deps(deb_file_t **deb_f Line 972  static int check_deps(deb_file_t **deb_f
972   * installed package for conflicts*/   * installed package for conflicts*/
973   while (deb_file[i] != NULL) {   while (deb_file[i] != NULL) {
974   const unsigned package_num = deb_file[i]->package;   const unsigned package_num = deb_file[i]->package;
975   conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));   conflicts = xrealloc_vector(conflicts, 2, conflicts_num);
976   conflicts[conflicts_num] = package_num;   conflicts[conflicts_num] = package_num;
977   conflicts_num++;   conflicts_num++;
978   /* add provides to conflicts list */   /* add provides to conflicts list */
# Line 986  static int check_deps(deb_file_t **deb_f Line 989  static int check_deps(deb_file_t **deb_f
989   new_node->version = package_hashtable[package_num]->edge[j]->version;   new_node->version = package_hashtable[package_num]->edge[j]->version;
990   package_hashtable[conflicts_package_num] = new_node;   package_hashtable[conflicts_package_num] = new_node;
991   }   }
992   conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));   conflicts = xrealloc_vector(conflicts, 2, conflicts_num);
993   conflicts[conflicts_num] = conflicts_package_num;   conflicts[conflicts_num] = conflicts_package_num;
994   conflicts_num++;   conflicts_num++;
995   }   }
# Line 1071  static int check_deps(deb_file_t **deb_f Line 1074  static int check_deps(deb_file_t **deb_f
1074   const edge_t *package_edge = package_node->edge[j];   const edge_t *package_edge = package_node->edge[j];
1075   unsigned package_num;   unsigned package_num;
1076    
1077   if (package_edge->type == EDGE_OR_PRE_DEPENDS ||   if (package_edge->type == EDGE_OR_PRE_DEPENDS
1078      package_edge->type == EDGE_OR_DEPENDS) { /* start an EDGE_OR_ list */   || package_edge->type == EDGE_OR_DEPENDS
1079     ) { /* start an EDGE_OR_ list */
1080   number_of_alternatives = package_edge->version;   number_of_alternatives = package_edge->version;
1081   root_of_alternatives = package_edge;   root_of_alternatives = package_edge;
1082   continue;   continue;
1083   } else if (number_of_alternatives == 0) { /* not in the middle of an EDGE_OR_ list */   }
1084     if (number_of_alternatives == 0) { /* not in the middle of an EDGE_OR_ list */
1085   number_of_alternatives = 1;   number_of_alternatives = 1;
1086   root_of_alternatives = NULL;   root_of_alternatives = NULL;
1087   }   }
# Line 1126  static int check_deps(deb_file_t **deb_f Line 1131  static int check_deps(deb_file_t **deb_f
1131   name_hashtable[package_node->name],   name_hashtable[package_node->name],
1132   package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",   package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
1133   name_hashtable[root_of_alternatives->name]);   name_hashtable[root_of_alternatives->name]);
1134   else   bb_error_msg_and_die(
1135   bb_error_msg_and_die(   "package %s %sdepends on %s, which %s\n",
1136   "package %s %sdepends on %s, which %s\n",   name_hashtable[package_node->name],
1137   name_hashtable[package_node->name],   package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
1138   package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",   name_hashtable[package_edge->name],
1139   name_hashtable[package_edge->name],   describe_status(status_num));
1140   describe_status(status_num));   }
1141   } else if (result == 0 && number_of_alternatives) {   if (result == 0 && number_of_alternatives) {
1142   /* we've found a package which   /* we've found a package which
1143   * satisfies the dependency,   * satisfies the dependency,
1144   * so skip over the rest of   * so skip over the rest of
# Line 1152  static int check_deps(deb_file_t **deb_f Line 1157  static int check_deps(deb_file_t **deb_f
1157  static char **create_list(const char *filename)  static char **create_list(const char *filename)
1158  {  {
1159   FILE *list_stream;   FILE *list_stream;
1160   char **file_list = NULL;   char **file_list;
1161   char *line = NULL;   char *line;
1162   int count = 0;   int count;
1163    
1164   /* don't use [xw]fopen here, handle error ourself */   /* don't use [xw]fopen here, handle error ourself */
1165   list_stream = fopen(filename, "r");   list_stream = fopen_for_read(filename);
1166   if (list_stream == NULL) {   if (list_stream == NULL) {
1167   return NULL;   return NULL;
1168   }   }
1169    
1170   while ((line = xmalloc_getline(list_stream)) != NULL) {   file_list = NULL;
1171   file_list = xrealloc(file_list, sizeof(char *) * (count + 2));   count = 0;
1172   file_list[count] = line;   while ((line = xmalloc_fgetline(list_stream)) != NULL) {
1173   count++;   file_list = xrealloc_vector(file_list, 2, count);
1174     file_list[count++] = line;
1175     /*file_list[count] = NULL; - xrealloc_vector did it */
1176   }   }
1177   fclose(list_stream);   fclose(list_stream);
1178    
1179   if (count == 0) {   return file_list;
  return NULL;  
  } else {  
  file_list[count] = NULL;  
  return file_list;  
  }  
1180  }  }
1181    
1182  /* maybe i should try and hook this into remove_file.c somehow */  /* maybe i should try and hook this into remove_file.c somehow */
1183  static int remove_file_array(char **remove_names, char **exclude_names)  static int remove_file_array(char **remove_names, char **exclude_names)
1184  {  {
1185   struct stat path_stat;   struct stat path_stat;
1186   int match_flag;   int remove_flag = 1; /* not removed anything yet */
1187   int remove_flag = FALSE;   int i, j;
  int i,j;  
1188    
1189   if (remove_names == NULL) {   if (remove_names == NULL) {
1190   return FALSE;   return 0;
1191   }   }
1192   for (i = 0; remove_names[i] != NULL; i++) {   for (i = 0; remove_names[i] != NULL; i++) {
  match_flag = FALSE;  
1193   if (exclude_names != NULL) {   if (exclude_names != NULL) {
1194   for (j = 0; exclude_names[j] != 0; j++) {   for (j = 0; exclude_names[j] != NULL; j++) {
1195   if (strcmp(remove_names[i], exclude_names[j]) == 0) {   if (strcmp(remove_names[i], exclude_names[j]) == 0) {
1196   match_flag = TRUE;   goto skip;
  break;  
1197   }   }
1198   }   }
1199   }   }
1200   if (!match_flag) {   /* TODO: why we are checking lstat? we can just try rm/rmdir */
1201   if (lstat(remove_names[i], &path_stat) < 0) {   if (lstat(remove_names[i], &path_stat) < 0) {
1202   continue;   continue;
1203   }   }
1204   if (S_ISDIR(path_stat.st_mode)) {   if (S_ISDIR(path_stat.st_mode)) {
1205   if (rmdir(remove_names[i]) != -1) {   remove_flag &= rmdir(remove_names[i]); /* 0 if no error */
1206   remove_flag = TRUE;   } else {
1207   }   remove_flag &= unlink(remove_names[i]); /* 0 if no error */
  } else {  
  if (unlink(remove_names[i]) != -1) {  
  remove_flag = TRUE;  
  }  
  }  
1208   }   }
1209     skip:
1210     continue;
1211   }   }
1212   return remove_flag;   return (remove_flag == 0);
1213  }  }
1214    
1215  static int run_package_script(const char *package_name, const char *script_type)  static void run_package_script_or_die(const char *package_name, const char *script_type)
1216  {  {
  struct stat path_stat;  
1217   char *script_path;   char *script_path;
1218   int result;   int result;
1219    
1220   script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);   script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
1221    
1222   /* If the file doesnt exist is isnt a fatal */   /* If the file doesnt exist is isnt fatal */
1223   result = lstat(script_path, &path_stat) < 0 ? EXIT_SUCCESS : system(script_path);   result = access(script_path, F_OK) ? EXIT_SUCCESS : system(script_path);
1224   free(script_path);   free(script_path);
1225   return result;   if (result)
1226     bb_error_msg_and_die("%s failed, exit code %d", script_type, result);
1227  }  }
1228    
1229  static const char *all_control_files[] = {"preinst", "postinst", "prerm", "postrm",  /*
1230   "list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL };  The policy manual defines what scripts get called when and with
1231    what arguments. I realize that busybox does not support all of
1232    these scenarios, but it does support some of them; it does not,
1233    however, run them with any parameters in run_package_script_or_die().
1234    Here are the scripts:
1235    
1236    preinst install
1237    preinst install <old_version>
1238    preinst upgrade <old_version>
1239    preinst abort_upgrade <new_version>
1240    postinst configure <most_recent_version>
1241    postinst abort-upgade <new_version>
1242    postinst abort-remove
1243    postinst abort-remove in-favour <package> <version>
1244    postinst abort-deconfigure in-favor <failed_install_package> removing <conflicting_package> <version>
1245    prerm remove
1246    prerm upgrade <new_version>
1247    prerm failed-upgrade <old_version>
1248    prerm remove in-favor <package> <new_version>
1249    prerm deconfigure in-favour <package> <version> removing <package> <version>
1250    postrm remove
1251    postrm purge
1252    postrm upgrade <new_version>
1253    postrm failed-upgrade <old_version>
1254    postrm abort-install
1255    postrm abort-install <old_version>
1256    postrm abort-upgrade <old_version>
1257    postrm disappear <overwriter> <version>
1258    */
1259    static const char *const all_control_files[] = {
1260     "preinst", "postinst", "prerm", "postrm",
1261     "list", "md5sums", "shlibs", "conffiles",
1262     "config", "templates"
1263    };
1264    
1265  static char **all_control_list(const char *package_name)  static char **all_control_list(const char *package_name)
1266  {  {
# Line 1239  static char **all_control_list(const cha Line 1268  static char **all_control_list(const cha
1268   char **remove_files;   char **remove_files;
1269    
1270   /* Create a list of all /var/lib/dpkg/info/<package> files */   /* Create a list of all /var/lib/dpkg/info/<package> files */
1271   remove_files = xzalloc(sizeof(all_control_files));   remove_files = xzalloc(sizeof(all_control_files) + sizeof(char*));
1272   while (all_control_files[i]) {   while (i < ARRAY_SIZE(all_control_files)) {
1273   remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);   remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s",
1274     package_name, all_control_files[i]);
1275   i++;   i++;
1276   }   }
1277    
# Line 1250  static char **all_control_list(const cha Line 1280  static char **all_control_list(const cha
1280    
1281  static void free_array(char **array)  static void free_array(char **array)
1282  {  {
   
1283   if (array) {   if (array) {
1284   unsigned i = 0;   unsigned i = 0;
1285   while (array[i]) {   while (array[i]) {
# Line 1265  static void free_array(char **array) Line 1294  static void free_array(char **array)
1294   * the status_hashtable to retrieve the info. This results in smaller code than   * the status_hashtable to retrieve the info. This results in smaller code than
1295   * scanning the status file. The resulting list, however, is unsorted.   * scanning the status file. The resulting list, however, is unsorted.
1296   */   */
1297  static void list_packages(void)  static void list_packages(const char *pattern)
1298  {  {
1299   int i;   int i;
1300    
# Line 1273  static void list_packages(void) Line 1302  static void list_packages(void)
1302   puts("+++-==============-==============");   puts("+++-==============-==============");
1303    
1304   /* go through status hash, dereference package hash and finally strings */   /* go through status hash, dereference package hash and finally strings */
1305   for (i=0; i<STATUS_HASH_PRIME+1; i++) {   for (i = 0; i < STATUS_HASH_PRIME+1; i++) {
   
1306   if (status_hashtable[i]) {   if (status_hashtable[i]) {
1307   const char *stat_str;  /* status string */   const char *stat_str;  /* status string */
1308   const char *name_str;  /* package name */   const char *name_str;  /* package name */
# Line 1287  static void list_packages(void) Line 1315  static void list_packages(void)
1315   name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];   name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
1316   vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];   vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
1317    
1318     if (pattern && fnmatch(pattern, name_str, 0))
1319     continue;
1320    
1321   /* get abbreviation for status field 1 */   /* get abbreviation for status field 1 */
1322   s1 = stat_str[0] == 'i' ? 'i' : 'r';   s1 = stat_str[0] == 'i' ? 'i' : 'r';
1323    
1324   /* get abbreviation for status field 2 */   /* get abbreviation for status field 2 */
1325   for (j=0, spccnt=0; stat_str[j] && spccnt<2; j++) {   for (j = 0, spccnt = 0; stat_str[j] && spccnt < 2; j++) {
1326   if (stat_str[j] == ' ') spccnt++;   if (stat_str[j] == ' ') spccnt++;
1327   }   }
1328   s2 = stat_str[j];   s2 = stat_str[j];
# Line 1299  static void list_packages(void) Line 1330  static void list_packages(void)
1330   /* print out the line formatted like Debian dpkg */   /* print out the line formatted like Debian dpkg */
1331   printf("%c%c  %-14s %s\n", s1, s2, name_str, vers_str);   printf("%c%c  %-14s %s\n", s1, s2, name_str, vers_str);
1332   }   }
1333      }   }
1334  }  }
1335    
1336  static void remove_package(const unsigned package_num, int noisy)  static void remove_package(const unsigned package_num, int noisy)
# Line 1312  static void remove_package(const unsigne Line 1343  static void remove_package(const unsigne
1343   char **exclude_files;   char **exclude_files;
1344   char list_name[package_name_length + 25];   char list_name[package_name_length + 25];
1345   char conffile_name[package_name_length + 30];   char conffile_name[package_name_length + 30];
  int return_value;  
1346    
1347   if (noisy)   if (noisy)
1348   printf("Removing %s (%s)...\n", package_name, package_version);   printf("Removing %s (%s)...\n", package_name, package_version);
1349    
1350   /* run prerm script */   /* Run prerm script */
1351   return_value = run_package_script(package_name, "prerm");   run_package_script_or_die(package_name, "prerm");
  if (return_value == -1) {  
  bb_error_msg_and_die("script failed, prerm failure");  
  }  
1352    
1353   /* Create a list of files to remove, and a separate list of those to keep */   /* Create a list of files to remove, and a separate list of those to keep */
1354   sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);   sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");
1355   remove_files = create_list(list_name);   remove_files = create_list(list_name);
1356    
1357   sprintf(conffile_name, "/var/lib/dpkg/info/%s.conffiles", package_name);   sprintf(conffile_name, "/var/lib/dpkg/info/%s.%s", package_name, "conffiles");
1358   exclude_files = create_list(conffile_name);   exclude_files = create_list(conffile_name);
1359    
1360   /* Some directories can't be removed straight away, so do multiple passes */   /* Some directories can't be removed straight away, so do multiple passes */
1361   while (remove_file_array(remove_files, exclude_files)) /*repeat */;   while (remove_file_array(remove_files, exclude_files))
1362     continue;
1363   free_array(exclude_files);   free_array(exclude_files);
1364   free_array(remove_files);   free_array(remove_files);
1365    
1366   /* 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  */
1367   exclude_files = xzalloc(sizeof(char*) * 3);   exclude_files = xzalloc(sizeof(char*) * 3);
1368   exclude_files[0] = xstrdup(conffile_name);   exclude_files[0] = xstrdup(conffile_name);
1369   exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.postrm", package_name);   exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");
1370    
1371   /* Create a list of all /var/lib/dpkg/info/<package> files */   /* Create a list of all /var/lib/dpkg/info/<package> files */
1372   remove_files = all_control_list(package_name);   remove_files = all_control_list(package_name);
# Line 1347  static void remove_package(const unsigne Line 1375  static void remove_package(const unsigne
1375   free_array(remove_files);   free_array(remove_files);
1376   free_array(exclude_files);   free_array(exclude_files);
1377    
1378   /* rename <package>.conffile to <package>.list */   /* rename <package>.conffiles to <package>.list
1379     * The conffiles control file isn't required in Debian packages, so don't
1380     * error out if it's missing.  */
1381   rename(conffile_name, list_name);   rename(conffile_name, list_name);
1382    
1383   /* Change package status */   /* Change package status */
# Line 1365  static void purge_package(const unsigned Line 1395  static void purge_package(const unsigned
1395    
1396   printf("Purging %s (%s)...\n", package_name, package_version);   printf("Purging %s (%s)...\n", package_name, package_version);
1397    
1398   /* run prerm script */   /* Run prerm script */
1399   if (run_package_script(package_name, "prerm") != 0) {   run_package_script_or_die(package_name, "prerm");
  bb_error_msg_and_die("script failed, prerm failure");  
  }  
1400    
1401   /* Create a list of files to remove */   /* Create a list of files to remove */
1402   sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);   sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");
1403   remove_files = create_list(list_name);   remove_files = create_list(list_name);
1404    
1405   exclude_files = xzalloc(sizeof(char*));   exclude_files = xzalloc(sizeof(char*));
# Line 1386  static void purge_package(const unsigned Line 1414  static void purge_package(const unsigned
1414   free_array(remove_files);   free_array(remove_files);
1415   free(exclude_files);   free(exclude_files);
1416    
1417   /* run postrm script */   /* Run postrm script */
1418   if (run_package_script(package_name, "postrm") == -1) {   run_package_script_or_die(package_name, "postrm");
  bb_error_msg_and_die("postrm fialure.. set status to what?");  
  }  
1419    
1420   /* Change package status */   /* Change package status */
1421   set_status(status_num, "not-installed", 3);   set_status(status_num, "not-installed", 3);
# Line 1416  static void init_archive_deb_control(arc Line 1442  static void init_archive_deb_control(arc
1442   tar_handle->src_fd = ar_handle->src_fd;   tar_handle->src_fd = ar_handle->src_fd;
1443    
1444   /* We don't care about data.tar.* or debian-binary, just control.tar.* */   /* We don't care about data.tar.* or debian-binary, just control.tar.* */
1445  #ifdef CONFIG_FEATURE_DEB_TAR_GZ  #if ENABLE_FEATURE_SEAMLESS_GZ
1446   llist_add_to(&(ar_handle->accept), "control.tar.gz");   llist_add_to(&(ar_handle->accept), (char*)"control.tar.gz");
1447  #endif  #endif
1448  #ifdef CONFIG_FEATURE_DEB_TAR_BZ2  #if ENABLE_FEATURE_SEAMLESS_BZ2
1449   llist_add_to(&(ar_handle->accept), "control.tar.bz2");   llist_add_to(&(ar_handle->accept), (char*)"control.tar.bz2");
1450  #endif  #endif
1451    
1452   /* Assign the tar handle as a subarchive of the ar handle */   /* Assign the tar handle as a subarchive of the ar handle */
1453   ar_handle->sub_archive = tar_handle;   ar_handle->sub_archive = tar_handle;
   
  return;  
1454  }  }
1455    
1456  static void init_archive_deb_data(archive_handle_t *ar_handle)  static void init_archive_deb_data(archive_handle_t *ar_handle)
# Line 1438  static void init_archive_deb_data(archiv Line 1462  static void init_archive_deb_data(archiv
1462   tar_handle->src_fd = ar_handle->src_fd;   tar_handle->src_fd = ar_handle->src_fd;
1463    
1464   /* We don't care about control.tar.* or debian-binary, just data.tar.* */   /* We don't care about control.tar.* or debian-binary, just data.tar.* */
1465  #ifdef CONFIG_FEATURE_DEB_TAR_GZ  #if ENABLE_FEATURE_SEAMLESS_GZ
1466   llist_add_to(&(ar_handle->accept), "data.tar.gz");   llist_add_to(&(ar_handle->accept), (char*)"data.tar.gz");
1467  #endif  #endif
1468  #ifdef CONFIG_FEATURE_DEB_TAR_BZ2  #if ENABLE_FEATURE_SEAMLESS_BZ2
1469   llist_add_to(&(ar_handle->accept), "data.tar.bz2");   llist_add_to(&(ar_handle->accept), (char*)"data.tar.bz2");
1470  #endif  #endif
1471    
1472   /* Assign the tar handle as a subarchive of the ar handle */   /* Assign the tar handle as a subarchive of the ar handle */
1473   ar_handle->sub_archive = tar_handle;   ar_handle->sub_archive = tar_handle;
   
  return;  
1474  }  }
1475    
1476  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)
# Line 1463  static char *deb_extract_control_file_to Line 1485  static char *deb_extract_control_file_to
1485   return ar_handle->sub_archive->buffer;   return ar_handle->sub_archive->buffer;
1486  }  }
1487    
1488  static void data_extract_all_prefix(archive_handle_t *archive_handle)  static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)
1489  {  {
1490   char *name_ptr = archive_handle->file_header->name;   char *name_ptr = archive_handle->file_header->name;
1491    
# Line 1472  static void data_extract_all_prefix(arch Line 1494  static void data_extract_all_prefix(arch
1494   archive_handle->file_header->name = xasprintf("%s%s", archive_handle->buffer, name_ptr);   archive_handle->file_header->name = xasprintf("%s%s", archive_handle->buffer, name_ptr);
1495   data_extract_all(archive_handle);   data_extract_all(archive_handle);
1496   }   }
  return;  
1497  }  }
1498    
1499  static void unpack_package(deb_file_t *deb_file)  static void unpack_package(deb_file_t *deb_file)
# Line 1484  static void unpack_package(deb_file_t *d Line 1505  static void unpack_package(deb_file_t *d
1505   char *list_filename;   char *list_filename;
1506   archive_handle_t *archive_handle;   archive_handle_t *archive_handle;
1507   FILE *out_stream;   FILE *out_stream;
1508   llist_t *accept_list = NULL;   llist_t *accept_list;
1509   int i = 0;   int i;
1510    
1511   /* If existing version, remove it first */   /* If existing version, remove it first */
1512   if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {   if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
# Line 1499  static void unpack_package(deb_file_t *d Line 1520  static void unpack_package(deb_file_t *d
1520   }   }
1521    
1522   /* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */   /* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */
1523   info_prefix = xasprintf("/var/lib/dpkg/info/%s.", package_name);   info_prefix = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "");
1524   archive_handle = init_archive_deb_ar(deb_file->filename);   archive_handle = init_archive_deb_ar(deb_file->filename);
1525   init_archive_deb_control(archive_handle);   init_archive_deb_control(archive_handle);
1526    
1527   while (all_control_files[i]) {   accept_list = NULL;
1528     i = 0;
1529     while (i < ARRAY_SIZE(all_control_files)) {
1530   char *c = xasprintf("./%s", all_control_files[i]);   char *c = xasprintf("./%s", all_control_files[i]);
1531   llist_add_to(&accept_list, c);   llist_add_to(&accept_list, c);
1532   i++;   i++;
# Line 1512  static void unpack_package(deb_file_t *d Line 1535  static void unpack_package(deb_file_t *d
1535   archive_handle->sub_archive->filter = filter_accept_list;   archive_handle->sub_archive->filter = filter_accept_list;
1536   archive_handle->sub_archive->action_data = data_extract_all_prefix;   archive_handle->sub_archive->action_data = data_extract_all_prefix;
1537   archive_handle->sub_archive->buffer = info_prefix;   archive_handle->sub_archive->buffer = info_prefix;
1538   archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;   archive_handle->sub_archive->ah_flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
1539   unpack_ar_archive(archive_handle);   unpack_ar_archive(archive_handle);
1540    
1541   /* Run the preinst prior to extracting */   /* Run the preinst prior to extracting */
1542   if (run_package_script(package_name, "preinst") != 0) {   run_package_script_or_die(package_name, "preinst");
  /* when preinst returns exit code != 0 then quit installation process */  
  bb_error_msg_and_die("subprocess pre-installation script returned error");  
  }  
1543    
1544   /* Extract data.tar.gz to the root directory */   /* Extract data.tar.gz to the root directory */
1545   archive_handle = init_archive_deb_ar(deb_file->filename);   archive_handle = init_archive_deb_ar(deb_file->filename);
1546   init_archive_deb_data(archive_handle);   init_archive_deb_data(archive_handle);
1547   archive_handle->sub_archive->action_data = data_extract_all_prefix;   archive_handle->sub_archive->action_data = data_extract_all_prefix;
1548   archive_handle->sub_archive->buffer = "/";   archive_handle->sub_archive->buffer = (char*)"/"; /* huh? */
1549   archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;   archive_handle->sub_archive->ah_flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
1550   unpack_ar_archive(archive_handle);   unpack_ar_archive(archive_handle);
1551    
1552   /* Create the list file */   /* Create the list file */
1553   list_filename = xasprintf("/var/lib/dpkg/info/%s.list", package_name);   list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list");
1554   out_stream = xfopen(list_filename, "w");   out_stream = xfopen_for_write(list_filename);
1555   while (archive_handle->sub_archive->passed) {   while (archive_handle->sub_archive->passed) {
1556   /* the leading . has been stripped by data_extract_all_prefix already */   /* the leading . has been stripped by data_extract_all_prefix already */
1557   fputs(archive_handle->sub_archive->passed->data, out_stream);   fputs(archive_handle->sub_archive->passed->data, out_stream);
# Line 1557  static void configure_package(deb_file_t Line 1577  static void configure_package(deb_file_t
1577   printf("Setting up %s (%s)...\n", package_name, package_version);   printf("Setting up %s (%s)...\n", package_name, package_version);
1578    
1579   /* Run the postinst script */   /* Run the postinst script */
1580   if (run_package_script(package_name, "postinst") != 0) {   /* TODO: handle failure gracefully */
1581   /* TODO: handle failure gracefully */   run_package_script_or_die(package_name, "postinst");
1582   bb_error_msg_and_die("postrm failure.. set status to what?");  
  }  
1583   /* Change status to reflect success */   /* Change status to reflect success */
1584   set_status(status_num, "install", 1);   set_status(status_num, "install", 1);
1585   set_status(status_num, "installed", 3);   set_status(status_num, "installed", 3);
1586  }  }
1587    
1588  int dpkg_main(int argc, char **argv)  int dpkg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1589    int dpkg_main(int argc UNUSED_PARAM, char **argv)
1590  {  {
1591   deb_file_t **deb_file = NULL;   deb_file_t **deb_file = NULL;
1592   status_node_t *status_node;   status_node_t *status_node;
# Line 1585  int dpkg_main(int argc, char **argv) Line 1605  int dpkg_main(int argc, char **argv)
1605   OPT_purge = 0x10,   OPT_purge = 0x10,
1606   OPT_remove = 0x20,   OPT_remove = 0x20,
1607   OPT_unpack = 0x40,   OPT_unpack = 0x40,
  REQ_package_name = 0x8000,  
  REQ_filename = 0x4000,  
1608   };   };
1609    
1610   opt = getopt32(argc, argv, "CF:ilPru", &str_f);   INIT_G();
1611   if (opt & OPT_configure) opt |= REQ_package_name; // -C  
1612     opt = getopt32(argv, "CF:ilPru", &str_f);
1613     //if (opt & OPT_configure) ... // -C
1614   if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg)   if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg)
1615   if (strcmp(str_f, "depends"))   if (strcmp(str_f, "depends"))
1616   opt &= ~OPT_force_ignore_depends;   opt &= ~OPT_force_ignore_depends;
1617   }   }
1618   if (opt & OPT_install) opt |= REQ_filename; // -i   //if (opt & OPT_install) ... // -i
1619   //if (opt & OPT_list_installed) ... // -l   //if (opt & OPT_list_installed) ... // -l
1620   if (opt & OPT_purge) opt |= REQ_package_name; // -P   //if (opt & OPT_purge) ... // -P
1621   if (opt & OPT_remove) opt |= REQ_package_name; // -r   //if (opt & OPT_remove) ... // -r
1622   if (opt & OPT_unpack) opt |= REQ_filename; // -u (--unpack in official dpkg)   //if (opt & OPT_unpack) ... // -u (--unpack in official dpkg)
  argc -= optind;  
1623   argv += optind;   argv += optind;
1624   /* check for non-option argument if expected  */   /* check for non-option argument if expected  */
1625   if (!opt || (!argc && !(opt && OPT_list_installed)))   if (!opt || (!argv[0] && !(opt && OPT_list_installed)))
1626   bb_show_usage();   bb_show_usage();
1627    
  name_hashtable = xzalloc(sizeof(name_hashtable[0]) * (NAME_HASH_PRIME + 1));  
  package_hashtable = xzalloc(sizeof(package_hashtable[0]) * (PACKAGE_HASH_PRIME + 1));  
  status_hashtable = xzalloc(sizeof(status_hashtable[0]) * (STATUS_HASH_PRIME + 1));  
   
1628  /* puts("(Reading database ... xxxxx files and directories installed.)"); */  /* puts("(Reading database ... xxxxx files and directories installed.)"); */
1629   index_status_file("/var/lib/dpkg/status");   index_status_file("/var/lib/dpkg/status");
1630    
1631   /* if the list action was given print the installed packages and exit */   /* if the list action was given print the installed packages and exit */
1632   if (opt & OPT_list_installed) {   if (opt & OPT_list_installed) {
1633   list_packages();   list_packages(argv[0]);
1634   return EXIT_SUCCESS;   return EXIT_SUCCESS;
1635   }   }
1636    
1637   /* Read arguments and store relevant info in structs */   /* Read arguments and store relevant info in structs */
1638   while (*argv) {   while (*argv) {
1639   /* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */   /* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */
1640   deb_file = xrealloc(deb_file, sizeof(deb_file_t *) * (deb_count + 2));   deb_file = xrealloc_vector(deb_file, 2, deb_count);
1641   deb_file[deb_count] = xzalloc(sizeof(deb_file_t));   deb_file[deb_count] = xzalloc(sizeof(deb_file[0][0]));
1642   if (opt & REQ_filename) {   if (opt & (OPT_install | OPT_unpack)) {
1643     /* -i/-u: require filename */
1644   archive_handle_t *archive_handle;   archive_handle_t *archive_handle;
1645   llist_t *control_list = NULL;   llist_t *control_list = NULL;
1646    
1647   /* Extract the control file */   /* Extract the control file */
1648   llist_add_to(&control_list, "./control");   llist_add_to(&control_list, (char*)"./control");
1649   archive_handle = init_archive_deb_ar(argv[0]);   archive_handle = init_archive_deb_ar(argv[0]);
1650   init_archive_deb_control(archive_handle);   init_archive_deb_control(archive_handle);
1651   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);
# Line 1647  int dpkg_main(int argc, char **argv) Line 1663  int dpkg_main(int argc, char **argv)
1663   deb_file[deb_count]->package = (unsigned) package_num;   deb_file[deb_count]->package = (unsigned) package_num;
1664    
1665   /* Add the package to the status hashtable */   /* Add the package to the status hashtable */
1666   if (opt & (OPT_unpack|OPT_install)) {   if (opt & (OPT_unpack | OPT_install)) {
1667   /* Try and find a currently installed version of this package */   /* Try and find a currently installed version of this package */
1668   status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);   status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);
1669   /* If no previous entry was found initialise a new entry */   /* If no previous entry was found initialise a new entry */
# Line 1665  int dpkg_main(int argc, char **argv) Line 1681  int dpkg_main(int argc, char **argv)
1681   set_status(status_num, "reinstreq", 2);   set_status(status_num, "reinstreq", 2);
1682   }   }
1683   }   }
1684   }   } else if (opt & (OPT_configure | OPT_purge | OPT_remove)) {
1685   else if (opt & REQ_package_name) {   /* -C/-p/-r: require package name */
1686   deb_file[deb_count]->package = search_package_hashtable(   deb_file[deb_count]->package = search_package_hashtable(
1687   search_name_hashtable(argv[0]),   search_name_hashtable(argv[0]),
1688   search_name_hashtable("ANY"), VER_ANY);   search_name_hashtable("ANY"), VER_ANY);
# Line 1685  int dpkg_main(int argc, char **argv) Line 1701  int dpkg_main(int argc, char **argv)
1701   bb_error_msg_and_die("%s is already removed", name_hashtable[package_hashtable[package_num]->name]);   bb_error_msg_and_die("%s is already removed", name_hashtable[package_hashtable[package_num]->name]);
1702   }   }
1703   set_status(status_num, "deinstall", 1);   set_status(status_num, "deinstall", 1);
1704   }   } else if (opt & OPT_purge) {
  else if (opt & OPT_purge) {  
1705   /* if package status is "conf-files" then its ok */   /* if package status is "conf-files" then its ok */
1706   if (strcmp(name_hashtable[state_status], "not-installed") == 0) {   if (strcmp(name_hashtable[state_status], "not-installed") == 0) {
1707   bb_error_msg_and_die("%s is already purged", name_hashtable[package_hashtable[package_num]->name]);   bb_error_msg_and_die("%s is already purged", name_hashtable[package_hashtable[package_num]->name]);
# Line 1697  int dpkg_main(int argc, char **argv) Line 1712  int dpkg_main(int argc, char **argv)
1712   deb_count++;   deb_count++;
1713   argv++;   argv++;
1714   }   }
1715     if (!deb_count)
1716     bb_error_msg_and_die("no package files specified");
1717   deb_file[deb_count] = NULL;   deb_file[deb_count] = NULL;
1718    
1719   /* Check that the deb file arguments are installable */   /* Check that the deb file arguments are installable */
1720   if (!(opt & OPT_force_ignore_depends)) {   if (!(opt & OPT_force_ignore_depends)) {
1721   if (!check_deps(deb_file, 0, deb_count)) {   if (!check_deps(deb_file, 0 /*, deb_count*/)) {
1722   bb_error_msg_and_die("dependency check failed");   bb_error_msg_and_die("dependency check failed");
1723   }   }
1724   }   }
# Line 1748  int dpkg_main(int argc, char **argv) Line 1765  int dpkg_main(int argc, char **argv)
1765   }   }
1766    
1767   for (i = 0; i < PACKAGE_HASH_PRIME; i++) {   for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
1768   if (package_hashtable[i] != NULL) {   free_package(package_hashtable[i]);
  free_package(package_hashtable[i]);  
  }  
1769   }   }
1770    
1771   for (i = 0; i < STATUS_HASH_PRIME; i++) {   for (i = 0; i < STATUS_HASH_PRIME; i++) {

Legend:
Removed from v.815  
changed lines
  Added in v.816