コード例 #1
0
ファイル: paccheck.c プロジェクト: andrewgregory/pacutils
static int check_sha256sum(alpm_pkg_t *pkg)
{
	int ret = 0;
	char path[PATH_MAX], *rel;
	pu_mtree_reader_t *reader;
	pu_mtree_t *m;

	if((reader = pu_mtree_reader_open_package(handle, pkg)) == NULL) {
		pu_ui_warn("%s: mtree data not available (%s)",
				alpm_pkg_get_name(pkg), strerror(errno));
		return require_mtree;
	}

	strcpy(path, alpm_option_get_root(handle));
	rel = path + strlen(alpm_option_get_root(handle));

	if((m = pu_mtree_new()) == NULL) {
		pu_ui_warn("%s: error reading mtree data (%s)",
				alpm_pkg_get_name(pkg), strerror(errno));
		pu_mtree_reader_free(reader);
		return require_mtree;
	}

	while(pu_mtree_reader_next(reader, m)) {
		char *sha;
		if(m->sha256digest[0] == '\0') { continue; }
		if(m->path[0] == '.') { continue; }
		if(skip_backups && match_backup(pkg, m->path)) { continue; }
		if(skip_noextract && match_noextract(handle, m->path)) { continue; }
		if(skip_noupgrade && match_noupgrade(handle, m->path)) { continue; }

		strcpy(rel, m->path);
		if((sha = alpm_compute_sha256sum(path)) == NULL) {
			pu_ui_warn("%s: '%s' read error (%s)",
					alpm_pkg_get_name(pkg), path, strerror(errno));
		} else if(memcmp(m->sha256digest, sha, 32) != 0) {
			eprintf("%s: '%s' sha256sum mismatch (expected %s)\n",
					alpm_pkg_get_name(pkg), path, m->sha256digest);
			ret = 1;
		}
		free(sha);
	}
	pu_mtree_free(m);

	if(!reader->eof) {
		pu_ui_warn("%s: error reading mtree data (%s)",
				alpm_pkg_get_name(pkg), strerror(errno));
		pu_mtree_reader_free(reader);
		return ret || require_mtree;
	}
	pu_mtree_reader_free(reader);

	if(!quiet && !ret) {
		eprintf("%s: all files match mtree sha256sums\n", alpm_pkg_get_name(pkg));
	}

	return ret;
}
コード例 #2
0
ファイル: main.c プロジェクト: Quintus/ruby-alpm
/**
 * call-seq:
 *   root() → a_string
 *
 * Returns the target path to install packages under.
 */
static VALUE root(VALUE self)
{
  alpm_handle_t* p_alpm = NULL;
  Data_Get_Struct(self, alpm_handle_t, p_alpm);

  return rb_str_new2(alpm_option_get_root(p_alpm));
}
コード例 #3
0
ファイル: check.c プロジェクト: andrewgregory/pacman
/* Loop through the files of the package to check if they exist. */
int check_pkg_fast(alpm_pkg_t *pkg)
{
	const char *root, *pkgname;
	size_t errors = 0;
	size_t rootlen;
	char filepath[PATH_MAX];
	alpm_filelist_t *filelist;
	size_t i;

	root = alpm_option_get_root(config->handle);
	rootlen = strlen(root);
	if(rootlen + 1 > PATH_MAX) {
		/* we are in trouble here */
		pm_printf(ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, "");
		return 1;
	}
	strcpy(filepath, root);

	pkgname = alpm_pkg_get_name(pkg);
	filelist = alpm_pkg_get_files(pkg);
	for(i = 0; i < filelist->count; i++) {
		const alpm_file_t *file = filelist->files + i;
		struct stat st;
		int exists;
		const char *path = file->name;
		size_t plen = strlen(path);

		if(rootlen + 1 + plen > PATH_MAX) {
			pm_printf(ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path);
			continue;
		}
		strcpy(filepath + rootlen, path);

		exists = check_file_exists(pkgname, filepath, rootlen, &st);
		if(exists == 0) {
			int expect_dir = path[plen - 1] == '/' ? 1 : 0;
			int is_dir = S_ISDIR(st.st_mode) ? 1 : 0;
			if(expect_dir != is_dir) {
				pm_printf(ALPM_LOG_WARNING, _("%s: %s (File type mismatch)\n"),
						pkgname, filepath);
				++errors;
			}
		} else if(exists == 1) {
			++errors;
		}
	}

	if(!config->quiet) {
		printf(_n("%s: %jd total file, ", "%s: %jd total files, ",
					(unsigned long)filelist->count), pkgname, (intmax_t)filelist->count);
		printf(_n("%jd missing file\n", "%jd missing files\n",
					(unsigned long)errors), (intmax_t)errors);
	}

	return (errors != 0 ? 1 : 0);
}
コード例 #4
0
ファイル: query.c プロジェクト: moben/pacman
/* Loop through the packages. For each package,
 * loop through files to check if they exist. */
static int check(alpm_pkg_t *pkg)
{
	const char *root, *pkgname;
	size_t errors = 0;
	size_t rootlen;
	char f[PATH_MAX];
	alpm_filelist_t *filelist;
	size_t i;

	root = alpm_option_get_root(config->handle);
	rootlen = strlen(root);
	if(rootlen + 1 > PATH_MAX) {
		/* we are in trouble here */
		pm_fprintf(stderr, ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, "");
		return 1;
	}
	strcpy(f, root);

	pkgname = alpm_pkg_get_name(pkg);
	filelist = alpm_pkg_get_files(pkg);
	for(i = 0; i < filelist->count; i++) {
		const alpm_file_t *file = filelist->files + i;
		struct stat st;
		const char *path = file->name;

		if(rootlen + 1 + strlen(path) > PATH_MAX) {
			pm_fprintf(stderr, ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path);
			continue;
		}
		strcpy(f + rootlen, path);
		/* use lstat to prevent errors from symlinks */
		if(lstat(f, &st) != 0) {
			if(config->quiet) {
				printf("%s %s\n", pkgname, f);
			} else {
				pm_printf(ALPM_LOG_WARNING, "%s: %s (%s)\n",
						pkgname, f, strerror(errno));
			}
			errors++;
		}
	}

	if(!config->quiet) {
		printf(_n("%s: %jd total file, ", "%s: %jd total files, ",
					(unsigned long)filelist->count), pkgname, (intmax_t)filelist->count);
		printf(_n("%jd missing file\n", "%jd missing files\n",
					(unsigned long)errors), (intmax_t)errors);
	}

	return (errors != 0 ? 1 : 0);
}
コード例 #5
0
ファイル: main.c プロジェクト: Quintus/ruby-alpm
/**
 * call-seq:
 *   inspect()  → a_string
 *
 * Human-readable description.
 */
static VALUE inspect(VALUE self)
{
  alpm_handle_t* p_alpm = NULL;
  char buf[256];
  int len;

  Data_Get_Struct(self, alpm_handle_t, p_alpm);

  len = sprintf(buf, "#<%s target=%s db=%s>",
                rb_obj_classname(self),
                alpm_option_get_root(p_alpm),
                alpm_option_get_dbpath(p_alpm));

  return rb_str_new(buf, len);
}
コード例 #6
0
static gboolean
pk_backend_get_files_thread (PkBackend *self)
{
	gchar **packages;
	GError *error = NULL;

	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (alpm != NULL, FALSE);

	packages = pk_backend_get_strv (self, "package_ids");

	g_return_val_if_fail (packages != NULL, FALSE);

	for (; *packages != NULL; ++packages) {
		alpm_pkg_t *pkg;
		const gchar *root;

		GString *files;
		alpm_filelist_t *filelist;
		gsize i;

		if (pk_backend_cancelled (self)) {
			break;
		}

		pkg = pk_backend_find_pkg (self, *packages, &error);
		if (pkg == NULL) {
			break;
		}

		root = alpm_option_get_root (alpm);
		files = g_string_new ("");

		filelist = alpm_pkg_get_files (pkg);
		for (i = 0; i < filelist->count; ++i) {
			const gchar *file = filelist->files[i].name;
			g_string_append_printf (files, "%s%s;", root, file);
		}

		g_string_truncate (files, MAX (files->len, 1) - 1);
		pk_backend_job_files (self, *packages, files->str);
		g_string_free (files, TRUE);
	}

	return pk_backend_finish (self, error);
}
コード例 #7
0
ファイル: check.c プロジェクト: cicero-arpini/pacman
/* Loop through the files of the package to check if they exist. */
int check_pkg_fast(alpm_pkg_t *pkg)
{
	const char *root, *pkgname;
	size_t errors = 0;
	size_t rootlen;
	char filepath[PATH_MAX];
	alpm_filelist_t *filelist;
	size_t i;

	root = alpm_option_get_root(config->handle);
	rootlen = strlen(root);
	if(rootlen + 1 > PATH_MAX) {
		/* we are in trouble here */
		pm_printf(ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, "");
		return 1;
	}
	strcpy(filepath, root);

	pkgname = alpm_pkg_get_name(pkg);
	filelist = alpm_pkg_get_files(pkg);
	for(i = 0; i < filelist->count; i++) {
		const alpm_file_t *file = filelist->files + i;
		struct stat st;
		const char *path = file->name;

		if(rootlen + 1 + strlen(path) > PATH_MAX) {
			pm_printf(ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path);
			continue;
		}
		strcpy(filepath + rootlen, path);

		errors += check_file_exists(pkgname, filepath, &st);
	}

	if(!config->quiet) {
		printf(_n("%s: %jd total file, ", "%s: %jd total files, ",
					(unsigned long)filelist->count), pkgname, (intmax_t)filelist->count);
		printf(_n("%jd missing file\n", "%jd missing files\n",
					(unsigned long)errors), (intmax_t)errors);
	}

	return (errors != 0 ? 1 : 0);
}
コード例 #8
0
ファイル: paccheck.c プロジェクト: andrewgregory/pacutils
/* verify that the filesystem matches the package database */
static int check_files(alpm_pkg_t *pkg)
{
	alpm_filelist_t *filelist = alpm_pkg_get_files(pkg);
	char path[PATH_MAX], *rel;
	const char *pkgname = alpm_pkg_get_name(pkg);
	unsigned int i;
	int ret = 0;
	size_t space;

	strncpy(path, alpm_option_get_root(handle), PATH_MAX);
	rel = path + strlen(path);
	space = PATH_MAX - (rel - path);

	for(i = 0; i < filelist->count; ++i) {
		alpm_file_t file = filelist->files[i];
		int isdir = 0;
		size_t len;

		if(skip_noextract && match_noextract(handle, file.name)) { continue; }

		strncpy(rel, file.name, space);
		len = strlen(file.name);
		if(rel[len - 1] == '/') {
			isdir = 1;
			rel[len - 1] = '\0';
		}

		if(check_file(pkgname, path, isdir) != 0) { ret = 1; }
	}

	if(include_db_files && check_db_files(pkg) != 0) {
		ret = 1;
	}

	if(!quiet && !ret) {
		eprintf("%s: all files match database\n", alpm_pkg_get_name(pkg));
	}

	return ret;
}
コード例 #9
0
ファイル: package.c プロジェクト: gtmanfred/pacman
/* Display list of backup files and their modification states
 */
void dump_pkg_backups(alpm_pkg_t *pkg)
{
    alpm_list_t *i;
    const char *root = alpm_option_get_root(config->handle);
    printf("%s%s%s", config->colstr.title, _("Backup Files:\n"),
           config->colstr.nocolor);
    if(alpm_pkg_get_backup(pkg)) {
        /* package has backup files, so print them */
        for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) {
            const alpm_backup_t *backup = i->data;
            const char *value;
            if(!backup->hash) {
                continue;
            }
            value = get_backup_file_status(root, backup);
            printf("%s\t%s%s\n", value, root, backup->name);
        }
    } else {
        /* package had no backup files */
        printf(_("(none)\n"));
    }
}
コード例 #10
0
ファイル: pk-alpm-search.c プロジェクト: klusark/PackageKit
static gpointer
pk_backend_pattern_chroot (PkBackend *backend, const gchar *needle, GError **error)
{
	PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);
	g_return_val_if_fail (needle != NULL, NULL);

	if (G_IS_DIR_SEPARATOR (*needle)) {
		const gchar *file = needle, *root = alpm_option_get_root (priv->alpm);

		/* adjust needle to the correct prefix */
		for (; *file == *root; ++file, ++root) {
			if (*root == '\0') {
				needle = file - 1;
				break;
			} else if (*file == '\0') {
				break;
			}
		}
	}

	return (gpointer) needle;
}
コード例 #11
0
ファイル: package.c プロジェクト: gtmanfred/pacman
/* List all files contained in a package
 */
void dump_pkg_files(alpm_pkg_t *pkg, int quiet)
{
    const char *pkgname, *root;
    alpm_filelist_t *pkgfiles;
    size_t i;

    pkgname = alpm_pkg_get_name(pkg);
    pkgfiles = alpm_pkg_get_files(pkg);
    root = alpm_option_get_root(config->handle);

    for(i = 0; i < pkgfiles->count; i++) {
        const alpm_file_t *file = pkgfiles->files + i;
        /* Regular: '<pkgname> <root><filepath>\n'
         * Quiet  : '<root><filepath>\n'
         */
        if(!quiet) {
            printf("%s%s%s ", config->colstr.title, pkgname, config->colstr.nocolor);
        }
        printf("%s%s\n", root, file->name);
    }

    fflush(stdout);
}
コード例 #12
0
ファイル: check.c プロジェクト: cicero-arpini/pacman
/* Loop though files in a package and perform full file property checking. */
int check_pkg_full(alpm_pkg_t *pkg)
{
	const char *root, *pkgname;
	size_t errors = 0;
	size_t rootlen;
	char filepath[PATH_MAX];
	struct archive *mtree;
	struct archive_entry *entry = NULL;
	size_t file_count = 0;
	const alpm_list_t *lp;

	root = alpm_option_get_root(config->handle);
	rootlen = strlen(root);
	if(rootlen + 1 > PATH_MAX) {
		/* we are in trouble here */
		pm_printf(ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, "");
		return 1;
	}
	strcpy(filepath, root);

	pkgname = alpm_pkg_get_name(pkg);
	mtree = alpm_pkg_mtree_open(pkg);
	if(mtree == NULL) {
		/* TODO: check error to confirm failure due to no mtree file */
		if(!config->quiet) {
			printf(_("%s: no mtree file\n"), pkgname);
		}
		return 0;
	}

	while(alpm_pkg_mtree_next(pkg, mtree, &entry) == ARCHIVE_OK) {
		struct stat st;
		const char *path = archive_entry_pathname(entry);
		mode_t type;
		size_t file_errors = 0;
		int backup = 0;

		/* strip leading "./" from path entries */
		if(path[0] == '.' && path[1] == '/') {
			path += 2;
		}

		if(strcmp(path, ".INSTALL") == 0) {
			char filename[PATH_MAX];
			snprintf(filename, PATH_MAX, "%slocal/%s-%s/install",
					alpm_option_get_dbpath(config->handle) + 1,
					pkgname, alpm_pkg_get_version(pkg));
			archive_entry_set_pathname(entry, filename);
			path = archive_entry_pathname(entry);
		} else if(strcmp(path, ".CHANGELOG") == 0) {
			char filename[PATH_MAX];
			snprintf(filename, PATH_MAX, "%slocal/%s-%s/changelog",
					alpm_option_get_dbpath(config->handle) + 1,
					pkgname, alpm_pkg_get_version(pkg));
			archive_entry_set_pathname(entry, filename);
			path = archive_entry_pathname(entry);
		} else if(*path == '.') {
			continue;
		}

		file_count++;

		if(rootlen + 1 + strlen(path) > PATH_MAX) {
			pm_printf(ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path);
			continue;
		}
		strcpy(filepath + rootlen, path);

		if(check_file_exists(pkgname, filepath, &st) == 1) {
			errors++;
			continue;
		}

		type = archive_entry_filetype(entry);

		if(type != AE_IFDIR && type != AE_IFREG && type != AE_IFLNK) {
			pm_printf(ALPM_LOG_WARNING, _("file type not recognized: %s%s\n"), root, path);
			continue;
		}

		if(check_file_type(pkgname, filepath, &st, entry) == 1) {
			errors++;
			continue;
		}

		file_errors += check_file_permissions(pkgname, filepath, &st, entry);

		if(type == AE_IFLNK) {
			file_errors += check_file_link(pkgname, filepath, &st, entry);
		}

		/* the following checks are expected to fail if a backup file has been
		   modified */
		for(lp = alpm_pkg_get_backup(pkg); lp; lp = lp->next) {
			alpm_backup_t *bl = lp->data;

			if(strcmp(path, bl->name) == 0) {
				backup = 1;
				break;
			}
		}

		if(type != AE_IFDIR) {
			/* file or symbolic link */
			file_errors += check_file_time(pkgname, filepath, &st, entry, backup);
		}

		if(type == AE_IFREG) {
			/* TODO: these are expected to be changed with backup files */
			file_errors += check_file_size(pkgname, filepath, &st, entry, backup);
			/* file_errors += check_file_md5sum(pkgname, filepath, &st, entry, backup); */
		}

		if(config->quiet && file_errors) {
			printf("%s %s\n", pkgname, filepath);
		}

		errors += (file_errors != 0 ? 1 : 0);
	}

	alpm_pkg_mtree_close(pkg, mtree);

	if(!config->quiet) {
		printf(_n("%s: %jd total file, ", "%s: %jd total files, ",
					(unsigned long)file_count), pkgname, (intmax_t)file_count);
		printf(_n("%jd altered file\n", "%jd altered files\n",
					(unsigned long)errors), (intmax_t)errors);
	}

	return (errors != 0 ? 1 : 0);
}
コード例 #13
0
ファイル: paccheck.c プロジェクト: andrewgregory/pacutils
/* check filesystem against extra mtree data if available,
 * NOT guaranteed to catch db/filesystem discrepencies */
static int check_file_properties(alpm_pkg_t *pkg)
{
	char path[PATH_MAX], *rel;
	int ret = 0;
	size_t space;
	struct archive *mtree = alpm_pkg_mtree_open(pkg);
	struct archive_entry *entry;

	if(!mtree) {
		pu_ui_warn("%s: mtree data not available (%s)",
				alpm_pkg_get_name(pkg), strerror(errno));
		return require_mtree;
	}

	strncpy(path, alpm_option_get_root(handle), PATH_MAX);
	rel = path + strlen(path);
	space = PATH_MAX - (rel - path);

	while(alpm_pkg_mtree_next(pkg, mtree, &entry) == ARCHIVE_OK) {
		const char *ppath = archive_entry_pathname(entry);
		const char *fpath;
		struct stat buf;

		if(strncmp("./", ppath, 2) == 0) { ppath += 2; }

		if(strcmp(ppath, ".INSTALL") == 0) {
			if((fpath = get_db_path(pkg, "install")) == NULL) {
				continue;
			}
		} else if(strcmp(ppath, ".CHANGELOG") == 0) {
			if((fpath = get_db_path(pkg, "changelog")) == NULL) {
				continue;
			}
		} else if(ppath[0] == '.') {
			continue;
		} else if(skip_noextract && match_noextract(handle, ppath)) {
			continue;
		} else {
			strncpy(rel, ppath, space);
			fpath = path;
		}

		if(lstat(fpath, &buf) != 0) {
			if(errno == ENOENT) {
				eprintf("%s: '%s' missing file\n", alpm_pkg_get_name(pkg), fpath);
			} else {
				pu_ui_warn("%s: '%s' read error (%s)",
						alpm_pkg_get_name(pkg), fpath, strerror(errno));
			}
			ret = 1;
			continue;
		}

		if(cmp_type(pkg, fpath, entry, &buf) != 0) { ret = 1; }

		if(skip_noupgrade && match_noupgrade(handle, ppath)) { continue; }

		if(cmp_mode(pkg, fpath, entry, &buf) != 0) { ret = 1; }
		if(cmp_uid(pkg, fpath, entry, &buf) != 0) { ret = 1; }
		if(cmp_gid(pkg, fpath, entry, &buf) != 0) { ret = 1; }

		if(skip_backups && match_backup(pkg, ppath)) {
			continue;
		}

		if(S_ISLNK(buf.st_mode) && S_ISLNK(archive_entry_mode(entry))) {
			if(cmp_target(pkg, fpath, entry) != 0) { ret = 1; }
		}
		if(!S_ISDIR(buf.st_mode)) {
			if(cmp_mtime(pkg, fpath, entry, &buf) != 0) { ret = 1; }
			if(!S_ISLNK(buf.st_mode)) {
				/* always fails for directories and symlinks */
				if(cmp_size(pkg, fpath, entry, &buf) != 0) { ret = 1; }
			}
		}
	}
	alpm_pkg_mtree_close(pkg, mtree);

	if(!quiet && !ret) {
		eprintf("%s: all files match mtree\n", alpm_pkg_get_name(pkg));
	}

	return ret;
}
コード例 #14
0
/**
 * pacman_manager_get_root_path:
 * @manager: A #PacmanManager.
 *
 * Gets the directory that pacman will use as the root filesystem.
 *
 * Returns: A directory name. Do not free.
 */
const gchar *pacman_manager_get_root_path (PacmanManager *manager) {
	g_return_val_if_fail (manager != NULL, NULL);
	
	return alpm_option_get_root ();
}
コード例 #15
0
ファイル: query.c プロジェクト: moben/pacman
static int query_fileowner(alpm_list_t *targets)
{
	int ret = 0;
	char path[PATH_MAX];
	const char *root;
	size_t rootlen;
	alpm_list_t *t;
	alpm_db_t *db_local;

	/* This code is here for safety only */
	if(targets == NULL) {
		pm_fprintf(stderr, ALPM_LOG_ERROR, _("no file was specified for --owns\n"));
		return 1;
	}

	/* Set up our root path buffer. We only need to copy the location of root in
	 * once, then we can just overwrite whatever file was there on the previous
	 * iteration. */
	root = alpm_option_get_root(config->handle);
	rootlen = strlen(root);
	if(rootlen + 1 > PATH_MAX) {
		/* we are in trouble here */
		pm_fprintf(stderr, ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, "");
		return 1;
	}
	strcpy(path, root);

	db_local = alpm_option_get_localdb(config->handle);

	for(t = targets; t; t = alpm_list_next(t)) {
		char *filename, *dname, *rpath;
		const char *bname;
		struct stat buf;
		alpm_list_t *i;
		int found = 0;

		filename = strdup(alpm_list_getdata(t));

		if(lstat(filename, &buf) == -1) {
			/*  if it is not a path but a program name, then check in PATH */
			if(strchr(filename, '/') == NULL) {
				if(search_path(&filename, &buf) == -1) {
					pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to find '%s' in PATH: %s\n"),
							filename, strerror(errno));
					ret++;
					free(filename);
					continue;
				}
			} else {
				pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to read file '%s': %s\n"),
						filename, strerror(errno));
				ret++;
				free(filename);
				continue;
			}
		}

		if(S_ISDIR(buf.st_mode)) {
			pm_fprintf(stderr, ALPM_LOG_ERROR,
				_("cannot determine ownership of directory '%s'\n"), filename);
			ret++;
			free(filename);
			continue;
		}

		bname = mbasename(filename);
		dname = mdirname(filename);
		/* for files in '/', there is no directory name to match */
		if(strcmp(dname, "") == 0) {
			rpath = NULL;
		} else {
			rpath = resolve_path(dname);

			if(!rpath) {
				pm_fprintf(stderr, ALPM_LOG_ERROR, _("cannot determine real path for '%s': %s\n"),
						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)) {
			alpm_pkg_t *info = alpm_list_getdata(i);
			alpm_filelist_t *filelist = alpm_pkg_get_files(info);
			size_t j;

			for(j = 0; j < filelist->count; j++) {
				const alpm_file_t *file = filelist->files + j;
				char *ppath, *pdname;
				const char *pkgfile = file->name;

				/* avoid the costly resolve_path usage if the basenames don't match */
				if(strcmp(mbasename(pkgfile), bname) != 0) {
					continue;
				}

				/* for files in '/', there is no directory name to match */
				if(!rpath) {
					print_query_fileowner(filename, info);
					found = 1;
					continue;
				}

				if(rootlen + 1 + strlen(pkgfile) > PATH_MAX) {
					pm_fprintf(stderr, ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, pkgfile);
				}
				/* concatenate our file and the root path */
				strcpy(path + rootlen, pkgfile);

				pdname = mdirname(path);
				ppath = resolve_path(pdname);
				free(pdname);

				if(ppath && strcmp(ppath, rpath) == 0) {
					print_query_fileowner(filename, info);
					found = 1;
				}
				free(ppath);
			}
		}
		if(!found) {
			pm_fprintf(stderr, ALPM_LOG_ERROR, _("No package owns %s\n"), filename);
			ret++;
		}
		free(filename);
		free(rpath);
	}

	return ret;
}