summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-07-05 15:11:11 -0500
committerDan McGee <dan@archlinux.org>2011-11-22 12:17:47 -0600
commit18a402d71e1efe41ced03933e439d0c253ce1a11 (patch)
treee4526ddbcdff614bb933fbf5d437f08cbbf4614c
parent96b3ba3470f11842312e4fdb34b74b391842fc33 (diff)
downloadpacman-dir-ownership.tar.gz
pacman-dir-ownership.zip
Allow checking ownership of directoriesdir-ownership
We have had this restriction in place for a while, but we do in fact have directory entries in all of our filelists. Allow passing a directory to the -Qo operation, with the knowledge that you might get multiple results returned for a given directory, for example: Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--src/pacman/query.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/src/pacman/query.c b/src/pacman/query.c
index 4c2ea817..b80799e9 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -115,6 +115,7 @@ static int query_fileowner(alpm_list_t *targets)
size_t rootlen;
alpm_list_t *t;
alpm_db_t *db_local;
+ alpm_list_t *packages;
/* This code is here for safety only */
if(targets == NULL) {
@@ -135,15 +136,21 @@ static int query_fileowner(alpm_list_t *targets)
strcpy(path, root);
db_local = alpm_option_get_localdb(config->handle);
+ packages = alpm_db_get_pkgcache(db_local);
for(t = targets; t; t = alpm_list_next(t)) {
char *filename, *dname, *rpath;
const char *bname;
+ size_t len, bname_len;
struct stat buf;
alpm_list_t *i;
- int found = 0;
+ int found = 0, isdir;
filename = strdup(t->data);
+ len = strlen(filename);
+ if(len != 0 && filename[len - 1] == '/') {
+ filename[len - 1] = '\0';
+ }
if(lstat(filename, &buf) == -1) {
/* if it is not a path but a program name, then check in PATH */
@@ -164,16 +171,11 @@ static int query_fileowner(alpm_list_t *targets)
}
}
- if(S_ISDIR(buf.st_mode)) {
- pm_printf(ALPM_LOG_ERROR,
- _("cannot determine ownership of directory '%s'\n"), filename);
- ret++;
- free(filename);
- continue;
- }
-
+ isdir = S_ISDIR(buf.st_mode);
bname = mbasename(filename);
+ bname_len = strlen(bname);
dname = mdirname(filename);
+
/* for files in '/', there is no directory name to match */
if(strcmp(dname, "") == 0) {
rpath = NULL;
@@ -185,14 +187,13 @@ static int query_fileowner(alpm_list_t *targets)
filename, strerror(errno));
free(filename);
free(dname);
- free(rpath);
ret++;
continue;
}
}
free(dname);
- for(i = alpm_db_get_pkgcache(db_local); i && !found; i = alpm_list_next(i)) {
+ for(i = packages; i && (!found || isdir); i = alpm_list_next(i)) {
alpm_pkg_t *info = i->data;
alpm_filelist_t *filelist = alpm_pkg_get_files(info);
size_t j;
@@ -201,17 +202,33 @@ static int query_fileowner(alpm_list_t *targets)
const alpm_file_t *file = filelist->files + j;
char *ppath, *pdname;
const char *pkgfile = file->name;
+ size_t pkgfile_len = strlen(pkgfile);
- /* avoid the costly resolve_path usage if the basenames don't match */
- if(strcmp(mbasename(pkgfile), bname) != 0) {
+ /* avoid the costly resolve_path usage if the basenames don't match;
+ * we can also cheat by comparing the final characters first and avoid
+ * a full string comparison */
+ if(!isdir && (pkgfile[pkgfile_len - 1] != bname[bname_len - 1] ||
+ strcmp(mbasename(pkgfile), bname) != 0)) {
continue;
+ } else if(isdir) {
+ const char *pkgfile_bname;
+ /* database path will have the trailing slash */
+ if(pkgfile_len - 2 < bname_len || pkgfile[pkgfile_len - 1] != '/' ||
+ pkgfile[pkgfile_len - bname_len - 2] != '/') {
+ continue;
+ }
+ /* we have a directory, so compare only the final directory portion */
+ pkgfile_bname = pkgfile + pkgfile_len - bname_len - 1;
+ if(strncmp(bname, pkgfile_bname, bname_len) != 0) {
+ continue;
+ }
}
/* for files in '/', there is no directory name to match */
if(!rpath) {
print_query_fileowner(filename, info);
found = 1;
- continue;
+ break;
}
if(rootlen + 1 + strlen(pkgfile) > PATH_MAX) {
@@ -219,6 +236,9 @@ static int query_fileowner(alpm_list_t *targets)
}
/* concatenate our file and the root path */
strcpy(path + rootlen, pkgfile);
+ if(pkgfile_len != 0 && path[rootlen + pkgfile_len - 1] == '/') {
+ path[rootlen + pkgfile_len - 1] = '\0';
+ }
pdname = mdirname(path);
ppath = resolve_path(pdname);
@@ -227,6 +247,8 @@ static int query_fileowner(alpm_list_t *targets)
if(ppath && strcmp(ppath, rpath) == 0) {
print_query_fileowner(filename, info);
found = 1;
+ free(ppath);
+ break;
}
free(ppath);
}