Fix pkg_depend_str() to not use pkg->depends_str.
[oweals/opkg-lede.git] / libopkg / pkg.c
index b0c2b69944129df17011c0222f14fe62a8ad6dcd..e37806b711753e98563f50d5b848cf549498f2ed 100644 (file)
@@ -208,21 +208,6 @@ void pkg_deinit(pkg_t *pkg)
        free(pkg->depends_str);
        pkg->depends_str = NULL;
 
-       for (i = 0; i < pkg->provides_count-1; i++)
-               free (pkg->provides_str[i]);
-       free(pkg->provides_str);
-       pkg->provides_str = NULL;
-
-       for (i = 0; i < pkg->conflicts_count; i++)
-               free (pkg->conflicts_str[i]);
-       free(pkg->conflicts_str);
-       pkg->conflicts_str = NULL;
-
-       for (i = 0; i < pkg->replaces_count; i++)
-               free (pkg->replaces_str[i]);
-       free(pkg->replaces_str);
-       pkg->replaces_str = NULL;
-
        for (i = 0; i < pkg->recommends_count; i++)
                free (pkg->recommends_str[i]);
        free(pkg->recommends_str);
@@ -315,26 +300,50 @@ void pkg_deinit(pkg_t *pkg)
        pkg->tags = NULL;
 }
 
-int pkg_init_from_file(pkg_t *pkg, const char *filename)
+int
+pkg_init_from_file(opkg_conf_t *conf, pkg_t *pkg, const char *filename)
 {
-     int err;
-     FILE *control_file;
+       int fd, err = 0;
+       FILE *control_file;
+       char *control_path;
+
+       pkg_init(pkg);
+
+       pkg->local_filename = xstrdup(filename);
+
+       sprintf_alloc(&control_path, "%s/%s.control.XXXXXX", 
+                        conf->tmp_dir,
+                        basename(filename));
+       fd = mkstemp(control_path);
+       if (fd == -1) {
+               perror_msg("%s: mkstemp(%s)", __FUNCTION__, control_path);
+               err = -1;
+               goto err0;
+       }
 
-     err = pkg_init(pkg);
-     if (err) { return err; }
+       control_file = fdopen(fd, "r+");
+       if (control_file == NULL) {
+               perror_msg("%s: fdopen", __FUNCTION__, control_path);
+               close(fd);
+               err = -1;
+               goto err1;
+       }
 
-     pkg->local_filename = xstrdup(filename);
-    
-     control_file = tmpfile();
-     err = pkg_extract_control_file_to_stream(pkg, control_file);
-     if (err) { return err; }
+       err = pkg_extract_control_file_to_stream(pkg, control_file);
+       if (err)
+               goto err2;
 
-     rewind(control_file);
-     pkg_parse_from_stream(pkg, control_file, PFM_ALL);
+       rewind(control_file);
+       pkg_parse_from_stream(pkg, control_file, PFM_ALL);
 
-     fclose(control_file);
+err2:
+       fclose(control_file);
+err1:
+       unlink(control_path);
+err0:
+       free(control_path);
 
-     return 0;
+       return err;
 }
 
 /* Merge any new information in newpkg into oldpkg */
@@ -351,6 +360,9 @@ int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
          return 0;
      }
 
+     if (!oldpkg->auto_installed)
+         oldpkg->auto_installed = newpkg->auto_installed;
+
      if (!oldpkg->src)
          oldpkg->src = newpkg->src;
      if (!oldpkg->dest)
@@ -403,9 +415,7 @@ int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
          newpkg->suggests_count = 0;
      }
 
-     if (!oldpkg->provides_str) {
-         oldpkg->provides_str = newpkg->provides_str;
-         newpkg->provides_str = NULL;
+     if (oldpkg->provides_count <= 1) {
          oldpkg->provides_count = newpkg->provides_count;
          newpkg->provides_count = 0;
 
@@ -415,9 +425,7 @@ int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
          }
      }
 
-     if (!oldpkg->conflicts_str) {
-         oldpkg->conflicts_str = newpkg->conflicts_str;
-         newpkg->conflicts_str = NULL;
+     if (!oldpkg->conflicts_count) {
          oldpkg->conflicts_count = newpkg->conflicts_count;
          newpkg->conflicts_count = 0;
 
@@ -425,9 +433,7 @@ int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
          newpkg->conflicts = NULL;
      }
 
-     if (!oldpkg->replaces_str) {
-         oldpkg->replaces_str = newpkg->replaces_str;
-         newpkg->replaces_str = NULL;
+     if (!oldpkg->replaces_count) {
          oldpkg->replaces_count = newpkg->replaces_count;
          newpkg->replaces_count = 0;
 
@@ -564,10 +570,18 @@ void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
                    }
               }
          } else if (strcasecmp(field, "Conflicts") == 0) {
+              struct depend *cdep;
               if (pkg->conflicts_count) {
                     fprintf(fp, "Conflicts:");
                    for(i = 0; i < pkg->conflicts_count; i++) {
-                        fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
+                       cdep = pkg->conflicts[i].possibilities[0];
+                        fprintf(fp, "%s %s", i == 0 ? "" : ",",
+                               cdep->pkg->name);
+                       if (cdep->version) {
+                               fprintf(fp, "(%s%s)",
+                                       constraint_to_str(cdep->constraint),
+                                       cdep->version);
+                       }
                     }
                     fprintf(fp, "\n");
               }
@@ -581,7 +595,9 @@ void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
               if (pkg->depends_count) {
                     fprintf(fp, "Depends:");
                    for(i = 0; i < pkg->depends_count; i++) {
-                        fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
+                       char *str = pkg_depend_str(pkg, i);
+                       fprintf(fp, "%s %s", i == 0 ? "" : ",", str);
+                       free(str);
                     }
                    fprintf(fp, "\n");
               }
@@ -636,8 +652,9 @@ void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
          } else if (strcasecmp(field, "Provides") == 0) {
               if (pkg->provides_count) {
                   fprintf(fp, "Provides:");
-                 for(i = 0; i < pkg->provides_count-1; i++) {
-                      fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->provides_str[i]);
+                 for(i = 1; i < pkg->provides_count; i++) {
+                      fprintf(fp, "%s %s", i == 1 ? "" : ",",
+                                     pkg->provides[i]->name);
                   }
                   fprintf(fp, "\n");
                }
@@ -651,7 +668,8 @@ void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
               if (pkg->replaces_count) {
                     fprintf(fp, "Replaces:");
                    for (i = 0; i < pkg->replaces_count; i++) {
-                        fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
+                        fprintf(fp, "%s %s", i == 0 ? "" : ",",
+                                       pkg->replaces[i]->name);
                     }
                     fprintf(fp, "\n");
               }
@@ -969,9 +987,12 @@ pkg_version_str_alloc(pkg_t *pkg)
        return version;
 }
 
+/*
+ * XXX: this should be broken into two functions
+ */
 str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
 {
-     int err;
+     int err, fd;
      char *list_file_name = NULL;
      FILE *list_file = NULL;
      char *line;
@@ -997,27 +1018,42 @@ str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
             file. In other words, change deb_extract so that it can
             simply return the file list as a char *[] rather than
             insisting on writing in to a FILE * as it does now. */
-         list_file = tmpfile();
+         sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
+                                         conf->tmp_dir, pkg->name);
+         fd = mkstemp(list_file_name);
+         if (fd == -1) {
+              opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
+                              __FUNCTION__, list_file_name, strerror(errno));
+              free(list_file_name);
+              return pkg->installed_files;
+         }
+         list_file = fdopen(fd, "r+");
+         if (list_file == NULL) {
+              opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
+                              __FUNCTION__, strerror(errno));
+              close(fd);
+              unlink(list_file_name);
+              free(list_file_name);
+              return pkg->installed_files;
+         }
          err = pkg_extract_data_file_names_to_stream(pkg, list_file);
          if (err) {
+              opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
+                              "from %s: %s\n", __FUNCTION__,
+                              pkg->local_filename, strerror(err));
               fclose(list_file);
-              fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
-                      __FUNCTION__, pkg->local_filename, strerror(err));
+              unlink(list_file_name);
+              free(list_file_name);
               return pkg->installed_files;
          }
          rewind(list_file);
      } else {
          sprintf_alloc(&list_file_name, "%s/%s.list",
                        pkg->dest->info_dir, pkg->name);
-         if (! file_exists(list_file_name)) {
-              free(list_file_name);
-              return pkg->installed_files;
-         }
-
          list_file = fopen(list_file_name, "r");
          if (list_file == NULL) {
-              fprintf(stderr, "WARNING: Cannot open %s: %s\n",
-                      list_file_name, strerror(errno));
+              opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
+                      __FUNCTION__, list_file_name, strerror(errno));
               free(list_file_name);
               return pkg->installed_files;
          }
@@ -1037,7 +1073,7 @@ str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
          str_chomp(line);
          file_name = line;
 
-         if (pkg->state_status == SS_NOT_INSTALLED) {
+         if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
               if (*file_name == '.') {
                    file_name++;
               }
@@ -1063,6 +1099,11 @@ str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
 
      fclose(list_file);
 
+     if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
+         unlink(list_file_name);
+         free(list_file_name);
+     }
+
      return pkg->installed_files;
 }