summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README1
-rw-r--r--doc/Makefile.am4
-rw-r--r--doc/PKGBUILD.5.txt2
-rw-r--r--doc/pacman.8.txt2
-rw-r--r--doc/pacman.conf.5.txt17
-rw-r--r--etc/makepkg.conf.in2
-rw-r--r--etc/pacman.conf.in5
-rw-r--r--lib/libalpm/alpm.h6
-rw-r--r--lib/libalpm/dload.c53
-rw-r--r--lib/libalpm/error.c2
-rw-r--r--lib/libalpm/handle.c12
-rw-r--r--lib/libalpm/handle.h2
-rw-r--r--lib/libalpm/trans.c33
-rw-r--r--lib/libalpm/util.c45
-rw-r--r--lib/libalpm/util.h1
-rw-r--r--pactest/tests/upgrade080.py16
-rw-r--r--pactest/tests/upgrade081.py16
-rw-r--r--pactest/tests/upgrade082.py19
-rw-r--r--pactest/tests/upgrade083.py19
-rw-r--r--pactest/tests/upgrade084.py16
-rw-r--r--scripts/makepkg.sh.in149
-rw-r--r--scripts/rankmirrors.py.in2
-rw-r--r--src/pacman/pacman.c108
-rw-r--r--src/pacman/remove.c6
-rw-r--r--src/pacman/sync.c6
-rw-r--r--src/pacman/upgrade.c6
-rw-r--r--src/pacman/util.c130
27 files changed, 419 insertions, 261 deletions
diff --git a/README b/README
index 48dc274f..b9eb399a 100644
--- a/README
+++ b/README
@@ -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/doc/Makefile.am b/doc/Makefile.am
index 4703b63a..6261d926 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -84,12 +84,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..e6f6edf5 100644
--- a/doc/PKGBUILD.5.txt
+++ b/doc/PKGBUILD.5.txt
@@ -145,7 +145,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')
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index b288a592..a534e057 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -166,6 +166,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]]
-------------------
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index a1c1f2a6..640e62bb 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -97,6 +97,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,
@@ -108,9 +116,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
@@ -176,10 +181,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/alpm.h b/lib/libalpm/alpm.h
index ce8c6919..1a83f725 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -151,8 +151,9 @@ 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);
+const char *alpm_option_get_arch();
+void alpm_option_set_arch(const char *arch);
+
void alpm_option_set_usedelta(unsigned short usedelta);
pmdb_t *alpm_option_get_localdb();
@@ -509,6 +510,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/dload.c b/lib/libalpm/dload.c
index 4695731a..f8fb09fe 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -76,30 +76,6 @@ static char *get_tempfile(const char *path, const char *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 int download_internal(const char *url, const char *localpath,
time_t mtimeold, time_t *mtimenew) {
fetchIO *dlf = NULL;
@@ -110,17 +86,20 @@ static int download_internal(const char *url, const char *localpath,
size_t dl_thisfile = 0, 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);
@@ -161,7 +140,7 @@ static int download_internal(const char *url, const char *localpath,
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);
@@ -214,14 +193,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;
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index 81aaa8b1..6ff1d675 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -117,6 +117,8 @@ 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");
/* Deltas */
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index d1a35ad9..012d4121 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);
@@ -213,13 +214,13 @@ 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 -1;
+ return NULL;
}
- return handle->nopassiveftp;
+ return handle->arch;
}
pmdb_t SYMEXPORT *alpm_option_get_localdb()
@@ -529,9 +530,10 @@ 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)
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index c7c262cf..a1eb1cde 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -58,7 +58,7 @@ typedef struct _pmhandle_t {
/* options */
unsigned short usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
- unsigned short nopassiveftp; /* Don't use PASV ftp connections */
+ char *arch; /* Architecture of packages we should allow */
unsigned short usedelta; /* Download deltas if possible */
} pmhandle_t;
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index 6e847e64..240bf816 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -317,6 +317,31 @@ int _alpm_trans_addtarget(pmtrans_t *trans, char *target)
return(0);
}
+static alpm_list_t *check_arch(alpm_list_t *pkgs)
+{
+ alpm_list_t *i;
+ alpm_list_t *invalid = NULL;
+
+ 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);
+}
+
int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data)
{
if(data) {
@@ -333,6 +358,14 @@ int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data)
return(0);
}
+ alpm_list_t *invalid = check_arch(trans->packages);
+ if(invalid) {
+ if(data) {
+ *data = invalid;
+ }
+ RET_ERR(PM_ERR_PKG_INVALID_ARCH, -1);
+ }
+
switch(trans->type) {
case PM_TRANS_TYPE_UPGRADE:
if(_alpm_add_prepare(trans, handle->db_local, data) == -1) {
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 082c095b..f78d193a 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -196,51 +196,6 @@ 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()
{
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 4bc8b92f..ccf169d3 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -60,7 +60,6 @@ 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);
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/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 99e19b4f..3e918e69 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -175,6 +175,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
@@ -355,7 +356,7 @@ check_deps() {
fi
}
-handledeps() {
+handle_deps() {
local R_DEPS_SATISFIED=0
local R_DEPS_MISSING=1
@@ -403,7 +404,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 $*)"
@@ -693,72 +694,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 +722,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 +746,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() {
@@ -966,6 +949,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 +968,8 @@ create_package() {
exit 1 # $E_MISSING_PKGDIR
fi
+ check_package
+
cd "$pkgdir"
msg "$(gettext "Creating package...")"
@@ -1175,6 +1172,22 @@ 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
diff --git a/scripts/rankmirrors.py.in b/scripts/rankmirrors.py.in
index 4b253b67..6bfa6612 100644
--- a/scripts/rankmirrors.py.in
+++ b/scripts/rankmirrors.py.in
@@ -156,6 +156,8 @@ if __name__ == "__main__":
# if the $repo var is used in the url, replace it by core
tempUrl = Template(serverUrl).safe_substitute(repo='core')
+ # if the $arch var is used in the url, replace it by i686
+ tempUrl = Template(tempUrl).safe_substitute(arch='i686')
# add @DBEXT@ to server name. the repo name is parsed
# from the mirror url; it is the third (or fourth) dir
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 77c558d1..454505a0 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
@@ -376,6 +390,7 @@ static int parseargs(int argc, char *argv[])
{"ignoregroup", required_argument, 0, 1010},
{"needed", no_argument, 0, 1011},
{"asexplicit", no_argument, 0, 1012},
+ {"arch", required_argument, 0, 1013},
{0, 0, 0, 0}
};
@@ -450,6 +465,9 @@ static int parseargs(int argc, char *argv[])
case 1012:
config->flags |= PM_TRANS_FLAG_ALLEXPLICIT;
break;
+ case 1013:
+ 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;
@@ -615,9 +633,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 +648,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 +668,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 +695,7 @@ cleanup:
}
free(destfile);
free(tempfile);
+ free(parsedcmd);
return(ret);
}
@@ -787,10 +794,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 +834,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 +886,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 +947,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
@@ -1049,6 +1096,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..b5119fa5 100644
--- a/src/pacman/remove.c
+++ b/src/pacman/remove.c
@@ -103,6 +103,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);
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index dc936219..4f101f99 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -639,6 +639,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);
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
index 1570f95e..e7691185 100644
--- a/src/pacman/upgrade.c
+++ b/src/pacman/upgrade.c
@@ -87,6 +87,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);
diff --git a/src/pacman/util.c b/src/pacman/util.c
index a02b43cd..1e8515c6 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -85,34 +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;
+ struct ttysize win;
+ if(ioctl(1, TIOCGSIZE, &win) == 0) {
+ return win.ts_cols;
}
- /* Original envvar way - prone to display issues
- const char *cenv = getenv("COLUMNS");
- if(cenv != NULL) {
- return atoi(cenv);
+#elif defined(TIOCGWINSZ)
+ struct winsize win;
+ if(ioctl(1, TIOCGWINSZ, &win) == 0) {
+ return win.ws_col;
}
- return -1;
- */
+#endif
+ return 0;
}
/* does the same thing as 'mkdir -p' */
@@ -256,6 +240,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 +257,6 @@ void indentprint(const char *str, int indent)
if(!p) {
return;
}
- cols = getcols();
while(*p) {
if(*p == L' ') {
@@ -284,7 +275,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 +283,7 @@ void indentprint(const char *str, int indent)
}
continue;
}
- fprintf(stdout, "%lc", (wint_t)*p);
+ printf("%lc", (wint_t)*p);
cidx += wcwidth(*p);
p++;
}
@@ -344,48 +335,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);
+
+ if(*p) {
+ /* add the rest of 'p' */
+ strcpy(newp, p);
+ newp += strlen(p);
}
+ *newp = '\0';
- return newstr;
+ return(newstr);
}
/** Splits a string into a list of strings using the chosen character as
@@ -476,7 +484,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");