index : pacman | |
Archlinux32 fork of pacman | gitolite user |
summaryrefslogtreecommitdiff |
author | Xavier Chantry <shiningxc@gmail.com> | 2009-07-17 15:48:57 +0200 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2009-07-20 10:13:25 -0500 |
commit | bfd6817112b34b552e9139bdc582d048bcba38b9 (patch) | |
tree | 1c33649fec71af2d5a16618bd9627689c0a54285 /lib | |
parent | a3ecbec6b584b3595c041850e4c8bf242f7ce74a (diff) |
-rw-r--r-- | lib/libalpm/add.c | 48 | ||||
-rw-r--r-- | lib/libalpm/conflict.c | 57 |
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 4bd52dea..ddbcfeea 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -353,28 +353,30 @@ static int extract_single_file(struct archive *archive, if(_alpm_lstat(filename, &lsbuf) != 0 || stat(filename, &sbuf) != 0) { /* cases 1,2,3: couldn't stat an existing file, skip all backup checks */ } else { - if(S_ISDIR(lsbuf.st_mode) && S_ISDIR(entrymode)) { - /* case 12: existing dir, ignore it */ - if(lsbuf.st_mode != entrymode) { - /* if filesystem perms are different than pkg perms, warn user */ - int mask = 07777; - _alpm_log(PM_LOG_WARNING, _("directory permissions differ on %s\n" - "filesystem: %o package: %o\n"), entryname, lsbuf.st_mode & mask, - entrymode & mask); - alpm_logaction("warning: directory permissions differ on %s\n" + if(S_ISDIR(lsbuf.st_mode)) { + if(S_ISDIR(entrymode)) { + /* case 12: existing dir, ignore it */ + if(lsbuf.st_mode != entrymode) { + /* if filesystem perms are different than pkg perms, warn user */ + int mask = 07777; + _alpm_log(PM_LOG_WARNING, _("directory permissions differ on %s\n" + "filesystem: %o package: %o\n"), entryname, lsbuf.st_mode & mask, + entrymode & mask); + alpm_logaction("warning: directory permissions differ on %s\n" "filesystem: %o package: %o\n", entryname, lsbuf.st_mode & mask, - entrymode & mask); + entrymode & mask); + } + _alpm_log(PM_LOG_DEBUG, "extract: skipping dir extraction of %s\n", + entryname); + archive_read_data_skip(archive); + return(0); + } else { + /* case 10/11: trying to overwrite dir with file/symlink, don't allow it */ + _alpm_log(PM_LOG_ERROR, _("extract: not overwriting dir with file %s\n"), + entryname); + archive_read_data_skip(archive); + return(1); } - _alpm_log(PM_LOG_DEBUG, "extract: skipping dir extraction of %s\n", - entryname); - archive_read_data_skip(archive); - return(0); - } else if(S_ISDIR(lsbuf.st_mode) && S_ISLNK(entrymode)) { - /* case 11: existing dir, symlink in package, ignore it */ - _alpm_log(PM_LOG_DEBUG, "extract: skipping symlink extraction of %s\n", - entryname); - archive_read_data_skip(archive); - return(0); } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(entrymode)) { /* case 9: existing symlink, dir in package */ if(S_ISDIR(sbuf.st_mode)) { @@ -390,12 +392,6 @@ static int extract_single_file(struct archive *archive, archive_read_data_skip(archive); return(1); } - } else if(S_ISDIR(lsbuf.st_mode) && S_ISREG(entrymode)) { - /* case 10: trying to overwrite dir tree with file, don't allow it */ - _alpm_log(PM_LOG_ERROR, _("extract: not overwriting dir with file %s\n"), - entryname); - archive_read_data_skip(archive); - return(1); } else if(S_ISREG(lsbuf.st_mode) && S_ISDIR(entrymode)) { /* case 6: trying to overwrite file with dir */ _alpm_log(PM_LOG_DEBUG, "extract: overwriting file with dir %s\n", diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index db1656fa..c4c57cb0 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -29,6 +29,7 @@ #include <string.h> #include <limits.h> #include <sys/stat.h> +#include <dirent.h> /* libalpm */ #include "conflict.h" @@ -348,6 +349,50 @@ void _alpm_fileconflict_free(pmfileconflict_t *conflict) FREE(conflict); } +static int dir_belongsto_pkg(char *dirpath, pmpkg_t *pkg) +{ + struct dirent *ent = NULL; + struct stat sbuf; + char path[PATH_MAX]; + char abspath[PATH_MAX]; + DIR *dir; + + snprintf(abspath, PATH_MAX, "%s%s", handle->root, dirpath); + dir = opendir(abspath); + if(dir == NULL) { + return(1); + } + while((ent = readdir(dir)) != NULL) { + const char *name = ent->d_name; + + if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + continue; + } + snprintf(path, PATH_MAX, "%s/%s", dirpath, name); + snprintf(abspath, PATH_MAX, "%s%s", handle->root, path); + if(stat(abspath, &sbuf) != 0) { + continue; + } + if(S_ISDIR(sbuf.st_mode)) { + if(dir_belongsto_pkg(path, pkg)) { + continue; + } else { + closedir(dir); + return(0); + } + } else { + if(alpm_list_find_str(alpm_pkg_get_files(pkg),path)) { + continue; + } else { + closedir(dir); + return(0); + } + } + } + closedir(dir); + return(1); +} + /* 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 */ @@ -474,6 +519,18 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, } } + /* check if all files of the dir belong to the installed pkg */ + if(!resolved_conflict && S_ISDIR(lsbuf.st_mode) && dbpkg) { + char *dir = malloc(strlen(filestr) + 2); + sprintf(dir, "%s/", filestr); + if(alpm_list_find_str(alpm_pkg_get_files(dbpkg),dir)) { + _alpm_log(PM_LOG_DEBUG, "check if all files in %s belongs to %s\n", + dir, dbpkg->name); + resolved_conflict = dir_belongsto_pkg(filestr, dbpkg); + } + free(dir); + } + if(!resolved_conflict) { _alpm_log(PM_LOG_DEBUG, "file found in conflict: %s\n", path); conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_FILESYSTEM, |