diff options
86 files changed, 1944 insertions, 1767 deletions
diff --git a/PKGBUILD-split.proto b/PKGBUILD-split.proto index 08f98d62..68a8cc4d 100644 --- a/PKGBUILD-split.proto +++ b/PKGBUILD-split.proto @@ -21,6 +21,7 @@ replaces=() backup=() options=() install= +changelog= source=($pkgbase-$pkgver.tar.gz) noextract=() md5sums=() #generate with 'makepkg -g' @@ -33,7 +34,10 @@ build() { package_pkg1() { # options and directives that can be overridden + pkgver= + pkgrel= pkgdesc="" + arch=() license=() groups=() depends=() @@ -44,6 +48,7 @@ package_pkg1() { backup=() options=() install= + changelog= cd "$srcdir/$pkgbase-$pkgver" make DESTDIR="$pkgdir/" install-pkg1 diff --git a/PKGBUILD.proto b/PKGBUILD.proto index eddcf759..93da0fc5 100644 --- a/PKGBUILD.proto +++ b/PKGBUILD.proto @@ -21,6 +21,7 @@ replaces=() backup=() options=() install= +changelog= source=($pkgname-$pkgver.tar.gz) noextract=() md5sums=() #generate with 'makepkg -g' @@ -57,7 +57,6 @@ library is initialized. * dbpath: The toplevel database directory (Default: /var/lib/pacman) * logfile: The base path to pacman's log file (Default: /var/log/pacman.log) * usesyslog: Log to syslog instead of `logfile` for file-base logging. -* nopassiveftp: Do not use passive FTP commands for ftp connections. The following options also have `alpm_option_{add,remove}_*` functions, as the values are list structures. diff --git a/contrib/PKGBUILD.vim b/contrib/PKGBUILD.vim index 994eaccb..af0f9817 100644 --- a/contrib/PKGBUILD.vim +++ b/contrib/PKGBUILD.vim @@ -115,6 +115,12 @@ syn match pbValidInstall /\([[:alnum:]]\|\$\|+\|-\|_\)*\.install/ contained syn match pbIllegalInstall /[^=]/ contained contains=pbValidInstall syn match pbInstallGroup /^install=.*/ contains=pb_k_install,pbValidInstall,pbIllegalInstall,shDeref,shDoubleQuote,shSingleQuote +" changelog +syn keyword pb_k_changelog changelog contained +syn match pbValidChangelog /\([[:alnum:]]\|\$\|+\|-\|_\)*/ contained +syn match pbIllegalChangelog /[^=]/ contained contains=pbValidChangelog +syn match pbChangelogGroup /^changelog=.*/ contains=pb_k_changelog,pbValidChangelog,pbIllegalChangelog,shDeref,shDoubleQuote,shSingleQuote + " source: " XXX remove source from shStatement, fix strange bug syn clear shStatement @@ -212,6 +218,9 @@ hi def link pb_k_provides pbKeywords hi def link pbIllegalInstall Error hi def link pb_k_install pbKeywords +hi def link pbIllegalChangelog Error +hi def link pb_k_changelog pbKeywords + hi def link pb_k_source pbKeywords hi def link pbIllegalSource Error diff --git a/doc/Makefile.am b/doc/Makefile.am index de2c5eec..fcbcab88 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -85,12 +85,12 @@ ASCIIDOC_OPTS = \ -a pacman_version="$(REAL_PACKAGE_VERSION)" \ -a pacman_date="`date +%Y-%m-%d`" \ -a sysconfdir=$(sysconfdir) + A2X_OPTS = \ --no-xmllint \ -d manpage \ -f manpage \ - --xsltproc-opts='-param man.endnotes.list.enabled 0' \ - --xsltproc-opts='-param man.endnotes.are.numbered 0' + --xsltproc-opts='-param man.endnotes.list.enabled 0 -param man.endnotes.are.numbered 0' # These rules are due to the includes and files of the asciidoc text $(ASCIIDOC_MANS): asciidoc.conf footer.txt diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index 83cebcdb..28dd8c7c 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -79,6 +79,12 @@ similar to `$_basekernver`. be copied into the package by makepkg. It does not need to be included in the source array (e.g. `install=pkgname.install`). +*changelog*:: + Specifies a changelog file that is to be included in the package. + This file should reside in the same directory as the PKGBUILD, and will + be copied into the package by makepkg. It does not need to be included + in the source array (e.g. `changelog=$pkgname.changelog`). + *source (array)*:: An array of source files required to build the package. Source files must either reside in the same directory as the PKGBUILD file, or be a @@ -145,7 +151,7 @@ name. The syntax is: `source=('filename::url')`. base functionality, but may be necessary to make full use of the contents of this package. optdepends are currently for informational purposes only and are not utilized by pacman during dependency resolution. The format - should be similar to the following: + for specifying optdepends is: optdepends=('fakeroot: for makepkg usage as normal user') @@ -269,9 +275,9 @@ name of the split package. All options and directives for the split packages default to the global values given within the PKGBUILD. However, some of these can be overridden within each split -package's packaging function. The following variables can be overridden: `pkgdesc`, -`license`, `groups`, `depends`, `optdepends`, `provides`, `conflicts`, `replaces`, -`backup`, `options` and `install`. +package's packaging function. The following variables can be overridden: `pkgver`, +`pkgrel`, `pkgdesc`, `arch`, `license`, `groups`, `depends`, `optdepends`, +`provides`, `conflicts`, `replaces`, `backup`, `options`, `install` and `changelog`. An optional global directive is available when building a split package: diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index b288a592..7f92ec71 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -82,7 +82,8 @@ to determine which packages need upgrading. This behavior operates as follows: "bash>=3.2"`. *-U, \--upgrade*:: - Upgrade or add package(s) to the system. Either a URL or file path can be + Upgrade or add package(s) to the system and install the required + dependencies from sync repos. Either a URL or file path can be specified. This is a ``remove-then-add'' process. See <<HCF,Handling Config Files>> for an explanation on how pacman takes care of config files. @@ -166,6 +167,8 @@ Options If an install scriptlet exists, do not execute it. Do not use this unless you know what you are doing. +*\--arch* <'arch'>:: + Specify an alternate architecture. Query Options[[QO]] ------------------- @@ -330,7 +333,9 @@ linkman:pacman.conf[5]. necessary. Pass this option twice to enable package downgrade; in this case pacman will select sync packages whose version does not match with the local version. This can be useful when the user switches from a testing - repo to a stable one. + repo to a stable one. Additional targets can also be specified manually, so + that '-Su foo' will do a system upgrade and install/upgrade the foo package in + the same operation. *-w, \--downloadonly*:: Retrieve all packages from the server, but do not install/upgrade diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index 3e361102..89c22a12 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -100,6 +100,14 @@ Options Include another config file. This file can include repositories or general configuration options. +*Architecture =* auto | i686 | x86_64 | ...:: + If set, pacman will only allow installation of packages of the given + architecture (e.g. 'i686', 'x86_64', etc). The special value 'auto' will + use the system architecture, provided by in ``uname -m''. If unset, no + architecture checks are made. *NOTE*: packages with the special + architecture 'any' can always be installed, as they are meant to be + architecture independent. + *XferCommand =* /path/to/command %u:: If set, an external program will be used to download all remote files. All instances of `%u` will be replaced with the download URL. If present, @@ -111,9 +119,6 @@ Options http/ftp support, or need the more advanced proxy support that comes with utilities like wget. -*NoPassiveFtp*:: - Disables passive ftp connections when downloading packages. (aka Active Mode) - *NoUpgrade =* file ...:: All files listed with a `NoUpgrade` directive will never be touched during a package install/upgrade, and the new files will be installed with a @@ -179,10 +184,12 @@ Include = /etc/pacman.d/mirrorlist During parsing, pacman will define the `$repo` variable to the name of the current section. This is often utilized in files specified using the 'Include' -directive so all repositories can use the same mirrorfile. +directive so all repositories can use the same mirrorfile. pacman also defines +the `$arch` variable to the value of `Architecture`, so the same mirrorfile can +even be used for different architectures. -------- -Server = ftp://ftp.archlinux.org/$repo/os/arch +Server = ftp://ftp.archlinux.org/$repo/os/$arch -------- The order of repositories in the configuration files matters; repositories diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index 1368ff1f..3a3a4154 100644 --- a/etc/makepkg.conf.in +++ b/etc/makepkg.conf.in @@ -26,7 +26,7 @@ DLAGENTS=('ftp::/usr/bin/wget -c --passive-ftp -t 3 --waitretry=3 -O %o %u' CARCH="@CARCH@" CHOST="@CHOST@" -#-- Exclusive: will only run on @CARCHFLAGS@ +#-- Exclusive: will only run on @CARCH@ # -march (or -mcpu) builds exclusively for an architecture # -mtune optimizes for an architecture, but builds for whole processor family CFLAGS="@CARCHFLAGS@-mtune=generic -O2 -pipe" diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in index 30bfc321..fc841b70 100644 --- a/etc/pacman.conf.in +++ b/etc/pacman.conf.in @@ -19,6 +19,7 @@ SyncFirst = pacman #XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u #XferCommand = /usr/bin/curl %u > %o #CleanMethod = KeepInstalled +Architecture = auto # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup #IgnorePkg = @@ -28,7 +29,6 @@ SyncFirst = pacman #NoExtract = # Misc options (all disabled by default) -#NoPassiveFtp #UseSyslog #ShowSize #UseDelta @@ -42,6 +42,7 @@ SyncFirst = pacman # - repositories listed first will take precedence when packages # have identical names, regardless of version number # - URLs will have $repo replaced by the name of the current repo +# - URLs will have $arch replaced by the name of the architecture # # Repository entries are of the format: # [repo-name] @@ -57,7 +58,7 @@ SyncFirst = pacman # servers immediately after the header and they will be used before the # default mirrors. #[core] -#Server = ftp://ftp.example.com/foobar/$repo/os/i686/ +#Server = ftp://ftp.example.com/foobar/$repo/os/$arch/ # The file referenced here should contain a list of 'Server = ' lines. #Include = @sysconfdir@/pacman.d/mirrorlist diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 1d143c6f..ebcd6a55 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -50,21 +50,30 @@ #include "remove.h" #include "handle.h" -int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) +/** Add a file target to the transaction. + * @param target the name of the file target to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_add_target(char *target) { pmpkg_t *pkg = NULL; const char *pkgname, *pkgver; alpm_list_t *i; + pmtrans_t *trans; ALPM_LOG_FUNC; + /* Sanity checks */ + ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + trans = handle->trans; + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(name != NULL && strlen(name) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", name); + _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", target); - if(alpm_pkg_load(name, 1, &pkg) != 0) { + if(alpm_pkg_load(target, 1, &pkg) != 0) { goto error; } pkgname = alpm_pkg_get_name(pkg); @@ -72,17 +81,19 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) /* check if an older version of said package is already in transaction * packages. if so, replace it in the list */ - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *transpkg = i->data; if(strcmp(transpkg->name, pkgname) == 0) { if(alpm_pkg_vercmp(transpkg->version, pkgver) < 0) { - _alpm_log(PM_LOG_WARNING, _("replacing older version %s-%s by %s in target list\n"), - transpkg->name, transpkg->version, pkgver); + _alpm_log(PM_LOG_WARNING, + _("replacing older version %s-%s by %s in target list\n"), + transpkg->name, transpkg->version, pkgver); _alpm_pkg_free(i->data); i->data = pkg; } else { - _alpm_log(PM_LOG_WARNING, _("skipping %s-%s because newer version %s is in target list\n"), - pkgname, pkgver, transpkg->version); + _alpm_log(PM_LOG_WARNING, + _("skipping %s-%s because newer version %s is in target list\n"), + pkgname, pkgver, transpkg->version); _alpm_pkg_free(pkg); } return(0); @@ -90,7 +101,7 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) } /* add the package to the transaction */ - trans->packages = alpm_list_add(trans->packages, pkg); + trans->add = alpm_list_add(trans->add, pkg); return(0); @@ -99,176 +110,6 @@ error: return(-1); } -int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) -{ - alpm_list_t *lp = NULL; - - ALPM_LOG_FUNC; - - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - - /* Check dependencies - */ - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); - - /* look for unsatisfied dependencies */ - _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, NULL, trans->packages); - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); - alpm_list_free(lp); - } - RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1); - } - - /* no unsatisfied deps, so look for conflicts */ - _alpm_log(PM_LOG_DEBUG, "looking for conflicts\n"); - alpm_list_t *inner = _alpm_innerconflicts(trans->packages); - alpm_list_t *outer = _alpm_outerconflicts(db, trans->packages); - lp = alpm_list_join(inner, outer); - - /* TODO : factorize the conflict resolving code from sync.c to use it here (FS#3492) */ - - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_conflict_free); - alpm_list_free(lp); - } - if(inner) { - _alpm_log(PM_LOG_ERROR, _("conflicting packages were found in target list\n")); - _alpm_log(PM_LOG_ERROR, _("you cannot install two conflicting packages at the same time\n")); - } - if(outer) { - _alpm_log(PM_LOG_ERROR, _("replacing packages with -U is not supported yet\n")); - _alpm_log(PM_LOG_ERROR, _("you can replace packages manually using -Rd and -U\n")); - } - RET_ERR(PM_ERR_CONFLICTING_DEPS, -1); - } - - /* re-order w.r.t. dependencies */ - _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); - lp = _alpm_sortbydeps(trans->packages, 0); - /* free the old alltargs */ - alpm_list_free(trans->packages); - trans->packages = lp; - - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL); - } - - /* Check for file conflicts */ - if(!(trans->flags & PM_TRANS_FLAG_FORCE)) { - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); - - _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - lp = _alpm_db_find_fileconflicts(db, trans, trans->packages, NULL); - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_fileconflict_free); - alpm_list_free(lp); - } - RET_ERR(PM_ERR_FILE_CONFLICTS, -1); - } - - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); - } - - return(0); -} - -static int upgrade_remove(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans, pmdb_t *db) { - /* this is kinda odd. If the old package exists, at this point we make a - * NEW transaction, unrelated to handle->trans, and instantiate a "remove" - * with the type PM_TRANS_TYPE_REMOVEUPGRADE. TODO: kill this weird - * behavior. */ - pmtrans_t *tr = _alpm_trans_new(); - - ALPM_LOG_FUNC; - - _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n", - oldpkg->name, oldpkg->version); - - if(!tr) { - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - if(_alpm_trans_init(tr, PM_TRANS_TYPE_REMOVEUPGRADE, trans->flags, - NULL, NULL, NULL) == -1) { - _alpm_trans_free(tr); - tr = NULL; - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - if(_alpm_remove_loadtarget(tr, db, newpkg->name) == -1) { - _alpm_trans_free(tr); - tr = NULL; - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - /* copy the remove skiplist over */ - tr->skip_remove = alpm_list_strdup(trans->skip_remove); - const alpm_list_t *b; - - /* Add files in the NEW backup array to the NoUpgrade array - * so this removal operation doesn't kill them */ - alpm_list_t *old_noupgrade = alpm_list_strdup(handle->noupgrade); - /* old package backup list */ - alpm_list_t *filelist = alpm_pkg_get_files(newpkg); - for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { - char *backup = _alpm_backup_file(b->data); - /* safety check (fix the upgrade026 pactest) */ - if(!alpm_list_find_str(filelist, backup)) { - FREE(backup); - continue; - } - _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n", - backup); - handle->noupgrade = alpm_list_add(handle->noupgrade, - backup); - } - - /* TODO: we could also add files in the OLD backup array, but this would - * change the backup handling behavior, and break several pactests, and we - * can't do this just before 3.1 release. - * The unlink_file function in remove.c would also need to be reviewed. */ -#if 0 - /* new package backup list */ - for(b = alpm_pkg_get_backup(oldpkg); b; b = b->next) { - char *backup = _alpm_backup_file(b->data); - /* make sure we don't add duplicate entries */ - if(!alpm_list_find_ptr(handle->noupgrade, backup)) { - _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n", - backup); - handle->noupgrade = alpm_list_add(handle->noupgrade, - backup); - } - } -#endif - - int ret = _alpm_remove_commit(tr, db); - - _alpm_trans_free(tr); - tr = NULL; - - /* restore our "NoUpgrade" list to previous state */ - FREELIST(handle->noupgrade); - handle->noupgrade = old_noupgrade; - - if(ret == -1) { - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - return(0); -} - static int extract_single_file(struct archive *archive, struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg, pmtrans_t *trans, pmdb_t *db) @@ -291,13 +132,13 @@ static int extract_single_file(struct archive *archive, if(strcmp(entryname, ".INSTALL") == 0) { /* the install script goes inside the db */ - snprintf(filename, PATH_MAX, "%s%s-%s/install", db->path, - newpkg->name, newpkg->version); + snprintf(filename, PATH_MAX, "%s%s-%s/install", + _alpm_db_path(db), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(strcmp(entryname, ".CHANGELOG") == 0) { /* the changelog goes inside the db */ - snprintf(filename, PATH_MAX, "%s%s-%s/changelog", db->path, - newpkg->name, newpkg->version); + snprintf(filename, PATH_MAX, "%s%s-%s/changelog", + _alpm_db_path(db), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(*entryname == '.') { /* for now, ignore all files starting with '.' that haven't @@ -358,7 +199,7 @@ static int extract_single_file(struct archive *archive, /* case 12: existing dir, ignore it */ if(lsbuf.st_mode != entrymode) { /* if filesystem perms are different than pkg perms, warn user */ - int mask = 07777; + mode_t mask = 07777; _alpm_log(PM_LOG_WARNING, _("directory permissions differ on %s\n" "filesystem: %o package: %o\n"), entryname, lsbuf.st_mode & mask, entrymode & mask); @@ -642,8 +483,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, ALPM_LOG_FUNC; - snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path, - alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); + snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", + _alpm_db_path(db), alpm_pkg_get_name(newpkg), + alpm_pkg_get_version(newpkg)); /* see if this is an upgrade. if so, remove the old package first */ pmpkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name); @@ -691,8 +533,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, if(oldpkg) { /* set up fake remove transaction */ - int ret = upgrade_remove(oldpkg, newpkg, trans, db); - if(ret != 0) { + if(_alpm_upgraderemove_package(oldpkg, newpkg, trans) == -1) { + pm_errno = PM_ERR_TRANS_ABORT; + ret = -1; goto cleanup; } } @@ -858,7 +701,7 @@ cleanup: return(ret); } -int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) +int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) { int pkg_count, pkg_current; alpm_list_t *targ; @@ -868,15 +711,15 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - if(trans->packages == NULL) { + if(trans->add == NULL) { return(0); } - pkg_count = alpm_list_count(trans->packages); + pkg_count = alpm_list_count(trans->add); pkg_current = 1; /* loop through our package list adding/upgrading one at a time */ - for(targ = trans->packages; targ; targ = targ->next) { + for(targ = trans->add; targ; targ = targ->next) { if(handle->trans->state == STATE_INTERRUPTED) { return(0); } diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h index 6983de9e..b0467507 100644 --- a/lib/libalpm/add.h +++ b/lib/libalpm/add.h @@ -24,9 +24,7 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name); -int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data); -int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db); +int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db); #endif /* _ALPM_ADD_H */ diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index ce8c6919..c433b73d 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -67,10 +67,10 @@ const char *alpm_version(void); /* Levels */ typedef enum _pmloglevel_t { - PM_LOG_ERROR = 0x01, - PM_LOG_WARNING = 0x02, - PM_LOG_DEBUG = 0x04, - PM_LOG_FUNCTION = 0x08 + PM_LOG_ERROR = 1, + PM_LOG_WARNING = (1 << 1), + PM_LOG_DEBUG = (1 << 2), + PM_LOG_FUNCTION = (1 << 3) } pmloglevel_t; typedef void (*alpm_cb_log)(pmloglevel_t, char *, va_list); @@ -128,8 +128,8 @@ int alpm_option_set_logfile(const char *logfile); const char *alpm_option_get_lockfile(); /* no set_lockfile, path is determined from dbpath */ -unsigned short alpm_option_get_usesyslog(); -void alpm_option_set_usesyslog(unsigned short usesyslog); +int alpm_option_get_usesyslog(); +void alpm_option_set_usesyslog(int usesyslog); alpm_list_t *alpm_option_get_noupgrades(); void alpm_option_add_noupgrade(const char *pkg); @@ -151,9 +151,11 @@ void alpm_option_add_ignoregrp(const char *grp); void alpm_option_set_ignoregrps(alpm_list_t *ignoregrps); int alpm_option_remove_ignoregrp(const char *grp); -unsigned short alpm_option_get_nopassiveftp(); -void alpm_option_set_nopassiveftp(unsigned short nopasv); -void alpm_option_set_usedelta(unsigned short usedelta); +const char *alpm_option_get_arch(); +void alpm_option_set_arch(const char *arch); + +int alpm_option_get_usedelta(); +void alpm_option_set_usedelta(int usedelta); pmdb_t *alpm_option_get_localdb(); alpm_list_t *alpm_option_get_syncdbs(); @@ -194,7 +196,7 @@ typedef enum _pmpkgreason_t { PM_PKG_REASON_DEPEND = 1 /* installed as a dependency for another package */ } pmpkgreason_t; -int alpm_pkg_load(const char *filename, unsigned short full, pmpkg_t **pkg); +int alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg); int alpm_pkg_free(pmpkg_t *pkg); int alpm_pkg_checkmd5sum(pmpkg_t *pkg); char *alpm_fetch_pkgurl(const char *url); @@ -224,15 +226,14 @@ alpm_list_t *alpm_pkg_get_deltas(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_replaces(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg); -alpm_list_t *alpm_pkg_get_removes(pmpkg_t *pkg); pmdb_t *alpm_pkg_get_db(pmpkg_t *pkg); void *alpm_pkg_changelog_open(pmpkg_t *pkg); size_t alpm_pkg_changelog_read(void *ptr, size_t size, const pmpkg_t *pkg, const void *fp); /*int alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp);*/ int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp); -unsigned short alpm_pkg_has_scriptlet(pmpkg_t *pkg); -unsigned short alpm_pkg_has_force(pmpkg_t *pkg); +int alpm_pkg_has_scriptlet(pmpkg_t *pkg); +int alpm_pkg_has_force(pmpkg_t *pkg); off_t alpm_pkg_download_size(pmpkg_t *newpkg); @@ -262,34 +263,27 @@ pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync); * Transactions */ -/* Types */ -typedef enum _pmtranstype_t { - PM_TRANS_TYPE_UPGRADE = 1, - PM_TRANS_TYPE_REMOVE, - PM_TRANS_TYPE_REMOVEUPGRADE, - PM_TRANS_TYPE_SYNC -} pmtranstype_t; /* Flags */ typedef enum _pmtransflag_t { - PM_TRANS_FLAG_NODEPS = 0x01, - PM_TRANS_FLAG_FORCE = 0x02, - PM_TRANS_FLAG_NOSAVE = 0x04, - /* 0x08 flag can go here */ - PM_TRANS_FLAG_CASCADE = 0x10, - PM_TRANS_FLAG_RECURSE = 0x20, - PM_TRANS_FLAG_DBONLY = 0x40, - /* 0x80 flag can go here */ - PM_TRANS_FLAG_ALLDEPS = 0x100, - PM_TRANS_FLAG_DOWNLOADONLY = 0x200, - PM_TRANS_FLAG_NOSCRIPTLET = 0x400, - PM_TRANS_FLAG_NOCONFLICTS = 0x800, - /* 0x1000 flag can go here */ - PM_TRANS_FLAG_NEEDED = 0x2000, - PM_TRANS_FLAG_ALLEXPLICIT = 0x4000, - PM_TRANS_FLAG_UNNEEDED = 0x8000, - PM_TRANS_FLAG_RECURSEALL = 0x10000, - PM_TRANS_FLAG_NOLOCK = 0x20000 + PM_TRANS_FLAG_NODEPS = 1, + PM_TRANS_FLAG_FORCE = (1 << 1), + PM_TRANS_FLAG_NOSAVE = (1 << 2), + /* (1 << 3) flag can go here */ + PM_TRANS_FLAG_CASCADE = (1 << 4), + PM_TRANS_FLAG_RECURSE = (1 << 5), + PM_TRANS_FLAG_DBONLY = (1 << 6), + /* (1 << 7) flag can go here */ + PM_TRANS_FLAG_ALLDEPS = (1 << 8), + PM_TRANS_FLAG_DOWNLOADONLY = (1 << 9), + PM_TRANS_FLAG_NOSCRIPTLET = (1 << 10), + PM_TRANS_FLAG_NOCONFLICTS = (1 << 11), + /* (1 << 12) flag can go here */ + PM_TRANS_FLAG_NEEDED = (1 << 13), + PM_TRANS_FLAG_ALLEXPLICIT = (1 << 14), + PM_TRANS_FLAG_UNNEEDED = (1 << 15), + PM_TRANS_FLAG_RECURSEALL = (1 << 16), + PM_TRANS_FLAG_NOLOCK = (1 << 17) } pmtransflag_t; /** @@ -376,12 +370,12 @@ typedef enum _pmtransevt_t { /* Transaction Conversations (ie, questions) */ typedef enum _pmtransconv_t { - PM_TRANS_CONV_INSTALL_IGNOREPKG = 0x01, - PM_TRANS_CONV_REPLACE_PKG = 0x02, - PM_TRANS_CONV_CONFLICT_PKG = 0x04, - PM_TRANS_CONV_CORRUPTED_PKG = 0x08, - PM_TRANS_CONV_LOCAL_NEWER = 0x10, - PM_TRANS_CONV_REMOVE_PKGS = 0x20, + PM_TRANS_CONV_INSTALL_IGNOREPKG = 1, + PM_TRANS_CONV_REPLACE_PKG = (1 << 1), + PM_TRANS_CONV_CONFLICT_PKG = (1 << 2), + PM_TRANS_CONV_CORRUPTED_PKG = (1 << 3), + PM_TRANS_CONV_LOCAL_NEWER = (1 << 4), + PM_TRANS_CONV_REMOVE_PKGS = (1 << 5), } pmtransconv_t; /* Transaction Progress */ @@ -402,19 +396,23 @@ typedef void (*alpm_trans_cb_conv)(pmtransconv_t, void *, void *, /* Transaction Progress callback */ typedef void (*alpm_trans_cb_progress)(pmtransprog_t, const char *, int, int, int); -pmtranstype_t alpm_trans_get_type(); -unsigned int alpm_trans_get_flags(); -alpm_list_t * alpm_trans_get_pkgs(); -int alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, +int alpm_trans_get_flags(); +alpm_list_t * alpm_trans_get_add(); +alpm_list_t * alpm_trans_get_remove(); +int alpm_trans_init(pmtransflag_t flags, alpm_trans_cb_event cb_event, alpm_trans_cb_conv conv, alpm_trans_cb_progress cb_progress); -int alpm_trans_sysupgrade(int enable_downgrade); -int alpm_trans_addtarget(char *target); int alpm_trans_prepare(alpm_list_t **data); int alpm_trans_commit(alpm_list_t **data); int alpm_trans_interrupt(void); int alpm_trans_release(void); +int alpm_sync_sysupgrade(int enable_downgrade); +int alpm_sync_target(char *target); +int alpm_sync_dbtarget(char *db, char *target); +int alpm_add_target(char *target); +int alpm_remove_target(char *target); + /* * Dependencies and conflicts */ @@ -441,6 +439,7 @@ alpm_list_t *alpm_checkconflicts(alpm_list_t *pkglist); const char *alpm_conflict_get_package1(pmconflict_t *conflict); const char *alpm_conflict_get_package2(pmconflict_t *conflict); +const char *alpm_conflict_get_reason(pmconflict_t *conflict); pmdepmod_t alpm_dep_get_mod(const pmdepend_t *dep); const char *alpm_dep_get_name(const pmdepend_t *dep); @@ -509,6 +508,7 @@ enum _pmerrno_t { PM_ERR_PKG_OPEN, PM_ERR_PKG_CANT_REMOVE, PM_ERR_PKG_INVALID_NAME, + PM_ERR_PKG_INVALID_ARCH, PM_ERR_PKG_REPO_NOT_FOUND, /* Deltas */ PM_ERR_DLT_INVALID, diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 127f72ac..17bdfdf4 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -644,11 +644,65 @@ char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, } /** - * @brief Find the items in list `lhs` that are not present in list `rhs`. + * @brief Find the differences between list `left` and list `right` + * + * The two lists must be sorted. Items only in list `left` are added to the + * `onlyleft` list. Items only in list `right` are added to the `onlyright` + * list. * - * Entries are not duplicated. Operation is O(m*n). The first list is stepped - * through one node at a time, and for each node in the first list, each node - * in the second list is compared to it. + * @param left the first list + * @param right the second list + * @param fn the comparison function + * @param onlyleft pointer to the first result list + * @param onlyright pointer to the second result list + * + */ +void SYMEXPORT alpm_list_diff_sorted(alpm_list_t *left, + alpm_list_t *right, alpm_list_fn_cmp fn, + alpm_list_t **onlyleft, alpm_list_t **onlyright) +{ + alpm_list_t *l = left; + alpm_list_t *r = right; + + if(!onlyleft && !onlyright) { + return; + } + + while (l != NULL && r != NULL) { + int cmp = fn(l->data, r->data); + if(cmp < 0) { + if(onlyleft) { + *onlyleft = alpm_list_add(*onlyleft, l->data); + } + l = l->next; + } + else if(cmp > 0) { + if(onlyright) { + *onlyright = alpm_list_add(*onlyright, r->data); + } + r = r->next; + } else { + l = l->next; + r = r->next; + } + } + while (l != NULL) { + if(onlyleft) { + *onlyleft = alpm_list_add(*onlyleft, l->data); + } + l = l->next; + } + while (r != NULL) { + if(onlyright) { + *onlyright = alpm_list_add(*onlyright, r->data); + } + r = r->next; + } +} + + +/** + * @brief Find the items in list `lhs` that are not present in list `rhs`. * * @param lhs the first list * @param rhs the second list @@ -659,21 +713,18 @@ char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, alpm_list_t SYMEXPORT *alpm_list_diff(const alpm_list_t *lhs, const alpm_list_t *rhs, alpm_list_fn_cmp fn) { - const alpm_list_t *i, *j; + alpm_list_t *left, *right; alpm_list_t *ret = NULL; - for(i = lhs; i; i = i->next) { - int found = 0; - for(j = rhs; j; j = j->next) { - if(fn(i->data, j->data) == 0) { - found = 1; - break; - } - } - if(!found) { - ret = alpm_list_add(ret, i->data); - } - } + left = alpm_list_copy(lhs); + left = alpm_list_msort(left, alpm_list_count(left), fn); + right = alpm_list_copy(rhs); + right = alpm_list_msort(right, alpm_list_count(right), fn); + + alpm_list_diff_sorted(left, right, fn, &ret, NULL); + + alpm_list_free(left); + alpm_list_free(right); return(ret); } diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index f079ecfd..48e91173 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -78,6 +78,8 @@ void *alpm_list_find(const alpm_list_t *haystack, const void *needle, alpm_list_ void *alpm_list_find_ptr(const alpm_list_t *haystack, const void *needle); char *alpm_list_find_str(const alpm_list_t *haystack, const char *needle); alpm_list_t *alpm_list_diff(const alpm_list_t *lhs, const alpm_list_t *rhs, alpm_list_fn_cmp fn); +void alpm_list_diff_sorted(alpm_list_t *left, alpm_list_t *right, + alpm_list_fn_cmp fn, alpm_list_t **onlyleft, alpm_list_t **onlyright); #ifdef __cplusplus } diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c index e628131f..a0c6b7fc 100644 --- a/lib/libalpm/backup.c +++ b/lib/libalpm/backup.c @@ -33,7 +33,7 @@ #include "util.h" /* split a backup string "file\thash" into two strings : file and hash */ -int _alpm_backup_split(const char *string, char **file, char **hash) +static int backup_split(const char *string, char **file, char **hash) { char *str = strdup(string); char *ptr; @@ -65,14 +65,14 @@ int _alpm_backup_split(const char *string, char **file, char **hash) char *_alpm_backup_file(const char *string) { char *file = NULL; - _alpm_backup_split(string, &file, NULL); + backup_split(string, &file, NULL); return(file); } char *_alpm_backup_hash(const char *string) { char *hash = NULL; - _alpm_backup_split(string, NULL, &hash); + backup_split(string, NULL, &hash); return(hash); } @@ -95,7 +95,7 @@ char *_alpm_needbackup(const char *file, const alpm_list_t *backup) char *hash = NULL; /* no hash found */ - if(!_alpm_backup_split((char *)lp->data, &filename, &hash)) { + if(!backup_split((char *)lp->data, &filename, &hash)) { FREE(filename); continue; } diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c index bfe10867..ffbaa8d5 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -51,10 +51,11 @@ * Return the last update time as number of seconds from the epoch. * Returns 0 if the value is unknown or can't be read. */ -static time_t getlastupdate(const pmdb_t *db) +static time_t getlastupdate(pmdb_t *db) { FILE *fp; char *file; + const char *dbpath; time_t ret = 0; ALPM_LOG_FUNC; @@ -63,9 +64,10 @@ static time_t getlastupdate(const pmdb_t *db) return(ret); } - /* db->path + '.lastupdate' + NULL */ - MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); - sprintf(file, "%s.lastupdate", db->path); + dbpath = _alpm_db_path(db); + /* dbpath + '.lastupdate' + NULL */ + MALLOC(file, strlen(dbpath) + 12, RET_ERR(PM_ERR_MEMORY, ret)); + sprintf(file, "%s.lastupdate", dbpath); /* get the last update time, if it's there */ if((fp = fopen(file, "r")) == NULL) { @@ -85,10 +87,11 @@ static time_t getlastupdate(const pmdb_t *db) /* * writes the dbpath/.lastupdate file with the value in time */ -static int setlastupdate(const pmdb_t *db, time_t time) +static int setlastupdate(pmdb_t *db, time_t time) { FILE *fp; char *file; + const char *dbpath; int ret = 0; ALPM_LOG_FUNC; @@ -97,9 +100,10 @@ static int setlastupdate(const pmdb_t *db, time_t time) return(-1); } - /* db->path + '.lastupdate' + NULL */ - MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); - sprintf(file, "%s.lastupdate", db->path); + dbpath = _alpm_db_path(db); + /* dbpath + '.lastupdate' + NULL */ + MALLOC(file, strlen(dbpath) + 12, RET_ERR(PM_ERR_MEMORY, ret)); + sprintf(file, "%s.lastupdate", dbpath); if((fp = fopen(file, "w")) == NULL) { free(file); @@ -116,7 +120,7 @@ static int setlastupdate(const pmdb_t *db, time_t time) static int checkdbdir(pmdb_t *db) { struct stat buf; - char *path = db->path; + const char *path = _alpm_db_path(db); if(stat(path, &buf) != 0) { _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", @@ -148,7 +152,7 @@ static int checkdbdir(pmdb_t *db) * pmdb_t *db; * int result; * db = alpm_list_getdata(alpm_option_get_syncdbs()); - * if(alpm_trans_init(PM_TRANS_TYPE_SYNC, 0, NULL, NULL, NULL) == 0) { + * if(alpm_trans_init(0, NULL, NULL, NULL) == 0) { * result = alpm_db_update(0, db); * alpm_trans_release(); * @@ -191,7 +195,6 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) */ ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - ASSERT(handle->trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1)); if(!alpm_list_find_ptr(handle->dbs_sync, db)) { RET_ERR(PM_ERR_DB_NOT_FOUND, -1); @@ -225,8 +228,9 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) _alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast()); return(-1); } else { + const char *syncdbpath = _alpm_db_path(db); /* remove the old dir */ - if(_alpm_rmrf(db->path) != 0) { + if(_alpm_rmrf(syncdbpath) != 0) { _alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename); RET_ERR(PM_ERR_DB_REMOVE, -1); } @@ -241,7 +245,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) /* uncompress the sync database */ checkdbdir(db); - ret = _alpm_unpack(dbfilepath, db->path, NULL); + ret = _alpm_unpack(dbfilepath, syncdbpath, NULL, 0); if(ret) { free(dbfilepath); RET_ERR(PM_ERR_SYSTEM, -1); @@ -306,13 +310,15 @@ int _alpm_db_populate(pmdb_t *db) struct dirent *ent = NULL; struct stat sbuf; char path[PATH_MAX]; + const char *dbpath; DIR *dbdir; ALPM_LOG_FUNC; ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - dbdir = opendir(db->path); + dbpath = _alpm_db_path(db); + dbdir = opendir(dbpath); if(dbdir == NULL) { return(0); } @@ -324,7 +330,7 @@ int _alpm_db_populate(pmdb_t *db) continue; } /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s%s", db->path, name); + snprintf(path, PATH_MAX, "%s%s", dbpath, name); if(stat(path, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) { continue; } @@ -367,10 +373,12 @@ static char *get_pkgpath(pmdb_t *db, pmpkg_t *info) { size_t len; char *pkgpath; + const char *dbpath; - len = strlen(db->path) + strlen(info->name) + strlen(info->version) + 3; + dbpath = _alpm_db_path(db); + len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3; MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL)); - sprintf(pkgpath, "%s%s-%s/", db->path, info->name, info->version); + sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version); return(pkgpath); } @@ -379,6 +387,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) FILE *fp = NULL; char path[PATH_MAX]; char line[513]; + int sline = sizeof(line)-1; char *pkgpath = NULL; ALPM_LOG_FUNC; @@ -410,7 +419,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) info->name, inforeq); /* clear out 'line', to be certain - and to make valgrind happy */ - memset(line, 0, 513); + memset(line, 0, sline+1); pkgpath = get_pkgpath(db, info); @@ -434,7 +443,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) } _alpm_strtrim(line); if(strcmp(line, "%NAME%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } if(strcmp(_alpm_strtrim(line), info->name) != 0) { @@ -442,7 +451,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%VERSION%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } if(strcmp(_alpm_strtrim(line), info->version) != 0) { @@ -450,44 +459,44 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%FILENAME%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->filename, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%DESC%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->desc, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%GROUPS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->groups = alpm_list_add(info->groups, linedup); } } else if(strcmp(line, "%URL%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->url, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%LICENSE%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->licenses = alpm_list_add(info->licenses, linedup); } } else if(strcmp(line, "%ARCH%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->arch, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%BUILDDATE%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } _alpm_strtrim(line); - char first = tolower(line[0]); + char first = tolower((unsigned char)line[0]); if(first > 'a' && first < 'z') { struct tm tmp_tm = {0}; /* initialize to null in case of failure */ setlocale(LC_TIME, "C"); @@ -498,12 +507,12 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) info->builddate = atol(line); } } else if(strcmp(line, "%INSTALLDATE%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } _alpm_strtrim(line); - char first = tolower(line[0]); + char first = tolower((unsigned char)line[0]); if(first > 'a' && first < 'z') { struct tm tmp_tm = {0}; /* initialize to null in case of failure */ setlocale(LC_TIME, "C"); @@ -514,12 +523,12 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) info->installdate = atol(line); } } else if(strcmp(line, "%PACKAGER%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->packager, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%REASON%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } info->reason = (pmpkgreason_t)atol(_alpm_strtrim(line)); @@ -529,7 +538,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) * is currently only used in sync databases, and SIZE is * only used in local databases. */ - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } info->size = atol(_alpm_strtrim(line)); @@ -540,19 +549,19 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) } else if(strcmp(line, "%ISIZE%") == 0) { /* ISIZE (installed size) tag only appears in sync repositories, * not the local one. */ - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } info->isize = atol(_alpm_strtrim(line)); } else if(strcmp(line, "%MD5SUM%") == 0) { /* MD5SUM tag only appears in sync repositories, * not the local one. */ - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->md5sum, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%REPLACES%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->replaces = alpm_list_add(info->replaces, linedup); @@ -575,13 +584,13 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) while(fgets(line, 256, fp)) { _alpm_strtrim(line); if(strcmp(line, "%FILES%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->files = alpm_list_add(info->files, linedup); } } else if(strcmp(line, "%BACKUP%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->backup = alpm_list_add(info->backup, linedup); @@ -603,24 +612,24 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) fgets(line, 255, fp); _alpm_strtrim(line); if(strcmp(line, "%DEPENDS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line)); info->depends = alpm_list_add(info->depends, dep); } } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->optdepends = alpm_list_add(info->optdepends, linedup); } } else if(strcmp(line, "%CONFLICTS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->conflicts = alpm_list_add(info->conflicts, linedup); } } else if(strcmp(line, "%PROVIDES%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->provides = alpm_list_add(info->provides, linedup); @@ -639,7 +648,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) fgets(line, 255, fp); _alpm_strtrim(line); if(strcmp(line, "%DELTAS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { pmdelta_t *delta = _alpm_delta_parse(line); if(delta) { info->deltas = alpm_list_add(info->deltas, delta); diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 9c7c1617..c1a43438 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -82,7 +82,7 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) } else if(!strcmp(key, "license")) { newpkg->licenses = alpm_list_add(newpkg->licenses, strdup(ptr)); } else if(!strcmp(key, "builddate")) { - char first = tolower(ptr[0]); + char first = tolower((unsigned char)ptr[0]); if(first > 'a' && first < 'z') { struct tm tmp_tm = {0}; /* initialize to null in case of failure */ setlocale(LC_TIME, "C"); @@ -132,7 +132,7 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) * through the full archive * @return An information filled pmpkg_t struct */ -static pmpkg_t *pkg_load(const char *pkgfile, unsigned short full) +static pmpkg_t *pkg_load(const char *pkgfile, int full) { int ret = ARCHIVE_OK; int config = 0; @@ -269,8 +269,7 @@ error: * @param pkg address of the package pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_pkg_load(const char *filename, unsigned short full, - pmpkg_t **pkg) +int SYMEXPORT alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg) { ALPM_LOG_FUNC; diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 07ef73cf..e934c01e 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -41,7 +41,7 @@ #include "cache.h" #include "deps.h" -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2) +pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason) { pmconflict_t *conflict; @@ -51,6 +51,7 @@ pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2) STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL)); STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->reason, reason, RET_ERR(PM_ERR_MEMORY, NULL)); return(conflict); } @@ -59,6 +60,7 @@ void _alpm_conflict_free(pmconflict_t *conflict) { FREE(conflict->package2); FREE(conflict->package1); + FREE(conflict->reason); FREE(conflict); } @@ -69,6 +71,7 @@ pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict) STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL)); STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newconflict->reason, conflict->reason, RET_ERR(PM_ERR_MEMORY, NULL)); return(newconflict); } @@ -122,9 +125,9 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2) * @param pkg2 package causing conflict */ static void add_conflict(alpm_list_t **baddeps, const char *pkg1, - const char *pkg2) + const char *pkg2, const char *reason) { - pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2); + pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2, reason); if(conflict && !_alpm_conflict_isin(conflict, *baddeps)) { *baddeps = alpm_list_add(*baddeps, conflict); } else { @@ -168,9 +171,9 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, if(does_conflict(pkg1, conflict, pkg2)) { if(order >= 0) { - add_conflict(baddeps, pkg1name, pkg2name); + add_conflict(baddeps, pkg1name, pkg2name, conflict); } else { - add_conflict(baddeps, pkg2name, pkg1name); + add_conflict(baddeps, pkg2name, pkg1name, conflict); } } } @@ -513,7 +516,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, /* skip removal of file, but not add. this will prevent a second * package from removing the file when it was already installed * by its new owner (whether the file is in backup array or not */ - trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(path)); + trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(filestr)); _alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s\n", filestr); resolved_conflict = 1; } @@ -578,6 +581,17 @@ const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict) return conflict->package2; } +const char SYMEXPORT *alpm_conflict_get_reason(pmconflict_t *conflict) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(conflict != NULL, return(NULL)); + + return conflict->reason; +} + const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict) { ALPM_LOG_FUNC; diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 149c728e..73a6e959 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -27,6 +27,7 @@ struct __pmconflict_t { char *package1; char *package2; + char *reason; }; struct __pmfileconflict_t { @@ -36,7 +37,7 @@ struct __pmfileconflict_t { char *ctarget; }; -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2); +pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason); pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict); void _alpm_conflict_free(pmconflict_t *conflict); int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack); diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 62c2e0a3..dca5452a 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -323,18 +323,15 @@ alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles) /** @} */ -pmdb_t *_alpm_db_new(const char *dbpath, const char *treename) +static pmdb_t *_alpm_db_new(const char *treename, int is_local) { pmdb_t *db; - const size_t pathsize = strlen(dbpath) + strlen(treename) + 2; ALPM_LOG_FUNC; CALLOC(db, 1, sizeof(pmdb_t), RET_ERR(PM_ERR_MEMORY, NULL)); - CALLOC(db->path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); - - sprintf(db->path, "%s%s/", dbpath, treename); STRDUP(db->treename, treename, RET_ERR(PM_ERR_MEMORY, NULL)); + db->is_local = is_local; return(db); } @@ -347,13 +344,44 @@ void _alpm_db_free(pmdb_t *db) _alpm_db_free_pkgcache(db); /* cleanup server list */ FREELIST(db->servers); - FREE(db->path); + FREE(db->_path); FREE(db->treename); FREE(db); return; } +const char *_alpm_db_path(pmdb_t *db) +{ + if(!db) { + return(NULL); + } + if(!db->_path) { + const char *dbpath; + size_t pathsize; + + dbpath = alpm_option_get_dbpath(); + if(!dbpath) { + _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); + RET_ERR(PM_ERR_DB_OPEN, NULL); + } + + if(db->is_local) { + pathsize = strlen(dbpath) + strlen(db->treename) + 2; + CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + sprintf(db->_path, "%s%s/", dbpath, db->treename); + } else { + pathsize = strlen(dbpath) + 5 + strlen(db->treename) + 2; + CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + /* all sync DBs now reside in the sync/ subdir of the dbpath */ + sprintf(db->_path, "%ssync/%s/", dbpath, db->treename); + } + _alpm_log(PM_LOG_DEBUG, "database path for tree %s set to %s\n", + db->treename, db->_path); + } + return(db->_path); +} + int _alpm_db_cmp(const void *d1, const void *d2) { pmdb_t *db1 = (pmdb_t *)d1; @@ -440,7 +468,6 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) pmdb_t *_alpm_db_register_local(void) { pmdb_t *db; - const char *dbpath; ALPM_LOG_FUNC; @@ -451,13 +478,7 @@ pmdb_t *_alpm_db_register_local(void) _alpm_log(PM_LOG_DEBUG, "registering local database\n"); - dbpath = alpm_option_get_dbpath(); - if(!dbpath) { - _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); - RET_ERR(PM_ERR_DB_OPEN, NULL); - } - - db = _alpm_db_new(dbpath, "local"); + db = _alpm_db_new("local", 1); if(db == NULL) { RET_ERR(PM_ERR_DB_CREATE, NULL); } @@ -469,8 +490,6 @@ pmdb_t *_alpm_db_register_local(void) pmdb_t *_alpm_db_register_sync(const char *treename) { pmdb_t *db; - const char *dbpath; - char path[PATH_MAX]; alpm_list_t *i; ALPM_LOG_FUNC; @@ -485,15 +504,7 @@ pmdb_t *_alpm_db_register_sync(const char *treename) _alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename); - dbpath = alpm_option_get_dbpath(); - if(!dbpath) { - _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); - RET_ERR(PM_ERR_DB_OPEN, NULL); - } - /* all sync DBs now reside in the sync/ subdir of the dbpath */ - snprintf(path, PATH_MAX, "%ssync/", dbpath); - - db = _alpm_db_new(path, treename); + db = _alpm_db_new(treename, 0); if(db == NULL) { RET_ERR(PM_ERR_DB_CREATE, NULL); } diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 950ace22..a540d02d 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -28,30 +28,32 @@ /* Database entries */ typedef enum _pmdbinfrq_t { - INFRQ_BASE = 0x01, - INFRQ_DESC = 0x02, - INFRQ_DEPENDS = 0x04, - INFRQ_FILES = 0x08, - INFRQ_SCRIPTLET = 0x10, - INFRQ_DELTAS = 0x20, + INFRQ_BASE = 1, + INFRQ_DESC = (1 << 1), + INFRQ_DEPENDS = (1 << 2), + INFRQ_FILES = (1 << 3), + INFRQ_SCRIPTLET = (1 << 4), + INFRQ_DELTAS = (1 << 5), /* ALL should be sum of all above */ INFRQ_ALL = 0x3F } pmdbinfrq_t; /* Database */ struct __pmdb_t { - char *path; char *treename; - unsigned short pkgcache_loaded; + /* do not access directly, use _alpm_db_path(db) for lazy access */ + char *_path; + int pkgcache_loaded; + int grpcache_loaded; + int is_local; alpm_list_t *pkgcache; - unsigned short grpcache_loaded; alpm_list_t *grpcache; alpm_list_t *servers; }; /* db.c, database general calls */ -pmdb_t *_alpm_db_new(const char *dbpath, const char *treename); void _alpm_db_free(pmdb_t *db); +const char *_alpm_db_path(pmdb_t *db); int _alpm_db_cmp(const void *d1, const void *d2); alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles); pmdb_t *_alpm_db_register_local(void); diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 599a1b76..523968ec 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -71,34 +71,16 @@ off_t SYMEXPORT alpm_delta_get_size(pmdelta_t *delta) /** @} */ -static alpm_list_t *delta_graph_init(alpm_list_t *deltas) +static alpm_list_t *graph_init(alpm_list_t *deltas) { alpm_list_t *i, *j; alpm_list_t *vertices = NULL; /* create the vertices */ for(i = deltas; i; i = i->next) { - char *fpath, *md5sum; pmgraph_t *v = _alpm_graph_new(); pmdelta_t *vdelta = i->data; vdelta->download_size = vdelta->delta_size; v->weight = LONG_MAX; - - /* determine whether the delta file already exists */ - fpath = _alpm_filecache_find(vdelta->delta); - md5sum = alpm_compute_md5sum(fpath); - if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { - vdelta->download_size = 0; - } - FREE(fpath); - FREE(md5sum); - - /* determine whether a base 'from' file exists */ - fpath = _alpm_filecache_find(vdelta->from); - if(fpath) { - v->weight = vdelta->download_size; - } - FREE(fpath); - v->data = vdelta; vertices = alpm_list_add(vertices, v); } @@ -128,8 +110,36 @@ static alpm_list_t *delta_graph_init(alpm_list_t *deltas) return(vertices); } -static off_t delta_vert(alpm_list_t *vertices, - const char *to, alpm_list_t **path) { +static void graph_init_size(alpm_list_t *vertices) +{ + alpm_list_t *i; + + for(i = vertices; i; i = i->next) { + char *fpath, *md5sum; + pmgraph_t *v = i->data; + pmdelta_t *vdelta = v->data; + + /* determine whether the delta file already exists */ + fpath = _alpm_filecache_find(vdelta->delta); + md5sum = alpm_compute_md5sum(fpath); + if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { + vdelta->download_size = 0; + } + FREE(fpath); + FREE(md5sum); + + /* determine whether a base 'from' file exists */ + fpath = _alpm_filecache_find(vdelta->from); + if(fpath) { + v->weight = vdelta->download_size; + } + FREE(fpath); + } +} + + +static void dijkstra(alpm_list_t *vertices) +{ alpm_list_t *i; pmgraph_t *v; while(1) { @@ -165,9 +175,14 @@ static off_t delta_vert(alpm_list_t *vertices, } } +} - v = NULL; +static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t **path) +{ + alpm_list_t *i; + pmgraph_t *v = NULL; off_t bestsize = 0; + alpm_list_t *rpath = NULL; for(i = vertices; i; i = i->next) { pmgraph_t *v_i = i->data; @@ -181,7 +196,6 @@ static off_t delta_vert(alpm_list_t *vertices, } } - alpm_list_t *rpath = NULL; while(v != NULL) { pmdelta_t *vdelta = v->data; rpath = alpm_list_add(rpath, vdelta); @@ -219,9 +233,10 @@ off_t _alpm_shortest_delta_path(alpm_list_t *deltas, _alpm_log(PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to); - vertices = delta_graph_init(deltas); - - bestsize = delta_vert(vertices, to, &bestpath); + vertices = graph_init(deltas); + graph_init_size(vertices); + dijkstra(vertices); + bestsize = shortest_path(vertices, to, &bestpath); _alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize); diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 02a4c7b6..46699ac6 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -605,7 +605,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *pkg, ALPM_LOG_FUNC; - if(local == NULL || dbs_sync == NULL) { + if(local == NULL) { return(-1); } diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 10be5e9d..a4c9f1f4 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -59,7 +59,7 @@ static char *get_filename(const char *url) { static char *get_destfile(const char *path, const char *filename) { char *destfile; /* len = localpath len + filename len + null */ - int len = strlen(path) + strlen(filename) + 1; + size_t len = strlen(path) + strlen(filename) + 1; CALLOC(destfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); snprintf(destfile, len, "%s%s", path, filename); @@ -69,37 +69,13 @@ static char *get_destfile(const char *path, const char *filename) { static char *get_tempfile(const char *path, const char *filename) { char *tempfile; /* len = localpath len + filename len + '.part' len + null */ - int len = strlen(path) + strlen(filename) + 6; + size_t len = strlen(path) + strlen(filename) + 6; CALLOC(tempfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); snprintf(tempfile, len, "%s%s.part", path, filename); return(tempfile); } -/* Build a 'struct url' from an url. */ -static struct url *url_for_string(const char *url) -{ - struct url *ret = NULL; - ret = fetchParseURL(url); - if(!ret) { - _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); - RET_ERR(PM_ERR_SERVER_BAD_URL, NULL); - } - - /* if no URL scheme specified, assume HTTP */ - if(strlen(ret->scheme) == 0) { - _alpm_log(PM_LOG_WARNING, _("url scheme not specified, assuming HTTP\n")); - strcpy(ret->scheme, SCHEME_HTTP); - } - /* add a user & password for anonymous FTP */ - if(strcmp(ret->scheme,SCHEME_FTP) == 0 && strlen(ret->user) == 0) { - strcpy(ret->user, "anonymous"); - strcpy(ret->pwd, "libalpm@guest"); - } - - return(ret); -} - static const char *gethost(struct url *fileurl) { const char *host = _("disk"); @@ -116,21 +92,24 @@ static int download_internal(const char *url, const char *localpath, struct url_stat ust; struct stat st; int chk_resume = 0, ret = 0; - size_t dl_thisfile = 0; + off_t dl_thisfile = 0; ssize_t nread = 0; char *tempfile, *destfile, *filename; struct sigaction new_action, old_action; - struct url *fileurl = url_for_string(url); + struct url *fileurl; char buffer[PM_DLBUF_LEN]; - if(!fileurl) { - return(-1); - } - filename = get_filename(url); if(!filename) { return(-1); } + + fileurl = fetchParseURL(url); + if(!fileurl) { + _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); + RET_ERR(PM_ERR_SERVER_BAD_URL, -1); + } + destfile = get_destfile(localpath, filename); tempfile = get_tempfile(localpath, filename); @@ -168,10 +147,11 @@ static int download_internal(const char *url, const char *localpath, * something along those lines. Store the old signal handler first. */ new_action.sa_handler = SIG_IGN; sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; sigaction(SIGPIPE, NULL, &old_action); sigaction(SIGPIPE, &new_action, NULL); - dlf = fetchXGet(fileurl, &ust, (handle->nopassiveftp ? "i" : "pi")); + dlf = fetchXGet(fileurl, &ust, "i"); if(fetchLastErrCode == FETCH_UNCHANGED) { _alpm_log(PM_LOG_DEBUG, "mtimes are identical, skipping %s\n", filename); @@ -220,14 +200,12 @@ static int download_internal(const char *url, const char *localpath, while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) { size_t nwritten = 0; - while(nwritten < nread) { - nwritten += fwrite(buffer, 1, (nread - nwritten), localf); - if(ferror(localf)) { - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - destfile, strerror(errno)); - ret = -1; - goto cleanup; - } + nwritten = fwrite(buffer, 1, nread, localf); + if((nwritten != nread) || ferror(localf)) { + _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), + destfile, strerror(errno)); + ret = -1; + goto cleanup; } dl_thisfile += nread; @@ -323,7 +301,7 @@ int _alpm_download_single_file(const char *filename, for(i = servers; i; i = i->next) { const char *server = i->data; char *fileurl = NULL; - int len; + size_t len; /* print server + filename into a buffer */ len = strlen(server) + strlen(filename) + 2; diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index 81aaa8b1..ae19786e 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -117,8 +117,10 @@ const char SYMEXPORT *alpm_strerror(int err) return _("cannot remove all files for package"); case PM_ERR_PKG_INVALID_NAME: return _("package filename is not valid"); + case PM_ERR_PKG_INVALID_ARCH: + return _("package architecture is not valid"); case PM_ERR_PKG_REPO_NOT_FOUND: - return _("no such repository"); + return _("could not find repository for target"); /* Deltas */ case PM_ERR_DLT_INVALID: return _("invalid or corrupted delta"); diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index d1a35ad9..5cbf363a 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -79,6 +79,7 @@ void _alpm_handle_free(pmhandle_t *handle) FREELIST(handle->cachedirs); FREE(handle->logfile); FREE(handle->lockfile); + FREE(handle->arch); FREELIST(handle->dbs_sync); FREELIST(handle->noupgrade); FREELIST(handle->noextract); @@ -168,7 +169,7 @@ const char SYMEXPORT *alpm_option_get_lockfile() return handle->lockfile; } -unsigned short SYMEXPORT alpm_option_get_usesyslog() +int SYMEXPORT alpm_option_get_usesyslog() { if (handle == NULL) { pm_errno = PM_ERR_HANDLE_NULL; @@ -213,13 +214,22 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps() return handle->ignoregrp; } -unsigned short SYMEXPORT alpm_option_get_nopassiveftp() +const char SYMEXPORT *alpm_option_get_arch() +{ + if (handle == NULL) { + pm_errno = PM_ERR_HANDLE_NULL; + return NULL; + } + return handle->arch; +} + +int SYMEXPORT alpm_option_get_usedelta() { if (handle == NULL) { pm_errno = PM_ERR_HANDLE_NULL; return -1; } - return handle->nopassiveftp; + return handle->usedelta; } pmdb_t SYMEXPORT *alpm_option_get_localdb() @@ -436,7 +446,7 @@ int SYMEXPORT alpm_option_set_logfile(const char *logfile) return(0); } -void SYMEXPORT alpm_option_set_usesyslog(unsigned short usesyslog) +void SYMEXPORT alpm_option_set_usesyslog(int usesyslog) { handle->usesyslog = usesyslog; } @@ -529,12 +539,13 @@ int SYMEXPORT alpm_option_remove_ignoregrp(const char *grp) return(0); } -void SYMEXPORT alpm_option_set_nopassiveftp(unsigned short nopasv) +void SYMEXPORT alpm_option_set_arch(const char *arch) { - handle->nopassiveftp = nopasv; + if(handle->arch) FREE(handle->arch); + if(arch) handle->arch = strdup(arch); } -void SYMEXPORT alpm_option_set_usedelta(unsigned short usedelta) +void SYMEXPORT alpm_option_set_usedelta(int usedelta) { handle->usedelta = usedelta; } diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index c7c262cf..a87d0fb2 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -57,9 +57,9 @@ typedef struct _pmhandle_t { alpm_list_t *ignoregrp; /* List of groups to ignore */ /* options */ - unsigned short usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ - unsigned short nopassiveftp; /* Don't use PASV ftp connections */ - unsigned short usedelta; /* Download deltas if possible */ + int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ + char *arch; /* Architecture of packages we should allow */ + int usedelta; /* Download deltas if possible */ } pmhandle_t; /* global handle variable */ diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 002b1c89..572b863e 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -295,7 +295,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg) return pkg->groups; } -unsigned short SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg) +int SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -423,13 +423,6 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg) return pkg->backup; } -alpm_list_t SYMEXPORT *alpm_pkg_get_removes(pmpkg_t *pkg) -{ - ASSERT(pkg != NULL, return(NULL)); - - return(pkg->removes); -} - pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg) { /* Sanity checks */ @@ -548,7 +541,7 @@ int SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp) return(ret); } -unsigned short SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) +int SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -858,7 +851,11 @@ void _alpm_pkg_free(pmpkg_t *pkg) FREE(pkg); } -/* Free transaction specific fields */ +/* This function should be used when removing a target from upgrade/sync target list + * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed. + * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed, + * only the transaction specific fields of pkg will be freed. + */ void _alpm_pkg_free_trans(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -867,6 +864,11 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg) return; } + if(pkg->origin == PKG_FROM_FILE) { + _alpm_pkg_free(pkg); + return; + } + alpm_list_free(pkg->removes); pkg->removes = NULL; } diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index aea3f394..b003b410 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -49,8 +49,8 @@ struct __pmpkg_t { off_t size; off_t isize; off_t download_size; - unsigned short scriptlet; - unsigned short force; + int scriptlet; + int force; pmpkgreason_t reason; alpm_list_t *licenses; alpm_list_t *replaces; diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 1e8f9156..80eec67f 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -47,35 +47,45 @@ #include "handle.h" #include "alpm.h" -int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) +int SYMEXPORT alpm_remove_target(char *target) { pmpkg_t *info; - const char *targ; + pmtrans_t *trans; + pmdb_t *db_local; + alpm_list_t *p; ALPM_LOG_FUNC; - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); + /* Sanity checks */ + ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + trans = handle->trans; + db_local = handle->db_local; ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - targ = strchr(name, '/'); - if(targ && strncmp(name, "local", 5) == 0) { - targ++; - } else { - targ = name; - } - if(_alpm_pkg_find(trans->packages, targ)) { + if(_alpm_pkg_find(trans->remove, target)) { RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); } - if((info = _alpm_db_get_pkgfromcache(db, targ)) == NULL) { - _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", targ); - RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + if((info = _alpm_db_get_pkgfromcache(db_local, target)) != NULL) { + _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", info->name); + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info)); + return(0); } - _alpm_log(PM_LOG_DEBUG, "adding %s in target list\n", info->name); - trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info)); + _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", target); + pmgrp_t *grp = alpm_db_readgrp(db_local, target); + if(grp == NULL) { + RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + } + for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) { + pmpkg_t *pkg = alpm_list_getdata(p); + _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", pkg->name); + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(pkg)); + } return(0); } @@ -91,10 +101,10 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db, pmdepmissing_t *miss = (pmdepmissing_t *)i->data; pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target); if(info) { - if(!_alpm_pkg_find(trans->packages, alpm_pkg_get_name(info))) { + if(!_alpm_pkg_find(trans->remove, alpm_pkg_get_name(info))) { _alpm_log(PM_LOG_DEBUG, "pulling %s in target list\n", alpm_pkg_get_name(info)); - trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info)); + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info)); } } else { _alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"), @@ -103,7 +113,7 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db, } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); } } @@ -118,11 +128,11 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, for(i = lp; i; i = i->next) { pmdepmissing_t *miss = (pmdepmissing_t *)i->data; void *vpkg; - pmpkg_t *pkg = _alpm_pkg_find(trans->packages, miss->causingpkg); + pmpkg_t *pkg = _alpm_pkg_find(trans->remove, miss->causingpkg); if(pkg == NULL) { continue; } - trans->packages = alpm_list_remove(trans->packages, pkg, _alpm_pkg_cmp, + trans->remove = alpm_list_remove(trans->remove, pkg, _alpm_pkg_cmp, &vpkg); pkg = vpkg; if(pkg) { @@ -133,7 +143,7 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); } } @@ -146,21 +156,16 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - /* skip all checks if we are doing this removal as part of an upgrade */ - if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) { - return(0); - } - if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) { _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); - _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL); + _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); } if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); if(lp != NULL) { if(trans->flags & PM_TRANS_FLAG_CASCADE) { @@ -183,15 +188,15 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) /* re-order w.r.t. dependencies */ _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); - lp = _alpm_sortbydeps(trans->packages, 1); + lp = _alpm_sortbydeps(trans->remove, 1); /* free the old alltargs */ - alpm_list_free(trans->packages); - trans->packages = lp; + alpm_list_free(trans->remove); + trans->remove = lp; /* -Rcs == -Rc then -Rs */ if((trans->flags & PM_TRANS_FLAG_CASCADE) && (trans->flags & PM_TRANS_FLAG_RECURSE)) { _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); - _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL); + _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); } if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { @@ -201,13 +206,13 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) return(0); } -static int can_remove_file(pmtrans_t *trans, const char *path) +static int can_remove_file(const char *path, alpm_list_t *skip) { char file[PATH_MAX+1]; snprintf(file, PATH_MAX, "%s%s", handle->root, path); - if(alpm_list_find_str(trans->skip_remove, file)) { + if(alpm_list_find_str(skip, file)) { /* return success because we will never actually remove this file */ return(1); } @@ -228,7 +233,7 @@ static int can_remove_file(pmtrans_t *trans, const char *path) /* Helper function for iterating through a package's file and deleting them * Used by _alpm_remove_commit. */ -static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) +static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, int nosave) { struct stat buf; char file[PATH_MAX+1]; @@ -237,13 +242,13 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) snprintf(file, PATH_MAX, "%s%s", handle->root, filename); - if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) { - /* check noupgrade */ - if(alpm_list_find_str(handle->noupgrade, filename)) { - _alpm_log(PM_LOG_DEBUG, "Skipping removal of '%s' due to NoUpgrade\n", - file); - return; - } + /* check the remove skip list before removing the file. + * see the big comment block in db_find_fileconflicts() for an + * explanation. */ + if(alpm_list_find_str(skip_remove, filename)) { + _alpm_log(PM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n", + file); + return; } /* we want to do a lstat here, and not a _alpm_lstat. @@ -263,19 +268,10 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) _alpm_log(PM_LOG_DEBUG, "removing directory %s\n", file); } } else { - /* check the remove skip list before removing the file. - * see the big comment block in db_find_fileconflicts() for an - * explanation. */ - if(alpm_list_find_str(trans->skip_remove, file)) { - _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_remove, skipping removal\n", - file); - return; - } - /* if the file needs backup and has been modified, back it up to .pacsave */ char *pkghash = _alpm_needbackup(filename, alpm_pkg_get_backup(info)); if(pkghash) { - if(trans->flags & PM_TRANS_FLAG_NOSAVE) { + if(nosave) { _alpm_log(PM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); FREE(pkghash); } else { @@ -303,7 +299,69 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) } } -int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) +int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans) +{ + alpm_list_t *skip_remove, *b; + alpm_list_t *newfiles, *lp; + alpm_list_t *files = alpm_pkg_get_files(oldpkg); + const char *pkgname = alpm_pkg_get_name(oldpkg); + + ALPM_LOG_FUNC; + + _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n", + oldpkg->name, oldpkg->version); + + /* copy the remove skiplist over */ + skip_remove = + alpm_list_join(alpm_list_strdup(trans->skip_remove),alpm_list_strdup(handle->noupgrade)); + /* Add files in the NEW backup array to the skip_remove array + * so this removal operation doesn't kill them */ + /* old package backup list */ + alpm_list_t *filelist = alpm_pkg_get_files(newpkg); + for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { + char *backup = _alpm_backup_file(b->data); + /* safety check (fix the upgrade026 pactest) */ + if(!alpm_list_find_str(filelist, backup)) { + FREE(backup); + continue; + } + _alpm_log(PM_LOG_DEBUG, "adding %s to the skip_remove array\n", backup); + skip_remove = alpm_list_add(skip_remove, backup); + } + + for(lp = files; lp; lp = lp->next) { + if(!can_remove_file(lp->data, skip_remove)) { + _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", + pkgname); + RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); + } + } + + /* iterate through the list backwards, unlinking files */ + newfiles = alpm_list_reverse(files); + for(lp = newfiles; lp; lp = alpm_list_next(lp)) { + unlink_file(oldpkg, lp->data, skip_remove, 0); + } + alpm_list_free(newfiles); + FREELIST(skip_remove); + + /* remove the package from the database */ + _alpm_log(PM_LOG_DEBUG, "updating database\n"); + _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); + if(_alpm_db_remove(handle->db_local, oldpkg) == -1) { + _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), + pkgname, alpm_pkg_get_version(oldpkg)); + } + /* remove the package from the cache */ + if(_alpm_db_remove_pkgfromcache(handle->db_local, oldpkg) == -1) { + _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), + pkgname); + } + + return(0); +} + +int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) { pmpkg_t *info; alpm_list_t *targ, *lp; @@ -314,14 +372,14 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - pkg_count = alpm_list_count(trans->packages); + pkg_count = alpm_list_count(trans->remove); - for(targ = trans->packages; targ; targ = targ->next) { + for(targ = trans->remove; targ; targ = targ->next) { int position = 0; char scriptlet[PATH_MAX]; - alpm_list_t *files; info = (pmpkg_t*)targ->data; const char *pkgname = NULL; + int targcount = alpm_list_count(targ); if(handle->trans->state == STATE_INTERRUPTED) { return(0); @@ -329,26 +387,23 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) /* get the name now so we can use it after package is removed */ pkgname = alpm_pkg_get_name(info); - snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path, - pkgname, alpm_pkg_get_version(info)); - - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL); - _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n", - pkgname, alpm_pkg_get_version(info)); - - /* run the pre-remove scriptlet if it exists */ - if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "pre_remove", - alpm_pkg_get_version(info), NULL, trans); - } - } + snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", + _alpm_db_path(db), pkgname, alpm_pkg_get_version(info)); - files = alpm_pkg_get_files(info); + EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL); + _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n", + pkgname, alpm_pkg_get_version(info)); + + /* run the pre-remove scriptlet if it exists */ + if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle->root, scriptlet, "pre_remove", + alpm_pkg_get_version(info), NULL, trans); + } if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) { + alpm_list_t *files = alpm_pkg_get_files(info); for(lp = files; lp; lp = lp->next) { - if(!can_remove_file(trans, lp->data)) { + if(!can_remove_file(lp->data, NULL)) { _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", pkgname); RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); @@ -356,20 +411,20 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) } int filenum = alpm_list_count(files); - double percent = 0.0; alpm_list_t *newfiles; _alpm_log(PM_LOG_DEBUG, "removing %d files\n", filenum); /* iterate through the list backwards, unlinking files */ newfiles = alpm_list_reverse(files); for(lp = newfiles; lp; lp = alpm_list_next(lp)) { - unlink_file(info, lp->data, trans); + double percent; + unlink_file(info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE); /* update progress bar after each file */ percent = (double)position / (double)filenum; PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, info->name, (double)(percent * 100), pkg_count, - (pkg_count - alpm_list_count(targ) + 1)); + (pkg_count - targcount + 1)); position++; } alpm_list_free(newfiles); @@ -377,14 +432,12 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) /* set progress to 100% after we finish unlinking files */ PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, pkgname, 100, - pkg_count, (pkg_count - alpm_list_count(targ) + 1)); + pkg_count, (pkg_count - targcount + 1)); - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - /* run the post-remove script if it exists */ - if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "post_remove", - alpm_pkg_get_version(info), NULL, trans); - } + /* run the post-remove script if it exists */ + if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle->root, scriptlet, "post_remove", + alpm_pkg_get_version(info), NULL, trans); } /* remove the package from the database */ @@ -400,16 +453,11 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) pkgname); } - /* call a done event if this isn't an upgrade */ - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL); - } + EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL); } /* run ldconfig if it exists */ - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - _alpm_ldconfig(handle->root); - } + _alpm_ldconfig(handle->root); return(0); } diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h index 716fbf72..fbbaa169 100644 --- a/lib/libalpm/remove.h +++ b/lib/libalpm/remove.h @@ -24,9 +24,10 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name); int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data); -int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db); +int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db); + +int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans); #endif /* _ALPM_REMOVE_H */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 47639248..2cdcd47b 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -43,11 +43,13 @@ #include "deps.h" #include "conflict.h" #include "trans.h" +#include "add.h" #include "util.h" #include "handle.h" #include "alpm.h" #include "dload.h" #include "delta.h" +#include "remove.h" /** Check for new version of pkg in sync repos * (only the first occurrence is considered in sync) @@ -80,17 +82,30 @@ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) return(NULL); } -int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade) +/** Search for packages to upgrade and add them to the transaction. + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) { alpm_list_t *i, *j, *k; + pmtrans_t *trans; + pmdb_t *db_local; + alpm_list_t *dbs_sync; ALPM_LOG_FUNC; + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + trans = handle->trans; + db_local = handle->db_local; + dbs_sync = handle->dbs_sync; + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + _alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n"); for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) { pmpkg_t *lpkg = i->data; - if(_alpm_pkg_find(trans->packages, lpkg->name)) { + if(_alpm_pkg_find(trans->add, lpkg->name)) { _alpm_log(PM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); continue; } @@ -113,7 +128,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s } else { _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); } } else if(cmp < 0) { if(enable_downgrade) { @@ -124,7 +139,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s } else { _alpm_log(PM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), lpkg->name, lpkg->version, spkg->version); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); } } else { _alpm_log(PM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), @@ -152,7 +167,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s } /* If spkg is already in the target list, we append lpkg to spkg's removes list */ - pmpkg_t *tpkg = _alpm_pkg_find(trans->packages, spkg->name); + pmpkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name); if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { @@ -173,7 +188,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s spkg->removes = alpm_list_add(NULL, lpkg); _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); } } } @@ -187,57 +202,18 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s return(0); } -int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name) +int _alpm_sync_pkg(pmpkg_t *spkg) { - char *targline; - char *targ; - alpm_list_t *j; - pmpkg_t *local, *spkg; - pmdepend_t *dep; /* provisions and dependencies are also allowed */ + pmtrans_t *trans; + pmdb_t *db_local; + pmpkg_t *local; ALPM_LOG_FUNC; - ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - - STRDUP(targline, name, RET_ERR(PM_ERR_MEMORY, -1)); - targ = strchr(targline, '/'); - if(targ) { - /* we are looking for a package in a specific database */ - alpm_list_t *dbs = NULL; - *targ = '\0'; - targ++; - _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", targ, targline); - for(j = dbs_sync; j; j = j->next) { - pmdb_t *db = j->data; - if(strcmp(db->treename, targline) == 0) { - dbs = alpm_list_add(NULL, db); - break; - } - } - if(dbs == NULL) { - _alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline); - FREE(targline); - RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1); - } - dep = _alpm_splitdep(targ); - spkg = _alpm_resolvedep(dep, dbs, NULL, 1); - _alpm_dep_free(dep); - alpm_list_free(dbs); - } else { - dep = _alpm_splitdep(targline); - spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1); - _alpm_dep_free(dep); - } - FREE(targline); - - if(spkg == NULL) { - /* pm_errno is set by _alpm_resolvedep */ - return(-1); - } + trans = handle->trans; + db_local = handle->db_local; - if(_alpm_pkg_find(trans->packages, alpm_pkg_get_name(spkg))) { + if(_alpm_pkg_find(trans->add, alpm_pkg_get_name(spkg))) { RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); } @@ -267,11 +243,108 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy spkg->reason = PM_PKG_REASON_EXPLICIT; _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg)); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); + + return(0); +} + +int _alpm_sync_target(alpm_list_t *dbs_sync, char *target) +{ + alpm_list_t *i, *j; + pmpkg_t *spkg; + pmdepend_t *dep; /* provisions and dependencies are also allowed */ + pmgrp_t *grp; + int found = 0; + + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + + dep = _alpm_splitdep(target); + spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1); + _alpm_dep_free(dep); + + if(spkg != NULL) { + return(_alpm_sync_pkg(spkg)); + } + + _alpm_log(PM_LOG_DEBUG, "%s package not found, searching for group...\n", target); + for(i = dbs_sync; i; i = i->next) { + pmdb_t *db = i->data; + grp = alpm_db_readgrp(db, target); + if(grp) { + found = 1; + for(j = alpm_grp_get_pkgs(grp); j; j = j->next) { + pmpkg_t *pkg = j->data; + if(_alpm_sync_pkg(pkg) == -1) { + if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) { + /* just skip duplicate or ignored targets */ + continue; + } else { + return(-1); + } + } + } + } + } + + if(!found) { + RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + } return(0); } +/** Add a sync target to the transaction. + * @param target the name of the sync target to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_sync_dbtarget(char *dbname, char *target) +{ + alpm_list_t *i; + alpm_list_t *dbs_sync; + + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + dbs_sync = handle->dbs_sync; + + /* we are looking for a package in a specific database */ + alpm_list_t *dbs = NULL; + _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", target, dbname); + for(i = dbs_sync; i; i = i->next) { + pmdb_t *db = i->data; + if(strcmp(db->treename, dbname) == 0) { + dbs = alpm_list_add(NULL, db); + break; + } + } + if(dbs == NULL) { + RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1); + } + return(_alpm_sync_target(dbs, target)); +} + +/** Add a sync target to the transaction. + * @param target the name of the sync target to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_sync_target(char *target) +{ + alpm_list_t *dbs_sync; + + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + dbs_sync = handle->dbs_sync; + + return(_alpm_sync_target(dbs_sync,target)); +} + /** Compute the size of the files that will be downloaded to install a * package. * @param newpkg the new package to upgrade to @@ -282,6 +355,11 @@ static int compute_download_size(pmpkg_t *newpkg) char *fpath; off_t size = 0; + if(newpkg->origin == PKG_FROM_FILE) { + newpkg->download_size = 0; + return(0); + } + fname = alpm_pkg_get_filename(newpkg); ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); fpath = _alpm_filecache_find(fname); @@ -321,10 +399,9 @@ static int compute_download_size(pmpkg_t *newpkg) int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data) { alpm_list_t *deps = NULL; - alpm_list_t *preferred = NULL; alpm_list_t *unresolvable = NULL; - alpm_list_t *remove = NULL; /* allow checkdeps usage with trans->packages */ alpm_list_t *i, *j; + alpm_list_t *remove = NULL; int ret = 0; ALPM_LOG_FUNC; @@ -344,32 +421,29 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n"); - /* build remove list and preferred list for resolvedeps */ - for(i = trans->packages; i; i = i->next) { + /* build remove list for resolvedeps */ + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { remove = alpm_list_add(remove, j->data); } - preferred = alpm_list_add(preferred, spkg); } /* Resolve packages in the transaction one at a time, in addtion building up a list of packages which could not be resolved. */ - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *pkg = i->data; - if(_alpm_resolvedeps(db_local, dbs_sync, pkg, preferred, + if(_alpm_resolvedeps(db_local, dbs_sync, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } /* Else, [resolved] now additionally contains [pkg] and all of its dependencies not already on the list */ } - alpm_list_free(preferred); /* If there were unresolvable top-level packages, prompt the user to see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { - unresolvable = alpm_list_remove_dupes(unresolvable); int remove_unresolvable = 0; QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); @@ -392,21 +466,21 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } } - /* Unresolvable packages will be removed from the target list, so - we free the transaction specific fields */ - alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); - /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { pmpkg_t *pkg = i->data; - if(!_alpm_pkg_find(trans->packages, pkg->name)) { + if(!_alpm_pkg_find(trans->add, pkg->name)) { pkg->reason = PM_PKG_REASON_DEPEND; } } + /* Unresolvable packages will be removed from the target list, so + we free the transaction specific fields */ + alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); + /* re-order w.r.t. dependencies */ - alpm_list_free(trans->packages); - trans->packages = _alpm_sortbydeps(resolved, 0); + alpm_list_free(trans->add); + trans->add = _alpm_sortbydeps(resolved, 0); alpm_list_free(resolved); EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); @@ -420,15 +494,15 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* 1. check for conflicts in the target list */ _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); - deps = _alpm_innerconflicts(trans->packages); + deps = _alpm_innerconflicts(trans->add); for(i = deps; i; i = i->next) { pmconflict_t *conflict = i->data; pmpkg_t *rsync, *sync, *sync1, *sync2; /* have we already removed one of the conflicting targets? */ - sync1 = _alpm_pkg_find(trans->packages, conflict->package1); - sync2 = _alpm_pkg_find(trans->packages, conflict->package2); + sync1 = _alpm_pkg_find(trans->add, conflict->package1); + sync2 = _alpm_pkg_find(trans->add, conflict->package2); if(!sync1 || !sync2) { continue; } @@ -468,8 +542,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _alpm_log(PM_LOG_WARNING, _("removing '%s' from target list because it conflicts with '%s'\n"), rsync->name, sync->name); + trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL); _alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */ - trans->packages = alpm_list_remove(trans->packages, rsync, _alpm_pkg_cmp, NULL); continue; } @@ -479,7 +553,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* 2. we check for target vs db conflicts (and resolve)*/ _alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n"); - deps = _alpm_outerconflicts(db_local, trans->packages); + deps = _alpm_outerconflicts(db_local, trans->add); for(i = deps; i; i = i->next) { pmconflict_t *conflict = i->data; @@ -487,7 +561,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* if conflict->package2 (the local package) is not elected for removal, we ask the user */ int found = 0; - for(j = trans->packages; j && !found; j = j->next) { + for(j = trans->add; j && !found; j = j->next) { pmpkg_t *spkg = j->data; if(_alpm_pkg_find(spkg->removes, conflict->package2)) { found = 1; @@ -500,11 +574,11 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", conflict->package1, conflict->package2); - pmpkg_t *sync = _alpm_pkg_find(trans->packages, conflict->package1); + pmpkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2); int doremove = 0; QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1, - conflict->package2, NULL, &doremove); + conflict->package2, conflict->reason, &doremove); if(doremove) { /* append to the removes list */ _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); @@ -529,19 +603,17 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync alpm_list_free(deps); } - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - /* rebuild remove list */ - alpm_list_free(remove); - remove = NULL; - for(i = trans->packages; i; i = i->next) { - pmpkg_t *spkg = i->data; - for(j = spkg->removes; j; j = j->next) { - remove = alpm_list_add(remove, j->data); - } + /* Build trans->remove list */ + for(i = trans->add; i; i = i->next) { + pmpkg_t *spkg = i->data; + for(j = spkg->removes; j; j = j->next) { + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(j->data)); } + } + if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { _alpm_log(PM_LOG_DEBUG, "checking dependencies\n"); - deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, remove, trans->packages); + deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, trans->remove, trans->add); if(deps) { pm_errno = PM_ERR_UNSATISFIED_DEPS; ret = -1; @@ -554,7 +626,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync goto cleanup; } } - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { /* update download size field */ pmpkg_t *spkg = i->data; if(compute_download_size(spkg) != 0) { @@ -564,8 +636,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } cleanup: - alpm_list_free(remove); alpm_list_free(unresolvable); + alpm_list_free(remove); return(ret); } @@ -601,7 +673,7 @@ static int apply_deltas(pmtrans_t *trans) int ret = 0; const char *cachedir = _alpm_filecache_setup(); - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; alpm_list_t *delta_path = spkg->delta_path; alpm_list_t *dlts = NULL; @@ -614,7 +686,7 @@ static int apply_deltas(pmtrans_t *trans) pmdelta_t *d = dlts->data; char *delta, *from, *to; char command[PATH_MAX]; - int len = 0; + size_t len = 0; delta = _alpm_filecache_find(d->delta); /* the initial package might be in a different cachedir */ @@ -711,7 +783,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) { alpm_list_t *i, *j, *files = NULL; alpm_list_t *deltas = NULL; - pmtrans_t *tr_remove = NULL, *tr_upgrade = NULL; int replaces = 0; int errors = 0; const char *cachedir = NULL; @@ -730,7 +801,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { off_t total_size = (off_t)0; /* sum up the download size for each package and store total */ - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; total_size += spkg->download_size; } @@ -741,11 +812,10 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) for(i = handle->dbs_sync; i; i = i->next) { pmdb_t *current = i->data; - for(j = trans->packages; j; j = j->next) { + for(j = trans->add; j; j = j->next) { pmpkg_t *spkg = j->data; - pmdb_t *dbs = spkg->origin_data.db; - if(current == dbs) { + if(spkg->origin == PKG_FROM_CACHE && current == spkg->origin_data.db) { const char *fname = NULL; fname = alpm_pkg_get_filename(spkg); @@ -835,15 +905,36 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL); errors = 0; - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; + if(spkg->origin == PKG_FROM_FILE) { + continue; /* pkg_load() has been already called, this package is valid */ + } + const char *filename = alpm_pkg_get_filename(spkg); const char *md5sum = alpm_pkg_get_md5sum(spkg); if(test_md5sum(trans, filename, md5sum) != 0) { errors++; *data = alpm_list_add(*data, strdup(filename)); + continue; + } + /* load the package file and replace pkgcache entry with it in the target list */ + /* TODO: alpm_pkg_get_db() will not work on this target anymore */ + _alpm_log(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name); + char *filepath = _alpm_filecache_find(filename); + pmpkg_t *pkgfile; + if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) { + _alpm_pkg_free(pkgfile); + errors++; + *data = alpm_list_add(*data, strdup(filename)); + FREE(filepath); + continue; } + FREE(filepath); + pkgfile->reason = spkg->reason; /* copy over install reason */ + i->data = pkgfile; + _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } if(errors) { pm_errno = PM_ERR_PKG_INVALID; @@ -856,71 +947,15 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) trans->state = STATE_COMMITING; - /* Create remove and upgrade transactions */ - tr_remove = _alpm_trans_new(); - if(tr_remove == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n")); - goto error; - } - tr_upgrade = _alpm_trans_new(); - if(tr_upgrade == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not create transaction\n")); - goto error; - } - - if(_alpm_trans_init(tr_remove, PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, NULL, NULL, NULL) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not initialize the removal transaction\n")); - goto error; - } - if(_alpm_trans_init(tr_upgrade, PM_TRANS_TYPE_UPGRADE, trans->flags, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not initialize transaction\n")); - goto error; - } - - /* adding targets */ - for(i = trans->packages; i; i = i->next) { - pmpkg_t *spkg = i->data; - alpm_list_t *j; - /* remove transaction */ - for(j = spkg->removes; j; j = j->next) { - pmpkg_t *pkg = j->data; - if(!_alpm_pkg_find(tr_remove->packages, pkg->name)) { - if(_alpm_trans_addtarget(tr_remove, pkg->name) == -1) { - goto error; - } - replaces++; - } - } - /* upgrade transaction */ - const char *fname; - char *fpath; - - fname = alpm_pkg_get_filename(spkg); - if(fname == NULL) { - goto error; - } - /* Loop through the cache dirs until we find a matching file */ - fpath = _alpm_filecache_find(fname); - - if(_alpm_trans_addtarget(tr_upgrade, fpath) == -1) { - FREE(fpath); - goto error; - } - FREE(fpath); - - /* using alpm_list_last() is ok because addtarget() adds the new target at the - * end of the tr->packages list */ - pmpkg_t *ipkg = alpm_list_last(tr_upgrade->packages)->data; - ipkg->reason = spkg->reason; - } + replaces = alpm_list_count(trans->remove); /* fileconflict check */ if(!(trans->flags & PM_TRANS_FLAG_FORCE)) { EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, tr_upgrade, - tr_upgrade->packages, tr_remove->packages); + alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans, + trans->add, trans->remove); if(conflict) { pm_errno = PM_ERR_FILE_CONFLICTS; if(data) { @@ -938,14 +973,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) /* remove conflicting and to-be-replaced packages */ if(replaces) { _alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); - if(_alpm_trans_prepare(tr_remove, data) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not prepare removal transaction\n")); - goto error; - } /* we want the frontend to be aware of commit details */ - tr_remove->cb_event = trans->cb_event; - tr_remove->cb_progress = trans->cb_progress; - if(_alpm_trans_commit(tr_remove, NULL) == -1) { + if(_alpm_remove_packages(trans, handle->db_local) == -1) { _alpm_log(PM_LOG_ERROR, _("could not commit removal transaction\n")); goto error; } @@ -953,8 +982,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) /* install targets */ _alpm_log(PM_LOG_DEBUG, "installing packages\n"); - /* add_prepare is not needed */ - if(_alpm_trans_commit(tr_upgrade, NULL) == -1) { + if(_alpm_upgrade_packages(trans, handle->db_local) == -1) { _alpm_log(PM_LOG_ERROR, _("could not commit transaction\n")); goto error; } @@ -963,8 +991,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) error: FREELIST(files); alpm_list_free(deltas); - _alpm_trans_free(tr_remove); - _alpm_trans_free(tr_upgrade); return(ret); } diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index c2905a45..b432b69e 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -24,9 +24,6 @@ #include "alpm.h" -int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade); - -int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name); int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data); int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data); diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index 6e847e64..aea71db1 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -52,17 +52,18 @@ */ /** Initialize the transaction. - * @param type type of the transaction * @param flags flags of the transaction (like nodeps, etc) * @param event event callback function pointer * @param conv question callback function pointer * @param progress progress callback function pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, +int SYMEXPORT alpm_trans_init(pmtransflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress) { + pmtrans_t *trans; + ALPM_LOG_FUNC; /* Sanity checks */ @@ -78,38 +79,53 @@ int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, } } - handle->trans = _alpm_trans_new(); - if(handle->trans == NULL) { + trans = _alpm_trans_new(); + if(trans == NULL) { RET_ERR(PM_ERR_MEMORY, -1); } - return(_alpm_trans_init(handle->trans, type, flags, event, conv, progress)); -} - -/** Search for packages to upgrade and add them to the transaction. - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_trans_sysupgrade(int enable_downgrade) -{ - pmtrans_t *trans; + trans->flags = flags; + trans->cb_event = event; + trans->cb_conv = conv; + trans->cb_progress = progress; + trans->state = STATE_INITIALIZED; - ALPM_LOG_FUNC; + handle->trans = trans; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + return(0); +} - trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - ASSERT(trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1)); +static alpm_list_t *check_arch(alpm_list_t *pkgs) +{ + alpm_list_t *i; + alpm_list_t *invalid = NULL; - return(_alpm_sync_sysupgrade(trans, handle->db_local, handle->dbs_sync, enable_downgrade)); + const char *arch = alpm_option_get_arch(); + if(!arch) { + return(NULL); + } + for(i = pkgs; i; i = i->next) { + pmpkg_t *pkg = i->data; + const char *pkgarch = alpm_pkg_get_arch(pkg); + if(strcmp(pkgarch,arch) && strcmp(pkgarch,"any")) { + char *string; + const char *pkgname = alpm_pkg_get_name(pkg); + const char *pkgver = alpm_pkg_get_version(pkg); + size_t len = strlen(pkgname) + strlen(pkgver) + strlen(pkgarch) + 3; + MALLOC(string, len, RET_ERR(PM_ERR_MEMORY, invalid)); + sprintf(string, "%s-%s-%s", pkgname, pkgver, pkgarch); + invalid = alpm_list_add(invalid, string); + } + } + return(invalid); } -/** Add a target to the transaction. - * @param target the name of the target to add +/** Prepare a transaction. + * @param data the address of an alpm_list where detailed description + * of an error can be dumped (ie. list of conflicting files) * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_trans_addtarget(char *target) +int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) { pmtrans_t *trans; @@ -117,32 +133,41 @@ int SYMEXPORT alpm_trans_addtarget(char *target) /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); trans = handle->trans; + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - return(_alpm_trans_addtarget(trans, target)); -} + /* If there's nothing to do, return without complaining */ + if(trans->add == NULL && trans->remove == NULL) { + return(0); + } -/** Prepare a transaction. - * @param data the address of an alpm_list where detailed description - * of an error can be dumped (ie. list of conflicting files) - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) -{ - ALPM_LOG_FUNC; + alpm_list_t *invalid = check_arch(trans->add); + if(invalid) { + if(data) { + *data = invalid; + } + RET_ERR(PM_ERR_PKG_INVALID_ARCH, -1); + } - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + if(trans->add == NULL) { + if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) { + /* pm_errno is set by _alpm_remove_prepare() */ + return(-1); + } + } else { + if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) { + /* pm_errno is set by _alpm_sync_prepare() */ + return(-1); + } + } - ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + trans->state = STATE_PREPARED; - return(_alpm_trans_prepare(handle->trans, data)); + return(0); } /** Commit a transaction. @@ -152,17 +177,42 @@ int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) */ int SYMEXPORT alpm_trans_commit(alpm_list_t **data) { + pmtrans_t *trans; + ALPM_LOG_FUNC; /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(handle->trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1)); + trans = handle->trans; + + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1)); + + ASSERT(!(trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1)); + + /* If there's nothing to do, return without complaining */ + if(trans->add == NULL && trans->remove == NULL) { + return(0); + } + + trans->state = STATE_COMMITING; - ASSERT(!(handle->trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1)); + if(trans->add == NULL) { + if(_alpm_remove_packages(trans, handle->db_local) == -1) { + /* pm_errno is set by _alpm_remove_commit() */ + return(-1); + } + } else { + if(_alpm_sync_commit(trans, handle->db_local, data) == -1) { + /* pm_errno is set by _alpm_sync_commit() */ + return(-1); + } + } - return(_alpm_trans_commit(handle->trans, data)); + trans->state = STATE_COMMITED; + + return(0); } /** Interrupt a transaction. @@ -203,7 +253,7 @@ int SYMEXPORT alpm_trans_release() ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(trans->state != STATE_IDLE, RET_ERR(PM_ERR_TRANS_NULL, -1)); - unsigned int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK; + int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK; _alpm_trans_free(trans); handle->trans = NULL; @@ -247,12 +297,10 @@ void _alpm_trans_free(pmtrans_t *trans) return; } - if(trans->type == PM_TRANS_TYPE_SYNC) { - alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free_trans); - } else { - alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free); - } - alpm_list_free(trans->packages); + alpm_list_free_inner(trans->add, (alpm_list_fn_free)_alpm_pkg_free_trans); + alpm_list_free(trans->add); + alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free); + alpm_list_free(trans->remove); FREELIST(trans->skip_add); FREELIST(trans->skip_remove); @@ -260,150 +308,6 @@ void _alpm_trans_free(pmtrans_t *trans) FREE(trans); } -int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags, - alpm_trans_cb_event event, alpm_trans_cb_conv conv, - alpm_trans_cb_progress progress) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - trans->type = type; - trans->flags = flags; - trans->cb_event = event; - trans->cb_conv = conv; - trans->cb_progress = progress; - trans->state = STATE_INITIALIZED; - - return(0); -} - -/** Add a target to the transaction. - * @param trans the current transaction - * @param target the name of the target to add - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int _alpm_trans_addtarget(pmtrans_t *trans, char *target) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(target != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - - switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_loadtarget(trans, handle->db_local, target) == -1) { - /* pm_errno is set by _alpm_add_loadtarget() */ - return(-1); - } - break; - case PM_TRANS_TYPE_REMOVE: - case PM_TRANS_TYPE_REMOVEUPGRADE: - if(_alpm_remove_loadtarget(trans, handle->db_local, target) == -1) { - /* pm_errno is set by _alpm_remove_loadtarget() */ - return(-1); - } - break; - case PM_TRANS_TYPE_SYNC: - if(_alpm_sync_addtarget(trans, handle->db_local, handle->dbs_sync, target) == -1) { - /* pm_errno is set by _alpm_sync_loadtarget() */ - return(-1); - } - break; - } - - return(0); -} - -int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data) -{ - if(data) { - *data = NULL; - } - - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - /* If there's nothing to do, return without complaining */ - if(trans->packages == NULL) { - return(0); - } - - switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_prepare(trans, handle->db_local, data) == -1) { - /* pm_errno is set by _alpm_add_prepare() */ - return(-1); - } - break; - case PM_TRANS_TYPE_REMOVE: - case PM_TRANS_TYPE_REMOVEUPGRADE: - if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) { - /* pm_errno is set by _alpm_remove_prepare() */ - return(-1); - } - break; - case PM_TRANS_TYPE_SYNC: - if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) { - /* pm_errno is set by _alpm_sync_prepare() */ - return(-1); - } - break; - } - - trans->state = STATE_PREPARED; - - return(0); -} - -int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data) -{ - ALPM_LOG_FUNC; - - if(data!=NULL) - *data = NULL; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - /* If there's nothing to do, return without complaining */ - if(trans->packages == NULL) { - return(0); - } - - trans->state = STATE_COMMITING; - - switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_commit(trans, handle->db_local) == -1) { - /* pm_errno is set by _alpm_add_commit() */ - return(-1); - } - break; - case PM_TRANS_TYPE_REMOVE: - case PM_TRANS_TYPE_REMOVEUPGRADE: - if(_alpm_remove_commit(trans, handle->db_local) == -1) { - /* pm_errno is set by _alpm_remove_commit() */ - return(-1); - } - break; - case PM_TRANS_TYPE_SYNC: - if(_alpm_sync_commit(trans, handle->db_local, data) == -1) { - /* pm_errno is set by _alpm_sync_commit() */ - return(-1); - } - break; - } - - trans->state = STATE_COMMITED; - - return(0); -} - /* A cheap grep for text files, returns 1 if a substring * was found in the text file fn, 0 if it wasn't */ @@ -416,7 +320,8 @@ static int grep(const char *fn, const char *needle) } while(!feof(fp)) { char line[1024]; - fgets(line, 1024, fp); + int sline = sizeof(line)-1; + fgets(line, sline, fp); if(feof(fp)) { continue; } @@ -464,7 +369,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn, /* either extract or copy the scriptlet */ snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir); if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) { - if(_alpm_unpack(installfn, tmpdir, ".INSTALL")) { + if(_alpm_unpack_single(installfn, tmpdir, ".INSTALL")) { retval = 1; } } else { @@ -503,30 +408,30 @@ cleanup: return(retval); } -pmtranstype_t SYMEXPORT alpm_trans_get_type() +int SYMEXPORT alpm_trans_get_flags() { /* Sanity checks */ ASSERT(handle != NULL, return(-1)); ASSERT(handle->trans != NULL, return(-1)); - return handle->trans->type; + return handle->trans->flags; } -unsigned int SYMEXPORT alpm_trans_get_flags() +alpm_list_t SYMEXPORT * alpm_trans_get_add() { /* Sanity checks */ - ASSERT(handle != NULL, return(-1)); - ASSERT(handle->trans != NULL, return(-1)); + ASSERT(handle != NULL, return(NULL)); + ASSERT(handle->trans != NULL, return(NULL)); - return handle->trans->flags; + return handle->trans->add; } -alpm_list_t SYMEXPORT * alpm_trans_get_pkgs() +alpm_list_t SYMEXPORT * alpm_trans_get_remove() { /* Sanity checks */ ASSERT(handle != NULL, return(NULL)); ASSERT(handle->trans != NULL, return(NULL)); - return handle->trans->packages; + return handle->trans->remove; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 0537bc72..ca1e141a 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -37,10 +37,10 @@ typedef enum _pmtransstate_t { /* Transaction */ struct __pmtrans_t { - pmtranstype_t type; pmtransflag_t flags; pmtransstate_t state; - alpm_list_t *packages; /* list of (pmpkg_t *) */ + alpm_list_t *add; /* list of (pmpkg_t *) */ + alpm_list_t *remove; /* list of (pmpkg_t *) */ alpm_list_t *skip_add; /* list of (char *) */ alpm_list_t *skip_remove; /* list of (char *) */ alpm_trans_cb_event cb_event; @@ -69,12 +69,9 @@ do { \ pmtrans_t *_alpm_trans_new(void); void _alpm_trans_free(pmtrans_t *trans); -int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags, +int _alpm_trans_init(pmtrans_t *trans, pmtransflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress); -int _alpm_trans_addtarget(pmtrans_t *trans, char *target); -int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data); -int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data); int _alpm_runscriptlet(const char *root, const char *installfn, const char *script, const char *ver, const char *oldver, pmtrans_t *trans); diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 082c095b..d9108096 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -175,7 +175,7 @@ char *_alpm_strtrim(char *str) return(str); } - while(isspace((int)*pch)) { + while(isspace((unsigned char)*pch)) { pch++; } if(pch != str) { @@ -188,7 +188,7 @@ char *_alpm_strtrim(char *str) } pch = (str + (strlen(str) - 1)); - while(isspace((int)*pch)) { + while(isspace((unsigned char)*pch)) { pch--; } *++pch = '\0'; @@ -196,57 +196,11 @@ char *_alpm_strtrim(char *str) return(str); } -/* Helper function for _alpm_strreplace */ -static void _strnadd(char **str, const char *append, unsigned int count) -{ - if(*str) { - *str = realloc(*str, strlen(*str) + count + 1); - } else { - *str = calloc(count + 1, sizeof(char)); - } - - strncat(*str, append, count); -} - -/* Replace all occurances of 'needle' with 'replace' in 'str', returning - * a new string (must be free'd) */ -char *_alpm_strreplace(const char *str, const char *needle, const char *replace) -{ - const char *p, *q; - p = q = str; - - char *newstr = NULL; - unsigned int needlesz = strlen(needle), - replacesz = strlen(replace); - - while (1) { - q = strstr(p, needle); - if(!q) { /* not found */ - if(*p) { - /* add the rest of 'p' */ - _strnadd(&newstr, p, strlen(p)); - } - break; - } else { /* found match */ - if(q > p){ - /* add chars between this occurance and last occurance, if any */ - _strnadd(&newstr, p, q - p); - } - _strnadd(&newstr, replace, replacesz); - p = q + needlesz; - } - } - - return newstr; -} - - /* Create a lock file */ int _alpm_lckmk() { int fd; - pid_t pid; - char *dir, *ptr, *spid = NULL; + char *dir, *ptr; const char *file = alpm_option_get_lockfile(); /* create the dir of the lockfile first */ @@ -261,13 +215,11 @@ int _alpm_lckmk() while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EINTR); if(fd > 0) { - pid = getpid(); - size_t len = snprintf(spid, 0, "%ld\n", (long)pid) + 1; - spid = malloc(len); - snprintf(spid, len, "%ld\n", (long)pid); - while(write(fd, (void *)spid, len) == -1 && errno == EINTR); + FILE *f = fdopen(fd, "w"); + fprintf(f, "%ld\n", (long)getpid()); + fflush(f); fsync(fd); - free(spid); + fclose(f); return(fd); } return(-1); @@ -286,14 +238,38 @@ int _alpm_lckrm() /* Compression functions */ /** - * @brief Unpack a specific file or all files in an archive. + * @brief Unpack a specific file in an archive. * * @param archive the archive to unpack * @param prefix where to extract the files - * @param fn a file within the archive to unpack or NULL for all + * @param fn a file within the archive to unpack * @return 0 on success, 1 on failure */ -int _alpm_unpack(const char *archive, const char *prefix, const char *fn) +int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn) +{ + alpm_list_t *list = NULL; + int ret = 0; + if(fn == NULL) { + return(1); + } + list = alpm_list_add(list, (void *)fn); + ret = _alpm_unpack(archive, prefix, list, 1); + alpm_list_free(list); + return(ret); +} + +/** + * @brief Unpack a list of files in an archive. + * + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param list a list of files within the archive to unpack or + * NULL for all + * @param breakfirst break after the first entry found + * + * @return 0 on success, 1 on failure + */ +int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst) { int ret = 0; mode_t oldmask; @@ -346,14 +322,23 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) archive_entry_set_perm(entry, 0755); } - /* If a specific file was requested skip entries that don't match. */ - if (fn && strcmp(fn, entryname)) { - _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname); - if (archive_read_data_skip(_archive) != ARCHIVE_OK) { - ret = 1; - goto cleanup; + /* If specific files were requested, skip entries that don't match. */ + if(list) { + char *prefix = strdup(entryname); + char *p = strstr(prefix,"/"); + if(p) { + *(p+1) = '\0'; + } + char *found = alpm_list_find_str(list, prefix); + free(prefix); + if(!found) { + _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname); + if (archive_read_data_skip(_archive) != ARCHIVE_OK) { + ret = 1; + goto cleanup; + } + continue; } - continue; } /* Extract the archive entry. */ @@ -369,7 +354,7 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) goto cleanup; } - if(fn) { + if(breakfirst) { break; } } @@ -425,8 +410,7 @@ int _alpm_rmrf(const char *path) return(0); } -int _alpm_logaction(unsigned short usesyslog, FILE *f, - const char *fmt, va_list args) +int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) { int ret = 0; diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 4bc8b92f..37893c8b 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -26,6 +26,8 @@ #include "config.h" +#include "alpm_list.h" + #include <stdio.h> #include <string.h> #include <stdarg.h> @@ -60,12 +62,12 @@ int _alpm_makepath(const char *path); int _alpm_makepath_mode(const char *path, mode_t mode); int _alpm_copyfile(const char *src, const char *dest); char *_alpm_strtrim(char *str); -char *_alpm_strreplace(const char *str, const char *needle, const char *replace); int _alpm_lckmk(); int _alpm_lckrm(); -int _alpm_unpack(const char *archive, const char *prefix, const char *fn); +int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn); +int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst); int _alpm_rmrf(const char *path); -int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *fmt, va_list args); +int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args); int _alpm_run_chroot(const char *root, const char *cmd); int _alpm_ldconfig(const char *root); int _alpm_str_cmp(const void *s1, const void *s2); diff --git a/pactest/tests/depconflict110.py b/pactest/tests/depconflict110.py index fd56fa89..82e17d0b 100644 --- a/pactest/tests/depconflict110.py +++ b/pactest/tests/depconflict110.py @@ -7,7 +7,7 @@ self.addpkg(p); lp = pmpkg("pkg2", "1.0-1") self.addpkg2db("local", lp) -self.args = "-U %s" % p.filename() -self.addrule("PACMAN_RETCODE=1") -self.addrule("!PKG_EXIST=pkg1") -self.addrule("PKG_EXIST=pkg2") +self.args = "-U %s --ask=4" % p.filename() +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/ignore002.py b/pactest/tests/ignore002.py index b2c5593a..9b09e8f7 100644 --- a/pactest/tests/ignore002.py +++ b/pactest/tests/ignore002.py @@ -28,7 +28,7 @@ self.addpkg2db("sync", package4up) self.option["IgnorePkg"] = ["package2"] self.args = "-Su" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_VERSION=package1|1.0-1") self.addrule("PKG_VERSION=package2|1.0-1") self.addrule("PKG_VERSION=package3|1.0-1") diff --git a/pactest/tests/ignore003.py b/pactest/tests/ignore003.py index 02b3c91c..8768a6ef 100644 --- a/pactest/tests/ignore003.py +++ b/pactest/tests/ignore003.py @@ -28,7 +28,7 @@ self.addpkg2db("sync", package4up) self.option["IgnorePkg"] = ["package2"] self.args = "-Su" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_VERSION=package1|1.0-1") self.addrule("PKG_VERSION=package2|1.0-1") self.addrule("PKG_VERSION=package3|1.0-1") diff --git a/pactest/tests/ignore004.py b/pactest/tests/ignore004.py index fff12f62..e6af48bd 100644 --- a/pactest/tests/ignore004.py +++ b/pactest/tests/ignore004.py @@ -38,7 +38,7 @@ self.addpkg2db("sync", packageA5up) self.option["IgnorePkg"] = ["packageA3"] self.args = "-S packageA1" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_VERSION=packageA1|1.0-1") self.addrule("PKG_VERSION=packageA2|1.0-1") self.addrule("PKG_VERSION=packageA3|1.0-1") diff --git a/pactest/tests/ignore005.py b/pactest/tests/ignore005.py index 1957ea4f..274e44c3 100644 --- a/pactest/tests/ignore005.py +++ b/pactest/tests/ignore005.py @@ -36,7 +36,7 @@ self.addpkg2db("sync", packageA5up) self.option["IgnorePkg"] = ["packageA3"] -self.args = "-S packageA1 packageA2" +self.args = "-S packageA1 packageA2 --ask=32" self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_VERSION=packageA1|1.0-1") diff --git a/pactest/tests/provision020.py b/pactest/tests/provision020.py index c9c0ac36..7cb0a01b 100644 --- a/pactest/tests/provision020.py +++ b/pactest/tests/provision020.py @@ -10,6 +10,6 @@ self.addpkg2db("local", lp) self.args = "-S %s" % p.name -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/provision022.py b/pactest/tests/provision022.py index 190a8b66..4883d428 100644 --- a/pactest/tests/provision022.py +++ b/pactest/tests/provision022.py @@ -10,6 +10,6 @@ self.addpkg2db("local", lp) self.args = "-S %s" % p.name -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/sync042.py b/pactest/tests/sync042.py index 0aa7e37b..7c3498d3 100644 --- a/pactest/tests/sync042.py +++ b/pactest/tests/sync042.py @@ -9,6 +9,6 @@ self.addpkg2db("local", lp); self.args = "-S %s" % sp.name -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_EXIST=pkg1") -self.addrule("!PKG_EXIST=pkg2") +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/sync043.py b/pactest/tests/sync043.py index 1302bf04..8461e9f9 100644 --- a/pactest/tests/sync043.py +++ b/pactest/tests/sync043.py @@ -7,10 +7,10 @@ self.addpkg2db("sync", sp); lp1 = pmpkg("pkg2") self.addpkg2db("local", lp1); -lp1 = pmpkg("pkg3") -self.addpkg2db("local", lp1); +lp2 = pmpkg("pkg3") +self.addpkg2db("local", lp2); -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync044.py b/pactest/tests/sync044.py index c4ff1549..0c8fd2e9 100644 --- a/pactest/tests/sync044.py +++ b/pactest/tests/sync044.py @@ -11,7 +11,7 @@ sp3 = pmpkg("pkg3") sp3.conflicts = ["pkg1"] self.addpkg2db("sync", sp3); -self.args = "-S pkg2" +self.args = "-S pkg2 --ask=4" self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/sync045.py b/pactest/tests/sync045.py new file mode 100644 index 00000000..574c0a52 --- /dev/null +++ b/pactest/tests/sync045.py @@ -0,0 +1,18 @@ +self.description = "Install a sync package conflicting with two local ones (-d)" + +sp = pmpkg("pkg1") +sp.conflicts = ["pkg2", "pkg3"] +self.addpkg2db("sync", sp); + +lp1 = pmpkg("pkg2") +self.addpkg2db("local", lp1); + +lp2 = pmpkg("pkg3") +self.addpkg2db("local", lp2); + +self.args = "-Sd %s --ask=4" % sp.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") +self.addrule("!PKG_EXIST=pkg3") diff --git a/pactest/tests/sync1004.py b/pactest/tests/sync1004.py index f87bbe9b..a9cee49c 100644 --- a/pactest/tests/sync1004.py +++ b/pactest/tests/sync1004.py @@ -11,7 +11,7 @@ self.addpkg2db("sync", sp2) lp = pmpkg("depend") self.addpkg2db("local", lp) -self.args = "-S pkg1 pkg2" +self.args = "-S pkg1 pkg2 --ask=4" self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=depend") diff --git a/pactest/tests/sync1008.py b/pactest/tests/sync1008.py index 90c61dfb..a6064597 100644 --- a/pactest/tests/sync1008.py +++ b/pactest/tests/sync1008.py @@ -14,6 +14,6 @@ self.addpkg2db("sync1", sp3) self.args = "-S pkg" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg") self.addrule("!PKG_EXIST=cpkg") diff --git a/pactest/tests/sync150.py b/pactest/tests/sync150.py new file mode 100644 index 00000000..b62bd984 --- /dev/null +++ b/pactest/tests/sync150.py @@ -0,0 +1,25 @@ +self.description = "-Su foo" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.depends = ["pkg2"] + +sp2 = pmpkg("pkg2") +sp2.depends = ["pkg3"] + +sp3 = pmpkg("pkg3") + +sp4 = pmpkg("pkg4") + +for p in sp1, sp2, sp3, sp4: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) + +self.args = "-Su %s" % sp4.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|1.0-2") +for p in sp2, sp3: + self.addrule("PKG_REASON=%s|1" % p.name) +self.addrule("PKG_REASON=%s|0" % sp4.name) diff --git a/pactest/tests/sync200.py.in b/pactest/tests/sync200.py.in index 3c11f83f..c83e9ac7 100644 --- a/pactest/tests/sync200.py.in +++ b/pactest/tests/sync200.py.in @@ -1,6 +1,6 @@ self.description = "Synchronize the local database" -if not "download" in "@LIBS@": +if not "fetch" in "@LIBS@": self.option['XferCommand'] = ['/usr/bin/curl %u > %o'] sp1 = pmpkg("spkg1", "1.0-1") diff --git a/pactest/tests/sync300.py b/pactest/tests/sync300.py index 36d6758a..31b520a8 100644 --- a/pactest/tests/sync300.py +++ b/pactest/tests/sync300.py @@ -9,6 +9,6 @@ self.addpkg2db("sync", sp2) self.args = "-S %s" % sp1.name -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync890.py b/pactest/tests/sync890.py index 75947e9a..e8380b79 100644 --- a/pactest/tests/sync890.py +++ b/pactest/tests/sync890.py @@ -12,7 +12,7 @@ lp2.conflicts = ["pkg3"] for p in lp1, lp2: self.addpkg2db("local", p) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync892.py b/pactest/tests/sync892.py index 04cc79c5..dfd889ea 100644 --- a/pactest/tests/sync892.py +++ b/pactest/tests/sync892.py @@ -16,7 +16,7 @@ lp2.conflicts = ["pkg3"] for p in lp1, lp2: self.addpkg2db("local", p) -self.args = "-S %s" % " ".join([p.name for p in sp1, sp2]) +self.args = "-S %s --ask=4" % " ".join([p.name for p in sp1, sp2]) self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/sync893.py b/pactest/tests/sync893.py index 1c8494a3..e96bb7b6 100644 --- a/pactest/tests/sync893.py +++ b/pactest/tests/sync893.py @@ -13,7 +13,7 @@ self.addpkg2db("local", lp1) lp2 = pmpkg("pkg2") self.addpkg2db("local", lp2) -self.args = "-S %s" % " ".join([p.name for p in sp1, sp2]) +self.args = "-S %s --ask=4" % " ".join([p.name for p in sp1, sp2]) self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync895.py b/pactest/tests/sync895.py index 1b348c19..fd987864 100644 --- a/pactest/tests/sync895.py +++ b/pactest/tests/sync895.py @@ -12,7 +12,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync896.py b/pactest/tests/sync896.py index a89b5c70..492bd7b4 100644 --- a/pactest/tests/sync896.py +++ b/pactest/tests/sync896.py @@ -13,7 +13,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/sync897.py b/pactest/tests/sync897.py index f7bd3d71..8a1c5a7c 100644 --- a/pactest/tests/sync897.py +++ b/pactest/tests/sync897.py @@ -16,7 +16,7 @@ self.addpkg2db("local", lp2) lp3 = pmpkg("pkg3") self.addpkg2db("local", lp3) -self.args = "-Su" +self.args = "-Su --ask=4" self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync899.py b/pactest/tests/sync899.py index a561ae63..fd308050 100644 --- a/pactest/tests/sync899.py +++ b/pactest/tests/sync899.py @@ -11,7 +11,7 @@ self.addpkg2db("local", lp1) lp2 = pmpkg("pkg2") self.addpkg2db("local", lp2) -self.args = "-Su" +self.args = "-Su --ask=4" self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync900.py b/pactest/tests/sync900.py index 16dfee12..744fad03 100644 --- a/pactest/tests/sync900.py +++ b/pactest/tests/sync900.py @@ -16,7 +16,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=foo") diff --git a/pactest/tests/sync901.py b/pactest/tests/sync901.py index bb420b79..f5834533 100644 --- a/pactest/tests/sync901.py +++ b/pactest/tests/sync901.py @@ -16,7 +16,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=foo") diff --git a/pactest/tests/sync992.py b/pactest/tests/sync992.py index a7ad1110..63faaaba 100644 --- a/pactest/tests/sync992.py +++ b/pactest/tests/sync992.py @@ -15,7 +15,7 @@ for p in sp1, sp2, sp3: lp1 = pmpkg("pkg2", "0.1-1") self.addpkg2db("local", lp1) -self.args = "-S %s" % " ".join([p.name for p in sp1, sp2]) +self.args = "-S %s --ask=4" % " ".join([p.name for p in sp1, sp2]) self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync999.py b/pactest/tests/sync999.py index 69089fa1..89447cad 100644 --- a/pactest/tests/sync999.py +++ b/pactest/tests/sync999.py @@ -14,7 +14,7 @@ self.addpkg2db("local", lp1) lp2 = pmpkg("pkg2") self.addpkg2db("local", lp2) -self.args = "-Su" +self.args = "-Su --ask=4" self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/upgrade051.py b/pactest/tests/upgrade051.py index 4346c24d..1d173218 100644 --- a/pactest/tests/upgrade051.py +++ b/pactest/tests/upgrade051.py @@ -8,10 +8,8 @@ p.conflicts = ["pkg1"] p.provides = ["pkg1"] self.addpkg(p) -self.args = "-U %s" % p.filename() +self.args = "-U %s --ask=4" % p.filename() self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") - -self.expectfailure = True diff --git a/pactest/tests/upgrade080.py b/pactest/tests/upgrade080.py new file mode 100644 index 00000000..9ddbd708 --- /dev/null +++ b/pactest/tests/upgrade080.py @@ -0,0 +1,16 @@ +self.description = "Install a package (correct architecture)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = 'testarch' +self.addpkg(p) + +self.option["Architecture"] = ['testarch'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade081.py b/pactest/tests/upgrade081.py new file mode 100644 index 00000000..99e22311 --- /dev/null +++ b/pactest/tests/upgrade081.py @@ -0,0 +1,16 @@ +self.description = "Install a package (wrong architecture)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = 'testarch' +self.addpkg(p) + +self.option["Architecture"] = ['nottestarch'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=dummy") +for f in p.files: + self.addrule("!FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade082.py b/pactest/tests/upgrade082.py new file mode 100644 index 00000000..0bdbdf71 --- /dev/null +++ b/pactest/tests/upgrade082.py @@ -0,0 +1,19 @@ +self.description = "Install a package (correct architecture, auto)" + +import os +machine = os.uname()[4] + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = machine +self.addpkg(p) + +self.option["Architecture"] = ['auto'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade083.py b/pactest/tests/upgrade083.py new file mode 100644 index 00000000..097ae02c --- /dev/null +++ b/pactest/tests/upgrade083.py @@ -0,0 +1,19 @@ +self.description = "Install a package (wrong architecture, auto)" + +import os +machine = os.uname()[4] + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = machine + 'wrong' +self.addpkg(p) + +self.option["Architecture"] = ['auto'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=dummy") +for f in p.files: + self.addrule("!FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade084.py b/pactest/tests/upgrade084.py new file mode 100644 index 00000000..8268e3ff --- /dev/null +++ b/pactest/tests/upgrade084.py @@ -0,0 +1,16 @@ +self.description = "Install a package ('any' architecture)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = 'any' +self.addpkg(p) + +self.option["Architecture"] = ['auto'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade090.py b/pactest/tests/upgrade090.py new file mode 100644 index 00000000..26e531c9 --- /dev/null +++ b/pactest/tests/upgrade090.py @@ -0,0 +1,28 @@ +self.description = "-U syncdeps test" + +p1 = pmpkg("pkg1", "1.0-2") +p1.files = ["bin/pkg1"] + +p2 = pmpkg("pkg2", "1.0-2") +p2.depends = ["dep"] + +p3 = pmpkg("pkg3", "1.0-2") +p3.depends = ["unres"] + +for p in p1, p2, p3: + self.addpkg(p) + +sp = pmpkg("dep") +sp.files = ["bin/dep"] +self.addpkg2db("sync", sp) + +self.args = "-U %s --ask=32" % " ".join([p.filename() for p in p1, p2, p3]) + +self.addrule("PACMAN_RETCODE=0") +for p in p1, p2, sp: + self.addrule("PKG_EXIST=%s" % p.name) + for f in p.files: + self.addrule("FILE_EXIST=%s" % f) +self.addrule("PKG_VERSION=pkg1|1.0-2") +self.addrule("PKG_VERSION=pkg2|1.0-2") +self.addrule("!PKG_EXIST=pkg3") diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 5d656534..330acb98 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -16,7 +16,7 @@ EXTRA_DIST = \ makepkg.sh.in \ pacman-optimize.sh.in \ pkgdelta.sh.in \ - rankmirrors.py.in \ + rankmirrors.sh.in \ repo-add.sh.in # Files that should be removed, but which Automake does not know. @@ -62,7 +62,7 @@ $(OURSCRIPTS): Makefile makepkg: $(srcdir)/makepkg.sh.in pacman-optimize: $(srcdir)/pacman-optimize.sh.in pkgdelta: $(srcdir)/pkgdelta.sh.in -rankmirrors: $(srcdir)/rankmirrors.py.in +rankmirrors: $(srcdir)/rankmirrors.sh.in repo-add: $(srcdir)/repo-add.sh.in repo-remove: $(srcdir)/repo-add.sh.in rm -f repo-remove diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 3662228c..0ce5353f 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -27,7 +27,7 @@ # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: -# awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils), +# bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils), # getopt (util-linux), gettext, grep, gzip, openssl, sed # gettext initialization @@ -46,8 +46,9 @@ pkgdir="$startdir/pkg" packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge') other_options=('ccache' 'distcc' 'makeflags' 'force') -splitpkg_overrides=('pkgdesc' 'license' 'groups' 'depends' 'optdepends' 'provides' \ - 'conflicts' 'replaces' 'backup' 'options' 'install') +splitpkg_overrides=('pkgver' 'pkgrel' 'pkgdesc' 'arch' 'license' 'groups' \ + 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' \ + 'backup' 'options' 'install' 'changelog') readonly -a packaging_options other_options splitpkg_overrides # Options @@ -175,6 +176,7 @@ clean_up() { ## # Signal Traps ## +set -E trap 'clean_up' 0 trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT @@ -187,15 +189,15 @@ trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR # extract the filename from a source entry get_filename() { # if a filename is specified, use it - local filename=$(echo $1 | sed 's|::.*||') + local filename="${1%%::*}" # if it is just an URL, we only keep the last component - echo "$filename" | sed 's|^.*://.*/||g' + echo "${filename##*/}" } # extract the URL from a source entry get_url() { # strip an eventual filename - echo $1 | sed 's|.*::||' + echo "${1#*::}" } ## @@ -245,11 +247,11 @@ check_buildenv() { # ? - not found ## in_opt_array() { - local needle=$(echo $1 | tr '[:upper:]' '[:lower:]'); shift + local needle="${1,,}"; shift local opt for opt in "$@"; do - opt=$(echo $opt | tr '[:upper:]' '[:lower:]') + opt="${opt,,}" if [ "$opt" = "$needle" ]; then echo 'y' # Enabled return @@ -281,14 +283,14 @@ in_array() { get_downloadclient() { # $1 = URL with valid protocol prefix local url=$1 - local proto=$(echo "$url" | sed 's|://.*||') + local proto="${url%%://*}" # loop through DOWNLOAD_AGENTS variable looking for protocol local i for i in "${DLAGENTS[@]}"; do - local handler=$(echo $i | sed 's|::.*||') + local handler="${i%%::*}" if [ "$proto" = "$handler" ]; then - agent=$(echo $i | sed 's|^.*::||') + agent="${i##*::}" break fi done @@ -301,7 +303,7 @@ get_downloadclient() { fi # ensure specified program is installed - local program="$(echo $agent | awk '{print $1 }')" + local program="${agent%% *}" if [ ! -x "$program" ]; then local baseprog=$(basename $program) error "$(gettext "The download program %s is not installed.")" "$baseprog" @@ -320,7 +322,7 @@ download_file() { # destination file local file=$3 # temporary download file, default to last component of the URL - local dlfile=$(echo "$url" | sed 's|^.*://.*/||g') + local dlfile="${url##*/}" # replace %o by the temporary dlfile if it exists if echo "$dlcmd" | grep -q "%o" ; then @@ -355,7 +357,7 @@ check_deps() { fi } -handledeps() { +handle_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 @@ -403,7 +405,7 @@ resolve_deps() { return $R_DEPS_SATISFIED fi - if handledeps $deplist; then + if handle_deps $deplist; then pkgdeps="$pkgdeps $deplist" # check deps again to make sure they were resolved deplist="$(check_deps $*)" @@ -430,7 +432,7 @@ remove_deps() { local dep depstrip deplist deplist="" for dep in $pkgdeps; do - depstrip=$(echo $dep | sed -e 's|=.*$||' -e 's|>.*$||' -e 's|<.*$||') + depstrip="${dep%%[<=>]*}" deplist="$deplist $depstrip" done @@ -512,7 +514,7 @@ generate_checksums() { local integ for integ in ${INTEGRITY_CHECK[@]}; do - integ="$(echo $integ | tr '[:upper:]' '[:lower:]')" + integ="${integ,,}" case "$integ" in md5|sha1|sha256|sha384|sha512) : ;; *) @@ -545,7 +547,8 @@ generate_checksums() { fi fi - local sum="$(openssl dgst -${integ} "$file" | awk '{print $NF}')" + local sum="$(openssl dgst -${integ} "$file")" + sum=${sum##* } [ $ct -gt 0 ] && echo -n "$indent" echo -n "'$sum'" ct=$(($ct+1)) @@ -590,8 +593,9 @@ check_checksums() { fi if [ $found -gt 0 ] ; then - local expectedsum="$(echo ${integrity_sums[$idx]} | tr '[A-F]' '[a-f]')" - local realsum="$(openssl dgst -${integ} "$file" | awk '{print $NF}')" + local expectedsum="${integrity_sums[$idx],,}" + local realsum="$(openssl dgst -${integ} "$file")" + realsum="${realsum##* }" if [ "$expectedsum" = "$realsum" ]; then echo "$(gettext "Passed")" >&2 else @@ -693,72 +697,23 @@ extract_sources() { fi } -run_build() { - # use distcc if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv distcc)" = "y" -a "$(check_option distcc)" != "n" ]; then - [ -d /usr/lib/distcc/bin ] && export PATH="/usr/lib/distcc/bin:$PATH" - export DISTCC_HOSTS - elif [ "$(check_option distcc)" = "n" ]; then - # if it is not wanted, clear the makeflags too - MAKEFLAGS="" - fi - - # use ccache if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv ccache)" = "y" -a "$(check_option ccache)" != "n" ]; then - [ -d /usr/lib/ccache/bin ] && export PATH="/usr/lib/ccache/bin:$PATH" - fi - - # clear user-specified makeflags if requested - if [ "$(check_option makeflags)" = "n" ]; then - MAKEFLAGS="" - fi - - msg "$(gettext "Starting build()...")" - cd "$srcdir" - - # ensure all necessary build variables are exported - export CFLAGS CXXFLAGS MAKEFLAGS LDFLAGS CHOST - # save our shell options so build() can't override what we need - local shellopts=$(shopt -p) - - local ret=0 - if [ "$LOGGING" -eq 1 ]; then - BUILDLOG="${startdir}/${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log" - if [ -f "$BUILDLOG" ]; then - local i=1 - while true; do - if [ -f "$BUILDLOG.$i" ]; then - i=$(($i +1)) - else - break - fi - done - mv "$BUILDLOG" "$BUILDLOG.$i" - fi - - build 2>&1 | tee "$BUILDLOG"; ret=${PIPESTATUS[0]} - else - build 2>&1 || ret=$? +error_function() { + if [ -p "$logpipe" ]; then + rm "$logpipe" fi - # reset our shell options - eval "$shellopts" - - if [ $ret -gt 0 ]; then - error "$(gettext "Build Failed.")" + # first exit all subshells, then print the error + if [ $BASH_SUBSHELL -eq 0 ]; then plain "$(gettext "Aborting...")" remove_deps - exit 2 # $E_BUILD_FAILED fi + exit 2 # $E_BUILD_FAILED } -run_package() { +run_function() { if [ -z "$1" ]; then - pkgfunc="package" - nameofpkg="$pkgname" - else - pkgfunc="package_$1" - nameofpkg="$1" + return 1 fi + pkgfunc="$1" # clear user-specified makeflags if requested if [ "$(check_option makeflags)" = "n" ]; then @@ -770,10 +725,12 @@ run_package() { # ensure all necessary build variables are exported export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST + # save our shell options so pkgfunc() can't override what we need + local shellopts=$(shopt -p) local ret=0 if [ "$LOGGING" -eq 1 ]; then - BUILDLOG="${startdir}/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}-package.log" + BUILDLOG="${startdir}/${pkgname}-${pkgver}-${pkgrel}-${CARCH}-$pkgfunc.log" if [ -f "$BUILDLOG" ]; then local i=1 while true; do @@ -792,20 +749,49 @@ run_package() { exec 3>&1 tee "$BUILDLOG" < "$logpipe" & exec 1>"$logpipe" 2>"$logpipe" - $pkgfunc 2>&1 || ret=$? + restoretrap=$(trap -p ERR) + trap 'error_function' ERR + $pkgfunc 2>&1 + eval $restoretrap sync exec 1>&3 2>&3 3>&- rm "$logpipe" else - $pkgfunc 2>&1 || ret=$? + restoretrap=$(trap -p ERR) + trap 'error_function' ERR + $pkgfunc 2>&1 + eval $restoretrap fi + # reset our shell options + eval "$shellopts" +} - if [ $ret -gt 0 ]; then - error "$(gettext "Packaging Failed.")" - plain "$(gettext "Aborting...")" - remove_deps - exit 2 # $E_BUILD_FAILED +run_build() { + # use distcc if it is requested (check buildenv and PKGBUILD opts) + if [ "$(check_buildenv distcc)" = "y" -a "$(check_option distcc)" != "n" ]; then + [ -d /usr/lib/distcc/bin ] && export PATH="/usr/lib/distcc/bin:$PATH" + export DISTCC_HOSTS + elif [ "$(check_option distcc)" = "n" ]; then + # if it is not wanted, clear the makeflags too + MAKEFLAGS="" fi + + # use ccache if it is requested (check buildenv and PKGBUILD opts) + if [ "$(check_buildenv ccache)" = "y" -a "$(check_option ccache)" != "n" ]; then + [ -d /usr/lib/ccache/bin ] && export PATH="/usr/lib/ccache/bin:$PATH" + fi + + run_function "build" +} + +run_package() { + if [ -z "$1" ]; then + pkgfunc="package" + else + pkgfunc="package_$1" + fi + + run_function "$pkgfunc" } tidy_install() { @@ -899,7 +885,8 @@ write_pkginfo() { else local packager="Unknown Packager" fi - local size=$(du -sk | awk '{print $1 * 1024}') + local size="$(du -sk)" + size="$(( ${size%%[^0-9]*} * 1024 ))" msg2 "$(gettext "Generating .PKGINFO file...")" echo "# Generated by makepkg $myver" >.PKGINFO @@ -915,9 +902,7 @@ write_pkginfo() { echo "builddate = $builddate" >>.PKGINFO echo "packager = $packager" >>.PKGINFO echo "size = $size" >>.PKGINFO - if [ -n "$CARCH" ]; then - echo "arch = $CARCH" >>.PKGINFO - fi + echo "arch = $PKGARCH" >>.PKGINFO if [ "$(check_option force)" = "y" ]; then echo "force = true" >> .PKGINFO fi @@ -966,6 +951,18 @@ write_pkginfo() { fi } +check_package() { + cd "$pkgdir" + + # check existence of backup files + local file + for file in "${backup[@]}"; do + if [ ! -f "$file" ]; then + warning "$(gettext "Invalid backup entry : %s")" "$file" + fi + done +} + create_package() { if [ ! -d "$pkgdir" ]; then error "$(gettext "Missing pkg/ directory.")" @@ -973,6 +970,8 @@ create_package() { exit 1 # $E_MISSING_PKGDIR fi + check_package + cd "$pkgdir" msg "$(gettext "Creating package...")" @@ -982,6 +981,12 @@ create_package() { nameofpkg="$1" fi + if [ "$arch" = "any" ]; then + PKGARCH="any" + else + PKGARCH=$CARCH + fi + write_pkginfo $nameofpkg local comp_files=".PKGINFO" @@ -994,9 +999,9 @@ create_package() { fi # do we have a changelog? - if [ -f "$startdir/ChangeLog" ]; then + if [ -n "$changelog" ]; then msg2 "$(gettext "Adding package changelog...")" - cp "$startdir/ChangeLog" .CHANGELOG + cp "$startdir/$changelog" .CHANGELOG comp_files="$comp_files .CHANGELOG" fi @@ -1010,7 +1015,7 @@ create_package() { *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT" ; EXT=$PKGEXT ;; esac - local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}${EXT}" + local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${EXT}" local ret=0 @@ -1058,13 +1063,17 @@ create_srcpackage() { msg2 "$(gettext "Adding install script...")" ln -s "${startdir}/$install" "${srclinks}/${pkgbase}/" else - error "$(gettext "Install script %s not found.")" "$install" + error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" fi fi - if [ -f ChangeLog ]; then - msg2 "$(gettext "Adding %s...")" "ChangeLog" - ln -s "${startdir}/ChangeLog" "${srclinks}/${pkgbase}" + if [ -n "$changelog" ]; then + if [ -f "$changelog" ]; then + msg2 "$(gettext "Adding package changelog...")" + ln -s "${startdir}/$changelog" "${srclinks}/${pkgbase}/" + else + error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" + fi fi local netfile @@ -1112,7 +1121,11 @@ install_package() { local pkglist for pkg in ${pkgname[@]}; do - pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + if [ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} ]; then + pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + else + pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}" + fi done local ret=0 @@ -1155,15 +1168,14 @@ check_sanity() { return 1 fi - if [ "$arch" = 'any' ]; then - CARCH='any' - fi - if ! in_array $CARCH ${arch[@]}; then - if [ "$IGNOREARCH" -eq 0 ]; then - error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" - plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" - plain "$(gettext "such as arch=('%s').")" "$CARCH" - return 1 + if [ "$arch" != 'any' ]; then + if ! in_array $CARCH ${arch[@]}; then + if [ "$IGNOREARCH" -eq 0 ]; then + error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" + plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" + plain "$(gettext "such as arch=('%s').")" "$CARCH" + return 1 + fi fi fi @@ -1175,11 +1187,32 @@ check_sanity() { fi done + local file + for file in "${backup[@]}"; do + if [ "${file:0:1}" = "/" ]; then + error "$(gettext "Invalid backup entry : %s")" "$file" + return 1 + fi + done + + local optdepend + for optdepend in "${optdepends[@]}"; do + pkg=${optdepend%%:*} + if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]*$ ]]; then + error "$(gettext "Invalid syntax for optdepend : '%s'")" "$optdepend" + fi + done + if [ "$install" -a ! -f "$install" ]; then error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" return 1 fi + if [ -n "$changelog" -a ! -f "$changelog" ]; then + error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" + return 1 + fi + local valid_options=1 local opt known kopt for opt in ${options[@]}; do @@ -1414,31 +1447,30 @@ usage() { printf "$(gettext " -A, --ignorearch Ignore incomplete arch field in %s")\n" "$BUILDSCRIPT" echo "$(gettext " -c, --clean Clean up work files after build")" echo "$(gettext " -C, --cleancache Clean up source files from the cache")" - printf "$(gettext " --config <config> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" echo "$(gettext " -d, --nodeps Skip all dependency checks")" echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")" echo "$(gettext " -f, --force Overwrite existing package")" echo "$(gettext " -g, --geninteg Generate integrity checks for source files")" - echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " -h, --help This help")" echo "$(gettext " -i, --install Install package after successful build")" echo "$(gettext " -L, --log Log package build process")" echo "$(gettext " -m, --nocolor Disable colorized output messages")" echo "$(gettext " -o, --nobuild Download and extract files only")" - printf "$(gettext " -p <buildscript> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" + printf "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" echo "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")" - # fix flyspray feature request #2978 echo "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")" echo "$(gettext " -s, --syncdeps Install missing dependencies with pacman")" - echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" - echo "$(gettext " --asroot Allow makepkg to run as root user")" - echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" - echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" + echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" + echo "$(gettext " --asroot Allow makepkg to run as root user")" + printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" + echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" + echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" + echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" echo echo "$(gettext "These options can be passed to pacman:")" echo - echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" - echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" + echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" + echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" echo printf "$(gettext "If -p is not specified, makepkg will look for '%s'")\n" "$BUILDSCRIPT" echo @@ -1567,7 +1599,7 @@ if [ "$CLEANCACHE" -eq 1 ]; then echo -n "$(gettext " Are you sure you wish to do this? ")" echo -n "$(gettext "[Y/n]")" read answer - answer=$(echo $answer | tr '[:lower:]' '[:upper:]') + answer="${answer^^}" if [ "$answer" = "$(gettext "YES")" -o "$answer" = "$(gettext "Y")" ]; then rm "$SRCDEST"/* if [ $? -ne 0 ]; then @@ -1634,7 +1666,7 @@ if [ "$ASROOT" -eq 0 \ fi unset pkgname pkgbase pkgver pkgrel pkgdesc url license groups provides -unset md5sums replaces depends conflicts backup source install build +unset md5sums replaces depends conflicts backup source install changelog build unset makedepends optdepends options noextract BUILDFILE=${BUILDFILE:-$BUILDSCRIPT} @@ -1689,8 +1721,9 @@ fi pkgbase=${pkgbase:-${pkgname[0]}} if [ "$SPLITPKG" -eq 0 ]; then - if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ - -a "$FORCE" -eq 0 -a "$SOURCEONLY" -eq 0 -a "$NOBUILD" -eq 0 ]; then + if [ \( -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ + -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-any${PKGEXT}" \) \ + -a "$FORCE" -eq 0 -a "$SOURCEONLY" -eq 0 -a "$NOBUILD" -eq 0 ]; then if [ "$INSTALL" -eq 1 ]; then warning "$(gettext "A package has already been built, installing existing package...")" install_package @@ -1704,7 +1737,8 @@ else allpkgbuilt=1 somepkgbuilt=0 for pkg in ${pkgname[@]}; do - if [ -f "$PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" ]; then + if [ \( -f "$PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ + -f "$PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}" \) ]; then somepkgbuilt=1 else allpkgbuilt=0 @@ -1759,7 +1793,7 @@ if [ "$INFAKEROOT" -eq 1 ]; then exit 0 # $E_OK fi -msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel $CARCH ($(date))" +msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" # if we are creating a source-only package, go no further if [ "$SOURCEONLY" -ne 0 ]; then @@ -1883,7 +1917,7 @@ else fi fi -msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel $CARCH ($(date))" +msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" install_package diff --git a/scripts/rankmirrors.py.in b/scripts/rankmirrors.py.in deleted file mode 100644 index 4b253b67..00000000 --- a/scripts/rankmirrors.py.in +++ /dev/null @@ -1,189 +0,0 @@ -#! /usr/bin/python -# -# rankmirrors - read a list of mirrors from a file and rank them by speed -# @configure_input@ -# -# Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org> -# Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -import os, sys, datetime, time, socket, urllib2 -from optparse import OptionParser -from string import Template - -def createOptParser(): - usage = "usage: %prog [options] MIRRORFILE | URL" - version = "%prog (pacman) @PACKAGE_VERSION@\n" \ - "Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org>.\n" \ - "Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n" \ - "This is free software; see the source for copying conditions.\n" \ - "There is NO WARRANTY, to the extent permitted by law." - description = "Ranks pacman mirrors by their connection and opening " \ - "speed. Pacman mirror files are located in /etc/pacman.d/. It " \ - "can also rank one mirror if the URL is provided." - parser = OptionParser(usage = usage, version = version, - description = description) - parser.add_option("-n", type = "int", dest = "num", default = 0, - help = "number of servers to output, 0 for all") - parser.add_option("-t", "--times", action = "store_true", - dest = "times", default = False, - help = "only output mirrors and their response times") - parser.add_option("-u", "--url", action = "store_true", dest = "url", - default = False, help = "test a specific url") - parser.add_option("-v", "--verbose", action = "store_true", - dest = "verbose", default = False, - help = "be verbose in ouptut") - # The following two options should be automatic - #parser.add_option("-h", "--help", action = "help") - #parser.add_option("-V", "--version", action = "version") - return parser - -def timeCmd(cmd): - before = time.time() - try: - cmd() - except KeyboardInterrupt, ki: - raise ki - except socket.timeout, ioe: - return 'timeout' - except Exception, e: - return 'unreachable' - return time.time() - before - -def talkToServer(serverUrl): - opener = urllib2.build_opener() - # retrieve first 50,000 bytes only - tmp = opener.open(serverUrl).read(50000) - -def getFuncToTime(serverUrl): - return lambda : talkToServer(serverUrl) - -def cmpPairBySecond(p1, p2): - if p1[1] == p2[1]: - return 0 - if p1[1] < p2[1]: - return -1 - return 1 - -def printResults(servers, time, verbose, num): - items = servers.items() - items.sort(cmpPairBySecond) - itemsLen = len(items) - numToShow = num - if numToShow > itemsLen or numToShow == 0: - numToShow = itemsLen - if itemsLen > 0: - if time: - print - print ' Servers sorted by time (seconds):' - for i in items[0:numToShow]: - if i[1] == 'timeout' or i[1] == 'unreachable': - print i[0], ':', i[1] - else: - print i[0], ':', "%.2f" % i[1] - else: - for i in items[0:numToShow]: - print 'Server =', i[0] - -if __name__ == "__main__": - parser = createOptParser() - (options, args) = parser.parse_args() - - if len(args) != 1: - parser.print_help(sys.stderr) - sys.exit(0) - - # allows connections to time out if they take too long - socket.setdefaulttimeout(10) - - if options.url: - if options.verbose: - print 'Testing', args[0] + '...' - try: - serverToTime = timeCmd(getFuncToTime(args[0])) - except KeyboardInterrupt, ki: - sys.exit(1) - if serverToTime == 'timeout' or serverToTime == 'unreachable': - print args[0], ':', serverToTime - else: - print args[0], ':', "%.2f" % serverToTime - sys.exit(0) - - if not os.path.isfile(args[0]) and args[0] != "-": - print >>sys.stderr, 'rankmirrors: file', args[0], 'does not exist.' - sys.exit(1) - - if args[0] == "-": - fl = sys.stdin - else: - fl = open(args[0], 'r') - - serverToTime = {} - if options.times: - print 'Querying servers, this may take some time...' - else: - print "# Server list generated by rankmirrors on", - print datetime.date.today() - for ln in fl.readlines(): - splitted = ln.split('=') - if splitted[0].strip() != 'Server': - if not options.times: - print ln, - continue - - serverUrl = splitted[1].strip() - if serverUrl[-1] == '\n': - serverUrl = serverUrl[0:-1] - if options.verbose and options.times: - print serverUrl, '...', - elif options.verbose: - print '#', serverUrl, '...', - elif options.times: - print ' * ', - sys.stdout.flush() - - # if the $repo var is used in the url, replace it by core - tempUrl = Template(serverUrl).safe_substitute(repo='core') - - # add @DBEXT@ to server name. the repo name is parsed - # from the mirror url; it is the third (or fourth) dir - # from the end, where the url is http://foo/bar/REPO/os/arch - try: - splitted2 = tempUrl.split('/') - if tempUrl[-1] != '/': - repoName = splitted2[-3] - dbFileName = '/' + repoName + '@DBEXT@' - else: - repoName = splitted2[-4] - dbFileName = repoName + '@DBEXT@' - except: - dbFileName = '' - - try: - serverToTime[serverUrl] = timeCmd(getFuncToTime(tempUrl + dbFileName)) - if options.verbose: - try: - print "%.2f" % serverToTime[serverUrl] - except: - print serverToTime[serverUrl] - except: - print - printResults(serverToTime, options.times, options.verbose, - options.num) - sys.exit(0) - - printResults(serverToTime, options.times, options.verbose, options.num) - -# vim: set ts=4 sw=4 et: diff --git a/scripts/rankmirrors.sh.in b/scripts/rankmirrors.sh.in new file mode 100644 index 00000000..015b39a7 --- /dev/null +++ b/scripts/rankmirrors.sh.in @@ -0,0 +1,202 @@ +#!/bin/bash +# +# rankmirrors - read a list of mirrors from a file and rank them by speed +# @configure_input@ +# +# Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# traps interrupt key to spit out pre-interrupt info +trap finaloutput INT + +usage() { + echo "Usage: rankmirrors [options] MIRRORFILE | URL" + echo + echo "Ranks pacman mirrors by their connection and opening speed. Pacman mirror" + echo "files are located in /etc/pacman.d/. It can also rank one mirror if the URL is" + echo "provided." + echo + echo "Options:" + echo " --version show program's version number and exit" + echo " -h, --help show this help message and exit" + echo " -n NUM number of servers to output, 0 for all" + echo " -t, --times only output mirrors and their response times" + echo " -u, --url test a specific url" + echo " -v, --verbose be verbose in ouptut" + exit 0 +} + +version() { + echo "rankmirrors (pacman) @PACKAGE_VERSION@" + echo "Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com>." + echo + echo "This is free software; see the source for copying conditions." + echo "There is NO WARRANTY, to the extent permitted by law." + exit 0 +} + +err() { + echo "$1" + exit 1 +} + +# gettime fetchurl (e.g gettime http://foo.com/core/os/i686/core.db.tar.gz) +# returns the fetching time, or timeout, or unreachable +gettime() { + IFS=' ' output=( $(curl -s -m 10 -w "%{time_total} %{http_code}" "$1" -o/dev/null) ) + [[ $? = 28 ]] && echo timeout && return + [[ ${output[1]} -ge 400 || ${output[1]} -eq 0 ]] && echo unreachable && return + echo "${output[0]}" +} + +# getfetchurl serverurl (e.g. getturl http://foo.com/core/os/i686) +# if $repo is in the line, then assumes core +# if $arch is in the line, then assumes $(uname -m) +# returns a fetchurl (e.g. http://foo.com/core/os/i686/core.db.tar.gz) +ARCH="$(uname -m)" +getfetchurl() { + local strippedurl="${1%/}" + + local replacedurl="${strippedurl//'$repo'/core}" + replacedurl="${replacedurl//'$arch'/$ARCH}" + + local tmp="${replacedurl%/*}" + tmp="${tmp%/*}" + + local reponame="${tmp##*/}" + if [[ -z $reponame || $reponame = $replacedurl ]]; then + echo "fail" + else + local fetchurl="${replacedurl}/$reponame@DBEXT@" + echo "$fetchurl" + fi +} + +# This exists to remove the need for a separate interrupt function +finaloutput() { + IFS=$'\n' sortedarray=( $(LC_COLLATE=C printf "%s\n" "${timesarray[@]}" | sort) ) + + # Final output for mirrorfile + numiterator="0" + if [[ $TIMESONLY ]]; then + echo + echo " Servers sorted by time (seconds):" + for line in "${sortedarray[@]}"; do + echo "${line#* } : ${line% *}" + ((numiterator++)) + [[ $NUM -ne 0 && $numiterator -ge $NUM ]] && break + done + else + for line in "${sortedarray[@]}"; do + echo "Server = ${line#* }" + ((numiterator++)) + [[ $NUM -ne 0 && $numiterator -ge $NUM ]] && break + done + fi + exit 0 +} + + +# Argument parsing +[[ $1 ]] || usage +while [[ $1 ]]; do + if [[ "${1:0:2}" = -- ]]; then + case "${1:2}" in + help) usage ;; + version) version ;; + times) TIMESONLY=1 ; shift ;; + verbose) VERBOSE=1 ; shift ;; + url) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; shift 2;; + *) err "\`$1' is an invalid argument." + esac + elif [[ ${1:0:1} = - ]]; then + + if [[ ! ${1:1:1} ]]; then + [[ -t 0 ]] && err "Stdin is empty." + IFS=$'\n' linearray=( $(</dev/stdin) ) + STDIN=1 + shift + else + snum=1 + for ((i=1 ; i<${#1}; i++)); do + case ${1:$i:1} in + h) usage ;; + t) TIMESONLY=1 ;; + v) VERBOSE=1 ;; + u) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; snum=2;; + n) [[ $2 ]] || err "Must specify number." ; NUM="$2" ; snum=2;; + *) err "\`-$1' is an invald argument." ;; + esac + done + shift $snum + fi + elif [[ -f "$1" ]]; then + FILE="1" + IFS=$'\n' linearray=( $(<$1) ) + [[ $linearray ]] || err "File is empty." + shift + else + err "\`$1' does not exist." + fi +done + +# Some sanity checks +[[ $NUM ]] || NUM=0 +[[ $FILE && $CHECKURL ]] && err "Cannot specify a url and mirrorfile." +[[ $FILE || $CHECKURL || $STDIN ]] || err "Must specify url, mirrorfile, or stdin." + +# Single url handling +if [[ $CHECKURL ]]; then + url="$(getfetchurl "$URL")" + [[ $url = fail ]] && err "url \`$URL' is malformed." + [[ $VERBOSE ]] && echo "Testing $url..." + time=$(gettime "$url") + echo "$URL : $time" + exit 0 +fi + +# Get url results from mirrorfile, fill up the array, and so on +if [[ $TIMESONLY ]]; then + echo "Querying servers, this may take some time..." +elif [[ $FILE ]]; then + echo "# Server list generated by rankmirrors on $(date +%Y-%m-%d)" +fi + +timesarray=() +for line in "${linearray[@]}"; do + if [[ $line =~ ^# ]]; then + [[ $TIMESONLY ]] || echo $line + elif [[ $line =~ ^Server ]]; then + + # Getting values and times and such + server="${line#*= }" + url="$(getfetchurl "$server")" + [[ $url = fail ]] && err "url \`$URL' is malformed." + time=$(gettime "$url") + timesarray+=("$time $server") + + # Output + if [[ $VERBOSE && $TIMESONLY ]]; then + echo "$server ... $time" + elif [[ $VERBOSE ]]; then + echo "# $server ... $time" + elif [[ $TIMESONLY ]]; then + echo -n " *" + fi + fi +done +finaloutput + +# vim: set ts=2 sw=2 noet: diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index c8380c4e..3f00441a 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -136,7 +136,8 @@ db_write_delta() echo -e "%DELTAS%" >>$deltas fi # get md5sum and compressed size of package - md5sum="$(openssl dgst -md5 "$deltafile" | awk '{print $NF}')" + md5sum="$(openssl dgst -md5 "$deltafile")" + md5sum="${md5sum##* }" csize=$(@SIZECMD@ "$deltafile") oldfile=$(xdelta3 printhdr $deltafile | grep "XDELTA filename (source)" | sed 's/.*: *//') @@ -213,7 +214,8 @@ db_write_entry() IFS=$OLDIFS # get md5sum and compressed size of package - md5sum="$(openssl dgst -md5 "$pkgfile" | awk '{print $NF}')" + md5sum="$(openssl dgst -md5 "$pkgfile")" + md5sum="${md5sum##* }" csize=$(@SIZECMD@ "$pkgfile") # ensure $pkgname and $pkgver variables were found @@ -357,7 +359,7 @@ add() fi pkgfile=$1 - if ! bsdtar -tqf "$pkgfile" .PKGINFO 2>&1 >/dev/null; then + if ! bsdtar -tqf "$pkgfile" .PKGINFO >/dev/null 2>&1; then error "$(gettext "'%s' is not a package file, skipping")" "$pkgfile" return 1 fi @@ -423,12 +425,6 @@ case "$1" in -V|--version) version; exit 0;; esac -# check for correct number of args -if [ $# -lt 2 ]; then - usage - exit 1 -fi - # figure out what program we are cmd="$(basename $0)" if [ "$cmd" != "repo-add" -a "$cmd" != "repo-remove" ]; then @@ -450,12 +446,6 @@ success=0 for arg in "$@"; do case "$arg" in -q|--quiet) QUIET=1;; - - -f|--force) - warning "$(gettext "the -f and --force options are no longer recognized")" - msg2 "$(gettext "use options=(force) in the PKGBUILD instead")" - ;; - *) if [ -z "$REPO_DB_FILE" ]; then REPO_DB_FILE="$arg" @@ -499,6 +489,7 @@ if [ $success -eq 1 ]; then [ -f "$tmpdir/$filename" ] && mv "$tmpdir/$filename" "$REPO_DB_FILE" else msg "$(gettext "No packages modified, nothing to do.")" + exit 1 fi exit 0 diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 1cdb1153..858bfdf4 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -259,10 +259,20 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, alpm_pkg_get_name(data2)); break; case PM_TRANS_CONV_CONFLICT_PKG: - *response = yesno(_(":: %s conflicts with %s. Remove %s?"), - (char *)data1, - (char *)data2, - (char *)data2); + /* data parameters: target package, local package, conflict (strings) */ + /* print conflict only if it contains new information */ + if(!strcmp(data1, data3) || !strcmp(data2, data3)) { + *response = noyes(_(":: %s and %s are in conflict. Remove %s?"), + (char *)data1, + (char *)data2, + (char *)data2); + } else { + *response = noyes(_(":: %s and %s are in conflict (%s). Remove %s?"), + (char *)data1, + (char *)data2, + (char *)data3, + (char *)data2); + } break; case PM_TRANS_CONV_REMOVE_PKGS: { @@ -275,7 +285,7 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, printf(_(":: the following package(s) cannot be upgraded due to " "unresolvable dependencies:\n")); list_display(" ", namelist); - *response = yesno(_("\nDo you want to skip the above " + *response = noyes(_("\nDo you want to skip the above " "package(s) for this upgrade?")); alpm_list_free(namelist); } @@ -294,6 +304,12 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, (char *)data1); break; } + if(config->noask) { + if(config->ask & event) { + /* inverse the default answer */ + *response = !*response; + } + } } /* callback to handle display of transaction progress */ diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 2d3de987..c97e5d78 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -63,6 +63,8 @@ typedef struct __config_t { unsigned short group; pmtransflag_t flags; + unsigned short noask; + unsigned int ask; /* conf file options */ unsigned short chomp; /* I Love Candy! */ @@ -86,6 +88,24 @@ enum { PM_OP_DEPTEST }; +/* Long Operations */ +enum { + OP_NOCONFIRM = 1000, + OP_CONFIG, + OP_IGNORE, + OP_DEBUG, + OP_NOPROGRESSBAR, + OP_NOSCRIPTLET, + OP_ASK, + OP_CACHEDIR, + OP_ASDEPS, + OP_LOGFILE, + OP_IGNOREGROUP, + OP_NEEDED, + OP_ASEXPLICIT, + OP_ARCH +}; + /* clean method */ enum { PM_CLEAN_KEEPINST = 0, /* default */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 4c556a7d..f4f80449 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -149,6 +149,7 @@ static void usage(int op, const char * const myname) printf(_(" -r, --root <path> set an alternate installation root\n")); printf(_(" -b, --dbpath <path> set an alternate database location\n")); printf(_(" --cachedir <dir> set an alternate package cache location\n")); + printf(_(" --arch <arch> set an alternate architecture\n")); } } @@ -195,6 +196,19 @@ static void setuseragent(void) setenv("HTTP_USER_AGENT", agent, 0); } +static void setarch(const char *arch) +{ + if (strcmp(arch, "auto") == 0) { + struct utsname un; + uname(&un); + pm_printf(PM_LOG_DEBUG, "config: architecture: %s\n", un.machine); + alpm_option_set_arch(un.machine); + } else { + pm_printf(PM_LOG_DEBUG, "config: architecture: %s\n", arch); + alpm_option_set_arch(arch); + } +} + /** Free the resources. * * @param ret the return value @@ -364,18 +378,20 @@ static int parseargs(int argc, char *argv[]) {"verbose", no_argument, 0, 'v'}, {"downloadonly", no_argument, 0, 'w'}, {"refresh", no_argument, 0, 'y'}, - {"noconfirm", no_argument, 0, 1000}, - {"config", required_argument, 0, 1001}, - {"ignore", required_argument, 0, 1002}, - {"debug", optional_argument, 0, 1003}, - {"noprogressbar", no_argument, 0, 1004}, - {"noscriptlet", no_argument, 0, 1005}, - {"cachedir", required_argument, 0, 1007}, - {"asdeps", no_argument, 0, 1008}, - {"logfile", required_argument, 0, 1009}, - {"ignoregroup", required_argument, 0, 1010}, - {"needed", no_argument, 0, 1011}, - {"asexplicit", no_argument, 0, 1012}, + {"noconfirm", no_argument, 0, OP_NOCONFIRM}, + {"config", required_argument, 0, OP_CONFIG}, + {"ignore", required_argument, 0, OP_IGNORE}, + {"debug", optional_argument, 0, OP_DEBUG}, + {"noprogressbar", no_argument, 0, OP_NOPROGRESSBAR}, + {"noscriptlet", no_argument, 0, OP_NOSCRIPTLET}, + {"ask", required_argument, 0, OP_ASK}, + {"cachedir", required_argument, 0, OP_CACHEDIR}, + {"asdeps", no_argument, 0, OP_ASDEPS}, + {"logfile", required_argument, 0, OP_LOGFILE}, + {"ignoregroup", required_argument, 0, OP_IGNOREGROUP}, + {"needed", no_argument, 0, OP_NEEDED}, + {"asexplicit", no_argument, 0, OP_ASEXPLICIT}, + {"arch", required_argument, 0, OP_ARCH}, {0, 0, 0, 0} }; @@ -387,21 +403,21 @@ static int parseargs(int argc, char *argv[]) } switch(opt) { case 0: break; - case 1000: config->noconfirm = 1; break; - case 1001: + case OP_NOCONFIRM: config->noconfirm = 1; break; + case OP_CONFIG: if(config->configfile) { free(config->configfile); } config->configfile = strndup(optarg, PATH_MAX); break; - case 1002: + case OP_IGNORE: list = strsplit(optarg, ','); for(item = list; item; item = alpm_list_next(item)) { alpm_option_add_ignorepkg((char *)alpm_list_getdata(item)); } FREELIST(list); break; - case 1003: + case OP_DEBUG: /* debug levels are made more 'human readable' than using a raw logmask * here, error and warning are set in config_new, though perhaps a * --quiet option will remove these later */ @@ -424,32 +440,36 @@ static int parseargs(int argc, char *argv[]) /* progress bars get wonky with debug on, shut them off */ config->noprogressbar = 1; break; - case 1004: config->noprogressbar = 1; break; - case 1005: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; break; - case 1007: + case OP_NOPROGRESSBAR: config->noprogressbar = 1; break; + case OP_NOSCRIPTLET: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; break; + case OP_ASK: config->noask = 1; config->ask = atoi(optarg); break; + case OP_CACHEDIR: if(alpm_option_add_cachedir(optarg) != 0) { pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), optarg, alpm_strerrorlast()); return(1); } break; - case 1008: + case OP_ASDEPS: config->flags |= PM_TRANS_FLAG_ALLDEPS; break; - case 1009: + case OP_LOGFILE: config->logfile = strndup(optarg, PATH_MAX); break; - case 1010: + case OP_IGNOREGROUP: list = strsplit(optarg, ','); for(item = list; item; item = alpm_list_next(item)) { alpm_option_add_ignoregrp((char *)alpm_list_getdata(item)); } FREELIST(list); break; - case 1011: config->flags |= PM_TRANS_FLAG_NEEDED; break; - case 1012: + case OP_NEEDED: config->flags |= PM_TRANS_FLAG_NEEDED; break; + case OP_ASEXPLICIT: config->flags |= PM_TRANS_FLAG_ALLEXPLICIT; break; + case OP_ARCH: + setarch(optarg); + break; case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break; case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break; case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break; @@ -592,7 +612,7 @@ static char *get_filename(const char *url) { static char *get_destfile(const char *path, const char *filename) { char *destfile; /* len = localpath len + filename len + null */ - int len = strlen(path) + strlen(filename) + 1; + size_t len = strlen(path) + strlen(filename) + 1; destfile = calloc(len, sizeof(char)); snprintf(destfile, len, "%s%s", path, filename); @@ -602,7 +622,7 @@ static char *get_destfile(const char *path, const char *filename) { static char *get_tempfile(const char *path, const char *filename) { char *tempfile; /* len = localpath len + filename len + '.part' len + null */ - int len = strlen(path) + strlen(filename) + 6; + size_t len = strlen(path) + strlen(filename) + 6; tempfile = calloc(len, sizeof(char)); snprintf(tempfile, len, "%s%s.part", path, filename); @@ -615,9 +635,7 @@ int download_with_xfercommand(const char *url, const char *localpath, int ret = 0; int retval; int usepart = 0; - char *ptr1, *ptr2; - char origCmd[PATH_MAX]; - char parsedCmd[PATH_MAX] = ""; + char *parsedcmd,*tempcmd; char cwd[PATH_MAX]; char *destfile, *tempfile, *filename; @@ -632,28 +650,18 @@ int download_with_xfercommand(const char *url, const char *localpath, destfile = get_destfile(localpath, filename); tempfile = get_tempfile(localpath, filename); - strncpy(origCmd, config->xfercommand, sizeof(origCmd)); + tempcmd = strdup(config->xfercommand); /* replace all occurrences of %o with fn.part */ - ptr1 = origCmd; - while((ptr2 = strstr(ptr1, "%o"))) { + if(strstr(tempcmd, "%o")) { usepart = 1; - ptr2[0] = '\0'; - strcat(parsedCmd, ptr1); - strcat(parsedCmd, tempfile); - ptr1 = ptr2 + 2; + parsedcmd = strreplace(tempcmd, "%o", tempfile); + free(tempcmd); + tempcmd = parsedcmd; } - strcat(parsedCmd, ptr1); /* replace all occurrences of %u with the download URL */ - strncpy(origCmd, parsedCmd, sizeof(origCmd)); - parsedCmd[0] = '\0'; - ptr1 = origCmd; - while((ptr2 = strstr(ptr1, "%u"))) { - ptr2[0] = '\0'; - strcat(parsedCmd, ptr1); - strcat(parsedCmd, url); - ptr1 = ptr2 + 2; - } - strcat(parsedCmd, ptr1); + parsedcmd = strreplace(tempcmd, "%u", url); + free(tempcmd); + /* cwd to the download directory */ getcwd(cwd, PATH_MAX); if(chdir(localpath)) { @@ -662,8 +670,8 @@ int download_with_xfercommand(const char *url, const char *localpath, goto cleanup; } /* execute the parsed command via /bin/sh -c */ - pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedCmd); - retval = system(parsedCmd); + pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedcmd); + retval = system(parsedcmd); if(retval == -1) { pm_printf(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); @@ -689,6 +697,7 @@ cleanup: } free(destfile); free(tempfile); + free(parsedcmd); return(ret); } @@ -749,11 +758,8 @@ static int _parseconfig(const char *file, const char *givensection, ret = 1; goto cleanup; } - /* if we are not looking at the options section, register a db and also - * ensure we have set all of our library paths as the library is too stupid - * at the moment to do lazy opening of the databases */ + /* if we are not looking at the options section, register a db */ if(strcmp(section, "options") != 0) { - setlibpaths(); db = alpm_db_register_sync(section); if(db == NULL) { pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"), @@ -787,10 +793,7 @@ static int _parseconfig(const char *file, const char *givensection, } if(ptr == NULL && strcmp(section, "options") == 0) { /* directives without settings, all in [options] */ - if(strcmp(key, "NoPassiveFtp") == 0) { - alpm_option_set_nopassiveftp(1); - pm_printf(PM_LOG_DEBUG, "config: nopassiveftp\n"); - } else if(strcmp(key, "UseSyslog") == 0) { + if(strcmp(key, "UseSyslog") == 0) { alpm_option_set_usesyslog(1); pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); } else if(strcmp(key, "ILoveCandy") == 0) { @@ -830,6 +833,10 @@ static int _parseconfig(const char *file, const char *givensection, setrepeatingoption(ptr, "HoldPkg", option_add_holdpkg); } else if(strcmp(key, "SyncFirst") == 0) { setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst); + } else if(strcmp(key, "Architecture") == 0) { + if(!alpm_option_get_arch()) { + setarch(ptr); + } } else if(strcmp(key, "DBPath") == 0) { /* don't overwrite a path specified on the command line */ if(!config->dbpath) { @@ -878,7 +885,23 @@ static int _parseconfig(const char *file, const char *givensection, } } else if(strcmp(key, "Server") == 0) { /* let's attempt a replacement for the current repo */ - char *server = strreplace(ptr, "$repo", section); + char *temp = strreplace(ptr, "$repo", section); + /* let's attempt a replacement for the arch */ + const char *arch = alpm_option_get_arch(); + char *server; + if(arch) { + server = strreplace(temp, "$arch", arch); + free(temp); + } else { + if(strstr(temp, "$arch")) { + free(temp); + pm_printf(PM_LOG_ERROR, _("The mirror '%s' contains the $arch" + " variable, but no Architecture is defined.\n"), ptr); + ret = 1; + goto cleanup; + } + server = temp; + } if(alpm_db_setserver(db, server) != 0) { /* pm_errno is set by alpm_db_setserver */ @@ -923,6 +946,29 @@ static int parseconfig(const char *file) return(_parseconfig(file, NULL, NULL)); } +/** print commandline to logfile + */ +static void cl_to_log(int argc, char* argv[]) +{ + size_t size = 0; + int i; + for(i = 0; i<argc; i++) { + size += strlen(argv[i]) + 1; + } + char *cl_text = malloc(size); + if(!cl_text) + return; + char *p = cl_text; + for(i = 0; i<argc-1; i++) { + strcpy(p, argv[i]); + p += strlen(argv[i]); + *p++ = ' '; + } + strcpy(p, argv[i]); + alpm_logaction("Running '%s'\n", cl_text); + free(cl_text); +} + /** Main function. * @param argc argc * @param argv argv @@ -1018,6 +1064,11 @@ int main(int argc, char *argv[]) alpm_option_set_totaldlcb(cb_dl_total); } + /* noask is meant to be non-interactive */ + if(config->noask) { + config->noconfirm = 1; + } + #if defined(HAVE_GETEUID) && !defined(CYGWIN) /* check if we have sufficient permission for the requested operation */ if(myuid > 0 && needs_root()) { @@ -1049,6 +1100,11 @@ int main(int argc, char *argv[]) cleanup(EXIT_FAILURE); } + /* Log commandline */ + if(needs_root()) { + cl_to_log(argc, argv); + } + /* start the requested operation */ switch(config->op) { case PM_OP_REMOVE: diff --git a/src/pacman/remove.c b/src/pacman/remove.c index 0efbd94e..6d44350b 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -51,50 +51,23 @@ int pacman_remove(alpm_list_t *targets) } /* Step 0: create a new transaction */ - if(trans_init(PM_TRANS_TYPE_REMOVE, config->flags) == -1) { + if(trans_init(config->flags) == -1) { return(1); } /* Step 1: add targets to the created transaction */ for(i = targets; i; i = alpm_list_next(i)) { - char *targ = alpm_list_getdata(i); - if(alpm_trans_addtarget(targ) == -1) { - if(pm_errno == PM_ERR_PKG_NOT_FOUND) { - printf(_("%s not found, searching for group...\n"), targ); - pmgrp_t *grp = alpm_db_readgrp(db_local, targ); - if(grp == NULL) { - pm_fprintf(stderr, PM_LOG_ERROR, _("'%s': not found in local db\n"), targ); - retval = 1; - goto cleanup; - } else { - alpm_list_t *p, *pkgnames = NULL; - /* convert packages to package names */ - for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) { - pmpkg_t *pkg = alpm_list_getdata(p); - pkgnames = alpm_list_add(pkgnames, (void *)alpm_pkg_get_name(pkg)); - } - printf(_(":: group %s:\n"), targ); - list_display(" ", pkgnames); - int all = yesno(_(" Remove whole content?")); - for(p = pkgnames; p; p = alpm_list_next(p)) { - char *pkgn = alpm_list_getdata(p); - if(all || yesno(_(":: Remove %s from group %s?"), pkgn, targ)) { - if(alpm_trans_addtarget(pkgn) == -1) { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, - alpm_strerrorlast()); - retval = 1; - alpm_list_free(pkgnames); - goto cleanup; - } - } - } - alpm_list_free(pkgnames); - } - } else { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); - retval = 1; - goto cleanup; - } + char *target = alpm_list_getdata(i); + char *targ = strchr(target, '/'); + if(targ && strncmp(target, "local", 5) == 0) { + targ++; + } else { + targ = target; + } + if(alpm_remove_target(targ) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); + retval = 1; + goto cleanup; } } @@ -103,6 +76,12 @@ int pacman_remove(alpm_list_t *targets) pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { + case PM_ERR_PKG_INVALID_ARCH: + for(i = data; i; i = alpm_list_next(i)) { + char *pkg = alpm_list_getdata(i); + printf(_(":: package %s does not have a valid architecture\n"), pkg); + } + break; case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); @@ -123,7 +102,7 @@ int pacman_remove(alpm_list_t *targets) /* Search for holdpkg in target list */ int holdpkg = 0; - for(i = alpm_trans_get_pkgs(); i; i = alpm_list_next(i)) { + for(i = alpm_trans_get_remove(); i; i = alpm_list_next(i)) { pmpkg_t *pkg = alpm_list_getdata(i); if(alpm_list_find_str(config->holdpkg, alpm_pkg_get_name(pkg))) { pm_printf(PM_LOG_WARNING, _("%s is designated as a HoldPkg.\n"), @@ -136,23 +115,19 @@ int pacman_remove(alpm_list_t *targets) goto cleanup; } - /* Warn user in case of dangerous operation */ - if(config->flags & PM_TRANS_FLAG_RECURSE || - config->flags & PM_TRANS_FLAG_CASCADE) { - /* list transaction targets */ - alpm_list_t *pkglist = alpm_trans_get_pkgs(); - - display_targets(pkglist, 0); - printf("\n"); - - /* get confirmation */ - if(yesno(_("Do you want to remove these packages?")) == 0) { - retval = 1; - goto cleanup; - } + /* Step 3: actually perform the removal */ + alpm_list_t *pkglist = alpm_trans_get_remove(); + if(pkglist == NULL) { + goto cleanup; /* we are done */ + } + /* print targets and ask user confirmation */ + display_targets(pkglist, 0); + printf("\n"); + if(yesno(_("Do you want to remove these packages?")) == 0) { + retval = 1; + goto cleanup; } - /* Step 3: actually perform the removal */ if(alpm_trans_commit(NULL) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerrorlast()); diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 12f67df2..a2ef616d 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -93,18 +93,21 @@ static int sync_cleandb(const char *dbpath, int keep_used) { if(rmrf(path)) { pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove repository directory\n")); + closedir(dir); return(1); } } - } + closedir(dir); return(0); } static int sync_cleandb_all(void) { - const char *dbpath = alpm_option_get_dbpath(); + const char *dbpath; char newdbpath[PATH_MAX]; + int ret = 0; + dbpath = alpm_option_get_dbpath(); printf(_("Database directory: %s\n"), dbpath); if(!yesno(_("Do you want to remove unused repositories?"))) { return(0); @@ -112,28 +115,26 @@ static int sync_cleandb_all(void) { /* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/, * so we will clean everything in dbpath/ (except dbpath/local/ and dbpath/sync/, * and only the unused sync dbs in dbpath/sync/ */ - sync_cleandb(dbpath, 0); + ret += sync_cleandb(dbpath, 0); sprintf(newdbpath, "%s%s", dbpath, "sync/"); - sync_cleandb(newdbpath, 1); + ret += sync_cleandb(newdbpath, 1); printf(_("Database directory cleaned up\n")); - return(0); + return(ret); } static int sync_cleancache(int level) { - /* TODO for now, just mess with the first cache directory */ - alpm_list_t* cachedirs = alpm_option_get_cachedirs(); - const char *cachedir = alpm_list_getdata(cachedirs); + alpm_list_t *i; + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + int ret = 0; + + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + printf(_("Cache directory: %s\n"), (char*)alpm_list_getdata(i)); + } if(level == 1) { - /* incomplete cleanup */ - DIR *dir; - struct dirent *ent; - /* Open up each package and see if it should be deleted, - * depending on the clean method used */ - printf(_("Cache directory: %s\n"), cachedir); switch(config->cleanmethod) { case PM_CLEAN_KEEPINST: if(!yesno(_("Do you want to remove uninstalled packages from cache?"))) { @@ -150,11 +151,23 @@ static int sync_cleancache(int level) return(1); } printf(_("removing old packages from cache...\n")); + } else { + if(!noyes(_("Do you want to remove ALL files from cache?"))) { + return(0); + } + printf(_("removing all files from cache...\n")); + } + + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + const char *cachedir = alpm_list_getdata(i); + DIR *dir = opendir(cachedir); + struct dirent *ent; - dir = opendir(cachedir); if(dir == NULL) { - pm_fprintf(stderr, PM_LOG_ERROR, _("could not access cache directory\n")); - return(1); + pm_fprintf(stderr, PM_LOG_ERROR, + _("could not access cache directory %s\n"), cachedir); + ret++; + continue; } rewinddir(dir); @@ -163,7 +176,6 @@ static int sync_cleancache(int level) char path[PATH_MAX]; int delete = 1; pmpkg_t *localpkg = NULL, *pkg = NULL; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); alpm_list_t *j; if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { @@ -172,11 +184,20 @@ static int sync_cleancache(int level) /* build the full filepath */ snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name); + /* short circuit for removing all packages from cache */ + if(level > 1) { + unlink(path); + continue; + } + /* attempt to load the package, prompt removal on failures as we may have * files here that aren't valid packages. we also don't need a full * load of the package, just the metadata. */ if(alpm_pkg_load(path, 0, &localpkg) != 0 || localpkg == NULL) { if(yesno(_("File %s does not seem to be a valid package, remove it?"), path)) { + if(localpkg) { + alpm_pkg_free(localpkg); + } unlink(path); } continue; @@ -215,26 +236,10 @@ static int sync_cleancache(int level) unlink(path); } } - } else { - /* full cleanup */ - printf(_("Cache directory: %s\n"), cachedir); - if(!noyes(_("Do you want to remove ALL files from cache?"))) { - return(0); - } - printf(_("removing all files from cache...\n")); - - if(rmrf(cachedir)) { - pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove cache directory\n")); - return(1); - } - - if(makepath(cachedir)) { - pm_fprintf(stderr, PM_LOG_ERROR, _("could not create new cache directory\n")); - return(1); - } + closedir(dir); } - return(0); + return(ret); } static int sync_synctree(int level, alpm_list_t *syncs) @@ -242,7 +247,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) alpm_list_t *i; int success = 0, ret; - if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) { + if(trans_init(0) == -1) { return(0); } @@ -548,89 +553,68 @@ static alpm_list_t *syncfirst() { return(res); } +static int process_target(char *target) +{ + /* process targets */ + char *targstring = strdup(target); + char *targname = strchr(targstring, '/'); + char *dbname = NULL; + int ret = 0; + if(targname) { + *targname = '\0'; + targname++; + dbname = targstring; + ret = alpm_sync_dbtarget(dbname,targname); + } else { + targname = targstring; + ret = alpm_sync_target(targname); + } + + if(ret == -1) { + if(pm_errno == PM_ERR_TRANS_DUP_TARGET + || pm_errno == PM_ERR_PKG_IGNORED) { + /* just skip duplicate or ignored targets */ + pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), target); + } else { + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, + alpm_strerrorlast()); + ret = 1; + } + } + + free(targstring); + return(ret); +} + static int sync_trans(alpm_list_t *targets) { int retval = 0; alpm_list_t *data = NULL; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); alpm_list_t *packages = NULL; + alpm_list_t *i; /* Step 1: create a new transaction... */ - if(trans_init(PM_TRANS_TYPE_SYNC, config->flags) == -1) { + if(trans_init(config->flags) == -1) { return(1); } + /* process targets */ + for(i = targets; i; i = alpm_list_next(i)) { + char *targ = alpm_list_getdata(i); + if(process_target(targ) == 1) { + retval = 1; + goto cleanup; + } + } + if(config->op_s_upgrade) { printf(_(":: Starting full system upgrade...\n")); alpm_logaction("starting full system upgrade\n"); - if(alpm_trans_sysupgrade(config->op_s_upgrade >= 2) == -1) { + if(alpm_sync_sysupgrade(config->op_s_upgrade >= 2) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerrorlast()); retval = 1; goto cleanup; } - } else { - alpm_list_t *i; - - /* process targets */ - for(i = targets; i; i = alpm_list_next(i)) { - char *targ = alpm_list_getdata(i); - if(alpm_trans_addtarget(targ) == -1) { - pmgrp_t *grp = NULL; - int found = 0; - alpm_list_t *j; - - if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) { - /* just skip duplicate or ignored targets */ - pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), targ); - continue; - } - if(pm_errno != PM_ERR_PKG_NOT_FOUND) { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", - targ, alpm_strerrorlast()); - retval = 1; - goto cleanup; - } - /* target not found: check if it's a group */ - printf(_("%s package not found, searching for group...\n"), targ); - for(j = sync_dbs; j; j = alpm_list_next(j)) { - pmdb_t *db = alpm_list_getdata(j); - grp = alpm_db_readgrp(db, targ); - if(grp) { - alpm_list_t *k, *pkgnames = NULL; - - found++; - printf(_(":: group %s (including ignored packages):\n"), targ); - /* remove dupe entries in case a package exists in multiple repos */ - alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp); - alpm_list_t *pkgs = alpm_list_remove_dupes(grppkgs); - for(k = pkgs; k; k = alpm_list_next(k)) { - pkgnames = alpm_list_add(pkgnames, - (char*)alpm_pkg_get_name(k->data)); - } - list_display(" ", pkgnames); - if(yesno(_(":: Install whole content?"))) { - for(k = pkgnames; k; k = alpm_list_next(k)) { - targets = alpm_list_add(targets, strdup(alpm_list_getdata(k))); - } - } else { - for(k = pkgnames; k; k = alpm_list_next(k)) { - char *pkgname = alpm_list_getdata(k); - if(yesno(_(":: Install %s from group %s?"), pkgname, targ)) { - targets = alpm_list_add(targets, strdup(pkgname)); - } - } - } - alpm_list_free(pkgnames); - alpm_list_free(pkgs); - } - } - if(!found) { - pm_fprintf(stderr, PM_LOG_ERROR, _("'%s': not found in sync db\n"), targ); - retval = 1; - goto cleanup; - } - } - } } /* Step 2: "compute" the transaction based on targets and flags */ @@ -639,6 +623,12 @@ static int sync_trans(alpm_list_t *targets) alpm_strerrorlast()); switch(pm_errno) { alpm_list_t *i; + case PM_ERR_PKG_INVALID_ARCH: + for(i = data; i; i = alpm_list_next(i)) { + char *pkg = alpm_list_getdata(i); + printf(_(":: package %s does not have a valid architecture\n"), pkg); + } + break; case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); @@ -650,10 +640,17 @@ static int sync_trans(alpm_list_t *targets) } break; case PM_ERR_CONFLICTING_DEPS: - for(i = data; i; i = alpm_list_next(i)) { + for(i = data; i; i = alpm_list_next(i)) { pmconflict_t *conflict = alpm_list_getdata(i); - printf(_(":: %s: conflicts with %s\n"), - alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict)); + const char *package1 = alpm_conflict_get_package1(conflict); + const char *package2 = alpm_conflict_get_package2(conflict); + const char *reason = alpm_conflict_get_reason(conflict); + /* only print reason if it contains new information */ + if(!strcmp(package1, reason) || !strcmp(package2, reason)) { + printf(_(":: %s and %s are in conflict\n"), package1, package2); + } else { + printf(_(":: %s and %s are in conflict (%s)\n"), package1, package2, reason); + } } break; default: @@ -663,7 +660,7 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - packages = alpm_trans_get_pkgs(); + packages = alpm_trans_get_add(); if(packages == NULL) { /* nothing to do: just exit without complaining */ printf(_(" local database is up to date\n")); @@ -691,7 +688,8 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - display_synctargets(packages); + display_targets(alpm_trans_get_remove(), 0); + display_targets(alpm_trans_get_add(), 1); printf("\n"); int confirm; @@ -768,7 +766,7 @@ int pacman_sync(alpm_list_t *targets) if(config->op_s_clean) { int ret = 0; - if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) { + if(trans_init(0) == -1) { return(1); } diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c index 1570f95e..57c7b790 100644 --- a/src/pacman/upgrade.c +++ b/src/pacman/upgrade.c @@ -42,7 +42,6 @@ int pacman_upgrade(alpm_list_t *targets) { alpm_list_t *i, *data = NULL; - pmtranstype_t transtype = PM_TRANS_TYPE_UPGRADE; int retval = 0; if(targets == NULL) { @@ -65,7 +64,7 @@ int pacman_upgrade(alpm_list_t *targets) } /* Step 1: create a new transaction */ - if(trans_init(transtype, config->flags) == -1) { + if(trans_init(config->flags) == -1) { return(1); } @@ -73,7 +72,7 @@ int pacman_upgrade(alpm_list_t *targets) printf(_("loading package data...\n")); for(i = targets; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); - if(alpm_trans_addtarget(targ) == -1) { + if(alpm_add_target(targ) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); trans_release(); @@ -87,6 +86,12 @@ int pacman_upgrade(alpm_list_t *targets) pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { + case PM_ERR_PKG_INVALID_ARCH: + for(i = data; i; i = alpm_list_next(i)) { + char *pkg = alpm_list_getdata(i); + printf(_(":: package %s does not have a valid architecture\n"), pkg); + } + break; case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); @@ -104,42 +109,75 @@ int pacman_upgrade(alpm_list_t *targets) case PM_ERR_CONFLICTING_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmconflict_t *conflict = alpm_list_getdata(i); - printf(_(":: %s: conflicts with %s\n"), - alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict)); + const char *package1 = alpm_conflict_get_package1(conflict); + const char *package2 = alpm_conflict_get_package2(conflict); + const char *reason = alpm_conflict_get_reason(conflict); + /* only print reason if it contains new information */ + if(!strcmp(package1, reason) || !strcmp(package2, reason)) { + printf(_(":: %s and %s are in conflict\n"), package1, package2); + } else { + printf(_(":: %s and %s are in conflict (%s)\n"), package1, package2, reason); + } } break; + default: + break; + } + trans_release(); + FREELIST(data); + return(1); + } + + /* Step 3: perform the installation */ + /* print targets and ask user confirmation */ + alpm_list_t *packages = alpm_trans_get_add(); + if(packages == NULL) { /* we are done */ + trans_release(); + return(retval); + } + display_targets(alpm_trans_get_remove(), 0); + display_targets(alpm_trans_get_add(), 1); + printf("\n"); + int confirm = yesno(_("Proceed with installation?")); + if(!confirm) { + trans_release(); + return(retval); + } + + if(alpm_trans_commit(&data) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), + alpm_strerrorlast()); + switch(pm_errno) { + alpm_list_t *i; case PM_ERR_FILE_CONFLICTS: for(i = data; i; i = alpm_list_next(i)) { pmfileconflict_t *conflict = alpm_list_getdata(i); switch(alpm_fileconflict_get_type(conflict)) { case PM_FILECONFLICT_TARGET: printf(_("%s exists in both '%s' and '%s'\n"), - alpm_fileconflict_get_file(conflict), - alpm_fileconflict_get_target(conflict), - alpm_fileconflict_get_ctarget(conflict)); - break; + alpm_fileconflict_get_file(conflict), + alpm_fileconflict_get_target(conflict), + alpm_fileconflict_get_ctarget(conflict)); + break; case PM_FILECONFLICT_FILESYSTEM: printf(_("%s: %s exists in filesystem\n"), - alpm_fileconflict_get_target(conflict), - alpm_fileconflict_get_file(conflict)); - break; + alpm_fileconflict_get_target(conflict), + alpm_fileconflict_get_file(conflict)); + break; } } - printf(_("\nerrors occurred, no packages were upgraded.\n")); + break; + case PM_ERR_PKG_INVALID: + case PM_ERR_DLT_INVALID: + for(i = data; i; i = alpm_list_next(i)) { + char *filename = alpm_list_getdata(i); + printf(_("%s is invalid or corrupted\n"), filename); + } break; default: break; } - trans_release(); FREELIST(data); - return(1); - } - alpm_list_free(data); - - /* Step 3: perform the installation */ - if(alpm_trans_commit(NULL) == -1) { - pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), - alpm_strerrorlast()); trans_release(); return(1); } diff --git a/src/pacman/util.c b/src/pacman/util.c index a02b43cd..1143befd 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -45,9 +45,9 @@ #include "callback.h" -int trans_init(pmtranstype_t type, pmtransflag_t flags) +int trans_init(pmtransflag_t flags) { - if(alpm_trans_init(type, flags, cb_trans_evt, + if(alpm_trans_init(flags, cb_trans_evt, cb_trans_conv, cb_trans_progress) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to init transaction (%s)\n"), alpm_strerrorlast()); @@ -85,70 +85,18 @@ int needs_root(void) /* gets the current screen column width */ int getcols(void) { - if(!isatty(1)) { - /* We will default to 80 columns if we're not a tty - * this seems a fairly standard file width. - */ - return 80; - } else { #ifdef TIOCGSIZE - struct ttysize win; - if(ioctl(1, TIOCGSIZE, &win) == 0) { - return win.ts_cols; - } -#elif defined(TIOCGWINSZ) - struct winsize win; - if(ioctl(1, TIOCGWINSZ, &win) == 0) { - return win.ws_col; - } -#endif - /* If we can't figure anything out, we'll just assume 80 columns */ - /* TODO any problems caused by this assumption? */ - return 80; - } - /* Original envvar way - prone to display issues - const char *cenv = getenv("COLUMNS"); - if(cenv != NULL) { - return atoi(cenv); + struct ttysize win; + if(ioctl(1, TIOCGSIZE, &win) == 0) { + return win.ts_cols; } - return -1; - */ -} - -/* does the same thing as 'mkdir -p' */ -int makepath(const char *path) -{ - /* A bit of pointer hell here. Descriptions: - * orig - a copy of path so we can safely butcher it with strsep - * str - the current position in the path string (after the delimiter) - * ptr - the original position of str after calling strsep - * incr - incrementally generated path for use in access/mkdir call - */ - char *orig, *str, *ptr, *incr; - mode_t oldmask = umask(0000); - int ret = 0; - - orig = strdup(path); - incr = calloc(strlen(orig) + 1, sizeof(char)); - str = orig; - while((ptr = strsep(&str, "/"))) { - if(strlen(ptr)) { - /* we have another path component- append the newest component to - * existing string and create one more level of dir structure */ - strcat(incr, "/"); - strcat(incr, ptr); - if(access(incr, F_OK)) { - if(mkdir(incr, 0755)) { - ret = 1; - break; - } - } - } +#elif defined(TIOCGWINSZ) + struct winsize win; + if(ioctl(1, TIOCGWINSZ, &win) == 0) { + return win.ws_col; } - free(orig); - free(incr); - umask(oldmask); - return(ret); +#endif + return 0; } /* does the same thing as 'rm -rf' */ @@ -256,6 +204,14 @@ void indentprint(const char *str, int indent) return; } + cols = getcols(); + + /* if we're not a tty, print without indenting */ + if(cols == 0) { + printf("%s", str); + return; + } + len = strlen(str) + 1; wcstr = calloc(len, sizeof(wchar_t)); len = mbstowcs(wcstr, str, len); @@ -265,7 +221,6 @@ void indentprint(const char *str, int indent) if(!p) { return; } - cols = getcols(); while(*p) { if(*p == L' ') { @@ -284,7 +239,7 @@ void indentprint(const char *str, int indent) } if(len > (cols - cidx - 1)) { /* wrap to a newline and reindent */ - fprintf(stdout, "\n%-*s", indent, ""); + printf("\n%-*s", indent, ""); cidx = indent; } else { printf(" "); @@ -292,7 +247,7 @@ void indentprint(const char *str, int indent) } continue; } - fprintf(stdout, "%lc", (wint_t)*p); + printf("%lc", (wint_t)*p); cidx += wcwidth(*p); p++; } @@ -306,7 +261,7 @@ char *strtoupper(char *str) char *ptr = str; while(*ptr) { - (*ptr) = toupper(*ptr); + (*ptr) = toupper((unsigned char)*ptr); ptr++; } return str; @@ -323,7 +278,7 @@ char *strtrim(char *str) return(str); } - while(isspace(*pch)) { + while(isspace((unsigned char)*pch)) { pch++; } if(pch != str) { @@ -336,7 +291,7 @@ char *strtrim(char *str) } pch = (str + (strlen(str) - 1)); - while(isspace(*pch)) { + while(isspace((unsigned char)*pch)) { pch--; } *++pch = '\0'; @@ -344,48 +299,65 @@ char *strtrim(char *str) return(str); } -/* Helper function for strreplace */ -static void _strnadd(char **str, const char *append, unsigned int count) -{ - if(*str) { - *str = realloc(*str, strlen(*str) + count + 1); - } else { - *str = calloc(sizeof(char), count + 1); - } - - strncat(*str, append, count); -} - /* Replace all occurances of 'needle' with 'replace' in 'str', returning * a new string (must be free'd) */ char *strreplace(const char *str, const char *needle, const char *replace) { - const char *p, *q; - p = q = str; + const char *p = NULL, *q = NULL; + char *newstr = NULL, *newp = NULL; + alpm_list_t *i = NULL, *list = NULL; + size_t needlesz = strlen(needle), replacesz = strlen(replace); + size_t newsz; - char *newstr = NULL; - unsigned int needlesz = strlen(needle), - replacesz = strlen(replace); + if(!str) { + return(NULL); + } - while (1) { + p = str; + q = strstr(p, needle); + while(q) { + list = alpm_list_add(list, (char *)q); + p = q + needlesz; q = strstr(p, needle); - if(!q) { /* not found */ - if(*p) { - /* add the rest of 'p' */ - _strnadd(&newstr, p, strlen(p)); - } - break; - } else { /* found match */ - if(q > p){ - /* add chars between this occurance and last occurance, if any */ - _strnadd(&newstr, p, q - p); - } - _strnadd(&newstr, replace, replacesz); - p = q + needlesz; + } + + /* no occurences of needle found */ + if(!list) { + return(strdup(str)); + } + /* size of new string = size of old string + "number of occurences of needle" + * x "size difference between replace and needle" */ + newsz = strlen(str) + 1 + + alpm_list_count(list) * (replacesz - needlesz); + newstr = malloc(newsz); + if(!newstr) { + return(NULL); + } + *newstr = '\0'; + + p = str; + newp = newstr; + for(i = list; i; i = alpm_list_next(i)) { + q = alpm_list_getdata(i); + if(q > p){ + /* add chars between this occurence and last occurence, if any */ + strncpy(newp, p, q - p); + newp += q - p; } + strncpy(newp, replace, replacesz); + newp += replacesz; + p = q + needlesz; } + alpm_list_free(list); - return newstr; + if(*p) { + /* add the rest of 'p' */ + strcpy(newp, p); + newp += strlen(p); + } + *newp = '\0'; + + return(newstr); } /** Splits a string into a list of strings using the chosen character as @@ -445,13 +417,13 @@ void string_display(const char *title, const char *string) int len = 0; if(title) { - /* compute the length of title + a space */ - len = string_length(title) + 1; printf("%s ", title); } if(string == NULL || string[0] == '\0') { printf(_("None")); } else { + /* compute the length of title + a space */ + len = string_length(title) + 1; indentprint(string, len); } printf("\n"); @@ -476,7 +448,7 @@ void list_display(const char *title, const alpm_list_t *list) /* two additional spaces are added to the length */ s += 2; int maxcols = getcols(); - if(s + cols > maxcols) { + if(s + cols > maxcols && maxcols > 0) { int j; cols = len; printf("\n"); @@ -576,37 +548,6 @@ void display_targets(const alpm_list_t *pkgs, int install) FREELIST(targets); } -/* Display a list of transaction targets. - * `pkgs` should be a list of pmpkg_t's, - * retrieved from a transaction object - */ -void display_synctargets(const alpm_list_t *syncpkgs) -{ - const alpm_list_t *i, *j; - alpm_list_t *pkglist = NULL, *rpkglist = NULL; - - for(i = syncpkgs; i; i = alpm_list_next(i)) { - pmpkg_t *pkg = alpm_list_getdata(i); - pkglist = alpm_list_add(pkglist, pkg); - - /* The removes member contains a list of packages to be removed - * due to the package that is being installed. */ - alpm_list_t *to_replace = alpm_pkg_get_removes(pkg); - - for(j = to_replace; j; j = alpm_list_next(j)) { - pmpkg_t *rp = alpm_list_getdata(j); - rpkglist = alpm_list_add(rpkglist, rp); - } - } - - /* start displaying information */ - display_targets(rpkglist, 0); - display_targets(pkglist, 1); - - alpm_list_free(pkglist); - alpm_list_free(rpkglist); -} - /* Helper function for comparing strings using the * alpm "compare func" signature */ int str_cmp(const void *s1, const void *s2) @@ -639,6 +580,7 @@ void display_optdepends(pmpkg_t *pkg) static int question(short preset, char *fmt, va_list args) { char response[32]; + int sresponse = sizeof(response)-1; FILE *stream; if(config->noconfirm) { @@ -661,7 +603,7 @@ static int question(short preset, char *fmt, va_list args) return(preset); } - if(fgets(response, 32, stdin)) { + if(fgets(response, sresponse, stdin)) { strtrim(response); if(strlen(response) == 0) { return(preset); diff --git a/src/pacman/util.h b/src/pacman/util.h index 12824221..7a8c39d1 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -37,11 +37,10 @@ /* update speed for the fill_progress based functions */ #define UPDATE_SPEED_SEC 0.2f -int trans_init(pmtranstype_t type, pmtransflag_t flags); +int trans_init(pmtransflag_t flags); int trans_release(void); int needs_root(void); int getcols(void); -int makepath(const char *path); int rmrf(const char *path); char *mbasename(const char *path); char *mdirname(const char *path); @@ -54,7 +53,6 @@ void string_display(const char *title, const char *string); void list_display(const char *title, const alpm_list_t *list); void list_display_linebreak(const char *title, const alpm_list_t *list); void display_targets(const alpm_list_t *pkgs, int install); -void display_synctargets(const alpm_list_t *syncpkgs); void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg); void display_optdepends(pmpkg_t *pkg); int yesno(char *fmt, ...); diff --git a/src/util/testdb.c b/src/util/testdb.c index e521e6b3..6d351ebd 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -92,6 +92,11 @@ static int db_test(char *dbpath, int local) } } } + if(closedir(dir)) { + fprintf(stderr, "error closing dbpath : %s\n", strerror(errno)); + return(1); + } + return(ret); } @@ -110,6 +115,7 @@ int checkdeps(alpm_list_t *pkglist) free(depstring); ret++; } + FREELIST(data); return(ret); } @@ -125,6 +131,7 @@ int checkconflicts(alpm_list_t *pkglist) alpm_conflict_get_package2(conflict)); ret++; } + FREELIST(data); return(ret); } @@ -163,21 +170,23 @@ int check_syncdbs(char *dbpath, alpm_list_t *dbnames) { snprintf(syncdbpath, PATH_MAX, "%s/sync/%s", dbpath, dbname); ret = db_test(syncdbpath, 0); if(ret) { - return(ret); + ret = 1; + goto cleanup; } db = alpm_db_register_sync(dbname); if(db == NULL) { fprintf(stderr, "error: could not register sync database (%s)\n", alpm_strerrorlast()); - cleanup(EXIT_FAILURE); + ret = 1; + goto cleanup; } pkglist = alpm_db_get_pkgcache(db); syncpkglist = alpm_list_join(syncpkglist, alpm_list_copy(pkglist)); } ret += checkdeps(syncpkglist); - alpm_list_free(syncpkglist); - alpm_db_unregister_all(); +cleanup: + alpm_list_free(syncpkglist); return(ret); } @@ -227,6 +236,7 @@ int main(int argc, char **argv) ret = check_localdb(dbpath); } else { ret = check_syncdbs(dbpath,dbnames); + alpm_list_free(dbnames); } cleanup(ret); |