index : pacman | |
Archlinux32 fork of pacman | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | lib/libalpm/conflict.c | 408 |
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 3ab4ee71..7b21c38a 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -1,12 +1,12 @@ /* * conflict.c - * + * * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org> * Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> * Copyright (c) 2006 by Christian Hamar <krics@linuxforum.hu> - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -19,7 +19,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ @@ -30,11 +30,7 @@ #include <unistd.h> #include <string.h> #include <limits.h> -#if defined(__APPLE__) || defined(__OpenBSD__) -#include <sys/syslimits.h> -#endif #include <sys/stat.h> -#include <libintl.h> /* libalpm */ #include "conflict.h" @@ -47,191 +43,145 @@ #include "cache.h" #include "deps.h" - -/** See if potential conflict 'name' matches package 'pkg'. - * @param target the name of the parent package we're checking - * @param depname the name of the dependency we're checking - * @param pkg the package to check - * @param conflict the name of the possible conflict - * @return A depmissing struct indicating the conflict - * @note The first two paramters are here to simplify the addition - * of new 'depmiss' objects. - * - * TODO WTF is a 'depmissing' doing indicating a conflict?? - */ -static pmdepmissing_t *does_conflict(const char *target, const char *depname, - pmpkg_t *pkg, const char *conflict) -{ - alpm_list_t *i; - - /* check the actual package name, easy */ - if(strcmp(alpm_pkg_get_name(pkg), conflict) == 0) { - _alpm_log(PM_LOG_DEBUG, _(" found conflict '%s' : package '%s'"), conflict, target); - return(_alpm_depmiss_new(target, PM_DEP_TYPE_CONFLICT, - PM_DEP_MOD_ANY, depname, NULL)); - } else { - /* check what this package provides, harder */ - for(i = alpm_pkg_get_provides(pkg); i; i = i->next) { - const char *provision = i->data; - - if(strcmp(provision, conflict) == 0) { - _alpm_log(PM_LOG_DEBUG, _(" found conflict '%s' : package '%s' provides '%s'"), - conflict, target, provision); - return(_alpm_depmiss_new(target, PM_DEP_TYPE_CONFLICT, - PM_DEP_MOD_ANY, depname, NULL)); - } - } - } - return(NULL); /* not a conflict */ -} - -static alpm_list_t *chk_pkg_vs_db(alpm_list_t *baddeps, pmpkg_t *pkg, pmdb_t *db) +pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2) { - pmdepmissing_t *miss = NULL; - const char *pkgname; - alpm_list_t *i, *j; + pmconflict_t *conflict; - pkgname = alpm_pkg_get_name(pkg); + ALPM_LOG_FUNC; - for(i = alpm_pkg_get_conflicts(pkg); i; i = i->next) { - const char *conflict = i->data; + MALLOC(conflict, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); - if(strcmp(pkgname, conflict) == 0) { - /* a package cannot conflict with itself -- that's just not nice */ - _alpm_log(PM_LOG_DEBUG, _("package '%s' conflicts with itself - packaging error"), - pkgname); - continue; - } + strncpy(conflict->package1, package1, PKG_NAME_LEN); + strncpy(conflict->package2, package2, PKG_NAME_LEN); - /* CHECK 1: check targets against database */ - _alpm_log(PM_LOG_DEBUG, _("checkconflicts: target '%s' vs db"), pkgname); + return(conflict); +} - for(j = _alpm_db_get_pkgcache(db); j; j = j->next) { - pmpkg_t *dbpkg = j->data; +int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack) +{ + alpm_list_t *i; - if(strcmp(alpm_pkg_get_name(dbpkg), pkgname) == 0) { - /* skip the package we're currently processing */ - continue; - } + ALPM_LOG_FUNC; - miss = does_conflict(pkgname, alpm_pkg_get_name(dbpkg), dbpkg, conflict); - if(miss && !_alpm_depmiss_isin(miss, baddeps)) { - baddeps = alpm_list_add(baddeps, miss); - } else { - FREE(miss); - } + for(i = haystack; i; i = i->next) { + pmconflict_t *conflict = i->data; + char *cpkg1 = conflict->package1; + char *cpkg2 = conflict->package2; + char *npkg1 = needle->package1; + char *npkg2 = needle->package2; + if((!strcmp(cpkg1, npkg1) && !strcmp(cpkg2, npkg2)) + || (!strcmp(cpkg1, npkg2) && !strcmp(cpkg2, npkg1))) { + return(1); } } - return(baddeps); + + return(0); } -static alpm_list_t *chk_pkg_vs_targets(alpm_list_t *baddeps, - pmpkg_t *pkg, pmdb_t *db, - alpm_list_t *targets) +/** Check if pkg1 conflicts with pkg2 + * @param pkg1 package we are looking at + * @param conflict name of the possible conflict + * @param pkg2 package to check + * @return 0 for no conflict, non-zero otherwise + */ +static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2) { - pmdepmissing_t *miss = NULL; - const char *pkgname; - alpm_list_t *i, *j; + const char *pkg1name = alpm_pkg_get_name(pkg1); + const char *pkg2name = alpm_pkg_get_name(pkg2); + pmdepend_t *conf = alpm_splitdep(conflict); + int match = 0; + + match = alpm_depcmp(pkg2, conf); + if(match) { + _alpm_log(PM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", + pkg1name, pkg2name, conflict); + } + FREE(conf); + return(match); +} - pkgname = alpm_pkg_get_name(pkg); +/** Adds the pkg1/pkg2 conflict to the baddeps list + * @param *baddeps list to add conflict to + * @param pkg1 first package + * @param pkg2 package causing conflict + */ +static void add_conflict(alpm_list_t **baddeps, const char *pkg1, + const char *pkg2) +{ + pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2); + if(conflict && !_alpm_conflict_isin(conflict, *baddeps)) { + *baddeps = alpm_list_add(*baddeps, conflict); + } else { + FREE(conflict); + } +} - for(i = alpm_pkg_get_conflicts(pkg); i; i = i->next) { - const char *conflict = i->data; +/** Check if packages from list1 conflict with packages from list2. + * This looks at the conflicts fields of all packages from list1, and sees + * if they match packages from list2. + * If a conflict (pkg1, pkg2) is found, it is added to the baddeps list + * in this order if order >= 0, or reverse order (pkg2,pkg1) otherwise. + * + * @param list1 first list of packages + * @param list2 second list of packages + * @param *baddeps list to store conflicts + * @param order if >= 0 the conflict order is preserved, if < 0 it's reversed + */ +static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, + alpm_list_t **baddeps, int order) { + alpm_list_t *i, *j, *k; - if(strcmp(pkgname, conflict) == 0) { - /* a package cannot conflict with itself -- that's just not nice */ - _alpm_log(PM_LOG_DEBUG, _("package '%s' conflicts with itself - packaging error"), - pkgname); - continue; - } + if(!baddeps) { + return; + } + for(i = list1; i; i = i->next) { + pmpkg_t *pkg1 = i->data; + const char *pkg1name = alpm_pkg_get_name(pkg1); - /* CHECK 2: check targets against targets */ - _alpm_log(PM_LOG_DEBUG, _("checkconflicts: target '%s' vs all targets"), pkgname); + for(j = alpm_pkg_get_conflicts(pkg1); j; j = j->next) { + const char *conflict = j->data; - for(j = targets; j; j = j->next) { - const char *targetname; - pmpkg_t *target = j->data; - targetname = alpm_pkg_get_name(target); + for(k = list2; k; k = k->next) { + pmpkg_t *pkg2 = k->data; + const char *pkg2name = alpm_pkg_get_name(pkg2); - if(strcmp(targetname, pkgname) == 0) { - /* skip the package we're currently processing */ - continue; - } + if(strcmp(pkg1name, pkg2name) == 0) { + /* skip the package we're currently processing */ + continue; + } - miss = does_conflict(pkgname, targetname, target, conflict); - if(miss && !_alpm_depmiss_isin(miss, baddeps)) { - baddeps = alpm_list_add(baddeps, miss); - } else { - FREE(miss); + if(does_conflict(pkg1, conflict, pkg2)) { + if(order >= 0) { + add_conflict(baddeps, pkg1name, pkg2name); + } else { + add_conflict(baddeps, pkg2name, pkg1name); + } + } } } } - return(baddeps); } -static alpm_list_t *chk_db_vs_targets(alpm_list_t *baddeps, pmpkg_t *pkg, - pmdb_t *db, alpm_list_t *targets) +/* Check for inter-conflicts */ +alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages) { - pmdepmissing_t *miss = NULL; - const char *pkgname; - alpm_list_t *i, *j; + alpm_list_t *baddeps = NULL; - pkgname = alpm_pkg_get_name(pkg); - - _alpm_log(PM_LOG_DEBUG, _("checkconflicts: db vs target '%s'"), pkgname); - - for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { - alpm_list_t *conflicts = NULL; - const char *dbpkgname; - - pmpkg_t *dbpkg = i->data; - dbpkgname = alpm_pkg_get_name(dbpkg); - - if(strcmp(dbpkgname, pkgname) == 0) { - /* skip the package we're currently processing */ - continue; - } - - /* is this db package in the targets? if so use the - * new package's conflict list to pick up new changes */ - int use_newconflicts = 0; - for(j = targets; j; j = j->next) { - pmpkg_t *targ = j->data; - if(strcmp(alpm_pkg_get_name(targ), dbpkgname) == 0) { - _alpm_log(PM_LOG_DEBUG, _("target '%s' is also in target list, using NEW conflicts"), - dbpkgname); - conflicts = alpm_pkg_get_conflicts(targ); - use_newconflicts = 1; - break; - } - } - /* if we didn't find newer conflicts, use the original list */ - if(!use_newconflicts) { - conflicts = alpm_pkg_get_conflicts(dbpkg); - } - - for(j = conflicts; j; j = j->next) { - const char *conflict = j->data; + ALPM_LOG_FUNC; + _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); + check_conflict(packages, packages, &baddeps, 0); - miss = does_conflict(pkgname, dbpkgname, pkg, conflict); - if(miss && !_alpm_depmiss_isin(miss, baddeps)) { - baddeps = alpm_list_add(baddeps, miss); - } else { - FREE(miss); - } - } - } return(baddeps); } -/* Returns a alpm_list_t* of pmdepmissing_t pointers. - * - * conflicts are always name only +/* Check for target vs (db - target) conflicts + * In case of conflict the package1 field of pmdepconflict_t contains + * the target package, package2 field contains the local package */ -alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages) +alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages) { - alpm_list_t *i, *baddeps = NULL; + alpm_list_t *baddeps = NULL; ALPM_LOG_FUNC; @@ -239,27 +189,23 @@ alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages) return(NULL); } - for(i = packages; i; i = i->next) { - pmpkg_t *pkg = i->data; - if(pkg == NULL) { - continue; - } - - /* run three different conflict checks on each package */ - baddeps = chk_pkg_vs_db(baddeps, pkg, db); - baddeps = chk_pkg_vs_targets(baddeps, pkg, db, packages); - baddeps = chk_db_vs_targets(baddeps, pkg, db, packages); - } + alpm_list_t *dblist = alpm_list_diff(_alpm_db_get_pkgcache(db), packages, + _alpm_pkg_cmp); - /* debug loop */ - for(i = baddeps; i; i = i->next) { - pmdepmissing_t *miss = i->data; - _alpm_log(PM_LOG_DEBUG, _("\tCONFLICTS:: %s conflicts with %s"), miss->target, miss->depend.name); - } + /* two checks to be done here for conflicts */ + _alpm_log(PM_LOG_DEBUG, "check targets vs db\n"); + check_conflict(packages, dblist, &baddeps, 1); + _alpm_log(PM_LOG_DEBUG, "check db vs targets\n"); + check_conflict(dblist, packages, &baddeps, -1); + alpm_list_free(dblist); return(baddeps); } +/* Check for transaction conflicts */ +alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages) { + return(alpm_list_join(_alpm_innerconflicts(packages), _alpm_outerconflicts(db, packages))); +} /* Returns a alpm_list_t* of file conflicts. * Hooray for set-intersects! @@ -335,32 +281,29 @@ static alpm_list_t *chk_filedifference(alpm_list_t *filesA, alpm_list_t *filesB) return(ret); } -/* Adds pmconflict_t to a conflicts list. Pass the conflicts list, type (either - * PM_CONFLICT_TYPE_TARGET or PM_CONFLICT_TYPE_FILE), a file string, and either +/* Adds pmfileconflict_t to a conflicts list. Pass the conflicts list, type (either + * PM_FILECONFLICT_TARGET or PM_FILECONFLICT_FILESYSTEM), a file string, and either * two package names or one package name and NULL. This is a wrapper for former * functionality that was done inline. */ static alpm_list_t *add_fileconflict(alpm_list_t *conflicts, - pmconflicttype_t type, const char *filestr, + pmfileconflicttype_t type, const char *filestr, const char* name1, const char* name2) { - pmconflict_t *conflict = malloc(sizeof(pmconflict_t)); - if(conflict == NULL) { - _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %d bytes"), - sizeof(pmconflict_t)); - return(conflicts); - } + pmfileconflict_t *conflict; + MALLOC(conflict, sizeof(pmfileconflict_t), return(conflicts)); + conflict->type = type; - STRNCPY(conflict->target, name1, PKG_NAME_LEN); - STRNCPY(conflict->file, filestr, CONFLICT_FILE_LEN); + strncpy(conflict->target, name1, PKG_NAME_LEN); + strncpy(conflict->file, filestr, CONFLICT_FILE_LEN); if(name2) { - STRNCPY(conflict->ctarget, name2, PKG_NAME_LEN); + strncpy(conflict->ctarget, name2, PKG_NAME_LEN); } else { conflict->ctarget[0] = '\0'; } conflicts = alpm_list_add(conflicts, conflict); - _alpm_log(PM_LOG_DEBUG, "found file conflict %s, packages %s and %s", + _alpm_log(PM_LOG_DEBUG, "found file conflict %s, packages %s and %s\n", filestr, name1, name2 ? name2 : "(filesystem)"); return(conflicts); @@ -369,11 +312,12 @@ static alpm_list_t *add_fileconflict(alpm_list_t *conflicts, /* Find file conflicts that may occur during the transaction with two checks: * 1: check every target against every target * 2: check every target against the filesystem */ -alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root) +alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *root) { alpm_list_t *i, *conflicts = NULL; alpm_list_t *targets = trans->packages; int numtargs = alpm_list_count(targets); + int current; ALPM_LOG_FUNC; @@ -381,7 +325,11 @@ alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root) return(NULL); } - for(i = targets; i; i = i->next) { + /* TODO this whole function needs a huge change, which hopefully will + * be possible with real transactions. Right now we only do half as much + * here as we do when we actually extract files in add.c with our 12 + * different cases. */ + for(current = 1, i = targets; i; i = i->next, current++) { alpm_list_t *j, *k, *tmpfiles = NULL; pmpkg_t *p1, *p2, *dbpkg; char path[PATH_MAX+1]; @@ -391,37 +339,35 @@ alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root) continue; } - double percent = (double)(alpm_list_count(targets) - alpm_list_count(i) + 1) - / alpm_list_count(targets); + double percent = (double)current / numtargs; PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", (percent * 100), - numtargs, (numtargs - alpm_list_count(i) +1)); + numtargs, current); /* CHECK 1: check every target against every target */ for(j = i->next; j; j = j->next) { p2 = j->data; if(!p2) { continue; } - _alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s and %s", + _alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s and %s\n", alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)); tmpfiles = chk_fileconflicts(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2)); if(tmpfiles) { for(k = tmpfiles; k; k = k->next) { snprintf(path, PATH_MAX, "%s%s", root, (char *)k->data); - conflicts = add_fileconflict(conflicts, PM_CONFLICT_TYPE_TARGET, path, + conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_TARGET, path, alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)); } - alpm_list_free_inner(tmpfiles, &free); - alpm_list_free(tmpfiles); + FREELIST(tmpfiles); } } /* declarations for second check */ - struct stat buf; + struct stat lsbuf, sbuf; char *filestr = NULL; /* CHECK 2: check every target against the filesystem */ - _alpm_log(PM_LOG_DEBUG, "searching for filesystem conflicts: %s", p1->name); + _alpm_log(PM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", p1->name); dbpkg = _alpm_db_get_pkgfromcache(db, p1->name); /* Do two different checks here. f the package is currently installed, @@ -441,22 +387,31 @@ alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root) snprintf(path, PATH_MAX, "%s%s", root, filestr); - /* stat the file - if it exists and is not a dir, do some checks */ - if(lstat(path, &buf) == 0 && !S_ISDIR(buf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, "checking possible conflict: %s", path); + /* stat the file - if it exists, do some checks */ + if(_alpm_lstat(path, &lsbuf) != 0) { + continue; + } + stat(path, &sbuf); + + if(S_ISDIR(lsbuf.st_mode)) { + _alpm_log(PM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); + } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { + _alpm_log(PM_LOG_DEBUG, "%s is a symlink to a dir, hopefully not a conflict\n", path); + } else { + _alpm_log(PM_LOG_DEBUG, "checking possible conflict: %s\n", path); /* Make sure the possible conflict is not a symlink that points to a * path in the old package. This is kind of dirty with inode usage */ + /* TODO this seems ripe for a cleanup */ if(dbpkg) { - struct stat buf2; + struct stat pkgbuf; char str[PATH_MAX+1]; unsigned ok = 0; for(k = dbpkg->files; k; k = k->next) { snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data); - lstat(str, &buf2); - if(buf.st_ino == buf2.st_ino) { + if(!_alpm_lstat(str, &pkgbuf) && lsbuf.st_ino == pkgbuf.st_ino) { ok = 1; - _alpm_log(PM_LOG_DEBUG, "conflict was a symlink: %s", path); + _alpm_log(PM_LOG_DEBUG, "conflict was a symlink: %s\n", path); break; } } @@ -487,7 +442,7 @@ alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root) /* keep file intact if it is in backup array */ trans->skip_add = alpm_list_add(trans->skip_add, strdup(path)); trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(path)); - _alpm_log(PM_LOG_DEBUG, "file in backup array, adding to add and remove skiplist: %s", filestr); + _alpm_log(PM_LOG_DEBUG, "file in backup array, adding to add and remove skiplist: %s\n", filestr); resolved_conflict = 1; break; } else { @@ -495,29 +450,48 @@ alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root) * package from removing the file when it was already installed * by its new owner */ trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(path)); - _alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s", filestr); + _alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s\n", filestr); resolved_conflict = 1; break; } } } if(!resolved_conflict) { - _alpm_log(PM_LOG_DEBUG, "file found in conflict: %s", path); - conflicts = add_fileconflict(conflicts, PM_CONFLICT_TYPE_FILE, + _alpm_log(PM_LOG_DEBUG, "file found in conflict: %s\n", path); + conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_FILESYSTEM, path, p1->name, NULL); } - } else { - _alpm_log(PM_LOG_DEBUG, "%s is a directory, not a conflict", path); } } - alpm_list_free_inner(tmpfiles, &free); - alpm_list_free(tmpfiles); + FREELIST(tmpfiles); } return(conflicts); } -const char SYMEXPORT *alpm_conflict_get_target(pmconflict_t *conflict) +const char SYMEXPORT *alpm_conflict_get_package1(pmconflict_t *conflict) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(conflict != NULL, return(NULL)); + + return conflict->package1; +} + +const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(conflict != NULL, return(NULL)); + + return conflict->package2; +} + +const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict) { ALPM_LOG_FUNC; @@ -528,7 +502,7 @@ const char SYMEXPORT *alpm_conflict_get_target(pmconflict_t *conflict) return conflict->target; } -pmconflicttype_t SYMEXPORT alpm_conflict_get_type(pmconflict_t *conflict) +pmfileconflicttype_t SYMEXPORT alpm_fileconflict_get_type(pmfileconflict_t *conflict) { ALPM_LOG_FUNC; @@ -539,7 +513,7 @@ pmconflicttype_t SYMEXPORT alpm_conflict_get_type(pmconflict_t *conflict) return conflict->type; } -const char SYMEXPORT *alpm_conflict_get_file(pmconflict_t *conflict) +const char SYMEXPORT *alpm_fileconflict_get_file(pmfileconflict_t *conflict) { ALPM_LOG_FUNC; @@ -550,7 +524,7 @@ const char SYMEXPORT *alpm_conflict_get_file(pmconflict_t *conflict) return conflict->file; } -const char SYMEXPORT *alpm_conflict_get_ctarget(pmconflict_t *conflict) +const char SYMEXPORT *alpm_fileconflict_get_ctarget(pmfileconflict_t *conflict) { ALPM_LOG_FUNC; |