1
0
forked from mirrors/pacman

Compare commits

...

9 Commits

Author SHA1 Message Date
morganamilo
2b4c022925 libalpm: add iterator interface for syncdb files
This commit adds an iterator interface for reading files from the
syncdbs. Instead of using alpm_pkg_get_files(), you now get the files
from the database using alpm_db_files_open(), you then use
alpm_db_files_next() to iterate through the files for each package. If
you want to actually load the files from that package you then use
alpm_db_files_load().

This means alpm_pkg_get_files() will always return empty for syncdbs,
even on .files databases, however these functions still work on the
localdb and loaded packages.

This aproach is faster when dumping the entire file list but slower when
searching for a specific package.

The memory usage of pacman is drastically less. See below.

build/pacman -Fl        0.55s user 0.01s system 99% cpu 0.556 total
build/pacman -Fl pacman 0.46s user 0.01s system 99% cpu 0.472 total
build/pacman -Fx pacman 2.88s user 0.09s system 99% cpu 2.965 total

pacman -Fl              1.60s user 0.13s system 99% cpu 1.731 total
pacman -Fl pacman       0.24s user 0.04s system 99% cpu 0.283 total
pacman -Fx pacman       2.45s user 0.14s system 99% cpu 2.593 total

                         Peak Memory
build/pacman -Fl         43.52MB
build/pacman -Fl pacmam  11.292MB

pacman -Fl               677.048MB
pacman -Fl pacman        163.288MB
2021-10-06 08:18:55 +01:00
Allan McRae
39c3cbdf56 _alpm_key_import: Initialise fetch_key
Prevents build warning.

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-05 09:58:18 +10:00
morganamilo
165e492485 pacman: don't run hooks when using --dbonly
--dbonly is meant to only touch the database and not the actual system.
However hooks still run which can leave files in place or run commands
you may not want.

The hooks being run also means `fakeroot pacman -S --dbpath test/ foo --dbonly`
fails because alpm tries to chroot for hooks which requires real root.

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-04 20:46:57 +10:00
morganamilo
be76f8bf06 libalpm: add ALPM_TRANS_FLAG_NOHOOKS
Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-04 20:46:47 +10:00
morganamilo
625f3d645b libalpm: don't use alpm_pgpkey_t in import question
When constructing an import question we never really used a proper gpg
key. We just zero initialize the key, set the uid and fingerprint, and
sent that to the front end.

Instead lets just give the import question a uid and fingerprint field.

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-04 20:43:16 +10:00
morganamilo
e187aa9b48 libalpm: use else when setting fingerprint
The docs [1] say keyid will always be there, so no need to check if it
exists.

[1] https://www.gnupg.org/documentation/manuals/gpgme/Key-objects.html

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-04 19:52:23 +10:00
morganamilo
c5c6633dd1 libalpm: rename __foo tyes to _foo
__foo is reserved in c and should not be used.

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-04 19:52:23 +10:00
morganamilo
2109de613a libalpm: take alpm_trans_t out of the public API
this type is only used internally by alpm

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-04 19:52:23 +10:00
Allan McRae
fbb29b5047 repo-add: add --include-sigs option
Pacman now downloads the signature files for all packages when present in a
repository.  That makes distributing signatures within repository databases
redundant and costly.

Do not distribute the package signature files within the repo databases by
default and add an --include-sigs to revert to the old behaviour.

Signed-off-by: Allan McRae <allan@archlinux.org>
2021-09-04 19:52:23 +10:00
20 changed files with 390 additions and 156 deletions

View File

@@ -70,6 +70,8 @@ repo-add Options
Remove old package files from the disk when updating their entry in the
database.
*\--include-sigs*::
Include package PGP signatures in the repository database (if available)
Example
-------

View File

@@ -78,7 +78,7 @@ extern "C" {
* This struct represents an instance of libalpm.
* @ingroup libalpm_handle
*/
typedef struct __alpm_handle_t alpm_handle_t;
typedef struct _alpm_handle_t alpm_handle_t;
/** A database.
*
@@ -98,9 +98,14 @@ typedef struct __alpm_handle_t alpm_handle_t;
* Databases are automatically unregistered when the \link alpm_handle_t \endlink is released.
* @ingroup libalpm_databases
*/
typedef struct __alpm_db_t alpm_db_t;
typedef struct _alpm_db_t alpm_db_t;
/** A Database file iterator
* @ingroup libalpm_databases
*/
typedef struct __alpm_db_files_t alpm_db_files_t;
/** A package.
*
* A package can be loaded from disk via \link alpm_pkg_load \endlink or retrieved from a database.
@@ -111,13 +116,7 @@ typedef struct __alpm_db_t alpm_db_t;
* to be added or removed from the system.
* @ingroup libalpm_packages
*/
typedef struct __alpm_pkg_t alpm_pkg_t;
/** Transaction structure used internally by libalpm
* @ingroup libalpm_trans
* */
typedef struct __alpm_trans_t alpm_trans_t;
typedef struct _alpm_pkg_t alpm_pkg_t;
/** The time type used by libalpm. Represents a unix time stamp
* @ingroup libalpm_misc */
@@ -164,6 +163,9 @@ typedef struct _alpm_backup_t {
*/
alpm_file_t *alpm_filelist_contains(alpm_filelist_t *filelist, const char *path);
/** Frees a file list */
void alpm_filelist_free(alpm_filelist_t *files);
/* End of libalpm_files */
/** @} */
@@ -1080,8 +1082,10 @@ typedef struct _alpm_question_import_key_t {
alpm_question_type_t type;
/** Answer: whether or not to import key */
int import;
/** The key to import */
alpm_pgpkey_t *key;
/** UID of the key to import */
const char *uid;
/** Fingerprint the key to import */
const char *fingerprint;
} alpm_question_import_key_t;
/**
@@ -1448,6 +1452,42 @@ int alpm_db_get_usage(alpm_db_t *db, int *usage);
/* End of usage accessors */
/** @} */
/** @name File iterators
* @{
*/
/** Opens a handle to the db files iterator.
* @param db the db files to iterate over
* @return handle to the iterator
*/
alpm_db_files_t *alpm_db_files_open(alpm_db_t *db);
/** Goes to the next package.
* @param files handle to the file iterator
* @param pkgname stores the pkgname of the current package
* @return 0 on success, 1 if end of iterator, -1 on error
*/
int alpm_db_files_next(alpm_db_files_t *files, char** pkgname);
/** Loads the files for a package into a file list.
*
* This extends the file list as needed, reusing the memory alloced.
* You can reuse the same file list for calls to this function but
* the list should be freed with \link alpm_filelist_free alpm_filelist_free \endlink
* after use.
* @param files handle to the file iterator
* @param filelist the filelist to load files into
* @return 0 on success, -1 on error
*/
int alpm_db_files_load(alpm_db_files_t *files, alpm_filelist_t *filelist);
/** Close the db file iterator
* @param files handle to the file iterator
*/
void alpm_db_files_close(alpm_db_files_t *files);
/* End of file iterators */
/** @} */
/* End of libalpm_databases */
/** @} */
@@ -2682,7 +2722,6 @@ int alpm_pkg_mtree_close(const alpm_pkg_t *pkg, struct archive *archive);
/* End of mtree accessors */
/** @} */
/* End of libalpm_packages */
/** @} */
@@ -2719,7 +2758,8 @@ typedef enum _alpm_transflag_t {
ALPM_TRANS_FLAG_RECURSE = (1 << 5),
/** Modify database but do not commit changes to the filesystem. */
ALPM_TRANS_FLAG_DBONLY = (1 << 6),
/* (1 << 7) flag can go here */
/** Do not run hooks during a transaction */
ALPM_TRANS_FLAG_NOHOOKS = (1 << 7),
/** Use ALPM_PKG_REASON_DEPEND when installing packages. */
ALPM_TRANS_FLAG_ALLDEPS = (1 << 8),
/** Only download packages and do not actually install. */

View File

@@ -48,13 +48,13 @@ extern "C" {
*/
/** A doubly linked list */
typedef struct __alpm_list_t {
typedef struct _alpm_list_t {
/** data held by the list node */
void *data;
/** pointer to the previous node */
struct __alpm_list_t *prev;
struct _alpm_list_t *prev;
/** pointer to the next node */
struct __alpm_list_t *next;
struct _alpm_list_t *next;
} alpm_list_t;
/** Frees a list and its contents */

View File

@@ -566,8 +566,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
return 0;
}
if(strcmp(filename, "desc") == 0 || strcmp(filename, "depends") == 0
|| strcmp(filename, "files") == 0) {
if(strcmp(filename, "desc") == 0 || strcmp(filename, "depends") == 0) {
int ret;
while((ret = _alpm_archive_fgets(archive, &buf)) == ARCHIVE_OK) {
char *line = buf.line;
@@ -636,36 +635,6 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
READ_AND_SPLITDEP(pkg->conflicts);
} else if(strcmp(line, "%PROVIDES%") == 0) {
READ_AND_SPLITDEP(pkg->provides);
} else if(strcmp(line, "%FILES%") == 0) {
/* TODO: this could lazy load if there is future demand */
size_t files_count = 0, files_size = 0;
alpm_file_t *files = NULL;
while(1) {
if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) {
goto error;
}
line = buf.line;
if(_alpm_strip_newline(line, buf.real_line_size) == 0) {
break;
}
if(!_alpm_greedy_grow((void **)&files, &files_size,
(files_count ? (files_count + 1) * sizeof(alpm_file_t) : 8 * sizeof(alpm_file_t)))) {
goto error;
}
STRDUP(files[files_count].name, line, goto error);
files_count++;
}
/* attempt to hand back any memory we don't need */
if(files_count > 0) {
REALLOC(files, sizeof(alpm_file_t) * files_count, (void)0);
} else {
FREE(files);
}
pkg->files.count = files_count;
pkg->files.files = files;
_alpm_filelist_sort(&pkg->files);
}
}
if(ret != ARCHIVE_EOF) {
@@ -716,3 +685,152 @@ alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
handle->dbs_sync = alpm_list_add(handle->dbs_sync, db);
return db;
}
static int load_files(struct archive *archive, alpm_filelist_t *filelist)
{
struct archive_read_buffer buf = {0};
/* 512K for a line length seems reasonable */
buf.max_line_size = 512 * 1024;
_alpm_filelist_truncate(filelist);
int ret;
while((ret = _alpm_archive_fgets(archive, &buf)) == ARCHIVE_OK) {
char *line = buf.line;
if(_alpm_strip_newline(line, buf.real_line_size) == 0) {
/* length of stripped line was zero */
continue;
}
if(strcmp(line, "%FILES%") == 0) {
size_t files_size = 0;
while(1) {
if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) {
goto error;
}
line = buf.line;
if(_alpm_strip_newline(line, buf.real_line_size) == 0) {
break;
}
if(!_alpm_greedy_grow((void **)&filelist->files, &files_size,
(filelist->count ? (filelist->count + 1) * sizeof(alpm_file_t) : 8 * sizeof(alpm_file_t)))) {
goto error;
}
STRDUP(filelist->files[filelist->count].name, line, goto error);
filelist->count++;
}
_alpm_filelist_sort(filelist);
}
}
if(ret != ARCHIVE_EOF) {
goto error;
}
return 0;
error:
return -1;
}
alpm_db_files_t SYMEXPORT *alpm_db_files_open(alpm_db_t *db)
{
const char *dbpath;
int fd;
struct stat buf;
struct archive *archive;
alpm_db_files_t *files = NULL;
ASSERT(db != NULL, return NULL);
dbpath = _alpm_db_path(db);
if(!dbpath) {
/* pm_errno set in _alpm_db_path() */
return NULL;
}
if(db->status & DB_STATUS_INVALID || db->status & DB_STATUS_MISSING) {
return NULL;
}
fd = _alpm_open_archive(db->handle, dbpath, &buf,
&archive, ALPM_ERR_DB_OPEN);
if(fd < 0) {
db->status &= ~DB_STATUS_VALID;
db->status |= DB_STATUS_INVALID;
_alpm_archive_read_free(archive);
return NULL;
}
MALLOC(files, sizeof(alpm_db_files_t), RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL));
files->archive = archive;
files->fd = fd;
files->db = db;
return files;
}
int SYMEXPORT alpm_db_files_next(alpm_db_files_t *files, char** pkgname)
{
struct archive_entry *entry;
const char *entryname;
int archive_ret;
char *filename;
ASSERT(files != NULL, return -1);
ASSERT(pkgname != NULL, return -1);
while((archive_ret = archive_read_next_header(files->archive, &entry)) == ARCHIVE_OK) {
mode_t mode = archive_entry_mode(entry);
if(!S_ISDIR(mode)) {
entryname = archive_entry_pathname(entry);
if(entryname == NULL) {
_alpm_log(files->db->handle, ALPM_LOG_DEBUG,
"invalid archive entry provided to alpm_db_files_next, skipping\n");
return -1;
}
if(_alpm_splitname(entryname, pkgname, NULL, NULL) != 0) {
_alpm_log(files->db->handle, ALPM_LOG_ERROR,
_("invalid name for database entry '%s'\n"), entryname);
return -1;
}
filename = strrchr(entryname, '/');
filename++;
/* we only want to read the file list */
if(filename && strcmp(filename, "files") == 0) {
return 0;
}
}
}
if(archive_ret != ARCHIVE_EOF) {
return -1;
}
return 1;
}
int SYMEXPORT alpm_db_files_load(alpm_db_files_t *files, alpm_filelist_t *filelist)
{
ASSERT(files != NULL, return -1);
ASSERT(filelist != NULL, return -1);
_alpm_filelist_truncate(filelist);
if(load_files(files->archive, filelist) != 0) {
_alpm_log(files->db->handle, ALPM_LOG_ERROR,
_("could not parse package description file '%s' from db '%s'\n"),
"files", files->db->treename);
return -1;
}
return 0;
}
void SYMEXPORT alpm_db_files_close(alpm_db_files_t *files)
{
ASSERT(files != NULL, return);
_alpm_archive_read_free(files->archive);
close(files->fd);
free(files);
}

View File

@@ -61,8 +61,15 @@ struct db_operations {
void (*unregister) (alpm_db_t *);
};
/* Database files iterator */
struct __alpm_db_files_t {
struct archive *archive;
int fd;
alpm_db_t *db;
};
/* Database */
struct __alpm_db_t {
struct _alpm_db_t {
alpm_handle_t *handle;
char *treename;
/* do not access directly, use _alpm_db_path(db) for lazy access */

View File

@@ -43,7 +43,7 @@ enum mount_fsinfo {
MOUNT_FSINFO_FAIL,
};
typedef struct __alpm_mountpoint_t {
typedef struct _alpm_mountpoint_t {
/* mount point information */
char *mount_dir;
size_t mount_dir_len;

View File

@@ -145,3 +145,17 @@ void _alpm_filelist_sort(alpm_filelist_t *filelist)
}
}
}
void _alpm_filelist_truncate(alpm_filelist_t *files)
{
for(size_t i = 0; i < files->count; i++) {
FREE(files->files[i].name);
}
files->count = 0;
}
void SYMEXPORT alpm_filelist_free(alpm_filelist_t *files)
{
_alpm_filelist_truncate(files);
free(files->files);
}

View File

@@ -28,5 +28,6 @@ alpm_list_t *_alpm_filelist_intersection(alpm_filelist_t *filesA,
alpm_filelist_t *filesB);
void _alpm_filelist_sort(alpm_filelist_t *filelist);
void _alpm_filelist_truncate(alpm_filelist_t *filelist);
#endif /* ALPM_FILELIST_H */

View File

@@ -23,19 +23,19 @@
#include "alpm_list.h"
enum __alpm_graph_vertex_state {
enum _alpm_graph_vertex_state {
ALPM_GRAPH_STATE_UNPROCESSED,
ALPM_GRAPH_STATE_PROCESSING,
ALPM_GRAPH_STATE_PROCESSED
};
typedef struct __alpm_graph_t {
typedef struct _alpm_graph_t {
void *data;
struct __alpm_graph_t *parent; /* where did we come from? */
struct _alpm_graph_t *parent; /* where did we come from? */
alpm_list_t *children;
alpm_list_t *iterator; /* used for DFS without recursion */
off_t weight; /* weight of the node */
enum __alpm_graph_vertex_state state;
enum _alpm_graph_vertex_state state;
} alpm_graph_t;
alpm_graph_t *_alpm_graph_new(void);

View File

@@ -26,6 +26,7 @@
#include "alpm_list.h"
#include "alpm.h"
#include "trans.h"
#ifdef HAVE_LIBCURL
#include <curl/curl.h>
@@ -50,7 +51,7 @@ do { \
} \
} while(0)
struct __alpm_handle_t {
struct _alpm_handle_t {
/* internal usage */
alpm_db_t *db_local; /* local db pointer */
alpm_list_t *dbs_sync; /* List of (alpm_db_t *) */

View File

@@ -99,6 +99,7 @@ static alpm_list_t *_pkg_get_replaces(alpm_pkg_t *pkg) { return pkg->replaces;
static alpm_filelist_t *_pkg_get_files(alpm_pkg_t *pkg) { return &(pkg->files); }
static alpm_list_t *_pkg_get_backup(alpm_pkg_t *pkg) { return pkg->backup; }
static void *_pkg_changelog_open(alpm_pkg_t UNUSED *pkg)
{
return NULL;

View File

@@ -85,7 +85,7 @@ struct pkg_operations {
*/
extern const struct pkg_operations default_pkg_ops;
struct __alpm_pkg_t {
struct _alpm_pkg_t {
unsigned long name_hash;
char *filename;
char *base;

View File

@@ -32,7 +32,7 @@
* A combination of a hash table and a list, allowing for fast look-up
* by package name but also iteration over the packages.
*/
struct __alpm_pkghash_t {
struct _alpm_pkghash_t {
/** data held by the hash table */
alpm_list_t **hash_table;
/** head node of the hash table data in normal list format */
@@ -45,7 +45,7 @@ struct __alpm_pkghash_t {
unsigned int limit;
};
typedef struct __alpm_pkghash_t alpm_pkghash_t;
typedef struct _alpm_pkghash_t alpm_pkghash_t;
alpm_pkghash_t *_alpm_pkghash_create(unsigned int size);

View File

@@ -350,7 +350,7 @@ static int key_search_keyserver(alpm_handle_t *handle, const char *fpr,
pgpkey->data = key;
if(key->subkeys->fpr) {
pgpkey->fingerprint = key->subkeys->fpr;
} else if(key->subkeys->keyid) {
} else {
pgpkey->fingerprint = key->subkeys->keyid;
}
pgpkey->uid = key->uids->uid;
@@ -504,19 +504,15 @@ int _alpm_key_import(alpm_handle_t *handle, const char *uid, const char *fpr)
return -1;
}
STRDUP(fetch_key.uid, uid, return -1);
STRDUP(fetch_key.fingerprint, fpr, free(fetch_key.uid); return -1);
alpm_question_import_key_t question = {
.type = ALPM_QUESTION_IMPORT_KEY,
.import = 0,
.key = &fetch_key
.uid = uid,
.fingerprint = fpr
};
QUESTION(handle, &question);
free(fetch_key.uid);
free(fetch_key.fingerprint);
if(question.import) {
/* Try to import the key from a WKD first */
if(email_from_uid(uid, &email) == 0) {

View File

@@ -198,7 +198,8 @@ int SYMEXPORT alpm_trans_commit(alpm_handle_t *handle, alpm_list_t **data)
}
}
if(_alpm_hook_run(handle, ALPM_HOOK_PRE_TRANSACTION) != 0) {
if(!(trans->flags & ALPM_TRANS_FLAG_NOHOOKS) &&
_alpm_hook_run(handle, ALPM_HOOK_PRE_TRANSACTION) != 0) {
RET_ERR(handle, ALPM_ERR_TRANS_HOOK_FAILED, -1);
}
@@ -232,7 +233,10 @@ int SYMEXPORT alpm_trans_commit(alpm_handle_t *handle, alpm_list_t **data)
event.type = ALPM_EVENT_TRANSACTION_DONE;
EVENT(handle, (void *)&event);
alpm_logaction(handle, ALPM_CALLER_PREFIX, "transaction completed\n");
_alpm_hook_run(handle, ALPM_HOOK_POST_TRANSACTION);
if(!(trans->flags & ALPM_TRANS_FLAG_NOHOOKS)) {
_alpm_hook_run(handle, ALPM_HOOK_POST_TRANSACTION);
}
}
trans->state = STATE_COMMITED;

View File

@@ -36,7 +36,7 @@ typedef enum _alpm_transstate_t {
} alpm_transstate_t;
/* Transaction */
struct __alpm_trans_t {
typedef struct _alpm_trans_t {
/* bitfield of alpm_transflag_t flags */
int flags;
alpm_transstate_t state;
@@ -44,7 +44,7 @@ struct __alpm_trans_t {
alpm_list_t *add; /* list of (alpm_pkg_t *) */
alpm_list_t *remove; /* list of (alpm_pkg_t *) */
alpm_list_t *skip_remove; /* list of (char *) */
};
} alpm_trans_t;
void _alpm_trans_free(alpm_trans_t *trans);
/* flags is a bitfield of alpm_transflag_t flags */

View File

@@ -42,6 +42,7 @@ LOCKFILE=
CLEAN_LOCK=0
USE_COLOR='y'
PREVENT_DOWNGRADE=0
INCLUDE_SIGS=0
# Import libmakepkg
source "$LIBRARY"/util/compress.sh
@@ -260,7 +261,7 @@ db_write_entry() {
fi
# compute base64'd PGP signature
if [[ -f "$pkgfile.sig" ]]; then
if (( INCLUDE_SIGS )) && [[ -f "$pkgfile.sig" ]]; then
if grep -q 'BEGIN PGP SIGNATURE' "$pkgfile.sig"; then
error "$(gettext "Cannot use armored signatures for packages: %s")" "$pkgfile.sig"
return 1
@@ -622,6 +623,9 @@ while (( $# )); do
-p|--prevent-downgrade)
PREVENT_DOWNGRADE=1
;;
--include-sigs)
INCLUDE_SIGS=1
;;
*)
args+=("$1")
;;

View File

@@ -541,12 +541,12 @@ void cb_question(void *ctx, alpm_question_t *question)
{
alpm_question_import_key_t *q = &question->import_key;
/* the uid is unknown with db signatures */
if (q->key->uid == NULL) {
if (q->uid == NULL) {
q->import = yesno(_("Import PGP key %s?"),
q->key->fingerprint);
q->fingerprint);
} else {
q->import = yesno(_("Import PGP key %s, \"%s\"?"),
q->key->fingerprint, q->key->uid);
q->fingerprint, q->uid);
}
}
break;

View File

@@ -40,9 +40,8 @@ static void print_line_machinereadable(alpm_db_t *db, alpm_pkg_t *pkg, char *fil
fputs("\n", stdout);
}
static void dump_pkg_machinereadable(alpm_db_t *db, alpm_pkg_t *pkg)
static void dump_pkg_machinereadable(alpm_db_t *db, alpm_pkg_t *pkg, alpm_filelist_t *pkgfiles)
{
alpm_filelist_t *pkgfiles = alpm_pkg_get_files(pkg);
for(size_t filenum = 0; filenum < pkgfiles->count; filenum++) {
const alpm_file_t *file = pkgfiles->files + filenum;
print_line_machinereadable(db, pkg, file->name);
@@ -108,7 +107,9 @@ static void filetarget_free(struct filetarget *ftarg) {
static int files_search(alpm_list_t *syncs, alpm_list_t *targets, int regex) {
int ret = 0;
alpm_list_t *t, *filetargs = NULL;
alpm_list_t *t, *s, *filetargs = NULL;
alpm_filelist_t filelist = {0};
char *pkgname = NULL;
for(t = targets; t; t = alpm_list_next(t)) {
char *targ = t->data;
@@ -144,43 +145,58 @@ static int files_search(alpm_list_t *syncs, alpm_list_t *targets, int regex) {
goto cleanup;
}
for(t = filetargs; t; t = alpm_list_next(t)) {
struct filetarget *ftarg = t->data;
char *targ = ftarg->targ;
regex_t *reg = &ftarg->reg;
int exact_file = ftarg->exact_file;
alpm_list_t *s;
int found = 0;
for(s = syncs; s; s = alpm_list_next(s)) {
alpm_db_t *repo = s->data;
int m;
for(s = syncs; s; s = alpm_list_next(s)) {
alpm_list_t *p;
alpm_db_t *repo = s->data;
alpm_list_t *packages = alpm_db_get_pkgcache(repo);
int m;
alpm_db_files_t *files = alpm_db_files_open(repo);
for(p = packages; p; p = alpm_list_next(p)) {
alpm_pkg_t *pkg = p->data;
alpm_filelist_t *files = alpm_pkg_get_files(pkg);
if(!files) {
continue;
}
while(1) {
int ok = alpm_db_files_next(files, &pkgname);
if(ok == 1) {
break;
}
if(ok != 0) {
continue;
}
if(alpm_db_files_load(files, &filelist) != 0) {
ret = 1;
continue;
}
alpm_pkg_t *pkg = alpm_db_get_pkg(repo, pkgname);
for(t = filetargs; t; t = alpm_list_next(t)) {
struct filetarget *ftarg = t->data;
char *targ = ftarg->targ;
regex_t *reg = &ftarg->reg;
int exact_file = ftarg->exact_file;
int found = 0;
alpm_list_t *match = NULL;
if(exact_file) {
if (regex) {
for(size_t f = 0; f < files->count; f++) {
char *c = files->files[f].name;
if(regex) {
for(size_t f = 0; f < filelist.count; f++) {
char *c = filelist.files[f].name;
if(regexec(reg, c, 0, 0, 0) == 0) {
match = alpm_list_add(match, files->files[f].name);
match = alpm_list_add(match, filelist.files[f].name);
found = 1;
}
}
} else {
if(alpm_filelist_contains(files, targ)) {
if(alpm_filelist_contains(&filelist, targ)) {
match = alpm_list_add(match, targ);
found = 1;
}
}
} else {
for(size_t f = 0; f < files->count; f++) {
char *c = strrchr(files->files[f].name, '/');
for(size_t f = 0; f < filelist.count; f++) {
char *c = strrchr(filelist.files[f].name, '/');
if(c && *(c + 1)) {
if(regex) {
m = regexec(reg, (c + 1), 0, 0, 0);
@@ -188,7 +204,7 @@ static int files_search(alpm_list_t *syncs, alpm_list_t *targets, int regex) {
m = strcmp(c + 1, targ);
}
if(m == 0) {
match = alpm_list_add(match, files->files[f].name);
match = alpm_list_add(match, filelist.files[f].name);
found = 1;
}
}
@@ -199,28 +215,33 @@ static int files_search(alpm_list_t *syncs, alpm_list_t *targets, int regex) {
print_match(match, repo, pkg, exact_file);
alpm_list_free(match);
}
if(!found) {
ret = 1;
}
}
}
if(!found) {
ret = 1;
}
alpm_db_files_close(files);
}
cleanup:
alpm_list_free_inner(filetargs, (alpm_list_fn_free) filetarget_free);
alpm_list_free(filetargs);
alpm_filelist_free(&filelist);
if(pkgname) {
free(pkgname);
}
return ret;
}
static void dump_file_list(alpm_pkg_t *pkg) {
static void dump_file_list(alpm_pkg_t *pkg, alpm_filelist_t *pkgfiles) {
const char *pkgname;
alpm_filelist_t *pkgfiles;
size_t i;
pkgname = alpm_pkg_get_name(pkg);
pkgfiles = alpm_pkg_get_files(pkg);
for(i = 0; i < pkgfiles->count; i++) {
const alpm_file_t *file = pkgfiles->files + i;
@@ -239,73 +260,97 @@ static void dump_file_list(alpm_pkg_t *pkg) {
static int files_list(alpm_list_t *syncs, alpm_list_t *targets) {
alpm_list_t *i, *j;
int ret = 0;
size_t found = 0;
alpm_filelist_t filelist = {0};
char *pkgname = NULL;
if(targets != NULL) {
for(i = targets; i; i = alpm_list_next(i)) {
int found = 0;
char *targ = i->data;
char *repo = NULL;
char *c = strchr(targ, '/');
for(j = syncs; j; j = alpm_list_next(j)) {
alpm_db_t *db = j->data;
alpm_db_files_t *files = alpm_db_files_open(db);
if(c) {
if(! *(c + 1)) {
pm_printf(ALPM_LOG_ERROR,
_("invalid package: '%s'\n"), targ);
ret += 1;
if(!files) {
continue;
}
while(1) {
int ok = alpm_db_files_next(files, &pkgname);
if(ok == 1) {
break;
}
if(ok != 0) {
continue;
}
if(targets != NULL) {
int match = 0;
for(i = targets; i; i = alpm_list_next(i)) {
char *targ = i->data;
char *c = strchr(targ, '/');
char *repo = NULL;
if(c) {
if(! *(c + 1)) {
pm_printf(ALPM_LOG_ERROR,
_("invalid package: '%s'\n"), targ);
ret = 1;
continue;
}
repo = strndup(targ, c - targ);
targ = c + 1;
}
if(repo) {
if(strcmp(alpm_db_get_name(db), repo) != 0) {
free(repo);
continue;
}
free(repo);
}
if(strcmp(pkgname, targ) == 0) {
match = 1;
found++;
break;
}
}
if(!match) {
continue;
}
repo = strndup(targ, c - targ);
targ = c + 1;
}
for(j = syncs; j; j = alpm_list_next(j)) {
alpm_pkg_t *pkg;
alpm_db_t *db = j->data;
if(repo) {
if(strcmp(alpm_db_get_name(db), repo) != 0) {
continue;
}
}
if(alpm_db_files_load(files, &filelist) != 0) {
ret = 1;
continue;
}
if((pkg = alpm_db_get_pkg(db, targ)) != NULL) {
found = 1;
if(config->op_f_machinereadable) {
dump_pkg_machinereadable(db, pkg);
} else {
dump_file_list(pkg);
}
break;
}
alpm_pkg_t *pkg = alpm_db_get_pkg(db, pkgname);
if(config->op_f_machinereadable) {
dump_pkg_machinereadable(db, pkg, &filelist);
} else {
dump_file_list(pkg, &filelist);
}
if(!found) {
targ = i->data;
pm_printf(ALPM_LOG_ERROR,
_("package '%s' was not found\n"), targ);
ret += 1;
}
free(repo);
break;
}
} else {
for(i = syncs; i; i = alpm_list_next(i)) {
alpm_db_t *db = i->data;
alpm_db_files_close(files);
}
for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) {
alpm_pkg_t *pkg = j->data;
if(config->op_f_machinereadable) {
dump_pkg_machinereadable(db, pkg);
} else {
dump_file_list(pkg);
}
}
}
alpm_filelist_free(&filelist);
if(found != alpm_list_count(targets)) {
ret = 1;
}
if(pkgname) {
free(pkgname);
}
return ret;
}
int pacman_files(alpm_list_t *targets)
{
alpm_list_t *files_dbs = NULL;

View File

@@ -634,6 +634,7 @@ static int parsearg_trans(int opt)
case OP_DBONLY:
config->flags |= ALPM_TRANS_FLAG_DBONLY;
config->flags |= ALPM_TRANS_FLAG_NOSCRIPTLET;
config->flags |= ALPM_TRANS_FLAG_NOHOOKS;
break;
case OP_NOPROGRESSBAR:
config->noprogressbar = 1;