diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 3febd0ec..fc8f0bcd 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -155,7 +155,7 @@ typedef struct _alpm_conflict_t { unsigned long package2_hash; char *package1; char *package2; - char *reason; + alpm_depend_t *reason; } alpm_conflict_t; /** File conflict */ @@ -670,15 +670,15 @@ alpm_list_t *alpm_pkg_get_depends(alpm_pkg_t *pkg); */ alpm_list_t *alpm_pkg_get_optdepends(alpm_pkg_t *pkg); -/** Returns the list of package names conflicting with pkg. +/** Returns the list of packages conflicting with pkg. * @param pkg a pointer to package - * @return a reference to an internal list of strings. + * @return a reference to an internal list of alpm_depend_t structures. */ alpm_list_t *alpm_pkg_get_conflicts(alpm_pkg_t *pkg); -/** Returns the list of package names provided by pkg. +/** Returns the list of packages provided by pkg. * @param pkg a pointer to package - * @return a reference to an internal list of strings. + * @return a reference to an internal list of alpm_depend_t structures. */ alpm_list_t *alpm_pkg_get_provides(alpm_pkg_t *pkg); @@ -690,7 +690,7 @@ alpm_list_t *alpm_pkg_get_deltas(alpm_pkg_t *pkg); /** Returns the list of packages to be replaced by pkg. * @param pkg a pointer to package - * @return a reference to an internal list of strings. + * @return a reference to an internal list of alpm_depend_t structures. */ alpm_list_t *alpm_pkg_get_replaces(alpm_pkg_t *pkg); diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index fdb4ceaf..a874504e 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -509,6 +509,12 @@ static char *get_pkgpath(alpm_db_t *db, alpm_pkg_t *info) f = alpm_list_add(f, linedup); \ } while(1) /* note the while(1) and not (0) */ +#define READ_AND_SPLITDEP(f) do { \ + if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) goto error; \ + if(_alpm_strip_newline(line) == 0) break; \ + f = alpm_list_add(f, _alpm_splitdep(line)); \ +} while(1) /* note the while(1) and not (0) */ + static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { FILE *fp = NULL; @@ -601,20 +607,15 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) /* also store this value to isize */ info->isize = info->size; } else if(strcmp(line, "%REPLACES%") == 0) { - READ_AND_STORE_ALL(info->replaces); + READ_AND_SPLITDEP(info->replaces); } else if(strcmp(line, "%DEPENDS%") == 0) { - /* Different than the rest because of the _alpm_splitdep call. */ - while(1) { - READ_NEXT(); - if(strlen(line) == 0) break; - info->depends = alpm_list_add(info->depends, _alpm_splitdep(line)); - } + READ_AND_SPLITDEP(info->depends); } else if(strcmp(line, "%OPTDEPENDS%") == 0) { READ_AND_STORE_ALL(info->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { - READ_AND_STORE_ALL(info->conflicts); + READ_AND_SPLITDEP(info->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { - READ_AND_STORE_ALL(info->provides); + READ_AND_SPLITDEP(info->provides); } } fclose(fp); @@ -771,7 +772,9 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq if(info->replaces) { fputs("%REPLACES%\n", fp); for(lp = info->replaces; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + char *depstring = alpm_dep_compute_string(lp->data); + fprintf(fp, "%s\n", depstring); + free(depstring); } fprintf(fp, "\n"); } @@ -830,14 +833,18 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq if(info->conflicts) { fputs("%CONFLICTS%\n", fp); for(lp = info->conflicts; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + char *depstring = alpm_dep_compute_string(lp->data); + fprintf(fp, "%s\n", depstring); + free(depstring); } fprintf(fp, "\n"); } if(info->provides) { fputs("%PROVIDES%\n", fp); for(lp = info->provides; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + char *depstring = alpm_dep_compute_string(lp->data); + fprintf(fp, "%s\n", depstring); + free(depstring); } fprintf(fp, "\n"); } diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 9762cbca..3b5b0d0c 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -194,11 +194,14 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t * } else if(strcmp(key, "optdepend") == 0) { newpkg->optdepends = alpm_list_add(newpkg->optdepends, strdup(ptr)); } else if(strcmp(key, "conflict") == 0) { - newpkg->conflicts = alpm_list_add(newpkg->conflicts, strdup(ptr)); + alpm_depend_t *conflict = _alpm_splitdep(ptr); + newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict); } else if(strcmp(key, "replaces") == 0) { - newpkg->replaces = alpm_list_add(newpkg->replaces, strdup(ptr)); + alpm_depend_t *replace = _alpm_splitdep(ptr); + newpkg->replaces = alpm_list_add(newpkg->replaces, replace); } else if(strcmp(key, "provides") == 0) { - newpkg->provides = alpm_list_add(newpkg->provides, strdup(ptr)); + alpm_depend_t *provide = _alpm_splitdep(ptr); + newpkg->provides = alpm_list_add(newpkg->provides, provide); } else if(strcmp(key, "backup") == 0) { alpm_backup_t *backup; CALLOC(backup, 1, sizeof(alpm_backup_t), return -1); diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 069e39dd..66808a7f 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -460,6 +460,12 @@ static int sync_db_populate(alpm_db_t *db) f = alpm_list_add(f, linedup); \ } while(1) /* note the while(1) and not (0) */ +#define READ_AND_SPLITDEP(f) do { \ + if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ + if(_alpm_strip_newline(buf.line) == 0) break; \ + f = alpm_list_add(f, _alpm_splitdep(line)); \ +} while(1) /* note the while(1) and not (0) */ + static int sync_db_read(alpm_db_t *db, struct archive *archive, struct archive_entry *entry, alpm_pkg_t **likely_pkg) { @@ -547,20 +553,15 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, } else if(strcmp(line, "%PGPSIG%") == 0) { READ_AND_STORE(pkg->base64_sig); } else if(strcmp(line, "%REPLACES%") == 0) { - READ_AND_STORE_ALL(pkg->replaces); + READ_AND_SPLITDEP(pkg->replaces); } else if(strcmp(line, "%DEPENDS%") == 0) { - /* Different than the rest because of the _alpm_splitdep call. */ - while(1) { - READ_NEXT(); - if(strlen(line) == 0) break; - pkg->depends = alpm_list_add(pkg->depends, _alpm_splitdep(line)); - } + READ_AND_SPLITDEP(pkg->depends); } else if(strcmp(line, "%OPTDEPENDS%") == 0) { READ_AND_STORE_ALL(pkg->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { - READ_AND_STORE_ALL(pkg->conflicts); + READ_AND_SPLITDEP(pkg->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { - READ_AND_STORE_ALL(pkg->provides); + READ_AND_SPLITDEP(pkg->provides); } else if(strcmp(line, "%DELTAS%") == 0) { /* Different than the rest because of the _alpm_delta_parse call. */ while(1) { diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 91e6b677..fe182094 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -42,7 +42,7 @@ #include "deps.h" static alpm_conflict_t *conflict_new(alpm_pkg_t *pkg1, alpm_pkg_t *pkg2, - const char *reason) + alpm_depend_t *reason) { alpm_conflict_t *conflict; @@ -52,7 +52,7 @@ static alpm_conflict_t *conflict_new(alpm_pkg_t *pkg1, alpm_pkg_t *pkg2, conflict->package2_hash = pkg2->name_hash; STRDUP(conflict->package1, pkg1->name, return NULL); STRDUP(conflict->package2, pkg2->name, return NULL); - STRDUP(conflict->reason, reason, return NULL); + conflict->reason = reason; return conflict; } @@ -61,7 +61,6 @@ void _alpm_conflict_free(alpm_conflict_t *conflict) { FREE(conflict->package2); FREE(conflict->package1); - FREE(conflict->reason); FREE(conflict); } @@ -74,7 +73,7 @@ alpm_conflict_t *_alpm_conflict_dup(const alpm_conflict_t *conflict) newconflict->package2_hash = conflict->package2_hash; STRDUP(newconflict->package1, conflict->package1, return NULL); STRDUP(newconflict->package2, conflict->package2, return NULL); - STRDUP(newconflict->reason, conflict->reason, return NULL); + newconflict->reason = conflict->reason; return newconflict; } @@ -103,16 +102,18 @@ static int conflict_isin(alpm_conflict_t *needle, alpm_list_t *haystack) * @param reason reason for this conflict */ static int add_conflict(alpm_handle_t *handle, alpm_list_t **baddeps, - alpm_pkg_t *pkg1, alpm_pkg_t *pkg2, const char *reason) + alpm_pkg_t *pkg1, alpm_pkg_t *pkg2, alpm_depend_t *reason) { alpm_conflict_t *conflict = conflict_new(pkg1, pkg2, reason); if(!conflict) { return -1; } - _alpm_log(handle, ALPM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", - pkg1->name, pkg2->name, reason); if(!conflict_isin(conflict, *baddeps)) { + char *conflict_str = alpm_dep_compute_string(reason); *baddeps = alpm_list_add(*baddeps, conflict); + _alpm_log(handle, ALPM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", + pkg1->name, pkg2->name, conflict_str); + free(conflict_str); } else { _alpm_conflict_free(conflict); } @@ -144,9 +145,8 @@ static void check_conflict(alpm_handle_t *handle, alpm_list_t *j; for(j = alpm_pkg_get_conflicts(pkg1); j; j = j->next) { - const char *conflict = j->data; + alpm_depend_t *conflict = j->data; alpm_list_t *k; - alpm_depend_t *parsed_conflict = _alpm_splitdep(conflict); for(k = list2; k; k = k->next) { alpm_pkg_t *pkg2 = k->data; @@ -157,7 +157,7 @@ static void check_conflict(alpm_handle_t *handle, continue; } - if(_alpm_depcmp(pkg2, parsed_conflict)) { + if(_alpm_depcmp(pkg2, conflict)) { if(order >= 0) { add_conflict(handle, baddeps, pkg1, pkg2, conflict); } else { @@ -165,7 +165,6 @@ static void check_conflict(alpm_handle_t *handle, } } } - _alpm_dep_free(parsed_conflict); } } } diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 9e8e75bf..5765ab2c 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -437,7 +437,8 @@ alpm_list_t *_alpm_db_search(alpm_db_t *db, const alpm_list_t *needles) if(!matched) { /* check provides */ for(k = alpm_pkg_get_provides(pkg); k; k = k->next) { - if(regexec(®, k->data, 0, 0, 0) == 0) { + alpm_depend_t *provide = k->data; + if(regexec(®, provide->name, 0, 0, 0) == 0) { matched = k->data; break; } diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 992ebe23..6869087c 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -384,25 +384,19 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) } } - /* check provisions, format : "name=version" */ + /* check provisions, name and version if available */ for(i = alpm_pkg_get_provides(pkg); i && !satisfy; i = i->next) { - const char *provision = i->data; - const char *provver = strchr(provision, '='); + alpm_depend_t *provision = i->data; - if(provver == NULL) { /* no provision version */ - satisfy = (dep->mod == ALPM_DEP_MOD_ANY - && strcmp(provision, dep->name) == 0); - } else { - /* This is a bit tricker than the old code for performance reasons. To - * prevent the need to copy and duplicate strings, strncmp only the name - * portion if they are the same length, since there is a version and - * operator in play here. Cast is to silence sign conversion warning; - * we know provver >= provision if we are here. */ - size_t namelen = (size_t)(provver - provision); - provver += 1; - satisfy = (strlen(dep->name) == namelen - && strncmp(provision, dep->name, namelen) == 0 - && dep_vercmp(provver, dep->mod, dep->version)); + if(dep->mod == ALPM_DEP_MOD_ANY) { + /* any version will satisfy the requirement */ + satisfy = (provision->name_hash == dep->name_hash + && strcmp(provision->name, dep->name) == 0); + } else if (provision->mod == ALPM_DEP_MOD_EQ) { + /* provision specifies a version, so try it out */ + satisfy = (provision->name_hash == dep->name_hash + && strcmp(provision->name, dep->name) == 0 + && dep_vercmp(provision->version, dep->mod, dep->version)); } } diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a8dc1440..19d2c844 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -496,7 +496,9 @@ alpm_pkg_t *_alpm_pkg_dup(alpm_pkg_t *pkg) newpkg->reason = pkg->reason; newpkg->licenses = alpm_list_strdup(pkg->licenses); - newpkg->replaces = alpm_list_strdup(pkg->replaces); + for(i = pkg->replaces; i; i = alpm_list_next(i)) { + newpkg->replaces = alpm_list_add(newpkg->replaces, _alpm_dep_dup(i->data)); + } newpkg->groups = alpm_list_strdup(pkg->groups); if(pkg->files.count) { size_t filenum; @@ -517,8 +519,12 @@ alpm_pkg_t *_alpm_pkg_dup(alpm_pkg_t *pkg) newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data)); } newpkg->optdepends = alpm_list_strdup(pkg->optdepends); - newpkg->conflicts = alpm_list_strdup(pkg->conflicts); - newpkg->provides = alpm_list_strdup(pkg->provides); + for(i = pkg->conflicts; i; i = alpm_list_next(i)) { + newpkg->conflicts = alpm_list_add(newpkg->conflicts, _alpm_dep_dup(i->data)); + } + for(i = pkg->provides; i; i = alpm_list_next(i)) { + newpkg->provides = alpm_list_add(newpkg->provides, _alpm_dep_dup(i->data)); + } for(i = pkg->deltas; i; i = alpm_list_next(i)) { newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data)); } @@ -557,8 +563,10 @@ void _alpm_pkg_free(alpm_pkg_t *pkg) FREE(pkg->sha256sum); FREE(pkg->base64_sig); FREE(pkg->arch); + FREELIST(pkg->licenses); - FREELIST(pkg->replaces); + alpm_list_free_inner(pkg->replaces, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free(pkg->replaces); FREELIST(pkg->groups); if(pkg->files.count) { size_t i; @@ -572,8 +580,10 @@ void _alpm_pkg_free(alpm_pkg_t *pkg) alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free); alpm_list_free(pkg->depends); FREELIST(pkg->optdepends); - FREELIST(pkg->conflicts); - FREELIST(pkg->provides); + alpm_list_free_inner(pkg->conflicts, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free(pkg->conflicts); + alpm_list_free_inner(pkg->provides, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free(pkg->provides); alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free); alpm_list_free(pkg->deltas); alpm_list_free(pkg->delta_path); diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index f16489d9..3e38707e 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -150,14 +150,11 @@ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { spkg = k->data; for(l = alpm_pkg_get_replaces(spkg); l; l = l->next) { - const char *replace = l->data; - alpm_depend_t *parsed_replace = _alpm_splitdep(replace); - if(_alpm_depcmp(lpkg, parsed_replace)) { + alpm_depend_t *replace = l->data; + if(_alpm_depcmp(lpkg, replace)) { found = 1; - _alpm_dep_free(parsed_replace); break; } - _alpm_dep_free(parsed_replace); } if(found) { /* check IgnorePkg/IgnoreGroup */ diff --git a/src/pacman/package.c b/src/pacman/package.c index 8c101851..7fe33a9f 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -37,6 +37,22 @@ #define CLBUF_SIZE 4096 +/** Turn a depends list into a text list. + * @param deps a list with items of type alpm_depend_t + * @return a string list, must be freed + */ +static void deplist_display(const char *title, + alpm_list_t *deps) +{ + alpm_list_t *i, *text = NULL; + for(i = deps; i; i = alpm_list_next(i)) { + alpm_depend_t *dep = alpm_list_getdata(i); + text = alpm_list_add(text, alpm_dep_compute_string(dep)); + } + list_display(title, text); + FREELIST(text); +} + /** * Display the details of a package. * Extra information entails 'required by' info for sync packages and backup @@ -52,8 +68,7 @@ void dump_pkg_full(alpm_pkg_t *pkg, enum pkg_from from, int extra) char bdatestr[50] = "", idatestr[50] = ""; const char *label; double size; - const alpm_list_t *i; - alpm_list_t *requiredby = NULL, *depstrings = NULL; + alpm_list_t *requiredby = NULL; if(pkg == NULL) { return; @@ -81,12 +96,6 @@ void dump_pkg_full(alpm_pkg_t *pkg, enum pkg_from from, int extra) break; } - /* turn depends list into a text list */ - for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { - alpm_depend_t *dep = (alpm_depend_t *)alpm_list_getdata(i); - depstrings = alpm_list_add(depstrings, alpm_dep_compute_string(dep)); - } - if(extra || from == PKG_FROM_LOCALDB) { /* compute this here so we don't get a pause in the middle of output */ requiredby = alpm_pkg_compute_requiredby(pkg); @@ -102,14 +111,14 @@ void dump_pkg_full(alpm_pkg_t *pkg, enum pkg_from from, int extra) string_display(_("URL :"), alpm_pkg_get_url(pkg)); list_display(_("Licenses :"), alpm_pkg_get_licenses(pkg)); list_display(_("Groups :"), alpm_pkg_get_groups(pkg)); - list_display(_("Provides :"), alpm_pkg_get_provides(pkg)); - list_display(_("Depends On :"), depstrings); + deplist_display(_("Provides :"), alpm_pkg_get_provides(pkg)); + deplist_display(_("Depends On :"), alpm_pkg_get_depends(pkg)); list_display_linebreak(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg)); if(extra || from == PKG_FROM_LOCALDB) { list_display(_("Required By :"), requiredby); } - list_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg)); - list_display(_("Replaces :"), alpm_pkg_get_replaces(pkg)); + deplist_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg)); + deplist_display(_("Replaces :"), alpm_pkg_get_replaces(pkg)); size = humanize_size(alpm_pkg_get_size(pkg), 'K', 1, &label); if(from == PKG_FROM_SYNCDB) { @@ -162,7 +171,6 @@ void dump_pkg_full(alpm_pkg_t *pkg, enum pkg_from from, int extra) /* final newline to separate packages */ printf("\n"); - FREELIST(depstrings); FREELIST(requiredby); } diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 7b50d805..ea32a264 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -779,13 +779,14 @@ int sync_prepare_execute(void) for(i = data; i; i = alpm_list_next(i)) { alpm_conflict_t *conflict = alpm_list_getdata(i); /* only print reason if it contains new information */ - if(strcmp(conflict->package1, conflict->reason) == 0 || - strcmp(conflict->package2, conflict->reason) == 0) { + if(conflict->reason->mod == ALPM_DEP_MOD_ANY) { printf(_(":: %s and %s are in conflict\n"), conflict->package1, conflict->package2); } else { + char *reason = alpm_dep_compute_string(conflict->reason); printf(_(":: %s and %s are in conflict (%s)\n"), - conflict->package1, conflict->package2, conflict->reason); + conflict->package1, conflict->package2, reason); + free(reason); } } break;