Compare commits

..

47 Commits

Author SHA1 Message Date
morganamilo
83838214b7 Remove unused variables / assignments 2024-02-09 11:24:20 +10:00
morganamilo
4baeb8e40b libalpm: print errors when unknown keys in database 2024-02-09 11:24:20 +10:00
morganamilo
18b65ec909 pacman: remove uses of atoi 2024-02-09 11:24:20 +10:00
morganamilo
45ce932fd0 pacman: check for end of string when stripping ascii escapes 2024-02-09 11:24:20 +10:00
morganamilo
da4b590bce pacman: check if pkgname is empty instead of null in progress
The progress callback always uses an empty string when there is no
pkgname. However pacman checks if the argument is null.

Check if the string is empty instead and better document what is passed
to the progress callback.
2024-02-09 11:24:20 +10:00
Allan McRae
0649a66ee5 Add ALPM_PKG_REASON_UNKNOWN type
Return ALPM_PKG_REASON_UNKNOWN when parsing of %REASON% in the local
database fails.

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-09 11:14:38 +10:00
morganamilo
6e6d3f18e3 libalpm: don't use atio for pkgreason
atio's behaviour is undefined if the input is not valid. Also it does
all sorts of whitespace and prefix handling which we don't need for
pkgreason.

Instead of going into UB on invalid input we now return EXPLICIT as the
fallback and print an error. However we don't actually error out as the
DB parsing tries to be error tolerant.

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-09 11:14:38 +10:00
Andrew Gregory
0a394144b2 validate package metadata after loading
alpm has certain requirements for package metadata necessary for proper
functioning, name and version in particular.  These requirements are
already enforced in makepkg, but nowhere in alpm.

Exceptions are treated as errors for non-local packages because they
cannot be installed without potentially resulting in undefined behavior.
Exceptions for local packages are treated as warnings because they are
already installed, so any damage has already been done, and the user
would otherwise have no way to uninstall them.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2024-02-07 12:27:26 +00:00
Andrew Gregory
fde59b99e8 be_package: delay freeing archive resource
The error path uconditinally tries to free the archive, leading to a
double-free segmentation fault if the error path is triggered after
already freeing it.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2024-02-07 12:27:26 +00:00
Andrew Gregory
edd57c8b96 perform cleanup on sync db parsing errors
Cleanup was only being performed when libarchive failed to actually read
the file.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2024-02-07 12:27:26 +00:00
Andrew Gregory
5c75a55c7d allow freeing partial db package cache
The free function was checking DB_STATUS_PKGCACHE, which is only set
once the package cache has been fully built.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2024-02-07 12:27:26 +00:00
Allan McRae
56f1eeef4b Remove obsolete Doxyfile directives
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-06 20:03:08 +10:00
David Runge
f8c2e59ec5 pacman-key: Make signature verification more robust by checking pipes
To ensure we are not dropping the return code of the `gpg` call due to
piping into `grep`, we make use of `PIPESTATUS` to check the return code
of each command separately.

Additionally, we can now distinguish between two states: The signature
does not verify (e.g. due to technical reasons) and the signature is
not trusted.

Signed-off-by: David Runge <dvzrv@archlinux.org>
2024-02-04 10:06:43 +01:00
David Runge
16a064701a makepkg: Move check for signature metadata to central location
Move the check for the `NEWSIG` metadata keyword contained in the
GnuPG based statusfile to `parse_gpg_statusfile()` so that it is also
run when creating the statusfile in `verify_file_signature()` and not
only when running `verify_git_signature()`.

Signed-off-by: David Runge <dvzrv@archlinux.org>
2024-02-04 10:06:42 +01:00
David Runge
86ec26b2d3 makepkg: Improve robustness of signature verification by limiting terms
The output of
`gpg --quiet --batch --status-fd /dev/stdout --verify <signature_file> <file> 2> /dev/null`
or
`git verify-commit --raw <commit> 2>&1`
may contain binary data, if the signature has been created with an
OpenPGP implementation, that e.g. makes use of notations.
If the notation string (see `NOTATION_DATA` in /usr/share/doc/gnupg/
DETAILS) contains a trailing binary char, this will break signature
verification, as any following entry (e.g. `VALIDSIG`) will be offset.

As we are only making use of a narrow set of terms from the statusfile
(namely `NEWSIG`, `GOODSIG`, `EXPSIG`, `EXPKEYSIG`, `REVKEYSIG`,
`BADSIG`, `ERRSIG`, `VALIDSIG`, `TRUST_UNDEFINED`, `TRUST_NEVER`,
`TRUST_MARGINAL`, `TRUST_FULLY`, `TRUST_ULTIMATE`), we are applying a
filter, so that only understood terms are written to the file.

Signed-off-by: David Runge <dvzrv@archlinux.org>
2024-02-04 10:06:42 +01:00
David Runge
3aa096a74f makepkg: Emit early error if signature verification fails
Emit an early error message if tag or commit verification with git or
detached signature verification with gpg fails.
Make `verify_file_signature()` and `verify_git_signature()` return
non-zero in this case and set errors to `1`, so that later checks
in `check_pgpsigs()`, although still run, can not lead to a positive
result.

Signed-off-by: David Runge <dvzrv@archlinux.org>
2024-02-04 10:06:40 +01:00
morganamilo
bf76b5e89f libalpm: correctly log curl_download_internal return value
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 10:23:34 +10:00
Allan McRae
ce528a2654 libalpm/discspace.c: ensure mount points provide directories
In the very unlikely situtation where getmntent() and friends return
non-null, but the mount directory is NULL, a null dereference could
occur. It is unclear what the best course of action is in this case,
so just move on to the next mount point.

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 09:02:36 +10:00
Allan McRae
f996f30163 libalpm/remove.c: prevent undefined behaviour in shift_pacsave error path
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 09:02:36 +10:00
Daniel M. Capella
2ba08e622b Update maintainers list
Signed-off-by: Daniel M. Capella <polyzen@archlinux.org>
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 08:58:33 +10:00
Allan McRae
4856fb53ac Add -Wunused_result to debug build compiler flags
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 08:53:44 +10:00
Allan McRae
a6b2524762 Ensure paths fit in PATH_MAX when cleaning cache
If a path length exceeds the PATH_MAX value, then it gets truncated
when building the path of the file to delete. This could (in a very
unlikely case...) result in the wrong file being deleted.  Check the
path fittedin the buffer before removing files.

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 08:44:24 +10:00
Allan McRae
2079f6866a alpm_list_reverse: restore original list on failure
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 07:56:00 +10:00
Allan McRae
845dadf183 _cache_mtree_open: remove unused variable
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 07:56:00 +10:00
Allan McRae
dfee773364 clean_filename: use strdup instead of malloc and memcpy
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 07:56:00 +10:00
Allan McRae
c64f898c48 _alpm_pkg_load_internal: remove unneeded if statement
This statement is always true due to an earlier test.

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 07:56:00 +10:00
Allan McRae
16a2a79728 libalpm/signing.c: prevent underflow in length_check
The length_check function could underflow if the provided buffer index
is greater than the signature buffer length, leading to an out of
bounds read.

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 07:54:12 +10:00
Allan McRae
6711d10f96 pacman/conf.c: fix leak on error in setdefaults()
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-02-04 07:49:08 +10:00
Allan McRae
36fcff6e13 pacman/util.c: fix user after free in print_packages
Signed-off-by: Allan McRae <allan@archlinux.org>
2024-01-26 18:13:11 +10:00
Allan McRae
3c28c30133 Fix typo in exporting RUSTFLAGS
Fixes #77

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-01-14 08:50:29 +10:00
Ronan Pigott
4c93e63ddf add.c: drop newline in permission and ownership log messages
These are the only log messages produced by pacman that include an
embedded newline, and it looks very incongruous in a typical pacman.log.

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-01-10 08:52:35 +10:00
Allan McRae
f69d9b4475 makepkg: only check software once
Move the checks for software and gpg signing ability to after the
fakeroot section so that it is only executed once. This also fixes
gpg (lack of) interaction under fakeroot.

Fixes #69

Signed-off-by: Allan McRae <allan@archlinux.org>
2024-01-09 22:42:45 +00:00
Andrew Gregory
42fa74e91a free handle resources before running scripts
The primary purpose of this is to allow cleanup of file descriptors
allocated by curl that were left open in the child.  I am not aware of
any issues caused by the open file descriptors, but think it better to
not leave random open fd's lying around.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2024-01-09 22:39:14 +00:00
Andrew Gregory
929bad61c0 _alpm_handle_free: free all in-memory resources
Freeing handle resources was previously split awkwardly between
_alpm_handle_free and alpm_release.  This consolidates the freeing of
all in-memory resources to _alpm_handle_free, leaving alpm_release as a
thin wrapper that provides safety checks and frees any external
resources, e.g. removing lock files.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2024-01-09 22:39:14 +00:00
Morten Linderud
00d2b1f902 strip: don't create debug packages from .a files
.a files are not valid ELF files so we can't run objcopy nor debugedit
on them.

Rename STRIPLTO to STATICLIB to be more descriptive.

Signed-off-by: Morten Linderud <morten@linderud.pw>
2023-12-17 16:04:45 +01:00
Morten Linderud
7a4fff3310 strip: split off file stripping and debug package creation
Some projects might duplicate the file in multiple locations for one
reason or another. When debug packages are enabled, `makepkg` will only
strip the first occurrence of the binary and abort early on all the
other binaries.

Signed-off-by: Morten Linderud <morten@linderud.pw>
2023-12-17 16:04:45 +01:00
morganamilo
8d38746586 libalpm: fix check_pgp_signature docs
The function did have these return values a long time ago but now only
return 0 or -1.
2023-12-04 15:34:49 +00:00
Andrew Gregory
0df44c2e20 db.c: set pm_errno for server list modifications
Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-12-02 04:56:25 +00:00
Andrew Gregory
dc91476555 pacman: add cache server support
Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-12-02 04:56:25 +00:00
Andrew Gregory
bad3e13eaa conf.c: remove unnecessary _add_mirror function
It does very little, is only used in one place, and can't easily be
reused for other server types due to the inclusion of an error message.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-12-02 04:56:25 +00:00
Andrew Gregory
45e94e2dae pmtest: return pkg from addpkg2db
Allows more compact syntax:

p1 = self.addpkg2db('sync', pmpkg("foo"))

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-12-02 04:56:25 +00:00
Andrew Gregory
3aa1975c1d alpm: add cache server support
Cache servers differ from regular servers in that they do not produce
warnings and are not removed from the server pool for "soft errors"
(i.e. the server was reachable, but the download failed) and they are
not used for databases.  If a host is used for both a cache server and a
regular server, it may still be removed from the server pool for soft
errors that occur when used as cache server and removal from the server
pool for soft errors will not affect future attempted use as a cache
server.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-12-02 04:56:25 +00:00
Andrew Gregory
56626816b6 dload: differentiate between hard and soft errors
Set error count to -1 to indicate a hard error to allow them to be
treated differently.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-12-02 04:56:25 +00:00
Allan McRae
0f512ae46e Do not increment on every database error to avoid overflow
Signed-off-by: Allan McRae <allan@archlinux.org>
2023-12-02 04:55:29 +00:00
Allan McRae
d56e9ed083 Increment error count on filelist conflicts in local database
Signed-off-by: Allan McRae <allan@archlinux.org>
2023-12-02 04:55:29 +00:00
Andrew Gregory
2d190d5a33 meson.build: add _FILE_OFFSET_BITS to pkgconfig
Meson automatically sets _FILE_OFFSET_BITS but that value was not
getting carried through to the libalpm pkgconfig file, breaking
downstream projects that relied on it.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-11-25 13:05:00 -08:00
Andrew Gregory
2e23126e2a remove unused pkgconfig template
libalpm uses meson's pkgconfig module which does not use the template
file.

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
2023-11-25 13:04:56 -08:00
48 changed files with 638 additions and 297 deletions

View File

@@ -169,7 +169,6 @@ HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
@@ -239,7 +238,6 @@ USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output

View File

@@ -18,7 +18,6 @@ Current maintainers:
* Allan McRae <allan@archlinux.org>
* Andrew Gregory <andrew.gregory.8@gmail.com>
* Eli Schwartz <eschwartz@archlinux.org>
* Morgan Adamiec <morganamilo@archlinux.org>
Past major contributors:
@@ -30,6 +29,7 @@ Past major contributors:
* Xavier Chantry <shiningxc@gmail.com>
* Nagy Gabor <ngaba@bibl.u-szeged.hu>
* Dave Reisner <dreisner@archlinux.org>
* Eli Schwartz <eschwartz@archlinux.org>
For additional contributors, use `git shortlog -s` on the pacman.git
repository.

View File

@@ -240,6 +240,12 @@ number.
general configuration options. Wildcards in the specified paths will get
expanded based on linkman:glob[7] rules.
*CacheServer =* url::
A full URL to a location where the packages, and signatures (if
available) for this repository can be found. Cache servers will be tried
before any non-cache servers, will not be removed from the server pool for
404 download errors, and will not be used for database files.
*Server =* url::
A full URL to a location where the database, packages, and signatures (if
available) for this repository can be found.

View File

@@ -262,7 +262,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
"filesystem: %o package: %o\n"), filename, lsbuf.st_mode & mask,
entrymode & mask);
alpm_logaction(handle, ALPM_CALLER_PREFIX,
"warning: directory permissions differ on %s\n"
"warning: directory permissions differ on %s, "
"filesystem: %o package: %o\n", filename, lsbuf.st_mode & mask,
entrymode & mask);
}
@@ -277,7 +277,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
"filesystem: %u:%u package: %u:%u\n"), filename,
lsbuf.st_uid, lsbuf.st_gid, entryuid, entrygid);
alpm_logaction(handle, ALPM_CALLER_PREFIX,
"warning: directory ownership differs on %s\n"
"warning: directory ownership differs on %s, "
"filesystem: %u:%u package: %u:%u\n", filename,
lsbuf.st_uid, lsbuf.st_gid, entryuid, entrygid);
}
@@ -469,7 +469,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
!(trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) {
const char *scriptlet_name = is_upgrade ? "pre_upgrade" : "pre_install";
_alpm_runscriptlet(handle, newpkg->name, pkgfile, scriptlet_name,
_alpm_runscriptlet(handle, pkgfile, scriptlet_name,
newpkg->version, oldpkg ? oldpkg->version : NULL, 1);
}
@@ -641,7 +641,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
char *scriptlet = _alpm_local_db_pkgpath(db, newpkg, "install");
const char *scriptlet_name = is_upgrade ? "post_upgrade" : "post_install";
_alpm_runscriptlet(handle, newpkg->name, scriptlet, scriptlet_name,
_alpm_runscriptlet(handle, scriptlet, scriptlet_name,
newpkg->version, oldpkg ? oldpkg->version : NULL, 0);
free(scriptlet);
}

View File

@@ -93,34 +93,16 @@ cleanup:
return NULL;
}
/* check current state and free all resources including storage locks */
int SYMEXPORT alpm_release(alpm_handle_t *myhandle)
{
int ret = 0;
alpm_db_t *db;
CHECK_HANDLE(myhandle, return -1);
/* close local database */
db = myhandle->db_local;
if(db) {
db->ops->unregister(db);
myhandle->db_local = NULL;
}
if(alpm_unregister_all_syncdbs(myhandle) == -1) {
ret = -1;
}
#ifdef HAVE_LIBCURL
curl_multi_cleanup(myhandle->curlm);
curl_global_cleanup();
FREELIST(myhandle->server_errors);
#endif
ASSERT(myhandle->trans == NULL, RET_ERR(myhandle, ALPM_ERR_TRANS_NOT_NULL, -1));
_alpm_handle_unlock(myhandle);
_alpm_handle_free(myhandle);
return ret;
return 0;
}
const char SYMEXPORT *alpm_version(void)

View File

@@ -488,7 +488,7 @@ typedef struct _alpm_siglist_t {
* Check the PGP signature for the given package file.
* @param pkg the package to check
* @param siglist a pointer to storage for signature results
* @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
* @return 0 if valid, -1 if an error occurred or signature is invalid
*/
int alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, alpm_siglist_t *siglist);
@@ -496,7 +496,7 @@ int alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, alpm_siglist_t *siglist);
* Check the PGP signature for the given database.
* @param db the database to check
* @param siglist a pointer to storage for signature results
* @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
* @return 0 if valid, -1 if an error occurred or signature is invalid
*/
int alpm_db_check_pgp_signature(alpm_db_t *db, alpm_siglist_t *siglist);
@@ -750,10 +750,6 @@ typedef enum _alpm_event_type_t {
ALPM_EVENT_LOAD_START,
/** Target package is finished loading. */
ALPM_EVENT_LOAD_DONE,
/** An install file is about to be ran */
ALPM_EVENT_INSTALL_RUN_START,
/** An install file has finished running */
ALPM_EVENT_INSTALL_RUN_DONE,
/** Scriptlet has printed information; See alpm_event_scriptlet_info_t for
* arguments. */
ALPM_EVENT_SCRIPTLET_INFO,
@@ -844,32 +840,10 @@ typedef struct _alpm_event_optdep_removal_t {
alpm_depend_t *optdep;
} alpm_event_optdep_removal_t;
/** Enum of the kinds of scriptlets */
typedef enum _alpm_scriptlet_kind_t {
/** We are running an install file */
ALPM_SCRIPTLET_KIND_INSTALL_FILE,
/** We are running a hook */
ALPM_SCRIPTLET_KIND_HOOK,
/** We are running a command */
ALPM_SCRIPTLET_KIND_COMMAND,
} alpm_scriptlet_kind_t;
/** We are running an install file. */
typedef struct _alpm_event_install_run_t {
/** Type of event */
alpm_event_type_t type;
/** The name of the package */
const char *pkgname;
} alpm_event_install_run_t;
/** A scriptlet was ran. */
typedef struct _alpm_event_scriptlet_info_t {
/** Type of event */
alpm_event_type_t type;
/** The kind of scriptlet being ran */
alpm_scriptlet_kind_t kind;
/** The name of the scriptlet **/
const char *name;
/** Line of scriptlet output */
const char *line;
} alpm_event_scriptlet_info_t;
@@ -972,8 +946,6 @@ typedef union _alpm_event_t {
alpm_event_package_operation_t package_operation;
/** An optdept was remove */
alpm_event_optdep_removal_t optdep_removal;
/** An install file is about to be run */
alpm_event_install_run_t install_run;
/** A scriptlet was ran */
alpm_event_scriptlet_info_t scriptlet_info;
/** A database is missing */
@@ -1177,7 +1149,9 @@ typedef enum _alpm_progress_t {
* make take a while to complete.
* @param ctx user-provided context
* @param progress the kind of event that is progressing
* @param pkg for package operations, the name of the package being operated on
* @param pkg the name of the package being operated on. if the progress kind
* is a packae operation (add, upgrade, downgrade, reinstall, remove).
* otherwise this will be an empty string.
* @param percent the percent completion of the action
* @param howmany the total amount of items in the action
* @param current the current amount of items completed
@@ -1371,6 +1345,34 @@ int alpm_db_add_server(alpm_db_t *db, const char *url);
*/
int alpm_db_remove_server(alpm_db_t *db, const char *url);
/** Get the list of cache servers assigned to this db.
* @param db pointer to the database to get the servers from
* @return a char* list of servers
*/
alpm_list_t *alpm_db_get_cache_servers(const alpm_db_t *db);
/** Sets the list of cache servers for the database to use.
* @param db the database to set the servers. The list will be duped and
* the original will still need to be freed by the caller.
* @param servers a char* list of servers.
*/
int alpm_db_set_cache_servers(alpm_db_t *db, alpm_list_t *servers);
/** Add a download cache server to a database.
* @param db database pointer
* @param url url of the server
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
int alpm_db_add_cache_server(alpm_db_t *db, const char *url);
/** Remove a download cache server from a database.
* @param db database pointer
* @param url url of the server
* @return 0 on success, 1 on server not present,
* -1 on error (pm_errno is set accordingly)
*/
int alpm_db_remove_cache_server(alpm_db_t *db, const char *url);
/* End of server accessors */
/** @} */
@@ -2293,7 +2295,9 @@ typedef enum _alpm_pkgreason_t {
/** Explicitly requested by the user. */
ALPM_PKG_REASON_EXPLICIT = 0,
/** Installed as a dependency for another package. */
ALPM_PKG_REASON_DEPEND = 1
ALPM_PKG_REASON_DEPEND = 1,
/** Failed parsing of local database */
ALPM_PKG_REASON_UNKNOWN = 2
} alpm_pkgreason_t;
/** Location a package object was loaded from. */

View File

@@ -417,6 +417,7 @@ alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list)
while(lp) {
if(alpm_list_append(&newlist, lp->data) == NULL) {
alpm_list_free(newlist);
list->prev = backup;
return NULL;
}
lp = lp->prev;

View File

@@ -250,7 +250,6 @@ static int _cache_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp)
*/
static struct archive *_cache_mtree_open(alpm_pkg_t *pkg)
{
int r;
struct archive *mtree;
alpm_db_t *db = alpm_pkg_get_db(pkg);
@@ -268,7 +267,7 @@ static struct archive *_cache_mtree_open(alpm_pkg_t *pkg)
_alpm_archive_read_support_filter_all(mtree);
archive_read_support_format_mtree(mtree);
if((r = _alpm_archive_read_open_file(mtree, mtfile, ALPM_BUFFER_SIZE))) {
if(_alpm_archive_read_open_file(mtree, mtfile, ALPM_BUFFER_SIZE)) {
_alpm_log(pkg->handle, ALPM_LOG_ERROR, _("error while reading file %s: %s\n"),
mtfile, archive_error_string(mtree));
_alpm_archive_read_free(mtree);
@@ -631,6 +630,10 @@ static int local_db_populate(alpm_db_t *db)
continue;
}
/* treat local metadata errors as warning-only,
* they are already installed and otherwise they can't be operated on */
_alpm_pkg_check_meta(pkg);
/* add to the collection */
_alpm_log(db->handle, ALPM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n",
pkg->name, db->treename);
@@ -651,6 +654,17 @@ static int local_db_populate(alpm_db_t *db)
return 0;
}
static alpm_pkgreason_t _read_pkgreason(alpm_handle_t *handle, const char *pkgname, const char *line) {
if(strcmp(line, "0") == 0) {
return ALPM_PKG_REASON_EXPLICIT;
} else if(strcmp(line, "1") == 0) {
return ALPM_PKG_REASON_DEPEND;
} else {
_alpm_log(handle, ALPM_LOG_ERROR, _("unknown install reason for package %s: %s\n"), pkgname, line);
return ALPM_PKG_REASON_UNKNOWN;
}
}
/* Note: the return value must be freed by the caller */
char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info,
const char *filename)
@@ -773,7 +787,7 @@ static int local_db_read(alpm_pkg_t *info, int inforeq)
READ_AND_STORE(info->packager);
} else if(strcmp(line, "%REASON%") == 0) {
READ_NEXT();
info->reason = (alpm_pkgreason_t)atoi(line);
info->reason = _read_pkgreason(db->handle, info->name, line);
} else if(strcmp(line, "%VALIDATION%") == 0) {
alpm_list_t *i, *v = NULL;
READ_AND_STORE_ALL(v);
@@ -823,6 +837,12 @@ static int local_db_read(alpm_pkg_t *info, int inforeq)
}
}
FREELIST(lines);
} else {
_alpm_log(db->handle, ALPM_LOG_ERROR, _("%s: unknown key '%s' in sync database\n"), info->name, line);
alpm_list_t *lines = NULL;
READ_AND_STORE_ALL(lines);
FREELIST(lines);
}
}
fclose(fp);

View File

@@ -251,8 +251,10 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
return -1;
}
} else {
const char *pkgname = newpkg->name ? newpkg->name : "error";
_alpm_log(handle, ALPM_LOG_ERROR, _("%s: unknown key '%s' in package description\n"), pkgname, key);
_alpm_log(handle, ALPM_LOG_DEBUG, "%s: unknown key '%s' in description file line %d\n",
newpkg->name ? newpkg->name : "error", key, linenum);
pkgname, key, linenum);
}
}
}
@@ -652,8 +654,6 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
goto pkg_invalid;
}
_alpm_archive_read_free(archive);
/* internal fields for package struct */
newpkg->origin = ALPM_PKG_FROM_FILE;
STRDUP(newpkg->origin_data.file, pkgfile, goto error);
@@ -675,6 +675,11 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
newpkg->infolevel |= INFRQ_FILES;
}
if(_alpm_pkg_check_meta(newpkg) != 0) {
goto pkg_invalid;
}
_alpm_archive_read_free(archive);
close(fd);
return newpkg;
@@ -683,9 +688,7 @@ pkg_invalid:
error:
_alpm_pkg_free(newpkg);
_alpm_archive_read_free(archive);
if(fd >= 0) {
close(fd);
}
close(fd);
return NULL;
}

View File

@@ -344,6 +344,11 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,
pkg->ops = get_sync_pkg_ops();
pkg->handle = db->handle;
if(_alpm_pkg_check_meta(pkg) != 0) {
_alpm_pkg_free(pkg);
RET_ERR(db->handle, ALPM_ERR_PKG_INVALID, NULL);
}
/* add to the collection */
_alpm_log(db->handle, ALPM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n",
pkg->name, db->treename);
@@ -452,6 +457,14 @@ static int sync_db_populate(alpm_db_t *db)
}
}
}
/* the db file was successfully read, but contained errors */
if(ret == -1) {
db->status &= ~DB_STATUS_VALID;
db->status |= DB_STATUS_INVALID;
_alpm_db_free_pkgcache(db);
GOTO_ERR(db->handle, ALPM_ERR_DB_INVALID, cleanup);
}
/* reading the db file failed */
if(archive_ret != ARCHIVE_EOF) {
_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not read db '%s' (%s)\n"),
db->treename, archive_error_string(archive));
@@ -678,6 +691,11 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
}
}
FREELIST(lines);
} else {
_alpm_log(db->handle, ALPM_LOG_ERROR, _("%s: unknown key '%s' in local database\n"), pkg->name, line);
alpm_list_t *lines = NULL;
READ_AND_STORE_ALL(lines);
FREELIST(lines);
}
}
if(ret != ARCHIVE_EOF) {

View File

@@ -131,6 +131,26 @@ int SYMEXPORT alpm_db_unregister(alpm_db_t *db)
return 0;
}
alpm_list_t SYMEXPORT *alpm_db_get_cache_servers(const alpm_db_t *db)
{
ASSERT(db != NULL, return NULL);
return db->cache_servers;
}
int SYMEXPORT alpm_db_set_cache_servers(alpm_db_t *db, alpm_list_t *cache_servers)
{
alpm_list_t *i;
ASSERT(db != NULL, return -1);
FREELIST(db->cache_servers);
for(i = cache_servers; i; i = i->next) {
char *url = i->data;
if(alpm_db_add_cache_server(db, url) != 0) {
return -1;
}
}
return 0;
}
alpm_list_t SYMEXPORT *alpm_db_get_servers(const alpm_db_t *db)
{
ASSERT(db != NULL, return NULL);
@@ -164,6 +184,25 @@ static char *sanitize_url(const char *url)
return newurl;
}
int SYMEXPORT alpm_db_add_cache_server(alpm_db_t *db, const char *url)
{
char *newurl;
/* Sanity checks */
ASSERT(db != NULL, return -1);
db->handle->pm_errno = ALPM_ERR_OK;
ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1));
newurl = sanitize_url(url);
ASSERT(newurl != NULL, RET_ERR(db->handle, ALPM_ERR_MEMORY, -1));
db->cache_servers = alpm_list_add(db->cache_servers, newurl);
_alpm_log(db->handle, ALPM_LOG_DEBUG, "adding new cache server URL to database '%s': %s\n",
db->treename, newurl);
return 0;
}
int SYMEXPORT alpm_db_add_server(alpm_db_t *db, const char *url)
{
char *newurl;
@@ -174,9 +213,8 @@ int SYMEXPORT alpm_db_add_server(alpm_db_t *db, const char *url)
ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1));
newurl = sanitize_url(url);
if(!newurl) {
return -1;
}
ASSERT(newurl != NULL, RET_ERR(db->handle, ALPM_ERR_MEMORY, -1));
db->servers = alpm_list_add(db->servers, newurl);
_alpm_log(db->handle, ALPM_LOG_DEBUG, "adding new server URL to database '%s': %s\n",
db->treename, newurl);
@@ -184,6 +222,32 @@ int SYMEXPORT alpm_db_add_server(alpm_db_t *db, const char *url)
return 0;
}
int SYMEXPORT alpm_db_remove_cache_server(alpm_db_t *db, const char *url)
{
char *newurl, *vdata = NULL;
int ret = 1;
/* Sanity checks */
ASSERT(db != NULL, return -1);
db->handle->pm_errno = ALPM_ERR_OK;
ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1));
newurl = sanitize_url(url);
ASSERT(newurl != NULL, RET_ERR(db->handle, ALPM_ERR_MEMORY, -1));
db->cache_servers = alpm_list_remove_str(db->cache_servers, newurl, &vdata);
if(vdata) {
_alpm_log(db->handle, ALPM_LOG_DEBUG, "removed cache server URL from database '%s': %s\n",
db->treename, newurl);
free(vdata);
ret = 0;
}
free(newurl);
return ret;
}
int SYMEXPORT alpm_db_remove_server(alpm_db_t *db, const char *url)
{
char *newurl, *vdata = NULL;
@@ -195,9 +259,7 @@ int SYMEXPORT alpm_db_remove_server(alpm_db_t *db, const char *url)
ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1));
newurl = sanitize_url(url);
if(!newurl) {
return -1;
}
ASSERT(newurl != NULL, RET_ERR(db->handle, ALPM_ERR_MEMORY, -1));
db->servers = alpm_list_remove_str(db->servers, newurl, &vdata);
@@ -328,6 +390,7 @@ void _alpm_db_free(alpm_db_t *db)
/* cleanup pkgcache */
_alpm_db_free_pkgcache(db);
/* cleanup server list */
FREELIST(db->cache_servers);
FREELIST(db->servers);
FREE(db->_path);
FREE(db->treename);
@@ -500,18 +563,17 @@ static void free_groupcache(alpm_db_t *db)
void _alpm_db_free_pkgcache(alpm_db_t *db)
{
if(db == NULL || !(db->status & DB_STATUS_PKGCACHE)) {
if(db == NULL || db->pkgcache == NULL) {
return;
}
_alpm_log(db->handle, ALPM_LOG_DEBUG,
"freeing package cache for repository '%s'\n", db->treename);
if(db->pkgcache) {
alpm_list_free_inner(db->pkgcache->list,
(alpm_list_fn_free)_alpm_pkg_free);
_alpm_pkghash_free(db->pkgcache);
}
alpm_list_free_inner(db->pkgcache->list,
(alpm_list_fn_free)_alpm_pkg_free);
_alpm_pkghash_free(db->pkgcache);
db->pkgcache = NULL;
db->status &= ~DB_STATUS_PKGCACHE;
free_groupcache(db);

View File

@@ -69,6 +69,7 @@ struct _alpm_db_t {
char *_path;
alpm_pkghash_t *pkgcache;
alpm_list_t *grpcache;
alpm_list_t *cache_servers;
alpm_list_t *servers;
const struct db_operations *ops;

View File

@@ -556,7 +556,7 @@ static void _alpm_select_depends(alpm_list_t **from, alpm_list_t **to,
for(i = *from; i; i = next) {
alpm_pkg_t *deppkg = i->data;
next = i->next;
if((explicit || alpm_pkg_get_reason(deppkg) != ALPM_PKG_REASON_EXPLICIT)
if((explicit || alpm_pkg_get_reason(deppkg) == ALPM_PKG_REASON_DEPEND)
&& _alpm_pkg_depends_on(pkg, deppkg)) {
*to = alpm_list_add(*to, deppkg);
*from = alpm_list_remove_item(*from, i);

View File

@@ -111,6 +111,10 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
}
while((mnt = getmntent(fp))) {
if(mnt->mnt_dir == NULL) {
continue;
}
CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
STRDUP(mp->mount_dir, mnt->mnt_dir, free(mp); RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
mp->mount_dir_len = strlen(mp->mount_dir);
@@ -134,6 +138,10 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
}
while((ret = getmntent(fp, &mnt)) == 0) {
if(mnt->mnt_mountp == NULL) {
continue;
}
CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
STRDUP(mp->mount_dir, mnt->mnt_mountp, free(mp); RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
mp->mount_dir_len = strlen(mp->mount_dir);
@@ -161,6 +169,10 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
}
for(; entries-- > 0; fsp++) {
if(fsp->f_mntonname == NULL) {
continue;
}
CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
STRDUP(mp->mount_dir, fsp->f_mntonname, free(mp); RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
mp->mount_dir_len = strlen(mp->mount_dir);

View File

@@ -60,11 +60,11 @@ static int curl_gethost(const char *url, char *buffer, size_t buf_len);
/* number of "soft" errors required to blacklist a server, set to 0 to disable
* server blacklisting */
const unsigned int server_error_limit = 3;
const int server_error_limit = 3;
struct server_error_count {
char server[HOSTNAME_SIZE];
unsigned int errors;
int errors;
};
static struct server_error_count *find_server_errors(alpm_handle_t *handle, const char *server)
@@ -94,22 +94,34 @@ static struct server_error_count *find_server_errors(alpm_handle_t *handle, cons
}
}
/* skip for hard errors or too many soft errors */
static int should_skip_server(alpm_handle_t *handle, const char *server)
{
struct server_error_count *h;
if(server_error_limit && (h = find_server_errors(handle, server)) ) {
return h->errors >= server_error_limit;
return h->errors < 0 || h->errors >= server_error_limit;
}
return 0;
}
static void server_increment_error(alpm_handle_t *handle, const char *server, int count)
/* only skip for hard errors */
static int should_skip_cache_server(alpm_handle_t *handle, const char *server)
{
struct server_error_count *h;
if(server_error_limit && (h = find_server_errors(handle, server)) ) {
return h->errors < 0;
}
return 0;
}
/* block normal servers after too many errors */
static void server_soft_error(alpm_handle_t *handle, const char *server)
{
struct server_error_count *h;
if(server_error_limit
&& (h = find_server_errors(handle, server))
&& !should_skip_server(handle, server) ) {
h->errors += count;
h->errors++;
if(should_skip_server(handle, server)) {
_alpm_log(handle, ALPM_LOG_WARNING,
@@ -119,14 +131,46 @@ static void server_increment_error(alpm_handle_t *handle, const char *server, in
}
}
static void server_soft_error(alpm_handle_t *handle, const char *server)
{
server_increment_error(handle, server, 1);
}
/* immediate block for both servers and cache servers */
static void server_hard_error(alpm_handle_t *handle, const char *server)
{
server_increment_error(handle, server, server_error_limit);
struct server_error_count *h;
if(server_error_limit && (h = find_server_errors(handle, server))) {
if(h->errors != -1) {
/* always set even if already skipped for soft errors
* to disable cache servers too */
h->errors = -1;
_alpm_log(handle, ALPM_LOG_WARNING,
_("fatal error from %s, skipping for the remainder of this transaction\n"),
h->server);
}
}
}
static const char *payload_next_server(struct dload_payload *payload)
{
while(payload->cache_servers
&& should_skip_cache_server(payload->handle, payload->cache_servers->data)) {
payload->cache_servers = payload->cache_servers->next;
}
if(payload->cache_servers) {
const char *server = payload->cache_servers->data;
payload->cache_servers = payload->cache_servers->next;
payload->request_errors_ok = 1;
return server;
}
while(payload->servers
&& should_skip_server(payload->handle, payload->servers->data)) {
payload->servers = payload->servers->next;
}
if(payload->servers) {
const char *server = payload->servers->data;
payload->servers = payload->servers->next;
payload->request_errors_ok = payload->errors_ok;
return server;
}
return NULL;
}
static const char *get_filename(const char *url)
@@ -408,21 +452,16 @@ static FILE *create_tempfile(struct dload_payload *payload, const char *localpat
/* Return 0 if retry was successful, -1 otherwise */
static int curl_retry_next_server(CURLM *curlm, CURL *curl, struct dload_payload *payload)
{
const char *server;
const char *server = NULL;
size_t len;
struct stat st;
alpm_handle_t *handle = payload->handle;
while(payload->servers && should_skip_server(handle, payload->servers->data)) {
payload->servers = payload->servers->next;
}
if(!payload->servers) {
if((server = payload_next_server(payload)) == NULL) {
_alpm_log(payload->handle, ALPM_LOG_DEBUG,
"%s: no more servers to retry\n", payload->remote_name);
return -1;
}
server = payload->servers->data;
payload->servers = payload->servers->next;
/* regenerate a new fileurl */
FREE(payload->fileurl);
@@ -433,7 +472,6 @@ static int curl_retry_next_server(CURLM *curlm, CURL *curl, struct dload_payload
"%s: retrying from %s\n",
payload->remote_name, payload->fileurl);
fflush(payload->localf);
if(payload->allow_resume && stat(payload->tempfile_name, &st) == 0) {
@@ -503,7 +541,7 @@ static int curl_check_finished_download(alpm_handle_t *handle, CURLM *curlm, CUR
_alpm_log(handle, ALPM_LOG_DEBUG, "%s: response code %ld\n",
payload->remote_name, payload->respcode);
if(payload->respcode >= 400) {
if(!payload->errors_ok) {
if(!payload->request_errors_ok) {
handle->pm_errno = ALPM_ERR_RETRIEVE;
/* non-translated message is same as libcurl */
snprintf(payload->error_buffer, sizeof(payload->error_buffer),
@@ -535,7 +573,6 @@ static int curl_check_finished_download(alpm_handle_t *handle, CURLM *curlm, CUR
case CURLE_ABORTED_BY_CALLBACK:
/* handle the interrupt accordingly */
if(dload_interrupted == ABORT_OVER_MAXFILESIZE) {
curlerr = CURLE_FILESIZE_EXCEEDED;
payload->unlink_on_fail = 1;
handle->pm_errno = ALPM_ERR_LIBCURL;
_alpm_log(handle, ALPM_LOG_ERROR,
@@ -558,7 +595,7 @@ static int curl_check_finished_download(alpm_handle_t *handle, CURLM *curlm, CUR
goto cleanup;
}
default:
if(!payload->errors_ok) {
if(!payload->request_errors_ok) {
handle->pm_errno = ALPM_ERR_LIBCURL;
_alpm_log(handle, ALPM_LOG_ERROR,
_("failed retrieving file '%s' from %s : %s\n"),
@@ -764,18 +801,13 @@ static int curl_add_payload(alpm_handle_t *handle, CURLM *curlm,
if(payload->fileurl) {
ASSERT(!payload->servers, GOTO_ERR(handle, ALPM_ERR_WRONG_ARGS, cleanup));
ASSERT(!payload->filepath, GOTO_ERR(handle, ALPM_ERR_WRONG_ARGS, cleanup));
payload->request_errors_ok = payload->errors_ok;
} else {
const char *server;
while(payload->servers && should_skip_server(handle, payload->servers->data)) {
payload->servers = payload->servers->next;
}
const char *server = payload_next_server(payload);
ASSERT(payload->servers, GOTO_ERR(handle, ALPM_ERR_SERVER_NONE, cleanup));
ASSERT(server, GOTO_ERR(handle, ALPM_ERR_SERVER_NONE, cleanup));
ASSERT(payload->filepath, GOTO_ERR(handle, ALPM_ERR_WRONG_ARGS, cleanup));
server = payload->servers->data;
payload->servers = payload->servers->next;
len = strlen(server) + strlen(payload->filepath) + 2;
MALLOC(payload->fileurl, len, GOTO_ERR(handle, ALPM_ERR_MEMORY, cleanup));
snprintf(payload->fileurl, len, "%s/%s", server, payload->filepath);
@@ -934,12 +966,30 @@ static int curl_download_internal(alpm_handle_t *handle,
}
}
_alpm_log(handle, ALPM_LOG_DEBUG, "curl_download_internal return code is %d\n", err);
return err ? -1 : updated ? 0 : 1;
int ret = err ? -1 : updated ? 0 : 1;
_alpm_log(handle, ALPM_LOG_DEBUG, "curl_download_internal return code is %d\n", ret);
return ret;
}
#endif
static int payload_download_fetchcb(struct dload_payload *payload,
const char *server, const char *localpath)
{
int ret;
char *fileurl;
alpm_handle_t *handle = payload->handle;
size_t len = strlen(server) + strlen(payload->filepath) + 2;
MALLOC(fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
snprintf(fileurl, len, "%s/%s", server, payload->filepath);
ret = handle->fetchcb(handle->fetchcb_ctx, fileurl, localpath, payload->force);
free(fileurl);
return ret;
}
/* Returns -1 if an error happened for a required file
* Returns 0 if a payload was actually downloaded
* Returns 1 if no files were downloaded and all errors were non-fatal
@@ -965,16 +1015,11 @@ int _alpm_download(alpm_handle_t *handle,
if(payload->fileurl) {
ret = handle->fetchcb(handle->fetchcb_ctx, payload->fileurl, localpath, payload->force);
} else {
for(s = payload->cache_servers; s && ret == -1; s = s->next) {
ret = payload_download_fetchcb(payload, s->data, localpath);
}
for(s = payload->servers; s && ret == -1; s = s->next) {
const char *server = s->data;
char *fileurl;
size_t len = strlen(server) + strlen(payload->filepath) + 2;
MALLOC(fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
snprintf(fileurl, len, "%s/%s", server, payload->filepath);
ret = handle->fetchcb(handle->fetchcb_ctx, fileurl, localpath, payload->force);
free(fileurl);
ret = payload_download_fetchcb(payload, s->data, localpath);
}
}

View File

@@ -37,6 +37,7 @@ struct dload_payload {
*/
char *fileurl;
char *filepath; /* download URL path */
alpm_list_t *cache_servers;
alpm_list_t *servers;
long respcode;
off_t initial_size;
@@ -55,6 +56,7 @@ struct dload_payload {
char error_buffer[CURL_ERROR_SIZE];
FILE *localf; /* temp download file */
int signature; /* specifies if this payload is for a signature file */
int request_errors_ok; /* per-request errors-ok */
#endif
};

View File

@@ -48,12 +48,28 @@ alpm_handle_t *_alpm_handle_new(void)
return handle;
}
/* free all in-memory resources */
void _alpm_handle_free(alpm_handle_t *handle)
{
alpm_list_t *i;
alpm_db_t *db;
if(handle == NULL) {
return;
}
/* close local database */
if((db = handle->db_local)) {
db->ops->unregister(db);
}
/* unregister all sync dbs */
for(i = handle->dbs_sync; i; i = i->next) {
db = i->data;
db->ops->unregister(db);
}
alpm_list_free(handle->dbs_sync);
/* close logfile */
if(handle->logstream) {
fclose(handle->logstream);
@@ -68,6 +84,12 @@ void _alpm_handle_free(alpm_handle_t *handle)
FREELIST(handle->known_keys);
#endif
#ifdef HAVE_LIBCURL
curl_multi_cleanup(handle->curlm);
curl_global_cleanup();
FREELIST(handle->server_errors);
#endif
/* free memory */
_alpm_trans_free(handle->trans);
FREE(handle->root);

View File

@@ -522,10 +522,10 @@ static int _alpm_hook_run_hook(alpm_handle_t *handle, struct _alpm_hook_t *hook)
alpm_list_count(hook->matches), (alpm_list_fn_cmp)strcmp);
/* hooks with multiple triggers could have duplicate matches */
ctx = hook->matches = _alpm_strlist_dedup(hook->matches);
return _alpm_run_chroot(handle, hook->name, ALPM_SCRIPTLET_KIND_HOOK, hook->cmd[0], hook->cmd,
return _alpm_run_chroot(handle, hook->cmd[0], hook->cmd,
(_alpm_cb_io) _alpm_hook_feed_targets, &ctx);
} else {
return _alpm_run_chroot(handle, hook->name, ALPM_SCRIPTLET_KIND_HOOK, hook->cmd[0], hook->cmd, NULL, NULL);
return _alpm_run_chroot(handle, hook->cmd[0], hook->cmd, NULL, NULL);
}
}

View File

@@ -1,13 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libalpm
Description: Arch Linux package management library
URL: http://archlinux.org/pacman/
Version: @LIB_VERSION@
Requires.private: libarchive @pc_crypto@ @pc_libcurl@ @pc_gpgme@
Cflags: -I${includedir} @LFS_CFLAGS@
Libs: -L${libdir} -lalpm
Libs.private: @LIBS@ @pc_gpgme_libs@ @LIBINTL@

View File

@@ -21,6 +21,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
@@ -844,3 +845,58 @@ int SYMEXPORT alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg)
return 0;
}
/* check that package metadata meets our requirements */
int _alpm_pkg_check_meta(alpm_pkg_t *pkg)
{
char *c;
int error_found = 0;
#define EPKGMETA(error) do { \
error_found = -1; \
_alpm_log(pkg->handle, ALPM_LOG_ERROR, error, pkg->name, pkg->version); \
} while(0)
/* sanity check */
if(pkg->handle == NULL) {
return -1;
}
/* immediate bail if package doesn't have name or version */
if(pkg->name == NULL || pkg->name[0] == '\0'
|| pkg->version == NULL || pkg->version[0] == '\0') {
_alpm_log(pkg->handle, ALPM_LOG_ERROR,
_("invalid package metadata (name or version missing)"));
return -1;
}
if(pkg->name[0] == '-' || pkg->name[0] == '.') {
EPKGMETA(_("invalid metadata for package %s-%s "
"(package name cannot start with '.' or '-')\n"));
}
if(_alpm_fnmatch(pkg->name, "[![:alnum:]+_.@-]") == 0) {
EPKGMETA(_("invalid metadata for package %s-%s "
"(package name contains invalid characters)\n"));
}
/* multiple '-' in pkgver can cause local db entries for different packages
* to overlap (e.g. foo-1=2-3 and foo=1-2-3 both give foo-1-2-3) */
if((c = strchr(pkg->version, '-')) && (strchr(c + 1, '-'))) {
EPKGMETA(_("invalid metadata for package %s-%s "
"(package version contains invalid characters)\n"));
}
if(strchr(pkg->version, '/')) {
EPKGMETA(_("invalid metadata for package %s-%s "
"(package version contains invalid characters)\n"));
}
/* local db entry is <pkgname>-<pkgver> */
if(strlen(pkg->name) + strlen(pkg->version) + 1 > NAME_MAX) {
EPKGMETA(_("invalid metadata for package %s-%s "
"(package name and version too long)\n"));
}
#undef EPKGMETA
return error_found;
}

View File

@@ -165,4 +165,6 @@ int _alpm_pkg_compare_versions(alpm_pkg_t *local_pkg, alpm_pkg_t *pkg);
alpm_pkg_xdata_t *_alpm_pkg_parse_xdata(const char *string);
void _alpm_pkg_xdata_free(alpm_pkg_xdata_t *pd);
int _alpm_pkg_check_meta(alpm_pkg_t *pkg);
#endif /* ALPM_PACKAGE_H */

View File

@@ -420,7 +420,9 @@ static void shift_pacsave(alpm_handle_t *handle, const char *file)
cleanup:
free(dirname);
closedir(dir);
if(dir != NULL) {
closedir(dir);
}
}
@@ -692,7 +694,7 @@ int _alpm_remove_single_package(alpm_handle_t *handle,
!(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) {
char *scriptlet = _alpm_local_db_pkgpath(handle->db_local,
oldpkg, "install");
_alpm_runscriptlet(handle, oldpkg->name, scriptlet, "pre_remove", pkgver, NULL, 0);
_alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0);
free(scriptlet);
}
}
@@ -712,7 +714,7 @@ int _alpm_remove_single_package(alpm_handle_t *handle,
!(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) {
char *scriptlet = _alpm_local_db_pkgpath(handle->db_local,
oldpkg, "install");
_alpm_runscriptlet(handle, oldpkg->name, scriptlet, "post_remove", pkgver, NULL, 0);
_alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0);
free(scriptlet);
}

View File

@@ -1044,7 +1044,7 @@ int SYMEXPORT alpm_siglist_cleanup(alpm_siglist_t *siglist)
static size_t length_check(size_t length, size_t position, size_t a,
alpm_handle_t *handle, const char *identifier)
{
if( a == 0 || length - position <= a) {
if( a == 0 || position > length || length - position <= a) {
_alpm_log(handle, ALPM_LOG_ERROR,
_("%s: signature format error\n"), identifier);
return -1;

View File

@@ -828,6 +828,7 @@ static int download_files(alpm_handle_t *handle)
FREE(payload->remote_name); FREE(payload);
GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
payload->max_size = pkg->size;
payload->cache_servers = pkg->origin_data.db->cache_servers;
payload->servers = pkg->origin_data.db->servers;
payload->handle = handle;
payload->allow_resume = 1;

View File

@@ -334,7 +334,7 @@ static int grep(const char *fn, const char *needle)
return 0;
}
int _alpm_runscriptlet(alpm_handle_t *handle, const char *pkgname, const char *filepath,
int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath,
const char *script, const char *ver, const char *oldver, int is_archive)
{
char arg0[64], arg1[3], cmdline[PATH_MAX];
@@ -407,16 +407,7 @@ int _alpm_runscriptlet(alpm_handle_t *handle, const char *pkgname, const char *f
_alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\"\n", cmdline);
alpm_event_install_run_t event = {
.type = ALPM_EVENT_INSTALL_RUN_START,
.pkgname = pkgname,
};
EVENT(handle, &event);
retval = _alpm_run_chroot(handle, pkgname, ALPM_SCRIPTLET_KIND_INSTALL_FILE, SCRIPTLET_SHELL, argv, NULL, NULL);
event.type = ALPM_EVENT_INSTALL_RUN_DONE;
EVENT(handle, &event);
retval = _alpm_run_chroot(handle, SCRIPTLET_SHELL, argv, NULL, NULL);
cleanup:
if(scriptfn && unlink(scriptfn)) {

View File

@@ -49,7 +49,7 @@ typedef struct _alpm_trans_t {
void _alpm_trans_free(alpm_trans_t *trans);
/* flags is a bitfield of alpm_transflag_t flags */
int _alpm_trans_init(alpm_trans_t *trans, int flags);
int _alpm_runscriptlet(alpm_handle_t *handle, const char *name, const char *filepath,
int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath,
const char *script, const char *ver, const char *oldver, int is_archive);
#endif /* ALPM_TRANS_H */

View File

@@ -497,21 +497,18 @@ static int _alpm_chroot_write_to_child(alpm_handle_t *handle, int fd,
return 0;
}
static void _alpm_chroot_process_output(alpm_handle_t *handle, const char *name,
alpm_scriptlet_kind_t kind, const char *line)
static void _alpm_chroot_process_output(alpm_handle_t *handle, const char *line)
{
alpm_event_scriptlet_info_t event = {
.type = ALPM_EVENT_SCRIPTLET_INFO,
.kind = kind,
.name = name,
.line = line
};
alpm_logaction(handle, "ALPM-SCRIPTLET", "%s", line);
EVENT(handle, &event);
}
static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, const char *name,
alpm_scriptlet_kind_t kind, char *buf, ssize_t *buf_size, ssize_t buf_limit)
static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd,
char *buf, ssize_t *buf_size, ssize_t buf_limit)
{
ssize_t space = buf_limit - *buf_size - 2; /* reserve 2 for "\n\0" */
ssize_t nread = read(fd, buf + *buf_size, space);
@@ -523,7 +520,7 @@ static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, const cha
size_t linelen = newline - buf + 1;
char old = buf[linelen];
buf[linelen] = '\0';
_alpm_chroot_process_output(handle, name, kind, buf);
_alpm_chroot_process_output(handle, buf);
buf[linelen] = old;
*buf_size -= linelen;
@@ -533,14 +530,14 @@ static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, const cha
} else if(nread == space) {
/* we didn't read a full line, but we're out of space */
strcpy(buf + *buf_size, "\n");
_alpm_chroot_process_output(handle, name, kind, buf);
_alpm_chroot_process_output(handle, buf);
*buf_size = 0;
}
} else if(nread == 0) {
/* end-of-file */
if(*buf_size) {
strcpy(buf + *buf_size, "\n");
_alpm_chroot_process_output(handle, name, kind, buf);
_alpm_chroot_process_output(handle, buf);
}
return -1;
} else if(should_retry(errno)) {
@@ -549,7 +546,7 @@ static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, const cha
/* read error */
if(*buf_size) {
strcpy(buf + *buf_size, "\n");
_alpm_chroot_process_output(handle, name, kind, buf);
_alpm_chroot_process_output(handle, buf);
}
_alpm_log(handle, ALPM_LOG_ERROR,
_("unable to read from pipe (%s)\n"), strerror(errno));
@@ -585,16 +582,14 @@ static void _alpm_reset_signals(void)
/** Execute a command with arguments in a chroot.
* @param handle the context handle
* @param name a human readable name to describe the command
* @param kind what kind of scriptlet is running
* @param cmd command to execute
* @param argv arguments to pass to cmd
* @param stdin_cb callback to provide input to the chroot on stdin
* @param stdin_ctx context to be passed to @a stdin_cb
* @return 0 on success, 1 on error
*/
int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kind_t kind,
const char *cmd, char *const argv[], _alpm_cb_io stdin_cb, void *stdin_ctx)
int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[],
_alpm_cb_io stdin_cb, void *stdin_ctx)
{
pid_t pid;
int child2parent_pipefd[2], parent2child_pipefd[2];
@@ -655,7 +650,6 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kin
close(parent2child_pipefd[HEAD]);
close(child2parent_pipefd[TAIL]);
close(child2parent_pipefd[HEAD]);
if(cwdfd >= 0) {
close(cwdfd);
}
@@ -681,40 +675,27 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kin
unsetenv("BASH_ENV");
umask(0022);
_alpm_reset_signals();
_alpm_handle_free(handle);
execv(cmd, argv);
/* execv only returns if there was an error */
fprintf(stderr, _("%s: failed to execv '%s' (%s)\n"), name, cmd, strerror(errno));
fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno));
exit(1);
} else {
/* this code runs for the parent only (wait on the child) */
int status;
char obuf[PIPE_BUF]; /* writes <= PIPE_BUF are guaranteed atomic */
char ibuf[LINE_MAX];
char sciptlet_name[32];
ssize_t olen = 0, ilen = 0;
nfds_t nfds = 2;
struct pollfd fds[2], *child2parent = &(fds[0]), *parent2child = &(fds[1]);
int poll_ret;
switch(kind) {
case ALPM_SCRIPTLET_KIND_HOOK:
snprintf(sciptlet_name, 32, "hook '%s'", name);
break;
case ALPM_SCRIPTLET_KIND_INSTALL_FILE:
snprintf(sciptlet_name, 32, "'%s.install'", name);
break;
case ALPM_SCRIPTLET_KIND_COMMAND:
strncpy(sciptlet_name, "ldconfig", 32);
break;
}
child2parent->fd = child2parent_pipefd[TAIL];
child2parent->events = POLLIN;
fcntl(child2parent->fd, F_SETFL, O_NONBLOCK);
close(child2parent_pipefd[HEAD]);
close(parent2child_pipefd[TAIL]);
if(stdin_cb) {
parent2child->fd = parent2child_pipefd[HEAD];
parent2child->events = POLLOUT;
@@ -737,7 +718,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kin
}
}
if(child2parent->revents & POLLIN) {
if(_alpm_chroot_read_from_child(handle, child2parent->fd, name, kind,
if(_alpm_chroot_read_from_child(handle, child2parent->fd,
ibuf, &ilen, sizeof(ibuf)) != 0) {
/* we encountered end-of-file or an error */
STOP_POLLING(child2parent);
@@ -760,7 +741,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kin
if(ilen) {
/* buffer would have already been flushed if it had a newline */
strcpy(ibuf + ilen, "\n");
_alpm_chroot_process_output(handle, name, kind, ibuf);
_alpm_chroot_process_output(handle, ibuf);
}
#undef STOP_POLLING
@@ -776,7 +757,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kin
while(waitpid(pid, &status, 0) == -1) {
if(errno != EINTR) {
_alpm_log(handle, ALPM_LOG_ERROR, _("failed to run %s: call to waitpid failed (%s)\n"), sciptlet_name, strerror(errno));
_alpm_log(handle, ALPM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno));
retval = 1;
goto cleanup;
}
@@ -786,8 +767,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kin
if(WIFEXITED(status)) {
_alpm_log(handle, ALPM_LOG_DEBUG, "call to waitpid succeeded\n");
if(WEXITSTATUS(status) != 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("%s did not complete sucessfully (%s exited %d)\n"),
sciptlet_name, cmd, WEXITSTATUS(status));
_alpm_log(handle, ALPM_LOG_ERROR, _("command failed to execute correctly\n"));
retval = 1;
}
} else if(WIFSIGNALED(status) != 0) {
@@ -796,8 +776,8 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kin
if(signal_description == NULL) {
signal_description = _("Unknown signal");
}
_alpm_log(handle, ALPM_LOG_ERROR, _("%s terminated by signal %d: %s\n"),
sciptlet_name, WTERMSIG(status), signal_description);
_alpm_log(handle, ALPM_LOG_ERROR, _("command terminated by signal %d: %s\n"),
WTERMSIG(status), signal_description);
retval = 1;
}
}
@@ -828,9 +808,10 @@ int _alpm_ldconfig(alpm_handle_t *handle)
if(access(line, F_OK) == 0) {
snprintf(line, PATH_MAX, "%s%s", handle->root, LDCONFIG);
if(access(line, X_OK) == 0) {
char *arg0 = strdup(LDCONFIG);
char arg0[32];
char *argv[] = { arg0, NULL };
return _alpm_run_chroot(handle, "ldconfig", ALPM_SCRIPTLET_KIND_COMMAND, LDCONFIG, argv, NULL, NULL);
strcpy(arg0, "ldconfig");
return _alpm_run_chroot(handle, LDCONFIG, argv, NULL, NULL);
}
}

View File

@@ -129,8 +129,8 @@ ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, int fu
typedef ssize_t (*_alpm_cb_io)(void *buf, ssize_t len, void *ctx);
int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kind_t kind,
const char *cmd, char *const argv[], _alpm_cb_io in_cb, void *in_ctx);
int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[],
_alpm_cb_io in_cb, void *in_ctx);
int _alpm_ldconfig(alpm_handle_t *handle);
int _alpm_str_cmp(const void *s1, const void *s2);
char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename);

View File

@@ -233,6 +233,7 @@ if get_option('debug')
'-Wuninitialized',
'-Wunused-but-set-parameter',
'-Wunused-parameter',
'-Wunused-result',
'-Wwrite-strings',
]
add_project_arguments(cc.get_supported_arguments(extra_cflags), language : 'c')
@@ -359,7 +360,9 @@ pkgconfig.generate(
name : 'libalpm',
description : 'Arch Linux package management library',
version : libalpm_version,
url : 'http://archlinux.org/pacman/')
url : 'http://archlinux.org/pacman/',
extra_cflags: [ '-D_FILE_OFFSET_BITS=64' ],
)
pacman_bin = executable(
'pacman',

View File

@@ -26,7 +26,7 @@ MAKEPKG_LIBRARY=${MAKEPKG_LIBRARY:-'@libmakepkgdir@'}
source "$MAKEPKG_LIBRARY/util/option.sh"
source "$MAKEPKG_LIBRARY/util/util.sh"
buildenv_var+=('RUSTFLAGS' 'DEBUG_RUSTFLAGS')
buildenv_vars+=('RUSTFLAGS' 'DEBUG_RUSTFLAGS')
buildenv_functions+=('buildenv_rust')
buildenv_rust() {

View File

@@ -26,6 +26,12 @@ MAKEPKG_LIBRARY=${MAKEPKG_LIBRARY:-'@libmakepkgdir@'}
source "$MAKEPKG_LIBRARY/util/message.sh"
source "$MAKEPKG_LIBRARY/util/pkgbuild.sh"
# Filter the contents of a GnuPG statusfile to only contain understood terms to narrow the file's scope and circumvent
# the use of terms (e.g. NOTATION_DATA) that may contain unescaped binary data
filter_gnupg_statusfile() {
grep -E "(.*SIG| TRUST_.*)"
}
check_pgpsigs() {
(( SKIPPGPCHECK )) && return 0
! source_has_signatures && return 0
@@ -35,6 +41,7 @@ check_pgpsigs() {
local netfile proto pubkey success status fingerprint trusted
local warnings=0
local errors=0
local statusfile_raw="$(mktemp)"
local statusfile=$(mktemp)
local all_sources
@@ -103,7 +110,7 @@ check_pgpsigs() {
printf '\n' >&2
done
rm -f "$statusfile"
rm -f "$statusfile" "$statusfile_raw"
if (( errors )); then
error "$(gettext "One or more PGP signatures could not be verified!")"
@@ -157,7 +164,20 @@ verify_file_signature() {
"") decompress="cat" ;;
esac
$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
# verify the signature and write metadata to a status file
if ! $decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile_raw" --verify "$file" - 2> /dev/null; then
printf '%s\n' "$(gettext "%s is unable to verify the signature.")" "gpg" >&2
errors=1
return 1
fi
# create a statusfile that contains only understood terms
if ! filter_gnupg_statusfile > "$statusfile" < "$statusfile_raw"; then
printf '%s\n' "$(gettext "unable to extract signature metadata.")" >&2
errors=1
return 1
fi
return 0
}
@@ -189,18 +209,33 @@ verify_git_signature() {
printf " %s git repo ... " "${dir##*/}" >&2
git -C "$dir" verify-$fragtype --raw "$fragval" > "$statusfile" 2>&1
if ! grep -qs NEWSIG "$statusfile"; then
printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
# verify the signature and write metadata to a status file
if ! git -C "$dir" verify-$fragtype --raw "$fragval" > "$statusfile_raw" 2>&1; then
printf '%s\n' "$(gettext "%s is unable to verify the signature.")" "git" >&2
errors=1
return 1
fi
# create a statusfile that contains only understood terms
if ! filter_gnupg_statusfile > "$statusfile" < "$statusfile_raw"; then
printf '%s\n' "$(gettext "unable to extract signature metadata.")" >&2
errors=1
return 1
fi
return 0
}
parse_gpg_statusfile() {
local type arg1 arg6 arg10
# ensure the NEWSIG keyword is part of the metadata
if ! grep -qs NEWSIG "$statusfile"; then
printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
errors=1
return 1
fi
while read -r _ type arg1 _ _ _ _ arg6 _ _ _ arg10 _; do
case "$type" in
GOODSIG)

View File

@@ -66,7 +66,7 @@ package_source_files() {
done < <(source_files "$binary")
}
strip_file() {
collect_debug_symbols() {
local binary=$1; shift
if check_option "debug" "y"; then
@@ -118,7 +118,10 @@ strip_file() {
ln -s "$target" "$dbgdir/.build-id/${bid:0:2}/${bid:2}.debug"
fi
fi
}
strip_file(){
local binary=$1; shift
local tempfile=$(mktemp "$binary.XXXXXX")
if strip "$@" "$binary" -o "$tempfile"; then
cat "$tempfile" > "$binary"
@@ -153,7 +156,7 @@ tidy_strip() {
local binary strip_flags
find . -type f -perm -u+w -print0 2>/dev/null | LC_ALL=C sort -z | while IFS= read -rd '' binary ; do
local STRIPLTO=0
local STATICLIB=0
case "$(LC_ALL=C readelf -h "$binary" 2>/dev/null)" in
*Type:*'DYN (Shared object file)'*) # Libraries (.so) or Relocatable binaries
strip_flags="$STRIP_SHARED";;
@@ -164,7 +167,7 @@ tidy_strip() {
*Type:*'REL (Relocatable file)'*) # Libraries (.a) or objects
if ar t "$binary" &>/dev/null; then # Libraries (.a)
strip_flags="$STRIP_STATIC"
STRIPLTO=1
STATICLIB=1
elif [[ $binary = *'.ko' || $binary = *'.o' ]]; then # Kernel module or object file
strip_flags="$STRIP_SHARED"
else
@@ -174,8 +177,9 @@ tidy_strip() {
*)
continue ;;
esac
(( ! STATICLIB )) && collect_debug_symbols "$binary"
strip_file "$binary" ${strip_flags}
(( STRIPLTO )) && strip_lto "$binary"
(( STATICLIB )) && strip_lto "$binary"
done
elif check_option "debug" "y"; then

View File

@@ -1183,9 +1183,6 @@ if have_function pkgver; then
PKGVERFUNC=1
fi
# check we have the software required to process the PKGBUILD
check_software || exit $E_MISSING_MAKEPKG_DEPS
if (( ${#pkgname[@]} > 1 )) || have_function package_${pkgname}; then
SPLITPKG=1
fi
@@ -1216,19 +1213,6 @@ if have_function package; then
PKGFUNC=1
fi
# check if gpg signature is to be created and if signing key is valid
if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
SIGNPKG='y'
if ! gpg --list-secret-key ${GPGKEY:+"$GPGKEY"} &>/dev/null; then
if [[ ! -z $GPGKEY ]]; then
error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
else
error "$(gettext "There is no key in your keyring.")"
fi
exit $E_PRETTY_BAD_PRIVACY
fi
fi
if (( PACKAGELIST )); then
print_all_package_names
exit $E_OK
@@ -1266,6 +1250,22 @@ if (( INFAKEROOT )); then
exit $E_OK
fi
# check we have the software required to process the PKGBUILD
check_software || exit $E_MISSING_MAKEPKG_DEPS
# check if gpg signature is to be created and if signing key is valid
if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
SIGNPKG='y'
if ! gpg --list-secret-key ${GPGKEY:+"$GPGKEY"} &>/dev/null; then
if [[ ! -z $GPGKEY ]]; then
error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
else
error "$(gettext "There is no key in your keyring.")"
fi
exit $E_PRETTY_BAD_PRIVACY
fi
fi
msg "$(gettext "Making package: %s")" "$pkgbase $basever ($(date +%c))"
# if we are creating a source-only package, go no further

View File

@@ -591,10 +591,21 @@ verify_sig() {
error "$(gettext "Cannot use armored signatures for packages: %s")" "$sig"
exit 1
fi
if ! "${GPG_PACMAN[@]}" --status-fd 1 --verify "${files[@]}" | grep -qE '^\[GNUPG:\] TRUST_(FULLY|ULTIMATE).*$'; then
error "$(gettext "The signature identified by %s could not be verified.")" "$sig"
"${GPG_PACMAN[@]}" --status-fd 1 --verify "${files[@]}" | grep -qE '^\[GNUPG:\] TRUST_(FULLY|ULTIMATE).*$'
# return error if GnuPG fails to verify the signature
if [[ "${PIPESTATUS[0]}" -ne 0 ]]; then
error "$(gettext "The signature verification for %s failed.")" "$sig"
ret=1
fi
# return error if the signature is not trusted fully or ultimately
if [[ "${PIPESTATUS[1]}" -ne 0 ]]; then
error "$(gettext "The signature %s is not trusted.")" "$sig"
ret=1
fi
exit $ret
}

View File

@@ -217,10 +217,7 @@ static int number_length(size_t n)
/* callback to handle messages/notifications from libalpm transactions */
void cb_event(void *ctx, alpm_event_t *event)
{
static int install_line_count = 0;
const colstr_t *colstr = &config->colstr;
(void)ctx;
if(config->print) {
console_cursor_move_end();
return;
@@ -316,16 +313,8 @@ void cb_event(void *ctx, alpm_event_t *event)
printf(_("loading package files...\n"));
}
break;
case ALPM_EVENT_INSTALL_RUN_START:
install_line_count = 0;
break;
case ALPM_EVENT_SCRIPTLET_INFO:
/* onlt say we're running the install file if it outputs */
if(install_line_count == 0 && event->scriptlet_info.kind == ALPM_SCRIPTLET_KIND_INSTALL_FILE) {
printf("Running %s.install...\n", event->scriptlet_info.name);
}
install_line_count++;
printf(" %s%s%s", colstr->scriptlet, event->scriptlet_info.line, colstr->nocolor);
fputs(event->scriptlet_info.line, stdout);
break;
case ALPM_EVENT_DB_RETRIEVE_START:
on_progress = 1;
@@ -424,7 +413,6 @@ void cb_event(void *ctx, alpm_event_t *event)
case ALPM_EVENT_DISKSPACE_DONE:
case ALPM_EVENT_HOOK_DONE:
case ALPM_EVENT_HOOK_RUN_DONE:
case ALPM_EVENT_INSTALL_RUN_DONE:
/* nothing */
break;
}
@@ -601,7 +589,7 @@ void cb_progress(void *ctx, alpm_progress_t event, const char *pkgname,
} else {
if(current != prevcurrent) {
/* update always */
} else if(!pkgname || percent == prevpercent ||
} else if(pkgname[0] == '\0' || percent == prevpercent ||
get_update_timediff(0) < UPDATE_SPEED_MS) {
/* only update the progress bar when we have a package name, the
* percentage has changed, and it has been long enough. */
@@ -665,7 +653,7 @@ void cb_progress(void *ctx, alpm_progress_t event, const char *pkgname,
* by the output, and then pad it accordingly so we fill the terminal.
*/
/* len = opr len + pkgname len (if available) + space + null */
len = strlen(opr) + ((pkgname) ? strlen(pkgname) : 0) + 2;
len = strlen(opr) + strlen(pkgname) + 2;
wcstr = calloc(len, sizeof(wchar_t));
/* print our strings to the alloc'ed memory */
#if defined(HAVE_SWPRINTF)
@@ -766,14 +754,11 @@ static void init_total_progressbar(void)
static char *clean_filename(const char *filename)
{
int len = strlen(filename);
char *p;
char *fname = malloc(len + 1);
memcpy(fname, filename, len + 1);
char *fname = strdup(filename);
/* strip package or DB extension for cleaner look */
if((p = strstr(fname, ".pkg")) || (p = strstr(fname, ".db")) || (p = strstr(fname, ".files"))) {
len = p - fname;
fname[len] = '\0';
fname[p - fname] = '\0';
}
return fname;

View File

@@ -63,7 +63,6 @@ config_t *config = NULL;
#define BOLDMAGENTA "\033[1;35m"
#define BOLDCYAN "\033[1;36m"
#define BOLDWHITE "\033[1;37m"
#define BLUE117 "\033[38;5;117m"
#define GREY46 "\033[38;5;243m"
void enable_colors(int colors)
@@ -71,29 +70,27 @@ void enable_colors(int colors)
colstr_t *colstr = &config->colstr;
if(colors == PM_COLOR_ON) {
colstr->colon = BOLDBLUE "::" BOLD " ";
colstr->title = BOLD;
colstr->repo = BOLDMAGENTA;
colstr->version = BOLDGREEN;
colstr->groups = BOLDBLUE;
colstr->meta = BOLDCYAN;
colstr->warn = BOLDYELLOW;
colstr->err = BOLDRED;
colstr->scriptlet = BLUE117;
colstr->faint = GREY46;
colstr->nocolor = NOCOLOR;
colstr->colon = BOLDBLUE "::" BOLD " ";
colstr->title = BOLD;
colstr->repo = BOLDMAGENTA;
colstr->version = BOLDGREEN;
colstr->groups = BOLDBLUE;
colstr->meta = BOLDCYAN;
colstr->warn = BOLDYELLOW;
colstr->err = BOLDRED;
colstr->faint = GREY46;
colstr->nocolor = NOCOLOR;
} else {
colstr->colon = ":: ";
colstr->title = "";
colstr->repo = "";
colstr->version = "";
colstr->groups = "";
colstr->meta = "";
colstr->warn = "";
colstr->err = "";
colstr->scriptlet = "";
colstr->faint = "";
colstr->nocolor = "";
colstr->colon = ":: ";
colstr->title = "";
colstr->repo = "";
colstr->version = "";
colstr->groups = "";
colstr->meta = "";
colstr->warn = "";
colstr->err = "";
colstr->faint = "";
colstr->nocolor = "";
}
}
@@ -175,6 +172,7 @@ void config_repo_free(config_repo_t *repo)
return;
}
free(repo->name);
FREELIST(repo->cache_servers);
FREELIST(repo->servers);
free(repo);
}
@@ -784,15 +782,18 @@ static char *replace_server_vars(config_t *c, config_repo_t *r, const char *s)
}
}
static int _add_mirror(alpm_db_t *db, char *value)
static int replace_server_list_vars(config_t *c, config_repo_t *r, alpm_list_t *list)
{
if(alpm_db_add_server(db, value) != 0) {
/* pm_errno is set by alpm_db_setserver */
pm_printf(ALPM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"),
alpm_db_get_name(db), value, alpm_strerror(alpm_errno(config->handle)));
return 1;
alpm_list_t *i;
for(i = list; i; i = i->next) {
char *newurl = replace_server_vars(c, r, i->data);
if(newurl == NULL) {
return -1;
} else {
free(i->data);
i->data = newurl;
}
}
return 0;
}
@@ -812,8 +813,21 @@ static int register_repo(config_repo_t *repo)
repo->usage, repo->name);
alpm_db_set_usage(db, repo->usage);
for(i = repo->cache_servers; i; i = alpm_list_next(i)) {
const char *value = i->data;
if(alpm_db_add_cache_server(db, value) != 0) {
/* pm_errno is set by alpm_db_setserver */
pm_printf(ALPM_LOG_ERROR, _("could not add cache server URL to database '%s': %s (%s)\n"),
alpm_db_get_name(db), value, alpm_strerror(alpm_errno(config->handle)));
return 1;
}
}
for(i = repo->servers; i; i = alpm_list_next(i)) {
if(_add_mirror(db, i->data) != 0) {
const char *value = i->data;
if(alpm_db_add_server(db, value) != 0) {
/* pm_errno is set by alpm_db_setserver */
pm_printf(ALPM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"),
alpm_db_get_name(db), value, alpm_strerror(alpm_errno(config->handle)));
return 1;
}
}
@@ -993,7 +1007,10 @@ static int _parse_repo(const char *key, char *value, const char *file,
} \
} while(0)
if(strcmp(key, "Server") == 0) {
if(strcmp(key, "CacheServer") == 0) {
CHECK_VALUE(value);
repo->cache_servers = alpm_list_add(repo->cache_servers, strdup(value));
} else if(strcmp(key, "Server") == 0) {
CHECK_VALUE(value);
repo->servers = alpm_list_add(repo->servers, strdup(value));
} else if(strcmp(key, "SigLevel") == 0) {
@@ -1147,12 +1164,24 @@ int setdefaults(config_t *c)
}
char path[PATH_MAX];
if(!c->dbpath) {
char* ppath;
snprintf(path, PATH_MAX, "%s/%s", rootdir, &DBPATH[1]);
SETDEFAULT(c->dbpath, strdup(path));
ppath = strdup(path);
if(ppath == NULL) {
free(rootdir);
return -1;
}
SETDEFAULT(c->dbpath, ppath);
}
if(!c->logfile) {
char* ppath;
snprintf(path, PATH_MAX, "%s/%s", rootdir, &LOGFILE[1]);
SETDEFAULT(c->logfile, strdup(path));
ppath = strdup(path);
if(ppath == NULL) {
free(rootdir);
return -1;
}
SETDEFAULT(c->logfile, ppath);
}
free(rootdir);
} else {
@@ -1173,17 +1202,11 @@ int setdefaults(config_t *c)
for(i = c->repos; i; i = i->next) {
config_repo_t *r = i->data;
alpm_list_t *j;
SETDEFAULT(r->usage, ALPM_DB_USAGE_ALL);
r->siglevel = merge_siglevel(c->siglevel, r->siglevel, r->siglevel_mask);
for(j = r->servers; j; j = j->next) {
char *newurl = replace_server_vars(c, r, j->data);
if(newurl == NULL) {
return -1;
} else {
free(j->data);
j->data = newurl;
}
if(replace_server_list_vars(c, r, r->cache_servers) == -1
|| replace_server_list_vars(c, r, r->servers) == -1) {
return -1;
}
}

View File

@@ -32,12 +32,12 @@ typedef struct __colstr_t {
const char *warn;
const char *err;
const char *faint;
const char *scriptlet;
const char *nocolor;
} colstr_t;
typedef struct __config_repo_t {
char *name;
alpm_list_t *cache_servers;
alpm_list_t *servers;
int usage;
int siglevel;

View File

@@ -103,7 +103,7 @@ static int check_db_missing_deps(alpm_list_t *pkglist)
pm_printf(ALPM_LOG_ERROR, "missing '%s' dependency for '%s'\n",
depstring, miss->target);
free(depstring);
ret++;
ret = 1;
}
alpm_list_free_inner(data, (alpm_list_fn_free)alpm_depmissing_free);
alpm_list_free(data);
@@ -135,12 +135,12 @@ static int check_db_local_files(void)
snprintf(path, PATH_MAX, "%slocal/%s/desc", dbpath, ent->d_name);
if(access(path, F_OK)) {
pm_printf(ALPM_LOG_ERROR, "'%s': description file is missing\n", ent->d_name);
ret++;
ret = 1;
}
snprintf(path, PATH_MAX, "%slocal/%s/files", dbpath, ent->d_name);
if(access(path, F_OK)) {
pm_printf(ALPM_LOG_ERROR, "'%s': file list is missing\n", ent->d_name);
ret++;
ret = 1;
}
}
closedir(dbdir);
@@ -158,7 +158,7 @@ static int check_db_local_package_conflicts(alpm_list_t *pkglist)
alpm_conflict_t *conflict = i->data;
pm_printf(ALPM_LOG_ERROR, "'%s' conflicts with '%s'\n",
alpm_pkg_get_name(conflict->package1), alpm_pkg_get_name(conflict->package2));
ret++;
ret = 1;
}
alpm_list_free_inner(data, (alpm_list_fn_free)alpm_conflict_free);
alpm_list_free(data);
@@ -228,6 +228,7 @@ static int check_db_local_filelist_conflicts(alpm_list_t *pkglist)
alpm_pkg_get_name(prev_fileitem->pkg),
alpm_pkg_get_name(fileitem->pkg),
fileitem->file->name);
ret = 1;
}
prev_fileitem = fileitem;
}

View File

@@ -236,6 +236,7 @@ static void dump_repo(config_repo_t *repo)
{
show_usage("Usage", repo->usage);
show_siglevel("SigLevel", repo->siglevel, 0);
show_list_str("CacheServer", repo->cache_servers);
show_list_str("Server", repo->servers);
}
@@ -310,6 +311,8 @@ static int list_repo_directives(void)
for(i = directives; i; i = i->next) {
if(strcasecmp(i->data, "Server") == 0) {
show_list_str("Server", repo->servers);
} else if(strcasecmp(i->data, "CacheServer") == 0) {
show_list_str("CacheServer", repo->cache_servers);
} else if(strcasecmp(i->data, "SigLevel") == 0) {
show_siglevel("SigLevel", repo->siglevel, 0);
} else if(strcasecmp(i->data, "Usage") == 0) {

View File

@@ -381,7 +381,7 @@ static int parsearg_global(int opt)
break;
case OP_ASK:
config->noask = 1;
config->ask = (unsigned int)atoi(optarg);
config->ask = (unsigned int)strtol(optarg, NULL, 10);
break;
case OP_CACHEDIR:
config->cachedirs = alpm_list_add(config->cachedirs, strdup(optarg));
@@ -409,7 +409,7 @@ static int parsearg_global(int opt)
* here, error and warning are set in config_new, though perhaps a
* --quiet option will remove these later */
if(optarg) {
unsigned short debug = (unsigned short)atoi(optarg);
int debug = strtol(optarg, NULL, 10);
switch(debug) {
case 2:
config->logmask |= ALPM_LOG_FUNCTION;

View File

@@ -83,7 +83,11 @@ static int sync_cleandb(const char *dbpath)
}
/* build the full path */
snprintf(path, PATH_MAX, "%s%s", dbpath, dname);
len = snprintf(path, PATH_MAX, "%s%s", dbpath, dname);
if(len > PATH_MAX) {
pm_printf(ALPM_LOG_ERROR, _("could not remove %s%s: path exceeds PATH_MAX\n"),
dbpath, dname);
}
/* remove all non-skipped directories and non-database files */
if(stat(path, &buf) == -1) {
@@ -211,6 +215,7 @@ static int sync_cleancache(int level)
int delete = 1;
alpm_pkg_t *localpkg = NULL, *pkg = NULL;
const char *local_name, *local_version;
size_t len;
if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
continue;
@@ -239,7 +244,12 @@ static int sync_cleancache(int level)
}
/* build the full filepath */
snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name);
len=snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name);
if(len > PATH_MAX) {
pm_printf(ALPM_LOG_ERROR, _("skipping %s%s: path exceeds PATH_MAX\n"),
cachedir, ent->d_name);
continue;
}
/* short circuit for removing all files from cache */
if(level > 1) {

View File

@@ -462,7 +462,7 @@ static size_t string_length(const char *s)
int iter = 0;
for(; *s; s++) {
if(*s == '\033') {
while(*s != 'm') {
while(*s != 'm' && *s != '\0') {
s++;
}
} else {
@@ -1262,6 +1262,7 @@ void print_packages(const alpm_list_t *packages)
string = strreplace(temp, "%s", size);
free(size);
free(temp);
temp = string;
}
/* %u : url */
PRINT_FORMAT_STRING(temp, "%u", alpm_pkg_get_url)

View File

@@ -1,5 +1,6 @@
pacman_tests = [
'tests/backup001.py',
'tests/cache-server-basic.py',
'tests/clean001.py',
'tests/clean002.py',
'tests/clean003.py',
@@ -96,6 +97,9 @@ pacman_tests = [
'tests/pacman003.py',
'tests/pacman004.py',
'tests/pacman005.py',
'tests/pkg-meta-invalid-name-file.py',
'tests/pkg-meta-invalid-name-local.py',
'tests/pkg-meta-invalid-name-sync.py',
'tests/provision001.py',
'tests/provision002.py',
'tests/provision003.py',

View File

@@ -60,6 +60,7 @@ class pmtest(object):
if not treename in self.db:
self.db[treename] = pmdb.pmdb(treename, self.root)
self.db[treename].pkgs.append(pkg)
return pkg
def addpkg(self, pkg):
self.localpkgs.append(pkg)

View File

@@ -0,0 +1,37 @@
self.description = "basic cache server test"
self.require_capability("curl")
pkgs = [ self.addpkg2db('sync', pmpkg("pkg{}".format(i))) for i in range(0, 5) ]
# TODO: hack to prevent pacman trying to validate the downloaded packages
p404 = pmpkg('pkg404')
self.addpkg2db('sync', p404)
cache_url = self.add_simple_http_server({
'/{}'.format(pkgs[0].filename()): { 'body': 'CacheServer' },
# 404 for packages 1-3
'/{}'.format(pkgs[4].filename()): { 'body': 'CacheServer' },
})
normal_url = self.add_simple_http_server({
'/{}'.format(pkgs[0].filename()): { 'body': 'Server' },
'/{}'.format(pkgs[1].filename()): { 'body': 'Server' },
'/{}'.format(pkgs[2].filename()): { 'body': 'Server' },
'/{}'.format(pkgs[3].filename()): { 'body': 'Server' },
'/{}'.format(pkgs[4].filename()): { 'body': 'Server' },
})
self.db['sync'].option['CacheServer'] = [ cache_url ]
self.db['sync'].option['Server'] = [ normal_url ]
self.db['sync'].syncdir = False
self.cachepkgs = False
self.args = '-S pkg0 pkg1 pkg2 pkg3 pkg4 pkg404'
#self.addrule("PACMAN_RETCODE=0") # TODO
self.addrule("PACMAN_OUTPUT={}".format(normal_url.replace("http://", "")))
self.addrule("!PACMAN_OUTPUT={}".format(cache_url.replace("http://", "")))
self.addrule("CACHE_FCONTENTS={}|CacheServer".format(pkgs[0].filename()))
self.addrule("CACHE_FCONTENTS={}|Server".format(pkgs[1].filename()))
self.addrule("CACHE_FCONTENTS={}|Server".format(pkgs[2].filename()))
self.addrule("CACHE_FCONTENTS={}|Server".format(pkgs[3].filename()))
self.addrule("CACHE_FCONTENTS={}|CacheServer".format(pkgs[4].filename()))

View File

@@ -0,0 +1,9 @@
self.description = "package name with invalid characters cannot be installed (file)"
p = pmpkg("-foo")
self.addpkg(p)
self.args = "-U -- %s" % p.filename()
self.addrule("!PACMAN_RETCODE=0")
self.addrule("!PKG_EXIST=-foo")

View File

@@ -0,0 +1,9 @@
self.description = "local package name with invalid characters can be removed"
sp = pmpkg("-foo")
self.addpkg2db("local", sp)
self.args = "-R -- %s" % sp.name
self.addrule("PACMAN_RETCODE=0")
self.addrule("!PKG_EXIST=-foo")

View File

@@ -0,0 +1,9 @@
self.description = "package name with invalid characters cannot be installed"
sp = pmpkg("-foo")
self.addpkg2db("sync", sp)
self.args = "-S -- %s" % sp.name
self.addrule("!PACMAN_RETCODE=0")
self.addrule("!PKG_EXIST=-foo")