summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJudd Vinet <judd@archlinux.org>2004-02-18 08:09:00 +0100
committerJudd Vinet <judd@archlinux.org>2004-02-18 08:09:00 +0100
commita11fb0b581356b23b343683302e201ff7dfcfe48 (patch)
tree4079093d56377a07ef30f89422a62d88a92009e3
parent617b904b26037fac6296eb44fb36cfadfdaf27ec (diff)
downloadpacman-a11fb0b581356b23b343683302e201ff7dfcfe48.tar.gz
pacman-a11fb0b581356b23b343683302e201ff7dfcfe48.tar.xz
Imported from pacman-2.7.4.tar.gz
-rw-r--r--ChangeLog10
-rw-r--r--Makefile.in2
-rw-r--r--TODO6
-rw-r--r--doc/pacman.8.in5
-rw-r--r--etc/pacman.conf11
-rwxr-xr-xscripts/gensync2
-rwxr-xr-xscripts/makepkg2
-rwxr-xr-xscripts/makeworld2
-rw-r--r--src/db.c9
-rw-r--r--src/package.c40
-rw-r--r--src/package.h3
-rw-r--r--src/pacman.c140
-rw-r--r--src/pacman.c~3145
-rw-r--r--src/pacman.h2
14 files changed, 189 insertions, 3190 deletions
diff --git a/ChangeLog b/ChangeLog
index 5ae7e954..f1b87d4c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
VERSION DESCRIPTION
-----------------------------------------------------------------------------
+2.7.4 - fixed a bug in conflict handling, where installing a
+ conflicting package would fail even if the new package
+ "provided" it
+ - if pacman sees a newer version of itself during an upgrade,
+ it will ask to install itself first, then be re-run to upgrade
+ the other packages.
+ - You can now use the --info option with --sync to display an
+ uninstalled package's dependency info.
+ - Added a sane umask before db writes
+ - buffer overflow fix (bug #442)
2.7.3 - makepkg not longer strips files with .exe or .dll extensions
- Added Aurelien's patch:
- proxy support (no authentication yet)
diff --git a/Makefile.in b/Makefile.in
index 13a24109..d9fa642b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34,7 +34,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
-PACVER = 2.7.3
+PACVER = 2.7.4
TOPDIR = @srcdir@
SRCDIR = $(TOPDIR)/src/
diff --git a/TODO b/TODO
index 022d7f53..ec0fea3c 100644
--- a/TODO
+++ b/TODO
@@ -3,13 +3,7 @@
- replaces code doesn't run with -U or -A
- when performing replaces, pacman should not remove old packages until
the conflict checks are passed
-- --info should work with --sync to display dependencies
-- add an ETA to the download progress bar
-- add HTTP/1.1 support
-- fix the broken pipe bug
- handle version comparators in makepkg dep resolution (eg, glibc>=2.2.5)
- add post_remove, pre_install, pre_upgrade functions to scriptlets
-? record md5sums of all files in a package
-? use 'set -e' in makepkg?
- check $PACCONF env var
- add a --pretend option
diff --git a/doc/pacman.8.in b/doc/pacman.8.in
index 491604ce..622b6860 100644
--- a/doc/pacman.8.in
+++ b/doc/pacman.8.in
@@ -100,6 +100,11 @@ diskspace, you can remove these packages by using the --clean option.
Display all the members for each package group specified. If no group
names are provided, all groups will be listed.
.TP
+.B "\-i, \-\-info"
+Display dependency information for a given package. This will search
+through all repositories for a matching package and display the
+dependencies, conflicts, etc.
+.TP
.B "\-l, \-\-list"
List all files in the specified repositories. Multiple repositories can
be specified on the command line.
diff --git a/etc/pacman.conf b/etc/pacman.conf
index 73c9dcbf..7117c85d 100644
--- a/etc/pacman.conf
+++ b/etc/pacman.conf
@@ -5,6 +5,11 @@
# move it to the top of the server list, so pacman will choose it
# first.
#
+# To re-sort your mirror lists by ping/traceroute results, use the
+# /usr/bin/sortmirrors.pl script. It requires the "netselect" package.
+#
+# # sortmirrors.pl </etc/pacman.conf >pacman.conf.new
+#
# See the pacman manpage for option directives
@@ -25,10 +30,10 @@ NoUpgrade = etc/lilo.conf boot/grub/menu.lst
#
[current]
Server = ftp://ftp.archlinux.org/current
+Server = ftp://ftp.oit.unc.edu/pub/Linux/distributions/archlinux/current
Server = ftp://ftp.archlinux.de/pub/archlinux/current
Server = ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/current
Server = ftp://ftp.mpi-sb.mpg.de/pub/linux/mirror/ftp.ibiblio.org/pub/Linux/distributions/archlinux/current
-Server = ftp://ftp.oit.unc.edu/pub/Linux/distributions/archlinux/current
Server = ftp://ftp.tu-chemnitz.de/pub/linux/sunsite.unc-mirror/distributions/archlinux/current
Server = ftp://ftp.parrswood.net/Mirrors/ftp.archlinux.org/current
Server = ftp://ftp.kegep.tuc.gr/archlinux/current
@@ -41,12 +46,12 @@ Server = ftp://ftp.rez-gif.supelec.fr/pub/Linux/distrib/archlinux/current
# Uncomment this block to access the EXTRA package set
#
[extra]
-Server = ftp://ftp.archlinux.org/extra
+Server = ftp://ftp.oit.unc.edu/pub/Linux/distributions/archlinux/extra
Server = ftp://ftp.archlinux.de/pub/archlinux/extra
Server = ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/extra
Server = ftp://ftp.mpi-sb.mpg.de/pub/linux/mirror/ftp.ibiblio.org/pub/Linux/distributions/archlinux/extra
-Server = ftp://ftp.oit.unc.edu/pub/Linux/distributions/archlinux/extra
Server = ftp://ftp.tu-chemnitz.de/pub/linux/sunsite.unc-mirror/distributions/archlinux/extra
+Server = ftp://ftp.archlinux.org/extra
Server = ftp://ftp.parrswood.net/Mirrors/ftp.archlinux.org/extra
Server = ftp://ftp.kegep.tuc.gr/archlinux/extra
Server = http://darkstar.ist.utl.pt/archlinux/extra
diff --git a/scripts/gensync b/scripts/gensync
index 85774781..4af3a86b 100755
--- a/scripts/gensync
+++ b/scripts/gensync
@@ -20,7 +20,7 @@
# USA.
#
-myver='2.7.3'
+myver='2.7.4'
usage() {
echo "gensync $myver"
diff --git a/scripts/makepkg b/scripts/makepkg
index df6db755..f3922b2b 100755
--- a/scripts/makepkg
+++ b/scripts/makepkg
@@ -20,7 +20,7 @@
# USA.
#
-myver='2.7.3'
+myver='2.7.4'
startdir=`pwd`
USE_COLOR="n"
diff --git a/scripts/makeworld b/scripts/makeworld
index 20a5b8d9..bf273472 100755
--- a/scripts/makeworld
+++ b/scripts/makeworld
@@ -21,7 +21,7 @@
#
toplevel=`pwd`
-version="2.7.3"
+version="2.7.4"
usage() {
echo "makeworld version $version"
diff --git a/src/db.c b/src/db.c
index 862d8020..e70d0196 100644
--- a/src/db.c
+++ b/src/db.c
@@ -41,7 +41,7 @@ pacdb_t* db_open(char *root, char *pkgdir, char *treename)
if(db->dir == NULL) {
return(NULL);
}
- strncpy(db->treename, treename, 128);
+ strncpy(db->treename, treename, sizeof(db->treename));
return(db);
}
@@ -355,13 +355,15 @@ int db_write(pacdb_t *db, pkginfo_t *info)
info->name, info->version);
oldmask = umask(0000);
mkdir(topdir, 0755);
- umask(oldmask);
+ /* make sure we have a sane umask */
+ umask(0022);
/* DESC */
snprintf(path, PATH_MAX, "%s/desc", topdir);
fp = fopen(path, "w");
if(fp == NULL) {
perror("db_write");
+ umask(oldmask);
return(1);
}
fputs("%NAME%\n", fp);
@@ -392,6 +394,7 @@ int db_write(pacdb_t *db, pkginfo_t *info)
fp = fopen(path, "w");
if(fp == NULL) {
perror("db_write");
+ umask(oldmask);
return(1);
}
fputs("%FILES%\n", fp);
@@ -411,6 +414,7 @@ int db_write(pacdb_t *db, pkginfo_t *info)
fp = fopen(path, "w");
if(fp == NULL) {
perror("db_write");
+ umask(oldmask);
return(1);
}
fputs("%DEPENDS%\n", fp);
@@ -438,6 +442,7 @@ int db_write(pacdb_t *db, pkginfo_t *info)
/* INSTALL */
/* nothing needed here (script is automatically extracted) */
+ umask(oldmask);
return(0);
}
diff --git a/src/package.c b/src/package.c
index 0f6b0c91..6eeccd01 100644
--- a/src/package.c
+++ b/src/package.c
@@ -302,9 +302,9 @@ int is_pkgin(pkginfo_t *needle, PMList *haystack)
return(0);
}
-/* Display the content of a package
+/* Display the content of an installed package
*/
-void dump_pkg(pkginfo_t *info)
+void dump_pkg_full(pkginfo_t *info)
{
PMList *pm;
@@ -335,7 +335,41 @@ void dump_pkg(pkginfo_t *info)
pm = list_sort(info->conflicts);
list_display("Conflicts With :", pm);
FREELIST(pm);
- printf("Description : %s\n", info->desc);
+ printf("Description : ");
+ indentprint(info->desc, 17);
+ printf("\n");
+}
+
+/* Display the content of a sync package
+ */
+void dump_pkg_sync(pkginfo_t *info)
+{
+ PMList *pm;
+
+ if(info == NULL) {
+ return;
+ }
+
+ printf("Name : %s\n", info->name);
+ printf("Version : %s\n", info->version);
+ pm = list_sort(info->groups);
+ list_display("Groups :", pm);
+ FREELIST(pm);
+ pm = list_sort(info->provides);
+ list_display("Provides :", pm);
+ FREELIST(pm);
+ pm = list_sort(info->depends);
+ list_display("Depends On :", pm);
+ FREELIST(pm);
+ pm = list_sort(info->conflicts);
+ list_display("Conflicts With :", pm);
+ FREELIST(pm);
+ pm = list_sort(info->replaces);
+ list_display("Replaces :", pm);
+ FREELIST(pm);
+ printf("Description : ");
+ indentprint(info->desc, 17);
+ printf("\nMD5 Sum : %s\n", info->md5sum);
}
/* vim: set ts=2 sw=2 noet: */
diff --git a/src/package.h b/src/package.h
index b7d72f8f..4246486b 100644
--- a/src/package.h
+++ b/src/package.h
@@ -80,7 +80,8 @@ pkginfo_t* newpkg();
void freepkg(pkginfo_t *pkg);
int pkgcmp(const void *p1, const void *p2);
int is_pkgin(pkginfo_t *needle, PMList *haystack);
-void dump_pkg(pkginfo_t *info);
+void dump_pkg_full(pkginfo_t *info);
+void dump_pkg_sync(pkginfo_t *info);
#endif
/* vim: set ts=2 sw=2 noet: */
diff --git a/src/pacman.c b/src/pacman.c
index 803f39d6..18e36395 100644
--- a/src/pacman.c
+++ b/src/pacman.c
@@ -136,7 +136,8 @@ int main(int argc, char *argv[])
/* check for permission */
pm_access = READ_ONLY;
if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) {
- if(pmo_op == PM_SYNC && !pmo_s_sync && (pmo_s_search || pmo_group || pmo_q_list)) {
+ if(pmo_op == PM_SYNC && !pmo_s_sync &&
+ (pmo_s_search || pmo_group || pmo_q_list || pmo_q_info)) {
/* special case: PM_SYNC can be used w/ pmo_s_search by any user */
} else {
if(geteuid() != 0) {
@@ -178,7 +179,7 @@ int main(int argc, char *argv[])
/* check for db existence */
/* add a trailing '/' if there isn't one */
if(pmo_root[strlen(pmo_root)-1] != '/') {
- MALLOC(ptr, strlen(pmo_root)+1);
+ MALLOC(ptr, strlen(pmo_root)+2);
strcpy(ptr, pmo_root);
strcat(ptr, "/");
FREE(pmo_root);
@@ -459,6 +460,48 @@ int pacman_sync(pacdb_t *db, PMList *targets)
FREELIST(pkg);
}
FREELIST(groups);
+ } else if(pmo_q_info) {
+ PMList *pkgs = NULL;
+ int found;
+ if(targets) {
+ for(i = targets; i; i = i->next) {
+ pkgs = list_add(pkgs, strdup(i->data));
+ }
+ } else {
+ for(i = databases; i; i = i->next) {
+ dbsync_t *dbs = (dbsync_t *)i->data;
+ for(j = dbs->pkgcache; j; j = j->next) {
+ pkgs = list_add(pkgs, strdup(((pkginfo_t*)j->data)->name));
+ }
+ }
+ }
+ for(i = pkgs; i; i = i->next) {
+ found = 0;
+ for(j = databases; j; j = j->next) {
+ dbsync_t *dbs = (dbsync_t *)j->data;
+ for(k = dbs->pkgcache; k; k = k->next) {
+ pkginfo_t *p = (pkginfo_t*)k->data;
+ if(!strcmp(p->name, i->data)) {
+ /* re-fetch with dependency info */
+ p = db_scan(dbs->db, p->name, INFRQ_DESC | INFRQ_DEPENDS);
+ if(p == NULL) {
+ /* wtf */
+ continue;
+ }
+ dump_pkg_sync(p);
+ printf("\n");
+ freepkg(p);
+ found = 1;
+ }
+ }
+ }
+ if(!found) {
+ fprintf(stderr, "Package \"%s\" was not found.\n", (char *)i->data);
+ allgood = 0;
+ break;
+ }
+ }
+ FREELIST(pkgs);
} else if(pmo_q_list) {
PMList *reps = NULL;
int found;
@@ -493,6 +536,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
} else if(pmo_s_upgrade) {
int newer = 0;
int ignore = 0;
+ syncpkg_t *s = NULL;
+
logaction(NULL, "starting full system upgrade");
/* check for "recommended" package replacements */
for(i = databases; i && allgood; i = i->next) {
@@ -507,7 +552,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* if confirmed, add this to the 'final' list, designating 'p' as
* the package to replace.
*/
- if(yesno(":: replace %s with %s from \"%s\"? [Y/n] ", p->name, pkg->name, dbs->db->treename)) {
+ if(yesno(":: Replace %s with %s from \"%s\"? [Y/n] ", p->name, pkg->name, dbs->db->treename)) {
syncpkg_t *sync = NULL;
/* we save the dependency info so we can move p's requiredby stuff
* over to the replacing package
@@ -523,8 +568,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* none found -- enter pkg into the final sync list */
MALLOC(sync, sizeof(syncpkg_t));
sync->dbs = dbs;
- sync->replaces = NULL;
- sync->replaces = list_add(sync->replaces, q);
+ sync->replaces = list_add(NULL, q);
sync->pkg = db_scan(sync->dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
/* add to the targets list */
allgood = !resolvedeps(db, databases, sync, final, trail);
@@ -603,6 +647,27 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if((newer || ignore) && allgood) {
fprintf(stderr, ":: Above packages will be skipped. To manually upgrade use 'pacman -S <pkg>'\n");
}
+ /* check if pacman itself is one of the packages to upgrade. if so, we
+ * we should upgrade ourselves first and then re-exec as the new version.
+ *
+ * this can prevent some of the "syntax error" problems users can have
+ * when sysupgrade'ing with an older version of pacman.
+ */
+ s = find_pkginsync("pacman", final);
+ if(s && list_count(final) > 1) {
+ fprintf(stderr, "\n:: pacman has detected a newer version of the \"pacman\" package.\n");
+ fprintf(stderr, ":: It is recommended that you allow pacman to upgrade itself\n");
+ fprintf(stderr, ":: first, then you can re-run the operation with the newer version.\n");
+ fprintf(stderr, "::\n");
+ if(yesno(":: Upgrade pacman first? [Y/n] ")) {
+ /* XXX: leaving final un-freed is a big memory leak, but pacman quits
+ * right after this upgrade anyway, so...
+ */
+ /* and create a new final list with only "pacman" in it */
+ final = list_add(NULL, s);
+ trail = NULL;
+ }
+ }
} else {
/* process targets */
for(i = targets; i && allgood; i = i->next) {
@@ -664,7 +729,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
} else {
PMList *l;
for(l = k; l; l = l->next) {
- if(yesno(":: install %s from group %s? [Y/n] ", (char*)l->data, targ)) {
+ if(yesno(":: Install %s from group %s? [Y/n] ", (char*)l->data, targ)) {
targets = list_add(targets, strdup((char*)l->data));
}
}
@@ -762,30 +827,54 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* no unresolvable deps, so look for conflicts */
for(i = deps; i && !errorout; i = i->next) {
depmissing_t *miss = (depmissing_t*)i->data;
- if(miss->type == CONFLICT) {
- /* check if the conflicting package is one that's about to be removed/replaced.
- * if so, then just ignore it
- */
- found = 0;
- for(j = final; j && !found; j = j->next) {
- syncpkg_t *sync = (syncpkg_t*)j->data;
- for(k = sync->replaces; k && !found; k = k->next) {
- pkginfo_t *p = (pkginfo_t*)k->data;
- if(!strcmp(p->name, miss->depend.name)) {
- found = 1;
- }
+ if(miss->type != CONFLICT) {
+ continue;
+ }
+
+ /* check if the conflicting package is one that's about to be removed/replaced.
+ * if so, then just ignore it
+ */
+ found = 0;
+ for(j = final; j && !found; j = j->next) {
+ syncpkg_t *sync = (syncpkg_t*)j->data;
+ for(k = sync->replaces; k && !found; k = k->next) {
+ pkginfo_t *p = (pkginfo_t*)k->data;
+ if(!strcmp(p->name, miss->depend.name)) {
+ found = 1;
}
}
- /* if we didn't find it in any sync->replaces lists, then it's a conflict */
- if(!found && !is_in(miss->depend.name, rmtargs)) {
+ }
+ /* if we didn't find it in any sync->replaces lists, then it's a conflict */
+ if(!found && !is_in(miss->depend.name, rmtargs)) {
+ int solved = 0;
+ syncpkg_t *sync = find_pkginsync(miss->target, final);
+ for(j = sync->pkg->provides; j && j->data && !solved; j = j->next) {
+ if(!strcmp(j->data, miss->depend.name)) {
+ /* this package also "provides" the package it's conflicting with,
+ * so just treat it like a "replaces" item so the REQUIREDBY
+ * fields are inherited properly.
+ */
+
+ /* we save the dependency info so we can move p's requiredby stuff
+ * over to the replacing package
+ */
+ pkginfo_t *q = db_scan(db, miss->depend.name, INFRQ_DESC | INFRQ_DEPENDS);
+ /* append to the replaces list */
+ sync->replaces = list_add(sync->replaces, q);
+ solved = 1;
+ }
+ }
+ if(!solved) {
+ /* It's a conflict -- see if they want to remove it
+ */
pkginfo_t p1;
/* build a "fake" pkginfo_t so we can search with is_pkgin() */
snprintf(p1.name, sizeof(p1.name), miss->depend.name);
sprintf(p1.version, "1.0-1");
-
+
if(is_pkgin(&p1, pm_packages)) {
if(yesno(":: %s conflicts with %s. Remove %s? [Y/n] ",
- miss->target, miss->depend.name, miss->depend.name)) {
+ miss->target, miss->depend.name, miss->depend.name)) {
/* remove miss->depend.name */
rmtargs = list_add(rmtargs, strdup(miss->depend.name));
} else {
@@ -796,7 +885,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
} else {
if(!is_in(miss->depend.name, rmtargs) & !is_in(miss->target, rmtargs)) {
fprintf(stderr, "\nerror: %s conflicts with %s\n", miss->target,
- miss->depend.name);
+ miss->depend.name);
errorout = 1;
}
}
@@ -1705,7 +1794,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
}
} else {
for(j = pkgs; j; j = j->next) {
- if(yesno(":: remove %s from group %s? [Y/n] ", (char*)j->data, (char*)lp->data)) {
+ if(yesno(":: Remove %s from group %s? [Y/n] ", (char*)j->data, (char*)lp->data)) {
info = db_scan(db, (char *)j->data, INFRQ_ALL);
alltargs = list_add(alltargs, info);
}
@@ -2049,7 +2138,7 @@ int pacman_query(pacdb_t *db, PMList *targets)
fprintf(stderr, "Package \"%s\" was not found.\n", package);
return(2);
}
- dump_pkg(info);
+ dump_pkg_full(info);
if(pmo_q_info > 1 && info->backup) {
/* extra info */
printf("\n");
@@ -3049,6 +3138,7 @@ void usage(int op, char *myname)
printf(" -d, --nodeps skip dependency checks\n");
printf(" -f, --force force install, overwrite conflicting files\n");
printf(" -g, --groups view all members of a package group\n");
+ printf(" -i, --info view package information\n");
printf(" -l, --list list all packages belonging to the specified repository\n");
printf(" -s, --search search sync database for matching strings\n");
printf(" -u, --sysupgrade upgrade all packages that are out of date\n");
diff --git a/src/pacman.c~ b/src/pacman.c~
deleted file mode 100644
index e0018ba6..00000000
--- a/src/pacman.c~
+++ /dev/null
@@ -1,3145 +0,0 @@
-/*
- * pacman.c
- *
- * Copyright (c) 2002 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <time.h>
-#include <getopt.h>
-#include <zlib.h>
-#include <syslog.h>
-#include <libtar.h>
-/* pacman */
-#include "rpmvercmp.h"
-#include "md5.h"
-#include "list.h"
-#include "package.h"
-#include "util.h"
-#include "db.h"
-#include "pacsync.h"
-#include "pacman.h"
-
-/*
- * GLOBALS
- *
- */
-
-/* command line options */
-char *pmo_root = NULL;
-unsigned short pmo_op = PM_MAIN;
-unsigned short pmo_verbose = 0;
-unsigned short pmo_version = 0;
-unsigned short pmo_help = 0;
-unsigned short pmo_force = 0;
-unsigned short pmo_nodeps = 0;
-unsigned short pmo_upgrade = 0;
-unsigned short pmo_freshen = 0;
-unsigned short pmo_nosave = 0;
-unsigned short pmo_d_vertest = 0;
-unsigned short pmo_d_resolve = 0;
-unsigned short pmo_q_isfile = 0;
-unsigned short pmo_q_info = 0;
-unsigned short pmo_q_list = 0;
-unsigned short pmo_q_orphans = 0;
-unsigned short pmo_q_owns = 0;
-unsigned short pmo_r_cascade = 0;
-unsigned short pmo_s_upgrade = 0;
-unsigned short pmo_s_downloadonly = 0;
-unsigned short pmo_s_sync = 0;
-unsigned short pmo_s_search = 0;
-unsigned short pmo_s_clean = 0;
-unsigned short pmo_group = 0;
-/* configuration file options */
-char *pmo_dbpath = NULL;
-char *pmo_logfile = NULL;
-PMList *pmo_noupgrade = NULL;
-PMList *pmo_ignorepkg = NULL;
-unsigned short pmo_usesyslog = 0;
-unsigned short pmo_nopassiveftp = 0;
-
-
-/* list of sync_t structs for sync locations */
-PMList *pmc_syncs = NULL;
-/* list of installed packages */
-PMList *pm_packages = NULL;
-/* list of targets specified on command line */
-PMList *pm_targets = NULL;
-
-FILE *logfd = NULL;
-char *lckfile = "/tmp/pacman.lck";
-char *workfile = NULL;
-enum {READ_ONLY, READ_WRITE} pm_access;
-int maxcols = 80;
-
-int main(int argc, char *argv[])
-{
- int ret = 0;
- char *ptr = NULL;
- char path[PATH_MAX];
- pacdb_t *db_local = NULL;
- char *cenv = NULL;
-
- cenv = getenv("COLUMNS");
- if(cenv) {
- maxcols = atoi(cenv);
- }
-
- if(argc < 2) {
- usage(PM_MAIN, (char*)basename(argv[0]));
- return(0);
- }
-
- /* default root */
- MALLOC(pmo_root, PATH_MAX);
- strcpy(pmo_root, "/");
- /* default dbpath */
- MALLOC(pmo_dbpath, PATH_MAX);
- strcpy(pmo_dbpath, PKGDIR);
-
- /* parse the command line */
- ret = parseargs(PM_ADD, argc, argv);
- if(ret) {
- FREE(pmo_root);
- FREE(pmo_dbpath);
- return(ret);
- }
-
- /* check for permission */
- pm_access = READ_ONLY;
- if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) {
- if(pmo_op == PM_SYNC && !pmo_s_sync && (pmo_s_search || pmo_group)) {
- /* special case: PM_SYNC can be used w/ pmo_s_search by any user */
- } else {
- if(geteuid() != 0) {
- fprintf(stderr, "error: you cannot perform this operation unless you are root.\n");
- return(1);
- }
- pm_access = READ_WRITE;
- /* lock */
- if(lckmk(lckfile, 1, 1) == -1) {
- fprintf(stderr, "error: unable to lock pacman database.\n");
- fprintf(stderr, " if you're sure pacman is not already running, you\n");
- fprintf(stderr, " can remove %s\n", lckfile);
- return(32);
- }
- }
- }
-
- /* set signal handlers */
- signal(SIGINT, cleanup);
- signal(SIGTERM, cleanup);
-
- /* parse the system-wide config file */
- snprintf(path, PATH_MAX, "/%s", PACCONF);
- if(parseconfig(path)) {
- cleanup(1);
- }
-
- if(pmo_usesyslog) {
- openlog("pacman", 0, LOG_USER);
- }
- if(pmo_logfile && geteuid() == 0) {
- /* open the log file */
- logfd = fopen(pmo_logfile, "a");
- if(logfd == NULL) {
- perror("warning: cannot open logfile");
- }
- }
-
- /* check for db existence */
- /* add a trailing '/' if there isn't one */
- if(pmo_root[strlen(pmo_root)-1] != '/') {
- MALLOC(ptr, strlen(pmo_root)+1);
- strcpy(ptr, pmo_root);
- strcat(ptr, "/");
- FREE(pmo_root);
- pmo_root = ptr;
- }
-
- vprint("Installation Root: %s\n", pmo_root);
- /* db location */
- vprint("Top-level DB Path: %s%s\n", pmo_root, pmo_dbpath);
- if(pmo_verbose) {
- list_display("Targets:", pm_targets);
- }
-
- db_local = db_open(pmo_root, pmo_dbpath, "local");
- if(db_local == NULL) {
- /* couldn't open the db directory - try creating it */
- char path[PATH_MAX];
-
- snprintf(path, PATH_MAX, "%s%s/local", pmo_root, pmo_dbpath);
- vprint("initializing database %s...\n", path);
- ret = makepath(path);
-
- if(ret) {
- fprintf(stderr, "error: could not create database.\n");
- cleanup(1);
- }
- if((db_local = db_open(pmo_root, pmo_dbpath, "local")) == NULL) {
- fprintf(stderr, "error: could not open database.\n");
- cleanup(1);
- }
- }
-
- /* load pm_packages cache */
- pm_packages = db_loadpkgs(db_local);
-
- /* start the requested operation */
- switch(pmo_op) {
- case PM_ADD: ret = pacman_add(db_local, pm_targets); break;
- case PM_REMOVE: ret = pacman_remove(db_local, pm_targets); break;
- case PM_UPGRADE: ret = pacman_upgrade(db_local, pm_targets); break;
- case PM_QUERY: ret = pacman_query(db_local, pm_targets); break;
- case PM_SYNC: ret = pacman_sync(db_local, pm_targets); break;
- case PM_DEPTEST: ret = pacman_deptest(db_local, pm_targets); break;
- case PM_MAIN: ret = 0; break;
- default: fprintf(stderr, "error: no operation specified (use -h for help)\n\n");
- ret = 1;
- }
- db_close(db_local);
- cleanup(ret);
- /* not reached */
- return(0);
-}
-
-int pacman_deptest(pacdb_t *db, PMList *targets)
-{
- PMList *list = NULL;
- PMList *lp, *deps;
- pkginfo_t *dummy;
-
- if(pmo_d_vertest) {
- if(targets && targets->data && targets->next && targets->next->data) {
- int ret = rpmvercmp(targets->data, targets->next->data);
- printf("%d\n", ret);
- return(ret);
- }
- return(0);
- }
-
- dummy = newpkg();
- sprintf(dummy->name, "_dummy_");
- sprintf(dummy->version, "1.0-1");
- for(lp = targets; lp; lp = lp->next) {
- if(lp->data == NULL) continue;
- dummy->depends = list_add(dummy->depends, lp->data);
- }
- list = list_add(list, dummy);
- deps = checkdeps(db, PM_ADD, list);
- FREELIST(list);
- FREEPKG(dummy);
-
- if(deps) {
- /* return 126 = deps were missing, but successfully resolved
- * return 127 = deps were missing, and failed to resolve; OR
- * = deps were missing, but no resolution was attempted; OR
- * = unresolvable conflicts were found
- */
- int ret = 126;
- PMList *synctargs = NULL;
- for(lp = deps; lp; lp = lp->next) {
- depmissing_t *miss = (depmissing_t*)lp->data;
- if(miss->type == CONFLICT) {
- /* we can't auto-resolve conflicts */
- printf("conflict: %s\n", miss->depend.name);
- ret = 127;
- } else if(miss->type == DEPEND || miss->type == REQUIRED) {
- if(!pmo_d_resolve) {
- printf("requires: %s", miss->depend.name);
- switch(miss->depend.mod) {
- case DEP_EQ: printf("=%s", miss->depend.version); break;
- case DEP_GE: printf(">=%s", miss->depend.version); break;
- case DEP_LE: printf("<=%s", miss->depend.version); break;
- }
- printf("\n");
- }
- synctargs = list_add(synctargs, strdup(miss->depend.name));
- }
- FREE(miss);
- lp->data = NULL;
- }
- FREE(deps);
- /* attempt to resolve missing dependencies */
- /* TODO: handle version comparators (eg, glibc>=2.2.5) */
- if(ret == 126 && synctargs != NULL) {
- if(!pmo_d_resolve || pacman_sync(db, synctargs)) {
- /* error (or -D not used) */
- ret = 127;
- }
- }
- FREELIST(synctargs);
- return(ret);
- }
- return(0);
-}
-
-int pacman_sync(pacdb_t *db, PMList *targets)
-{
- int allgood = 1, confirm = 0;
- PMList *i, *j, *k;
- PMList *rmtargs = NULL; /* conflicting packages to remove */
- PMList *final = NULL; /* packages to upgrade */
- PMList *trail = NULL; /* a breadcrumb trail to avoid running in circles */
- PMList *databases = NULL;
-
- if(!list_count(pmc_syncs)) {
- fprintf(stderr, "error: no usable package repositories configured.\n");
- return(1);
- }
-
- if(pmo_s_clean) {
- mode_t oldmask;
-
- printf("removing packages from cache... ");
- if(rmrf("/var/cache/pacman/pkg")) {
- fprintf(stderr, "error: could not remove cache directory: %s\n", strerror(errno));
- return(1);
- }
-
- oldmask = umask(0000);
- if(makepath("/var/cache/pacman/pkg")) {
- fprintf(stderr, "error: could not create new cache directory: %s\n", strerror(errno));
- return(1);
- }
- umask(oldmask);
-
- printf("done.\n");
- return(0);
- }
-
- if(pmo_s_sync) {
- /* grab a fresh package list */
- printf(":: Synchronizing package databases... \n");
- logaction(NULL, "synchronizing package lists");
- sync_synctree();
- }
-
- /* open the database(s) */
- for(i = pmc_syncs; i; i = i->next) {
- pacdb_t *db_sync = NULL;
- dbsync_t *dbs = NULL;
- sync_t *sync = (sync_t*)i->data;
-
- db_sync = db_open(pmo_root, pmo_dbpath, sync->treename);
- if(db_sync == NULL) {
- fprintf(stderr, "error: could not open sync database: %s\n", sync->treename);
- fprintf(stderr, " have you used --refresh yet?\n");
- return(1);
- }
- MALLOC(dbs, sizeof(dbsync_t));
- dbs->sync = sync;
- dbs->db = db_sync;
- /* cache packages */
- dbs->pkgcache = db_loadpkgs(db_sync);
- databases = list_add(databases, dbs);
- }
-
- final = list_new();
- trail = list_new();
-
- if(pmo_s_search) {
- /* search sync databases */
- if(targets) {
- for(i = targets; i; i = i->next) {
- char *targ = strdup(i->data);
- strtoupper(targ);
- for(j = databases; j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- for(k = dbs->pkgcache; k; k = k->next) {
- pkginfo_t *pkg = (pkginfo_t*)k->data;
- char *haystack;
- /* check name */
- haystack = strdup(pkg->name);
- strtoupper(haystack);
- if(strstr(haystack, targ)) {
- printf("%s/%s %s\n ", dbs->sync->treename, pkg->name, pkg->version);
- indentprint(pkg->desc, 4);
- printf("\n");
- } else {
- /* check description */
- FREE(haystack);
- haystack = strdup(pkg->desc);
- strtoupper(haystack);
- if(strstr(haystack, targ)) {
- printf("%s/%s %s\n ", dbs->sync->treename, pkg->name, pkg->version);
- indentprint(pkg->desc, 4);
- printf("\n");
- }
- }
- FREE(haystack);
- }
- }
- FREE(targ);
- }
- } else {
- for(j = databases; j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- for(k = dbs->pkgcache; k; k = k->next) {
- pkginfo_t *pkg = (pkginfo_t*)k->data;
- printf("%s/%s %s\n ", dbs->sync->treename, pkg->name, pkg->version);
- indentprint(pkg->desc, 4);
- printf("\n");
- }
- }
- }
- } else if(pmo_group) {
- PMList *pm, *allgroups, *groups;
- i = NULL;
- /* fetch the list of existing groups */
- for(j = databases; j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- k = find_groups(dbs->db);
- for(pm = k; pm; pm = pm->next) {
- if(!is_in((char *)pm->data, i)) {
- i = list_add(i, strdup((char *)pm->data));
- }
- }
- FREELIST(k);
- }
- allgroups = list_sort(i);
- FREELIST(i);
- if(targets) {
- groups = NULL;
- for(j = targets; j; j = j->next) {
- if(is_in((char *)j->data, allgroups)) {
- groups = list_add(groups, strdup((char *)j->data));
- }
- }
- FREELIST(allgroups);
- } else {
- groups = allgroups;
- }
- /* display the packages belonging to groups */
- for(pm = groups; pm; pm = pm->next) {
- PMList *pkg;
- printf("%s\n", (char *)pm->data);
- if(targets == NULL) {
- continue;
- }
- i = NULL;
- for(j = databases; j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- PMList *l = pkg_ingroup(dbs->db, (char *)pm->data);
- i = list_merge(i, l);
- FREELIST(l);
- }
- pkg = list_sort(i);
- FREELIST(i);
- list_display(" ", pkg);
- FREELIST(pkg);
- }
- FREELIST(groups);
- } else if(pmo_s_upgrade) {
- int newer = 0;
- int ignore = 0;
- logaction(NULL, "starting full system upgrade");
- /* check for "recommended" package replacements */
- for(i = databases; i && allgood; i = i->next) {
- dbsync_t *dbs = (dbsync_t*)i->data;
- for(j = dbs->pkgcache; j; j = j->next) {
- pkginfo_t *pkg = (pkginfo_t*)j->data;
- for(k = pkg->replaces; k; k = k->next) {
- PMList *m;
- for(m = pm_packages; m; m = m->next) {
- pkginfo_t *p = (pkginfo_t*)m->data;
- if(!strcmp(k->data, p->name)) {
- /* if confirmed, add this to the 'final' list, designating 'p' as
- * the package to replace.
- */
- if(yesno(":: replace %s with %s from \"%s\"? [Y/n] ", p->name, pkg->name, dbs->db->treename)) {
- syncpkg_t *sync = NULL;
- /* we save the dependency info so we can move p's requiredby stuff
- * over to the replacing package
- */
- pkginfo_t *q = db_scan(db, p->name, INFRQ_DESC | INFRQ_DEPENDS);
-
- /* check if pkg->name is already in the final list. */
- sync = find_pkginsync(pkg->name, final);
- if(sync) {
- /* found it -- just append to the replaces list */
- sync->replaces = list_add(sync->replaces, q);
- } else {
- /* none found -- enter pkg into the final sync list */
- MALLOC(sync, sizeof(syncpkg_t));
- sync->dbs = dbs;
- sync->replaces = NULL;
- sync->replaces = list_add(sync->replaces, q);
- sync->pkg = db_scan(sync->dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
- /* add to the targets list */
- allgood = !resolvedeps(db, databases, sync, final, trail);
- /* check again, as resolvedeps could have added our target for us */
- if(find_pkginsync(sync->pkg->name, final) == NULL) {
- final = list_add(final, sync);
- }
- }
- }
- break;
- }
- }
- }
- }
- }
- /* match installed packages with the sync dbs and compare versions */
- for(i = pm_packages; i && allgood; i = i->next) {
- int cmp, found = 0;
- pkginfo_t *local = (pkginfo_t*)i->data;
- syncpkg_t *sync = NULL;
- MALLOC(sync, sizeof(syncpkg_t));
- sync->replaces = NULL;
-
- for(j = databases; !found && j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- for(k = dbs->pkgcache; !found && k; k = k->next) {
- pkginfo_t *pkg = (pkginfo_t*)k->data;
- if(!strcmp(local->name, pkg->name)) {
- found = 1;
- sync->pkg = pkg;
- sync->dbs = dbs;
- }
- }
- }
- if(!found) {
- /*fprintf(stderr, "%s: not found in sync db. skipping.", local->name);*/
- FREE(sync);
- continue;
- }
- /* compare versions and see if we need to upgrade */
- cmp = rpmvercmp(local->version, sync->pkg->version);
- if(cmp > 0) {
- /* local version is newer */
- fprintf(stderr, ":: %s-%s: local version is newer\n",
- local->name, local->version);
- newer = 1;
- FREE(sync);
- continue;
- } else if(cmp == 0) {
- /* versions are identical */
- FREE(sync);
- continue;
- } else if(is_in((char*)i->data, pmo_ignorepkg)) {
- /* package should be ignored (IgnorePkg) */
- fprintf(stderr, ":: %s-%s: ignoring package upgrade (%s)\n",
- local->name, local->version, sync->pkg->version);
- ignore = 1;
- FREE(sync);
- continue;
- }
-
- /* re-fetch the package record with dependency info */
- sync->pkg = db_scan(sync->dbs->db, sync->pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
-
- /* add to the targets list */
- found = (find_pkginsync(sync->pkg->name, final) != NULL);
- if(!found) {
- allgood = !resolvedeps(db, databases, sync, final, trail);
- /* check again, as resolvedeps could have added our target for us */
- found = (find_pkginsync(sync->pkg->name, final) != NULL);
- if(!found) {
- final = list_add(final, sync);
- }
- }
- }
- if((newer || ignore) && allgood) {
- fprintf(stderr, ":: Above packages will be skipped. To manually upgrade use 'pacman -S <pkg>'\n");
- }
- } else {
- /* process targets */
- for(i = targets; i && allgood; i = i->next) {
- if(i->data) {
- int cmp, found = 0;
- char *treename;
- char *targ;
- char *targline;
- pkginfo_t *local;
- syncpkg_t *sync = NULL;
- MALLOC(sync, sizeof(syncpkg_t));
- sync->replaces = NULL;
-
- targline = strdup((char*)i->data);
- targ = index(targline, '/');
- if(targ) {
- *targ = '\0';
- targ++;
- treename = targline;
- } else {
- targ = targline;
- treename = NULL;
- }
-
- for(j = databases; !found && j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- for(k = dbs->pkgcache; !found && k; k = k->next) {
- pkginfo_t *pkg = (pkginfo_t*)k->data;
- if(!strcmp(targ, pkg->name)) {
- if(treename == NULL ||
- (treename && !strcmp(treename, dbs->sync->treename))) {
- found = 1;
- sync->dbs = dbs;
- /* re-fetch the package record with dependency info */
- sync->pkg = db_scan(sync->dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
- if(sync->pkg == NULL) {
- found = 0;
- }
- }
- }
- }
- }
- if(!found) {
- if(treename == NULL) {
- /* target not found: check if it's a group */
- k = NULL;
- for(j = databases; j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- PMList *l = pkg_ingroup(dbs->db, targ);
- k = list_merge(k, l);
- FREELIST(l);
- }
- if(k != NULL) {
- printf(":: group %s:\n", targ);
- list_display(" ", k);
- if(yesno(" Install whole content? [Y/n] ")) {
- targets = list_merge(targets, k);
- FREELIST(k);
- } else {
- PMList *l;
- for(l = k; l; l = l->next) {
- if(yesno(":: install %s from group %s? [Y/n] ", (char*)l->data, targ)) {
- targets = list_add(targets, strdup((char*)l->data));
- }
- }
- }
- FREELIST(k);
- } else {
- fprintf(stderr, "%s: not found in sync db\n", targ);
- allgood = 0;
- }
- } else {
- fprintf(stderr, "%s: not present in \"%s\" repository\n", targ, treename);
- allgood = 0;
- }
- FREE(sync);
- FREE(targline);
- continue;
- }
- local = db_scan(db, targ, INFRQ_DESC);
- if(local && !pmo_s_downloadonly) {
- /* this is an upgrade, compare versions and determine if it is necessary */
- cmp = rpmvercmp(local->version, sync->pkg->version);
- if(cmp > 0) {
- /* local version is newer - get confirmation first */
- if(!yesno(":: %s-%s: local version is newer. Upgrade anyway? [Y/n] ", local->name, local->version)) {
- FREEPKG(local);
- FREEPKG(sync->pkg);
- FREE(sync);
- FREE(targline);
- continue;
- }
- } else if(cmp == 0) {
- /* versions are identical */
- if(!yesno(":: %s-%s: is up to date. Upgrade anyway? [Y/n] ", local->name, local->version)) {
- FREEPKG(local);
- FREEPKG(sync->pkg);
- FREE(sync);
- FREE(targline);
- continue;
- }
- }
- }
- FREEPKG(local);
-
- found = (find_pkginsync(sync->pkg->name, final) != NULL);
- if(!found && !pmo_nodeps) {
- allgood = !resolvedeps(db, databases, sync, final, trail);
- /* check again, as resolvedeps could have added our target for us */
- found = (find_pkginsync(sync->pkg->name, final) != NULL);
- }
- if(!found) {
- final = list_add(final, sync);
- }
- }
- }
- }
-
- if(allgood && !pmo_s_search) {
- /* check for inter-conflicts and whatnot */
- if(!pmo_nodeps && !pmo_s_downloadonly) {
- int errorout = 0;
- PMList *deps = NULL;
- PMList *list = NULL;
-
- for(i = final; i; i = i->next) {
- syncpkg_t *s = (syncpkg_t*)i->data;
- if(s) {
- list = list_add(list, s->pkg);
- }
- }
- deps = checkdeps(db, PM_UPGRADE, list);
- if(deps) {
- for(i = deps; i; i = i->next) {
- depmissing_t *miss = (depmissing_t*)i->data;
- if(miss->type == DEPEND || miss->type == REQUIRED) {
- if(!errorout) {
- fprintf(stderr, "error: unresolvable dependencies:\n");
- errorout = 1;
- }
- fprintf(stderr, " %s: requires %s", miss->target, miss->depend.name);
- switch(miss->depend.mod) {
- case DEP_EQ: fprintf(stderr, "=%s", miss->depend.version); break;
- case DEP_GE: fprintf(stderr, ">=%s", miss->depend.version); break;
- case DEP_LE: fprintf(stderr, "<=%s", miss->depend.version); break;
- }
- if(miss->type == DEPEND) {
- fprintf(stderr, " but it is not in the sync db\n");
- } else {
- fprintf(stderr, "\n");
- }
- }
- }
- if(!errorout) {
- int found;
- errorout = 0;
- /* no unresolvable deps, so look for conflicts */
- for(i = deps; i && !errorout; i = i->next) {
- depmissing_t *miss = (depmissing_t*)i->data;
- if(miss->type == CONFLICT) {
- /* check if the conflicting package is one that's about to be removed/replaced.
- * if so, then just ignore it
- */
- found = 0;
- for(j = final; j && !found; j = j->next) {
- syncpkg_t *sync = (syncpkg_t*)j->data;
- for(k = sync->replaces; k && !found; k = k->next) {
- pkginfo_t *p = (pkginfo_t*)k->data;
- if(!strcmp(p->name, miss->depend.name)) {
- found = 1;
- }
- }
- }
- /* if we didn't find it in any sync->replaces lists, then it's a conflict */
- if(!found && !is_in(miss->depend.name, rmtargs)) {
- pkginfo_t p1;
- /* build a "fake" pkginfo_t so we can search with is_pkgin() */
- snprintf(p1.name, sizeof(p1.name), miss->depend.name);
- sprintf(p1.version, "1.0-1");
-
- if(is_pkgin(&p1, pm_packages)) {
- if(yesno(":: %s conflicts with %s. Remove %s? [Y/n] ",
- miss->target, miss->depend.name, miss->depend.name)) {
- /* remove miss->depend.name */
- rmtargs = list_add(rmtargs, strdup(miss->depend.name));
- } else {
- /* abort */
- fprintf(stderr, "\nerror: package conflicts detected\n");
- errorout = 1;
- }
- } else {
- if(!is_in(miss->depend.name, rmtargs) & !is_in(miss->target, rmtargs)) {
- fprintf(stderr, "\nerror: %s conflicts with %s\n", miss->target,
- miss->depend.name);
- errorout = 1;
- }
- }
- }
- }
- }
- }
- list_free(deps);
- if(errorout) {
- /* abort mission */
- allgood = 0;
- }
- }
- /* cleanup */
- for(i = list; i; i = i->next) {
- i->data = NULL;
- }
- FREELIST(list);
- }
-
- /* any packages in rmtargs need to be removed from final. */
- /* rather than ripping out nodes from final, we just copy over */
- /* our "good" nodes to a new list and reassign. */
- k = NULL;
- for(i = final; i; i = i->next) {
- syncpkg_t *s = (syncpkg_t*)i->data;
- int keepit = 1;
- for(j = rmtargs; j && keepit; j = j->next) {
- if(!strcmp(j->data, s->pkg->name)) {
- FREE(i->data);
- keepit = 0;
- }
- }
- if(keepit) {
- k = list_add(k, s);
- }
- i->data = NULL;
- }
- FREELIST(final);
- final = k;
-
- /* list targets */
- if(final && final->data && allgood) {
- PMList *list = NULL;
- char *str;
- for(i = rmtargs; i; i = i->next) {
- list = list_add(list, strdup(i->data));
- }
- for(i = final; i; i = i->next) {
- syncpkg_t *s = (syncpkg_t*)i->data;
- for(j = s->replaces; j; j = j->next) {
- pkginfo_t *p = (pkginfo_t*)j->data;
- list = list_add(list, strdup(p->name));
- }
- }
- if(list) {
- printf("\nRemove: ");
- str = buildstring(list);
- indentprint(str, 9);
- printf("\n");
- FREELIST(list);
- FREE(str);
- }
- for(i = final; i; i = i->next) {
- syncpkg_t *s = (syncpkg_t*)i->data;
- if(s && s->pkg) {
- char *str = NULL;
- MALLOC(str, strlen(s->pkg->name)+strlen(s->pkg->version)+2);
- sprintf(str, "%s-%s", s->pkg->name, s->pkg->version);
- list = list_add(list, str);
- }
- }
- printf("\nTargets: ");
- str = buildstring(list);
- indentprint(str, 9);
- printf("\n");
- FREELIST(list);
- FREE(str);
- }
-
- /* get confirmation */
- confirm = 0;
- if(allgood && final && final->data) {
- if(pmo_s_downloadonly) {
- confirm = yesno("\nProceed with download? [Y/n] ");
- } else {
- /* don't get any confirmation if we're called from makepkg */
- if(pmo_d_resolve) {
- confirm = 1;
- } else {
- confirm = yesno("\nProceed with upgrade? [Y/n] ");
- }
- }
- }
- }
-
- if(allgood && confirm && final && final->data) {
- char ldir[PATH_MAX];
- int varcache = 1;
- int done = 0;
- int count = 0;
- sync_t *current = NULL;
- PMList *processed = NULL;
- PMList *files = NULL;
-
- snprintf(ldir, PATH_MAX, "%svar/cache/pacman/pkg", pmo_root);
-
- /* group sync records by repository and download */
- while(!done) {
- if(current) {
- processed = list_add(processed, current);
- current = NULL;
- }
- for(i = final; i; i = i->next) {
- syncpkg_t *sync = (syncpkg_t*)i->data;
- if(current == NULL) {
- /* we're starting on a new repository */
- if(!list_isin(processed, sync->dbs->sync)) {
- current = sync->dbs->sync;
- }
- }
- if(current && !strcmp(current->treename, sync->dbs->sync->treename)) {
- struct stat buf;
- char path[PATH_MAX];
-
- snprintf(path, PATH_MAX, "%s/%s-%s.pkg.tar.gz",
- ldir, sync->pkg->name, sync->pkg->version);
- if(stat(path, &buf)) {
- /* file is not in the cache dir, so add it to the list */
- snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version);
- files = list_add(files, strdup(path));
- } else {
- vprint(" %s-%s.pkg.tar.gz is already in the cache\n", sync->pkg->name, sync->pkg->version);
- count++;
- }
- }
- }
-
- if(files) {
- struct stat buf;
-
- printf("\n:: Retrieving packages from %s...\n", current->treename);
- fflush(stdout);
- if(stat(ldir, &buf)) {
- mode_t oldmask;
- char parent[PATH_MAX];
-
- /* no cache directory.... try creating it */
- snprintf(parent, PATH_MAX, "%svar/cache/pacman", pmo_root);
- logaction(stderr, "warning: no %s cache exists. creating...", ldir);
- oldmask = umask(0000);
- mkdir(parent, 0755);
- if(mkdir(ldir, 0755)) {
- /* couldn't mkdir the cache directory, so fall back to /tmp and unlink
- * the package afterwards.
- */
- logaction(stderr, "warning: couldn't create package cache, using /tmp instead");
- snprintf(ldir, PATH_MAX, "/tmp");
- varcache = 0;
- }
- umask(oldmask);
- }
- if(downloadfiles(current->servers, ldir, files)) {
- fprintf(stderr, "error: failed to retrieve some files from %s\n", current->treename);
- allgood = 0;
- }
- count += list_count(files);
- FREELIST(files);
- }
- if(count == list_count(final)) {
- done = 1;
- }
- }
- printf("\n");
-
- /* double-check */
- FREELIST(files);
-
- if(allgood) {
- /* Check integrity of files */
- printf("checking package integrity... ");
- fflush(stdout);
-
- for(i = final; i; i = i->next) {
- syncpkg_t *sync;
- char str[PATH_MAX], pkgname[PATH_MAX];
- char *md5sum1, *md5sum2;
-
- sync = (syncpkg_t*)i->data;
- snprintf(pkgname, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version);
-
- md5sum1 = sync->pkg->md5sum;
- if(md5sum1 == NULL || md5sum1[0] == '\0') {
- if(allgood) {
- printf("\n");
- }
- fprintf(stderr, "error: can't get md5 checksum for package %s\n", pkgname);
- allgood = 0;
- continue;
- }
- snprintf(str, PATH_MAX, "%s/%s", ldir, pkgname);
- md5sum2 = MDFile(str);
- if(md5sum2 == NULL || md5sum2[0] == '\0') {
- if(allgood) {
- printf("\n");
- }
- fprintf(stderr, "error: can't get md5 checksum for archive %s\n", pkgname);
- allgood = 0;
- continue;
- }
-
- if(strcmp(md5sum1, md5sum2) != 0) {
- if(allgood) {
- printf("\n");
- }
- fprintf(stderr, "error: archive %s is corrupted\n", pkgname);
- allgood = 0;
- }
-
- FREE(md5sum2);
- }
- if(allgood) {
- printf("done.\n");
- } else {
- fprintf(stderr, "\n");
- }
- }
-
- if(!pmo_s_downloadonly && allgood) {
- /* remove any conflicting packages (WITH dep checks) */
- if(rmtargs) {
- int retcode;
- retcode = pacman_remove(db, rmtargs);
- FREELIST(rmtargs);
- if(retcode == 1) {
- fprintf(stderr, "\nupgrade aborted.\n");
- allgood = 0;
- }
- /* reload package cache */
- FREELISTPKGS(pm_packages);
- pm_packages = db_loadpkgs(db);
- }
- FREELIST(rmtargs);
- for(i = final; allgood && i; i = i->next) {
- char *str;
- syncpkg_t *sync = (syncpkg_t*)i->data;
- if(sync->pkg) {
- MALLOC(str, PATH_MAX);
- snprintf(str, PATH_MAX, "%s/%s-%s.pkg.tar.gz", ldir, sync->pkg->name, sync->pkg->version);
- files = list_add(files, str);
- }
- for(j = sync->replaces; j; j = j->next) {
- pkginfo_t *pkg = (pkginfo_t*)j->data;
- rmtargs = list_add(rmtargs, strdup(pkg->name));
- }
- }
- /* remove to-be-replaced packages */
- if(allgood && rmtargs) {
- int oldval = pmo_nodeps;
- /* we make pacman_remove() skip dependency checks by setting pmo_nodeps high */
- pmo_nodeps = 1;
- allgood = !pacman_remove(db, rmtargs);
- pmo_nodeps = oldval;
- if(!allgood) {
- fprintf(stderr, "package removal failed. aborting...\n");
- }
- }
- /* install targets */
- if(allgood) {
- allgood = !pacman_upgrade(db, files);
- }
- /* propagate replaced packages' requiredby fields to their new owners */
- if(allgood) {
- for(i = final; i; i = i->next) {
- syncpkg_t *sync = (syncpkg_t*)i->data;
- if(sync->replaces) {
- pkginfo_t *new = db_scan(db, sync->pkg->name, INFRQ_ALL);
- for(j = sync->replaces; j; j = j->next) {
- pkginfo_t *old = (pkginfo_t*)j->data;
- /* merge lists */
- for(k = old->requiredby; k; k = k->next) {
- if(!is_in(k->data, new->requiredby)) {
- /* replace old's name with new's name in the requiredby's dependency list */
- PMList *m;
- pkginfo_t *depender = db_scan(db, k->data, INFRQ_ALL);
- for(m = depender->depends; m; m = m->next) {
- if(!strcmp(m->data, old->name)) {
- FREE(m->data);
- m->data = strdup(new->name);
- }
- }
- db_write(db, depender);
-
- /* add the new requiredby */
- new->requiredby = list_add(new->requiredby, strdup(k->data));
- }
- }
- }
- db_write(db, new);
- FREEPKG(new);
- }
- }
- }
- }
-
- if(!varcache && !pmo_s_downloadonly && allgood) {
- /* delete packages */
- for(i = files; i; i = i->next) {
- unlink(i->data);
- }
- }
- }
-
- /* cleanup */
- for(i = final; i; i = i->next) {
- syncpkg_t *sync = (syncpkg_t*)i->data;
- if(sync) {
- FREEPKG(sync->pkg);
- FREELISTPKGS(sync->replaces);
- }
- FREE(sync);
- i->data = NULL;
- }
- for(i = trail; i; i = i->next) {
- /* this list used the same pointers as final, so they're already freed */
- i->data = NULL;
- }
- for(i = databases; i; i = i->next) {
- dbsync_t *dbs = (dbsync_t*)i->data;
- db_close(dbs->db);
- dbs->db = NULL;
- FREELISTPKGS(dbs->pkgcache);
- FREE(dbs);
- i->data = NULL;
- }
- FREELIST(databases);
- FREELIST(final);
- FREELIST(trail);
- FREELIST(rmtargs);
- return(!allgood);
-}
-
-int pacman_add(pacdb_t *db, PMList *targets)
-{
- int i, ret = 0, errors = 0;
- TAR *tar = NULL;
- char expath[PATH_MAX];
- char pm_install[PATH_MAX];
- pkginfo_t *info = NULL;
- struct stat buf;
- PMList *targ, *file, *lp, *j, *k;
- PMList *alltargs = NULL;
- PMList *filenames = NULL;
- unsigned short real_pmo_upgrade;
- tartype_t gztype = {
- (openfunc_t) gzopen_frontend,
- (closefunc_t)gzclose,
- (readfunc_t) gzread,
- (writefunc_t)gzwrite
- };
-
- if(targets == NULL) {
- return(0);
- }
-
- printf("loading package data... ");
- fflush(stdout);
- for(targ = targets; targ; targ = targ->next) {
- /* Populate the package struct */
- vprint("reading %s... ", (char*)targ->data);
- info = load_pkg((char*)targ->data, 0);
- if(info == NULL) {
- return(1);
- }
- if(pmo_freshen) {
- /* only upgrade/install this package if it is already installed and at a lesser version */
- pkginfo_t *dummy = db_scan(db, info->name, INFRQ_DESC);
- if(dummy == NULL || rpmvercmp(dummy->version, info->version) >= 0) {
- vprint("not installed or lesser version\n");
- FREEPKG(info);
- FREEPKG(dummy);
- continue;
- }
- FREEPKG(dummy);
- }
- /* check if an older version of said package is already in alltargs.
- * if so, replace it in the list */
- for(j = alltargs, k = filenames; j && j->data && k; j = j->next, k = k->next) {
- pkginfo_t *pkg = (pkginfo_t*)j->data;
- if(!strcmp(pkg->name, info->name)) {
- if(rpmvercmp(pkg->version, info->version) < 0) {
- vprint("replacing older version in target list. ");
- FREEPKG(j->data);
- j->data = info;
- FREE(k->data);
- k->data = strdup(targ->data);
- }
- }
- }
- vprint("done\n");
- alltargs = list_add(alltargs, info);
- filenames = list_add(filenames, strdup(targ->data));
- }
- printf("done.\n");
-
- /* No need to check deps if pacman_add was called during a sync:
- * it is already done in pacman_sync. */
- if(!pmo_nodeps && pmo_op != PM_SYNC) {
- int errorout = 0;
- vprint("checking dependencies...\n");
- lp = checkdeps(db, (pmo_upgrade ? PM_UPGRADE : PM_ADD), alltargs);
- if(lp) {
- /* look for unsatisfied dependencies */
- for(j = lp; j; j = j->next) {
- depmissing_t* miss = (depmissing_t*)j->data;
- if(miss->type == DEPEND || miss->type == REQUIRED) {
- if(!errorout) {
- fprintf(stderr, "error: unsatisfied dependencies:\n");
- errorout = 1;
- }
- printf(" %s: requires %s", miss->target, miss->depend.name);
- switch(miss->depend.mod) {
- case DEP_EQ: printf("=%s", miss->depend.version); break;
- case DEP_GE: printf(">=%s", miss->depend.version); break;
- case DEP_LE: printf("<=%s", miss->depend.version); break;
- }
- printf("\n");
- }
- }
- if(!errorout) {
- PMList *rmtargs = NULL;
- errorout = 0;
- /* no unsatisfied deps, so look for conflicts */
- for(j = lp; j && !errorout; j = j->next) {
- depmissing_t* miss = (depmissing_t*)j->data;
- if(miss->type == CONFLICT && !is_in(miss->depend.name, rmtargs)) {
- pkginfo_t p1;
- /* build a "fake" pkginfo_t so we can search with is_pkgin() */
- snprintf(p1.name, sizeof(p1.name), miss->depend.name);
- sprintf(p1.version, "1.0-1");
-
- if(is_pkgin(&p1, pm_packages)) {
- if(yesno(":: %s conflicts with %s. Remove %s? [Y/n] ",
- miss->target, miss->depend.name, miss->depend.name)) {
- /* remove miss->depend.name */
- rmtargs = list_add(rmtargs, strdup(miss->depend.name));
- } else {
- /* abort */
- fprintf(stderr, "\nerror: package conflicts detected\n");
- errorout = 1;
- }
- } else {
- if(!is_in(miss->depend.name, rmtargs) & !is_in(miss->target, rmtargs)) {
- fprintf(stderr, "\nerror: %s conflicts with %s\n", miss->target,
- miss->depend.name);
- errorout = 1;
- }
- }
- }
- }
- if(rmtargs && !errorout) {
- int retcode;
- int oldupg = pmo_upgrade;
- /* any packages in rmtargs need to be removed from alltargs. */
- /* rather than ripping out nodes from alltargs, we just copy over */
- /* our "good" nodes to a new list and reassign. */
- k = NULL;
- for(lp = alltargs; lp; lp = lp->next) {
- pkginfo_t *p = (pkginfo_t*)lp->data;
- int keepit = 1;
- for(j = rmtargs; j && keepit; j = j->next) {
- if(!strcmp(j->data, p->name)) {
- /* gone! */
- FREE(lp->data);
- keepit = 0;
- }
- }
- if(keepit) {
- k = list_add(k, p);
- }
- lp->data = NULL;
- }
- FREELIST(alltargs);
- alltargs = k;
- /* make sure pacman_remove does it's own dependency check */
- pmo_upgrade = 0;
- retcode = pacman_remove(db, rmtargs);
- list_free(rmtargs);
- if(retcode == 1) {
- fprintf(stderr, "\n%s aborted.\n", oldupg ? "upgrade" : "install");
- return(1);
- }
- /* reload package cache */
- FREELISTPKGS(pm_packages);
- pm_packages = db_loadpkgs(db);
- pmo_upgrade = oldupg;
- }
- }
- if(errorout) {
- FREELIST(lp);
- return(1);
- }
- list_free(lp);
- }
-
- /* re-order w.r.t. dependencies */
- vprint("sorting by dependencies\n");
- lp = sortbydeps(alltargs);
- /* free the old alltargs */
- for(j = alltargs; j; j = j->next) {
- j->data = NULL;
- }
- FREELIST(alltargs);
- alltargs = lp;
- }
-
- if(!pmo_force) {
- printf("checking for file conflicts... ");
- fflush(stdout);
- lp = db_find_conflicts(db, alltargs, pmo_root);
- if(lp) {
- printf("\nerror: the following file conflicts were found:\n");
- for(j = lp; j; j = j->next) {
- printf(" %s\n", (char*)j->data);
- }
- printf("\n");
- FREELIST(lp);
- return(1);
- }
- printf("done.\n");
- FREELIST(lp);
- }
-
- /* this can get modified in the next for loop, so we reset it on each iteration */
- real_pmo_upgrade = pmo_upgrade;
-
- for(targ = alltargs, file = filenames; targ && file; targ = targ->next, file = file->next) {
- pkginfo_t* oldpkg = NULL;
- info = (pkginfo_t*)targ->data;
- errors = 0;
-
- pmo_upgrade = real_pmo_upgrade;
- /* check for an already installed package */
- if(!pmo_upgrade && is_pkgin(info, pm_packages)) {
- fprintf(stderr, "error: %s is already installed. (try --upgrade)\n", info->name);
- continue;
- }
-
- /* see if this is an upgrade. if so, remove the old package first */
- if(pmo_upgrade) {
- if(is_pkgin(info, pm_packages)) {
- PMList* tmp = list_new();
- int retcode;
-
- printf("upgrading %s... ", info->name);
- /* we'll need the full record for backup checks later */
- oldpkg = db_scan(db, info->name, INFRQ_ALL);
-
- if(oldpkg) {
- list_add(tmp, strdup(info->name));
- vprint("removing old package first...\n");
- retcode = pacman_remove(db, tmp);
- list_free(tmp);
- if(retcode == 1) {
- fprintf(stderr, "\nupgrade aborted.\n");
- return(1);
- }
- /* reload package cache */
- FREELISTPKGS(pm_packages);
- pm_packages = db_loadpkgs(db);
- }
- } else {
- /* no previous package version is installed, so this is actually just an
- * install
- */
- pmo_upgrade = 0;
- }
- }
- if(!pmo_upgrade) {
- printf("installing %s... ", info->name);
- }
- fflush(stdout);
-
- /* open the .tar.gz package */
- if(tar_open(&tar, (char*)file->data, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
- perror("could not open package");
- return(1);
- }
- vprint("extracting files...\n");
- for(i = 0; !th_read(tar); i++) {
- int nb = 0;
- int notouch = 0;
- char *md5_orig = NULL;
- char pathname[PATH_MAX];
- strncpy(pathname, th_get_pathname(tar), PATH_MAX);
-
- if(!strcmp(pathname, ".PKGINFO") || !strcmp(pathname, ".FILELIST")) {
- tar_skip_regfile(tar);
- continue;
- }
-
- if(!strcmp(pathname, "._install") || !strcmp(pathname, ".INSTALL")) {
- /* the install script goes inside the db */
- snprintf(expath, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root,
- pmo_dbpath, db->treename, info->name, info->version);
- } else {
- /* build the new pathname relative to pmo_root */
- snprintf(expath, PATH_MAX, "%s%s", pmo_root, pathname);
- }
-
- if(!stat(expath, &buf) && !S_ISDIR(buf.st_mode)) {
- /* file already exists */
- if(is_in(pathname, pmo_noupgrade)) {
- notouch = 1;
- } else {
- if(!pmo_upgrade || oldpkg == NULL) {
- nb = is_in(pathname, info->backup);
- } else {
- /* op == PM_UPGRADE */
- md5_orig = needbackup(pathname, oldpkg->backup);
- if(md5_orig) {
- nb = 1;
- }
- }
- }
- }
-
- if(nb) {
- char *temp;
- char *md5_local, *md5_pkg;
-
- md5_local = MDFile(expath);
- /* extract the package's version to a temporary file and md5 it */
- temp = strdup("/tmp/pacman_XXXXXX");
- mkstemp(temp);
- if(tar_extract_file(tar, temp)) {
- logaction(stderr, "could not extract %s: %s", pathname, strerror(errno));
- errors++;
- continue;
- }
- md5_pkg = MDFile(temp);
- /* append the new md5 hash to it's respective entry in info->backup
- * (it will be the new orginal)
- */
- for(lp = info->backup; lp; lp = lp->next) {
- char *fn;
-
- if(!lp->data) continue;
- if(!strcmp((char*)lp->data, pathname)) {
- /* 32 for the hash, 1 for the terminating NULL, and 1 for the tab delimiter */
- MALLOC(fn, strlen(lp->data)+34);
- sprintf(fn, "%s\t%s", (char*)lp->data, md5_pkg);
- FREE(lp->data);
- lp->data = fn;
- }
- }
-
- vprint("checking md5 hashes for %s\n", expath);
- vprint(" current: %s\n", md5_local);
- vprint(" new: %s\n", md5_pkg);
- if(md5_orig) {
- vprint(" original: %s\n", md5_orig);
- }
-
- if(!pmo_upgrade) {
- /* PM_ADD */
-
- /* if a file already exists with a different md5 hash,
- * then we rename it to a .pacorig extension and continue */
- if(strcmp(md5_local, md5_pkg)) {
- char newpath[PATH_MAX];
- snprintf(newpath, PATH_MAX, "%s.pacorig", expath);
- if(rename(expath, newpath)) {
- logaction(stderr, "error: could not rename %s: %s", expath, strerror(errno));
- }
- if(copyfile(temp, expath)) {
- logaction(stderr, "error: could not copy %s to %s: %s", temp, expath, strerror(errno));
- errors++;
- } else {
- logaction(stderr, "warning: %s saved as %s", expath, newpath);
- }
- }
- } else if(md5_orig) {
- /* PM_UPGRADE */
- int installnew = 0;
-
- /* the fun part */
- if(!strcmp(md5_orig, md5_local)) {
- if(!strcmp(md5_local, md5_pkg)) {
- vprint(" action: installing new file\n");
- installnew = 1;
- } else {
- vprint(" action: installing new file\n");
- installnew = 1;
- }
- } else if(!strcmp(md5_orig, md5_pkg)) {
- vprint(" action: leaving existing file in place\n");
- } else if(!strcmp(md5_local, md5_pkg)) {
- vprint(" action: installing new file\n");
- installnew = 1;
- } else {
- char newpath[PATH_MAX];
- vprint(" action: saving current file and installing new one\n");
- installnew = 1;
- snprintf(newpath, PATH_MAX, "%s.pacsave", expath);
- if(rename(expath, newpath)) {
- logaction(stderr, "error: could not rename %s: %s", expath, strerror(errno));
- } else {
- logaction(stderr, "warning: %s saved as %s", expath, newpath);
- }
- }
-
- if(installnew) {
- /*vprint(" %s\n", expath);*/
- if(copyfile(temp, expath)) {
- fprintf(stderr, "error: could not copy %s to %s: %s\n", temp, expath, strerror(errno));
- errors++;
- }
- }
- }
-
- FREE(md5_local);
- FREE(md5_pkg);
- FREE(md5_orig);
- unlink(temp);
- FREE(temp);
- } else {
- if(!notouch) {
- /*vprint(" %s\n", expath);*/
- } else {
- vprint("%s is in NoUpgrade - skipping\n", pathname);
- strncat(expath, ".pacnew", PATH_MAX);
- logaction(stderr, "warning: extracting %s%s as %s", pmo_root, pathname, expath);
- /*tar_skip_regfile(tar);*/
- }
- if(tar_extract_file(tar, expath)) {
- logaction(stderr, "could not extract %s: %s", pathname, strerror(errno));
- errors++;
- }
- /* calculate an md5 hash if this is in info->backup */
- for(lp = info->backup; lp; lp = lp->next) {
- char *fn, *md5;
- char path[PATH_MAX];
-
- if(!lp->data) continue;
- if(!strcmp((char*)lp->data, pathname)) {
- snprintf(path, PATH_MAX, "%s%s", pmo_root, (char*)lp->data);
- md5 = MDFile(path);
- /* 32 for the hash, 1 for the terminating NULL, and 1 for the tab delimiter */
- MALLOC(fn, strlen(lp->data)+34);
- sprintf(fn, "%s\t%s", (char*)lp->data, md5);
- free(lp->data);
- lp->data = fn;
- }
- }
- }
- }
- tar_close(tar);
- if(errors) {
- ret = 1;
- logaction(stderr, "errors occurred while %s %s",
- (pmo_upgrade ? "upgrading" : "installing"), info->name);
-
-/* XXX: this "else" is disabled so the db_write() ALWAYS occurs. If it doesn't
- * packages can get lost during an upgrade.
- */
- } /*else*/ {
- time_t t = time(NULL);
-
- /* Update the requiredby field by scaning the whole database
- * looking for packages depending on the package to add */
- for(lp = pm_packages; lp; lp = lp->next) {
- pkginfo_t *tmpp = NULL;
- PMList *tmppm = NULL;
-
- tmpp = db_scan(db, ((pkginfo_t*)lp->data)->name, INFRQ_DEPENDS);
- if(tmpp == NULL) {
- continue;
- }
- for(tmppm = tmpp->depends; tmppm; tmppm = tmppm->next) {
- depend_t depend;
- if(splitdep(tmppm->data, &depend)) {
- continue;
- }
- if(tmppm->data && !strcmp(depend.name, info->name)) {
- info->requiredby = list_add(info->requiredby, strdup(tmpp->name));
- continue;
- }
- }
- }
-
- vprint("Updating database...");
- /* make an install date (in UTC) */
- strncpy(info->installdate, asctime(gmtime(&t)), sizeof(info->installdate));
- if(db_write(db, info)) {
- logaction(stderr, "error updating database for %s!", info->name);
- return(1);
- }
- vprint("done.\n");
- if(pmo_upgrade && oldpkg) {
- logaction(NULL, "upgraded %s (%s -> %s)", info->name,
- oldpkg->version, info->version);
- } else {
- logaction(NULL, "installed %s (%s)", info->name, info->version);
- }
-
- /* update dependency packages' REQUIREDBY fields */
- for(lp = info->depends; lp; lp = lp->next) {
- pkginfo_t *depinfo = NULL;
- depend_t depend;
-
- if(splitdep(lp->data, &depend)) {
- continue;
- }
- depinfo = db_scan(db, depend.name, INFRQ_ALL);
- if(depinfo == NULL) {
- /* look for a provides package */
- PMList *provides = whatprovides(db, depend.name);
- if(provides) {
- /* use the first one */
- depinfo = db_scan(db, provides->data, INFRQ_ALL);
- if(depinfo == NULL) {
- /* wtf */
- continue;
- }
- } else {
- continue;
- }
- }
- depinfo->requiredby = list_add(depinfo->requiredby, strdup(info->name));
- db_write(db, depinfo);
- freepkg(depinfo);
- }
- printf("done.\n"); fflush(stdout);
-
- /* run the post-install script if it exists */
- snprintf(pm_install, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root, pmo_dbpath, db->treename, info->name, info->version);
- if(!stat(pm_install, &buf)) {
- char cmdline[PATH_MAX+1];
- snprintf(pm_install, PATH_MAX, "%s/%s/%s-%s/install", pmo_dbpath, db->treename, info->name, info->version);
- vprint("Executing post-install script...\n");
- snprintf(cmdline, PATH_MAX, "chroot %s /bin/sh %s post_%s %s %s", pmo_root, pm_install,
- (pmo_upgrade ? "upgrade" : "install"), info->version, ((pmo_upgrade && oldpkg) ? oldpkg->version : ""));
- system(cmdline);
- }
- }
-
- freepkg(oldpkg);
- }
-
- /* clean up */
- for(lp = alltargs; lp; lp = lp->next) {
- FREEPKG(lp->data);
- }
- FREELIST(alltargs);
- FREELIST(filenames);
-
- /* run ldconfig if it exists */
- snprintf(expath, PATH_MAX, "%setc/ld.so.conf", pmo_root);
- if(!stat(expath, &buf)) {
- snprintf(expath, PATH_MAX, "%ssbin/ldconfig", pmo_root);
- if(!stat(expath, &buf)) {
- char cmd[PATH_MAX];
- snprintf(cmd, PATH_MAX, "%s -r %s", expath, pmo_root);
- vprint("running \"%s\"\n", cmd);
- system(cmd);
- }
- }
-
- return(ret);
-}
-
-int pacman_remove(pacdb_t *db, PMList *targets)
-{
- char line[PATH_MAX+1];
- char pm_install[PATH_MAX+1];
- pkginfo_t *info = NULL;
- pkginfo_t *depinfo = NULL;
- struct stat buf;
- char *newpath = NULL;
- depend_t depend;
- PMList *alltargs = NULL;
- PMList *targ, *lp, *j;
-
- if(targets == NULL) {
- return(0);
- }
-
- /* load package info from all targets */
- for(lp = targets; lp; lp = lp->next) {
- info = db_scan(db, (char*)lp->data, INFRQ_ALL);
- if(info == NULL) {
- PMList *groups;
- /* if the target is a group, ask if its packages should be removed */
- groups = find_groups(db);
- if(is_in((char *)lp->data, groups)) {
- PMList *pkgs = pkg_ingroup(db, (char *)lp->data);
- printf(":: group %s:\n", (char*)lp->data);
- list_display(" ", pkgs);
- if(yesno(" Remove whole content? [Y/n] ")) {
- for(j = pkgs; j; j = j->next) {
- info = db_scan(db, (char *)j->data, INFRQ_ALL);
- alltargs = list_add(alltargs, info);
- }
- } else {
- for(j = pkgs; j; j = j->next) {
- if(yesno(":: remove %s from group %s? [Y/n] ", (char*)j->data, (char*)lp->data)) {
- info = db_scan(db, (char *)j->data, INFRQ_ALL);
- alltargs = list_add(alltargs, info);
- }
- }
- }
- FREELIST(pkgs);
- FREELIST(groups);
- continue;
- }
- FREELIST(groups);
- fprintf(stderr, "error: could not find %s in database\n", (char*)lp->data);
- return(1);
- }
- alltargs = list_add(alltargs, info);
- }
- if(!pmo_nodeps && !pmo_upgrade) {
- vprint("checking dependencies...\n");
- lp = checkdeps(db, PM_REMOVE, alltargs);
- if(lp) {
- if(pmo_r_cascade) {
- while(lp) {
- for(j = lp; j; j = j->next) {
- depmissing_t* miss = (depmissing_t*)j->data;
- info = db_scan(db, miss->depend.name, INFRQ_ALL);
- if(!is_pkgin(info, alltargs)) {
- list_add(alltargs, info);
- }
- }
- list_free(lp);
- lp = checkdeps(db, PM_REMOVE, alltargs);
- }
- /* list targets */
- list_display("\nTargets:", alltargs);
- /* get confirmation */
- if(yesno("\nDo you want to remove these packages? [Y/n] ") == 0) {
- list_free(alltargs);
- list_free(lp);
- return(1);
- }
- } else {
- fprintf(stderr, "error: this will break the following dependencies:\n");
- for(j = lp; j; j = j->next) {
- depmissing_t* miss = (depmissing_t*)j->data;
- printf(" %s: is required by %s\n", miss->target, miss->depend.name);
- }
- list_free(alltargs);
- list_free(lp);
- return(1);
- }
- }
- list_free(lp);
- }
-
- for(targ = alltargs; targ; targ = targ->next) {
- info = (pkginfo_t*)targ->data;
-
- if(!pmo_upgrade) {
- printf("removing %s... ", info->name);
- fflush(stdout);
- /* run the pre-remove script if it exists */
- snprintf(pm_install, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root, pmo_dbpath, db->treename, info->name, info->version);
- if(!stat(pm_install, &buf)) {
- vprint("Executing pre-remove script...\n");
- snprintf(pm_install, PATH_MAX, "%s/%s/%s-%s/install", pmo_dbpath, db->treename, info->name, info->version);
- snprintf(line, PATH_MAX, "chroot %s /bin/sh %s pre_remove %s", pmo_root, pm_install, info->version);
-
- system(line);
- }
- }
-
- /* iterate through the list backwards, unlinking files */
- for(lp = list_last(info->files); lp; lp = lp->prev) {
- int nb = 0;
- if(needbackup((char*)lp->data, info->backup)) {
- nb = 1;
- }
- if(!nb && pmo_upgrade) {
- /* check pmo_noupgrade */
- if(is_in((char*)lp->data, pmo_noupgrade)) {
- nb = 1;
- }
- }
- snprintf(line, PATH_MAX, "%s%s", pmo_root, (char*)lp->data);
- if(lstat(line, &buf)) {
- vprint("file %s does not exist\n", line);
- continue;
- }
- if(S_ISDIR(buf.st_mode)) {
- /*vprint(" removing directory %s\n", line);*/
- if(rmdir(line)) {
- /* this is okay, other packages are probably using it. */
- }
- } else {
- /* if the file is flagged, back it up to .pacsave */
- if(nb) {
- if(pmo_upgrade) {
- /* we're upgrading so just leave the file as is. pacman_add() will handle it */
- } else {
- if(!pmo_nosave) {
- newpath = (char*)realloc(newpath, strlen(line)+strlen(".pacsave")+1);
- sprintf(newpath, "%s.pacsave", line);
- rename(line, newpath);
- logaction(stderr, "warning: %s saved as %s", line, newpath);
- } else {
- /*vprint(" unlinking %s\n", line);*/
- if(unlink(line)) {
- perror("cannot remove file");
- }
- }
- }
- } else {
- /*vprint(" unlinking %s\n", line);*/
- if(unlink(line)) {
- perror("cannot remove file");
- }
- }
- }
- }
-
- /* remove the package from the database */
- snprintf(line, PATH_MAX, "%s%s/%s/%s-%s", pmo_root, pmo_dbpath, db->treename,
- info->name, info->version);
-
- /* DESC */
- snprintf(pm_install, PATH_MAX, "%s/desc", line);
- unlink(pm_install);
- /* FILES */
- snprintf(pm_install, PATH_MAX, "%s/files", line);
- unlink(pm_install);
- /* DEPENDS */
- snprintf(pm_install, PATH_MAX, "%s/depends", line);
- unlink(pm_install);
- /* INSTALL */
- snprintf(pm_install, PATH_MAX, "%s/install", line);
- unlink(pm_install);
- /* directory */
- rmdir(line);
-
- /* update dependency packages' REQUIREDBY fields */
- for(lp = info->depends; lp; lp = lp->next) {
- PMList *last, *j;
-
- if(splitdep((char*)lp->data, &depend)) {
- continue;
- }
- depinfo = db_scan(db, depend.name, INFRQ_ALL);
- if(depinfo == NULL) {
- /* look for a provides package */
- PMList *provides = whatprovides(db, depend.name);
- if(provides) {
- /* TODO: should check _all_ packages listed in provides, not just
- * the first one.
- */
- /* use the first one */
- depinfo = db_scan(db, provides->data, INFRQ_ALL);
- list_free(provides);
- if(depinfo == NULL) {
- /* wtf */
- continue;
- }
- } else {
- list_free(provides);
- continue;
- }
- }
- /* splice out this entry from requiredby */
- last = list_last(depinfo->requiredby);
- for(j = depinfo->requiredby; j; j = j->next) {
- if(!strcmp((char*)j->data, info->name)) {
- if(j == depinfo->requiredby) {
- depinfo->requiredby = j->next;
- }
- if(j->prev) j->prev->next = j->next;
- if(j->next) j->next->prev = j->prev;
- /* free the spliced node */
- j->prev = j->next = NULL;
- list_free(j);
- break;
- }
- }
- db_write(db, depinfo);
- freepkg(depinfo);
- }
- if(!pmo_upgrade) {
- printf("done.\n");
- logaction(NULL, "removed %s (%s)", info->name, info->version);
- }
- }
-
- FREELIST(alltargs);
-
- /* run ldconfig if it exists */
- snprintf(line, PATH_MAX, "%setc/ld.so.conf", pmo_root);
- if(!stat(line, &buf)) {
- snprintf(line, PATH_MAX, "%ssbin/ldconfig", pmo_root);
- if(!stat(line, &buf)) {
- char cmd[PATH_MAX];
- snprintf(cmd, PATH_MAX, "%s -r %s", line, pmo_root);
- vprint("running \"%s\"\n", cmd);
- system(cmd);
- }
- }
-
- return(0);
-}
-
-int pacman_query(pacdb_t *db, PMList *targets)
-{
- char *package = NULL;
- char path[PATH_MAX+1];
- pkginfo_t *info = NULL;
- PMList *targ, *lp, *q;
- int done = 0;
-
- for(targ = targets; !done; targ = (targ ? targ->next : NULL)) {
- if(targets == NULL) {
- done = 1;
- } else {
- if(targ->next == NULL) {
- done = 1;
- }
- package = (char*)targ->data;
- }
-
- /* looking for groups */
- if(pmo_group) {
- PMList *pkg, *groups;
- groups = find_groups(db);
- if(package == NULL) {
- for(lp = groups; lp; lp = lp->next) {
- pkg = pkg_ingroup(db, (char *)lp->data);
- for(q = pkg; q; q = q->next) {
- printf("%s %s\n", (char *)lp->data, (char *)q->data);
- }
- FREELIST(pkg);
- }
- } else {
- if(!is_in(package, groups)) {
- fprintf(stderr, "Group \"%s\" was not found.\n", package);
- FREELIST(groups);
- return(2);
- }
- pkg = pkg_ingroup(db, package);
- for(q = pkg; q; q = q->next) {
- printf("%s %s\n", package, (char *)q->data);
- }
- FREELIST(pkg);
- }
- FREELIST(groups);
- continue;
- }
-
- /* output info for a .tar.gz package */
- if(pmo_q_isfile) {
- if(package == NULL) {
- fprintf(stderr, "error: no package file was specified for --file\n");
- return(1);
- }
- info = load_pkg(package, pmo_q_info);
- if(info == NULL) {
- fprintf(stderr, "error: %s is not a package\n", package);
- return(1);
- }
- if(pmo_q_info) {
- printf("\n");
- } else if(pmo_q_list) {
- for(lp = info->files; lp; lp = lp->next) {
- printf("%s %s\n", info->name, (char*)lp->data);
- }
- } else {
- printf("%s %s\n", info->name, info->version);
- }
- FREEPKG(info);
- continue;
- }
-
- /* determine the owner of a file */
- if(pmo_q_owns) {
- char rpath[PATH_MAX];
- if(package == NULL) {
- fprintf(stderr, "error: no file was specified for --owns\n");
- return(1);
- }
- if(realpath(package, rpath)) {
- int gotcha = 0;
- rewinddir(db->dir);
- while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_FILES)) != NULL && !gotcha) {
- for(lp = info->files; lp && !gotcha; lp = lp->next) {
- sprintf(path, "%s%s", pmo_root, (char*)lp->data);
- if(!strcmp(path, rpath)) {
- printf("%s is owned by %s %s\n", package, info->name, info->version);
- gotcha = 1;
- }
- }
- FREEPKG(info);
- }
- if(!gotcha) {
- fprintf(stderr, "No package owns %s\n", package);
- }
- continue;
- } else {
- fprintf(stderr, "error: %s is not a file.\n", package);
- return(1);
- }
- }
-
- /* find packages in the db */
- if(package == NULL) {
- /* no target */
- for(lp = pm_packages; lp; lp = lp->next) {
- pkginfo_t *tmpp = (pkginfo_t*)lp->data;
- if(pmo_q_list) {
- info = db_scan(db, tmpp->name, INFRQ_DESC | INFRQ_FILES);
- if(info == NULL) {
- /* something weird happened */
- return(1);
- }
- for(q = info->files; q; q = q->next) {
- printf("%s %s%s\n", info->name, pmo_root, (char*)q->data);
- }
- FREEPKG(info);
- } else if(pmo_q_orphans) {
- info = db_scan(db, tmpp->name, INFRQ_DESC | INFRQ_DEPENDS);
- if(info == NULL) {
- return(1);
- }
- if(info->requiredby == NULL) {
- printf("%s %s\n", tmpp->name, tmpp->version);
- }
- FREEPKG(info);
- } else {
- printf("%s %s\n", tmpp->name, tmpp->version);
- }
- }
- } else {
- /* find a target */
- if(pmo_q_info) {
- info = db_scan(db, package, INFRQ_ALL);
- if(info == NULL) {
- fprintf(stderr, "Package \"%s\" was not found.\n", package);
- return(2);
- }
- dump_pkg(info);
- if(pmo_q_info > 1 && info->backup) {
- /* extra info */
- printf("\n");
- for(lp = info->backup; lp; lp = lp->next) {
- struct stat buf;
- char path[PATH_MAX];
- char *md5sum;
- char *str = strdup(lp->data);
- char *ptr = index(str, '\t');
- if(ptr == NULL) {
- FREE(str);
- continue;
- }
- *ptr = '\0';
- ptr++;
- snprintf(path, PATH_MAX-1, "%s%s", pmo_root, str);
- if(!stat(path, &buf)) {
- md5sum = MDFile(path);
- if(md5sum == NULL) {
- fprintf(stderr, "error calculating md5sum for %s\n", path);
- continue;
- }
- if(strcmp(md5sum, ptr)) {
- printf("MODIFIED\t%s\n", path);
- } else {
- printf("NOT MODIFIED\t%s\n", path);
- }
- } else {
- printf("MISSING\t\t%s\n", path);
- }
- FREE(str);
- }
- }
- printf("\n");
- } else if(pmo_q_list) {
- info = db_scan(db, package, INFRQ_DESC | INFRQ_FILES);
- if(info == NULL) {
- fprintf(stderr, "Package \"%s\" was not found.\n", package);
- return(2);
- }
- for(lp = info->files; lp; lp = lp->next) {
- printf("%s %s%s\n", info->name, pmo_root, (char*)lp->data);
- }
- } else if(pmo_q_orphans) {
- info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS);
- if(info == NULL) {
- fprintf(stderr, "Package \"%s\" was not found.\n", package);
- return(2);
- }
- if(info->requiredby == NULL) {
- printf("%s %s\n", info->name, info->version);
- }
- } else {
- info = db_scan(db, package, INFRQ_DESC);
- if(info == NULL) {
- fprintf(stderr, "Package \"%s\" was not found.\n", package);
- return(2);
- }
- printf("%s %s\n", info->name, info->version);
- }
- FREEPKG(info);
- }
- }
-
- return(0);
-}
-
-int pacman_upgrade(pacdb_t *db, PMList *targets)
-{
- /* this is basically just a remove-then-add process. pacman_add() will */
- /* handle it */
- pmo_upgrade = 1;
- return(pacman_add(db, targets));
-}
-
-/* Re-order a list of target packages with respect to their dependencies.
- *
- * Example:
- * A depends on C
- * B depends on A
- * Target order is A,B,C,D
- *
- * Should be re-ordered to C,A,B,D
- *
- * This function returns the new PMList* target list.
- *
- */
-PMList* sortbydeps(PMList *targets)
-{
- PMList *newtargs = NULL;
- PMList *i, *j, *k;
- int change = 1;
- int numscans = 0;
- int numtargs = 0;
- int clean = 0;
-
- /* count the number of targets */
- numtargs = list_count(targets);
-
- while(change) {
- change = 0;
- if(numscans > numtargs) {
- vprint("warning: possible dependency cycle detected\n");
- change = 0;
- continue;
- }
- newtargs = NULL;
- numscans++;
- /* run thru targets, moving up packages as necessary */
- for(i = targets; i; i = i->next) {
- pkginfo_t *p = (pkginfo_t*)i->data;
- for(j = p->depends; j; j = j->next) {
- depend_t dep;
- int found = 0;
- pkginfo_t *q = NULL;
-
- splitdep(j->data, &dep);
- /* look for dep.name -- if it's farther down in the list, then
- * move it up above p
- */
- for(k = i->next; k && !found; k = k->next) {
- q = (pkginfo_t*)k->data;
- if(!strcmp(dep.name, q->name)) {
- found = 1;
- }
- }
- if(found) {
- if(!is_pkgin(q, newtargs)) {
- change = 1;
- newtargs = list_add(newtargs, q);
- }
- }
- }
- if(!is_pkgin(p, newtargs)) {
- newtargs = list_add(newtargs, p);
- }
- }
- if(clean && change) {
- /* free up targets -- it's local now */
- for(i = targets; i; i = i->next) {
- i->data = NULL;
- }
- list_free(targets);
- }
- targets = newtargs;
- clean = 1;
- }
- return(targets);
-}
-
-/* populates *list with packages that need to be installed to satisfy all
- * dependencies (recursive) for *syncpkg->pkg
- *
- * make sure *list and *trail are already initialized
- */
-int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *list, PMList *trail)
-{
- PMList *i, *j, *k;
- PMList *targ = NULL;
- PMList *deps = NULL;
-
- targ = list_new();
- targ = list_add(targ, syncpkg->pkg);
- deps = checkdeps(local, PM_ADD, targ);
- targ->data = NULL;
- list_free(targ);
- for(i = deps; i; i = i->next) {
- int found = 0;
- depmissing_t *miss = (depmissing_t*)i->data;
-
- /* XXX: conflicts are now treated specially in the _add and _sync functions */
-
- /*if(miss->type == CONFLICT) {
- fprintf(stderr, "error: cannot resolve dependencies for \"%s\":\n", miss->target);
- fprintf(stderr, " %s conflicts with %s\n", miss->target, miss->depend.name);
- return(1);
- } else*/
- if(miss->type == DEPEND) {
- syncpkg_t *sync = NULL;
- MALLOC(sync, sizeof(syncpkg_t));
- sync->replaces = NULL;
-
- /* find the package in one of the repositories */
- for(j = databases; !found && j; j = j->next) {
- PMList *provides;
- dbsync_t *dbs = (dbsync_t*)j->data;
- /* check literals */
- for(k = dbs->pkgcache; !found && k; k = k->next) {
- pkginfo_t *pkg = (pkginfo_t*)k->data;
- if(!strcmp(miss->depend.name, pkg->name)) {
- found = 1;
- /* re-fetch the package record with dependency info */
- sync->pkg = db_scan(dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
- sync->dbs = dbs;
- }
- }
- /* check provides */
- if(!found) {
- provides = whatprovides(dbs->db, miss->depend.name);
- if(provides) {
- found = 1;
- /* re-fetch the package record with dependency info */
- sync->pkg = db_scan(dbs->db, provides->data, INFRQ_DESC | INFRQ_DEPENDS);
- sync->dbs = dbs;
- }
- list_free(provides);
- }
- }
- if(!found) {
- fprintf(stderr, "error: cannot resolve dependencies for \"%s\":\n", miss->target);
- fprintf(stderr, " \"%s\" is not in the package set\n", miss->depend.name);
- return(1);
- }
- found = 0;
- for(j = list; j; j = j->next) {
- syncpkg_t *tmp = (syncpkg_t*)j->data;
- if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) {
- found = 1;
- }
- }
- if(found) {
- /* this dep is already in the target list */
- continue;
- }
- vprint("resolving %s\n", sync->pkg->name);
- found = 0;
- for(j = trail; j; j = j->next) {
- syncpkg_t *tmp = (syncpkg_t*)j->data;
- if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) {
- found = 1;
- }
- }
- if(!found) {
- list_add(trail, sync);
- if(resolvedeps(local, databases, sync, list, trail)) {
- return(1);
- }
- vprint("adding %s-%s\n", sync->pkg->name, sync->pkg->version);
- list_add(list, sync);
- } else {
- /* cycle detected -- skip it */
- vprint("dependency cycle detected: %s\n", sync->pkg->name);
- }
- }
- }
- return(0);
-}
-
-/*
- * returns a PMList* of missing_t pointers.
- *
- * conflicts are always name only, but dependencies can include versions
- * with depmod operators.
- *
- */
-PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
-{
- pkginfo_t *info = NULL;
- depend_t depend;
- PMList *i, *j, *k;
- int cmp;
- int found = 0;
- PMList *baddeps = NULL;
- depmissing_t *miss = NULL;
-
- if(op == PM_UPGRADE) {
- /* PM_UPGRADE handles the backwards dependencies, ie, the packages
- * listed in the requiredby field.
- */
- for(i = targets; i; i = i->next) {
- pkginfo_t *tp, *oldpkg;
- if(i->data == NULL) {
- continue;
- }
- tp = (pkginfo_t*)i->data;
-
- if((oldpkg = db_scan(db, tp->name, INFRQ_DESC | INFRQ_DEPENDS)) == NULL) {
- continue;
- }
- for(j = oldpkg->requiredby; j; j = j->next) {
- char *ver;
- pkginfo_t *p;
- found = 0;
- if((p = db_scan(db, j->data, INFRQ_DESC | INFRQ_DEPENDS)) == NULL) {
- /* hmmm... package isn't installed.. */
- continue;
- }
- if(is_pkgin(p, targets)) {
- /* this package is also in the upgrade list, so don't worry about it */
- continue;
- }
- for(k = p->depends; k && !found; k = k->next) {
- /* find the dependency info in p->depends */
- if(splitdep(k->data, &depend)) {
- continue;
- }
- if(!strcmp(depend.name, oldpkg->name)) {
- found = 1;
- }
- }
- if(found == 0) {
- /* look for packages that list depend.name as a "provide" */
- PMList *provides = whatprovides(db, depend.name);
- if(provides == NULL) {
- /* not found */
- continue;
- }
- /* we found an installed package that provides depend.name */
- }
- found = 0;
- if(depend.mod == DEP_ANY) {
- found = 1;
- } else {
- /* note that we use the version from the NEW package in the check */
- ver = strdup(tp->version);
- if(!index(depend.version,'-')) {
- char *ptr;
- for(ptr = ver; *ptr != '-'; ptr++);
- *ptr = '\0';
- }
- cmp = rpmvercmp(ver, depend.version);
- switch(depend.mod) {
- case DEP_EQ: found = (cmp == 0); break;
- case DEP_GE: found = (cmp >= 0); break;
- case DEP_LE: found = (cmp <= 0); break;
- }
- FREE(ver);
- }
- if(!found) {
- MALLOC(miss, sizeof(depmissing_t));
- miss->type = REQUIRED;
- miss->depend.mod = depend.mod;
- strncpy(miss->target, p->name, 256);
- strncpy(miss->depend.name, depend.name, 256);
- strncpy(miss->depend.version, depend.version, 64);
- if(!list_isin(baddeps, miss)) {
- baddeps = list_add(baddeps, miss);
- }
- }
- }
- freepkg(oldpkg);
- }
- }
- if(op == PM_ADD || op == PM_UPGRADE) {
- for(i = targets; i; i = i->next) {
- pkginfo_t *tp;
- if(i->data == NULL) {
- continue;
- }
- tp = (pkginfo_t*)i->data;
-
- /* CONFLICTS */
- for(j = tp->conflicts; j; j = j->next) {
- /* check targets against database */
- for(k = pm_packages; k; k = k->next) {
- pkginfo_t *dp = (pkginfo_t*)k->data;
- if(!strcmp(j->data, dp->name)) {
- MALLOC(miss, sizeof(depmissing_t));
- miss->type = CONFLICT;
- miss->depend.mod = DEP_ANY;
- miss->depend.version[0] = '\0';
- strncpy(miss->target, tp->name, 256);
- strncpy(miss->depend.name, dp->name, 256);
- if(!list_isin(baddeps, miss)) {
- baddeps = list_add(baddeps, miss);
- }
- }
- }
- /* check targets against targets */
- for(k = targets; k; k = k->next) {
- pkginfo_t *a = (pkginfo_t*)k->data;
- if(!strcmp(a->name, (char*)j->data)) {
- MALLOC(miss, sizeof(depmissing_t));
- miss->type = CONFLICT;
- miss->depend.mod = DEP_ANY;
- miss->depend.version[0] = '\0';
- strncpy(miss->target, tp->name, 256);
- strncpy(miss->depend.name, a->name, 256);
- if(!list_isin(baddeps, miss)) {
- baddeps = list_add(baddeps, miss);
- }
- }
- }
- }
- /* check database against targets */
- rewinddir(db->dir);
- while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_DEPENDS)) != NULL) {
- for(j = info->conflicts; j; j = j->next) {
- if(!strcmp((char*)j->data, tp->name)) {
- MALLOC(miss, sizeof(depmissing_t));
- miss->type = CONFLICT;
- miss->depend.mod = DEP_ANY;
- miss->depend.version[0] = '\0';
- strncpy(miss->target, tp->name, 256);
- strncpy(miss->depend.name, info->name, 256);
- if(!list_isin(baddeps, miss)) {
- baddeps = list_add(baddeps, miss);
- }
- }
- }
- }
-
- /* PROVIDES -- check to see if another package already provides what
- * we offer
- */
- /* XXX: disabled -- we allow multiple packages to provide the same thing.
- * list packages in conflicts if they really do conflict.
- for(j = tp->provides; j; j = j->next) {
- PMList *provs = whatprovides(db, j->data);
- for(k = provs; k; k = k->next) {
- if(!strcmp(tp->name, k->data)) {
- // this is the same package -- skip it
- continue;
- }
- // we treat this just like a conflict
- MALLOC(miss, sizeof(depmissing_t));
- miss->type = CONFLICT;
- miss->depend.mod = DEP_ANY;
- miss->depend.version[0] = '\0';
- strncpy(miss->target, tp->name, 256);
- strncpy(miss->depend.name, k->data, 256);
- if(!list_isin(baddeps, miss)) {
- baddeps = list_add(baddeps, miss);
- }
- }
- }*/
-
- /* DEPENDENCIES -- look for unsatisfied dependencies */
- for(j = tp->depends; j; j = j->next) {
- /* split into name/version pairs */
- if(splitdep((char*)j->data, &depend)) {
- logaction(stderr, "warning: invalid dependency in %s", (char*)tp->name);
- continue;
- }
- found = 0;
- /* check database for literal packages */
- for(k = pm_packages; k && !found; k = k->next) {
- pkginfo_t *p = (pkginfo_t*)k->data;
- if(!strcmp(p->name, depend.name)) {
- if(depend.mod == DEP_ANY) {
- /* accept any version */
- found = 1;
- } else {
- char *ver = strdup(p->version);
- /* check for a release in depend.version. if it's
- * missing remove it from p->version as well.
- */
- if(!index(depend.version,'-')) {
- char *ptr;
- for(ptr = ver; *ptr != '-'; ptr++);
- *ptr = '\0';
- }
- cmp = rpmvercmp(ver, depend.version);
- switch(depend.mod) {
- case DEP_EQ: found = (cmp == 0); break;
- case DEP_GE: found = (cmp >= 0); break;
- case DEP_LE: found = (cmp <= 0); break;
- }
- FREE(ver);
- }
- }
- }
- /* check other targets */
- for(k = targets; k && !found; k = k->next) {
- pkginfo_t *p = (pkginfo_t*)k->data;
- /* see if the package names match OR if p provides depend.name */
- if(!strcmp(p->name, depend.name) || is_in(depend.name, p->provides)) {
- if(depend.mod == DEP_ANY) {
- /* accept any version */
- found = 1;
- } else {
- char *ver = strdup(p->version);
- /* check for a release in depend.version. if it's
- * missing remove it from p->version as well.
- */
- if(!index(depend.version,'-')) {
- char *ptr;
- for(ptr = ver; *ptr != '-'; ptr++);
- *ptr = '\0';
- }
- cmp = rpmvercmp(ver, depend.version);
- switch(depend.mod) {
- case DEP_EQ: found = (cmp == 0); break;
- case DEP_GE: found = (cmp >= 0); break;
- case DEP_LE: found = (cmp <= 0); break;
- }
- FREE(ver);
- }
- }
- }
- /* check database for provides matches */
- if(!found){
- k = whatprovides(db, depend.name);
- if(k) {
- /* grab the first one (there should only really be one, anyway) */
- pkginfo_t *p = db_scan(db, k->data, INFRQ_DESC);
- if(p == NULL) {
- /* wtf */
- fprintf(stderr, "data error: %s supposedly provides %s, but it was not found in db\n",
- (char*)k->data, depend.name);
- list_free(k);
- continue;
- }
- if(depend.mod == DEP_ANY) {
- /* accept any version */
- found = 1;
- } else {
- char *ver = strdup(p->version);
- /* check for a release in depend.version. if it's
- * missing remove it from p->version as well.
- */
- if(!index(depend.version,'-')) {
- char *ptr;
- for(ptr = ver; *ptr != '-'; ptr++);
- *ptr = '\0';
- }
- cmp = rpmvercmp(ver, depend.version);
- switch(depend.mod) {
- case DEP_EQ: found = (cmp == 0); break;
- case DEP_GE: found = (cmp >= 0); break;
- case DEP_LE: found = (cmp <= 0); break;
- }
- FREE(ver);
- }
- }
- list_free(k);
- }
- /* else if still not found... */
- if(!found) {
- MALLOC(miss, sizeof(depmissing_t));
- miss->type = DEPEND;
- miss->depend.mod = depend.mod;
- strncpy(miss->target, tp->name, 256);
- strncpy(miss->depend.name, depend.name, 256);
- strncpy(miss->depend.version, depend.version, 64);
- if(!list_isin(baddeps, miss)) {
- baddeps = list_add(baddeps, miss);
- }
- }
- }
- }
- } else if(op == PM_REMOVE) {
- /* check requiredby fields */
- for(i = targets; i; i = i->next) {
- pkginfo_t* tp;
- if(i->data == NULL) {
- continue;
- }
- tp = (pkginfo_t*)i->data;
- for(j = tp->requiredby; j; j = j->next) {
- if(!is_in((char*)j->data, targets)) {
- MALLOC(miss, sizeof(depmissing_t));
- miss->type = REQUIRED;
- miss->depend.mod = DEP_ANY;
- miss->depend.version[0] = '\0';
- strncpy(miss->target, tp->name, 256);
- strncpy(miss->depend.name, (char*)j->data, 256);
- if(!list_isin(baddeps, miss)) {
- baddeps = list_add(baddeps, miss);
- }
- }
- }
- }
- }
-
- return(baddeps);
-}
-
-int splitdep(char *depstr, depend_t *depend)
-{
- char *str = NULL;
- char *ptr = NULL;
-
- str = strdup(depstr);
-
- if((ptr = strstr(str, ">="))) {
- depend->mod = DEP_GE;
- } else if((ptr = strstr(str, "<="))) {
- depend->mod = DEP_LE;
- } else if((ptr = strstr(str, "="))) {
- depend->mod = DEP_EQ;
- } else {
- /* no version specified - accept any */
- depend->mod = DEP_ANY;
- strncpy(depend->name, str, sizeof(depend->name));
- strncpy(depend->version, "", sizeof(depend->version));
- }
-
- if(ptr == NULL) {
- FREE(str);
- return(0);
- }
- *ptr = '\0';
- strncpy(depend->name, str, sizeof(depend->name));
- ptr++;
- if(depend->mod != DEP_EQ) {
- ptr++;
- }
- strncpy(depend->version, ptr, sizeof(depend->version));
- FREE(str);
- return(0);
-}
-
-/* Look for a filename in a pkginfo_t.backup list. If we find it,
- * then we return the md5 hash (parsed from the same line)
- */
-char* needbackup(char* file, PMList *backup)
-{
- PMList *lp;
-
- /* run through the backup list and parse out the md5 hash for our file */
- for(lp = backup; lp; lp = lp->next) {
- char* str = strdup(lp->data);
- char* ptr;
-
- /* tab delimiter */
- ptr = index(str, '\t');
- if(ptr == NULL) {
- FREE(str);
- continue;
- }
- *ptr = '\0';
- ptr++;
- /* now str points to the filename and ptr points to the md5 hash */
- if(!strcmp(file, str)) {
- char *md5 = strdup(ptr);
- FREE(str);
- return(md5);
- }
- FREE(str);
- }
- return(NULL);
-}
-
-/* Parse command-line arguments for each operation
- * op: the operation code requested
- * argc: argc
- * argv: argv
- *
- * Returns: 0 on success, 1 on error
- */
-int parseargs(int op, int argc, char **argv)
-{
- int opt;
- int option_index = 0;
- static struct option opts[] =
- {
- {"add", no_argument, 0, 'A'},
- {"remove", no_argument, 0, 'R'},
- {"upgrade", no_argument, 0, 'U'},
- {"freshen", no_argument, 0, 'F'},
- {"query", no_argument, 0, 'Q'},
- {"sync", no_argument, 0, 'S'},
- {"deptest", no_argument, 0, 'T'},
- {"vertest", no_argument, 0, 'Y'},
- {"resolve", no_argument, 0, 'D'},
- {"root", required_argument, 0, 'r'},
- {"dbpath", required_argument, 0, 'b'},
- {"verbose", no_argument, 0, 'v'},
- {"version", no_argument, 0, 'V'},
- {"help", no_argument, 0, 'h'},
- {"search", no_argument, 0, 's'},
- {"clean", no_argument, 0, 'c'},
- {"force", no_argument, 0, 'f'},
- {"nodeps", no_argument, 0, 'd'},
- {"orphans", no_argument, 0, 'e'},
- {"nosave", no_argument, 0, 'n'},
- {"owns", no_argument, 0, 'o'},
- {"list", no_argument, 0, 'l'},
- {"file", no_argument, 0, 'p'},
- {"info", no_argument, 0, 'i'},
- {"sysupgrade", no_argument, 0, 'u'},
- {"downloadonly", no_argument, 0, 'w'},
- {"refresh", no_argument, 0, 'y'},
- {"cascade", no_argument, 0, 'c'},
- {"groups", no_argument, 0, 'g'},
- {0, 0, 0, 0}
- };
-
- while((opt = getopt_long(argc, argv, "ARUFQSTDYr:b:vhscVfnoldepiuwyg", opts, &option_index))) {
- if(opt < 0) {
- break;
- }
- switch(opt) {
- case 0: break;
- case 'A': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_ADD); break;
- case 'R': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_REMOVE); break;
- case 'U': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); break;
- case 'F': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); pmo_freshen = 1; break;
- case 'Q': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_QUERY); break;
- case 'S': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_SYNC); break;
- case 'T': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); break;
- case 'Y': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); pmo_d_vertest = 1; break;
- case 'D': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); pmo_d_resolve = 1; break;
- case 'h': pmo_help = 1; break;
- case 'V': pmo_version = 1; break;
- case 'b': strcpy(pmo_dbpath, optarg); break;
- case 'c': pmo_s_clean = 1; pmo_r_cascade = 1; break;
- case 'd': pmo_nodeps = 1; break;
- case 'e': pmo_q_orphans = 1; break;
- case 'f': pmo_force = 1; break;
- case 'g': pmo_group = 1; break;
- case 'i': pmo_q_info++; break;
- case 'l': pmo_q_list = 1; break;
- case 'n': pmo_nosave = 1; break;
- case 'p': pmo_q_isfile = 1; break;
- case 'o': pmo_q_owns = 1; break;
- case 'r': if(realpath(optarg, pmo_root) == NULL) {
- perror("bad root path");
- return(1);
- } break;
- case 's': pmo_s_search = 1; break;
- case 'u': pmo_s_upgrade = 1; break;
- case 'v': pmo_verbose = 1; break;
- case 'w': pmo_s_downloadonly = 1; break;
- case 'y': pmo_s_sync = 1; break;
- case '?': return(1);
- default: return(1);
- }
- }
-
- if(pmo_op == 0) {
- fprintf(stderr, "error: only one operation may be used at a time\n\n");
- return(1);
- }
-
- if(pmo_help) {
- usage(pmo_op, (char*)basename(argv[0]));
- return(2);
- }
- if(pmo_version) {
- version();
- return(2);
- }
-
- while(optind < argc) {
- /* add the target to our target array */
- char *s = strdup(argv[optind]);
- pm_targets = list_add(pm_targets, s);
- optind++;
- }
-
- return(0);
-}
-
-int parseconfig(char *configfile)
-{
- FILE *fp = NULL;
- char line[PATH_MAX+1];
- char *ptr = NULL;
- char *key = NULL;
- int linenum = 0;
- char section[256] = "";
- sync_t *sync = NULL;
-
- if((fp = fopen(configfile, "r")) == NULL) {
- perror(configfile);
- return(1);
- }
-
- while(fgets(line, PATH_MAX, fp)) {
- linenum++;
- trim(line);
- if(strlen(line) == 0 || line[0] == '#') {
- continue;
- }
- if(line[0] == '[' && line[strlen(line)-1] == ']') {
- /* new config section */
- ptr = line;
- ptr++;
- strncpy(section, ptr, min(255, strlen(ptr)-1));
- section[min(255, strlen(ptr)-1)] = '\0';
- vprint("config: new section '%s'\n", section);
- if(!strlen(section)) {
- fprintf(stderr, "config: line %d: bad section name\n", linenum);
- return(1);
- }
- if(!strcmp(section, "local")) {
- fprintf(stderr, "config: line %d: %s is reserved and cannot be used as a package tree\n",
- linenum, section);
- return(1);
- }
- if(strcmp(section, "options")) {
- /* start a new sync record */
- MALLOC(sync, sizeof(sync_t));
- sync->treename = strdup(section);
- sync->servers = NULL;
- pmc_syncs = list_add(pmc_syncs, sync);
- }
- } else {
- /* directive */
- if(!strlen(section)) {
- fprintf(stderr, "config: line %d: all directives must belong to a section\n", linenum);
- return(1);
- }
- ptr = line;
- key = strsep(&ptr, "=");
- if(key == NULL) {
- fprintf(stderr, "config: line %d: syntax error\n", linenum);
- return(1);
- }
- trim(key);
- key = strtoupper(key);
- if(ptr == NULL) {
- if(!strcmp(key, "NOPASSIVEFTP")) {
- pmo_nopassiveftp = 1;
- vprint("config: nopassiveftp\n");
- } else if(!strcmp(key, "USESYSLOG")) {
- pmo_usesyslog = 1;
- vprint("config: usesyslog\n");
- } else {
- fprintf(stderr, "config: line %d: syntax error\n", linenum);
- return(1);
- }
- } else {
- trim(ptr);
- if(!strcmp(section, "options")) {
- if(!strcmp(key, "NOUPGRADE")) {
- char *p = ptr;
- char *q;
- while((q = strchr(p, ' '))) {
- *q = '\0';
- pmo_noupgrade = list_add(pmo_noupgrade, strdup(p));
- vprint("config: noupgrade: %s\n", p);
- p = q;
- p++;
- }
- pmo_noupgrade = list_add(pmo_noupgrade, strdup(p));
- vprint("config: noupgrade: %s\n", p);
- } else if(!strcmp(key, "IGNOREPKG")) {
- char *p = ptr;
- char *q;
- while((q = strchr(p, ' '))) {
- *q = '\0';
- pmo_ignorepkg = list_add(pmo_ignorepkg, strdup(p));
- vprint("config: ignorepkg: %s\n", p);
- p = q;
- p++;
- }
- pmo_ignorepkg = list_add(pmo_ignorepkg, strdup(p));
- vprint("config: ignorepkg: %s\n", p);
- } else if(!strcmp(key, "DBPATH")) {
- /* shave off the leading slash, if there is one */
- if(*ptr == '/') {
- ptr++;
- }
- strncpy(pmo_dbpath, ptr, PATH_MAX);
- vprint("config: dbpath: %s\n", pmo_dbpath);
- } else if (!strcmp(key, "LOGFILE")) {
- pmo_logfile = strndup(ptr, PATH_MAX);
- vprint("config: log file: %s\n", pmo_logfile);
- } else {
- fprintf(stderr, "config: line %d: syntax error\n", linenum);
- return(1);
- }
- } else {
- if(!strcmp(key, "SERVER")) {
- /* parse our special url */
- server_t *server;
- char *p;
-
- MALLOC(server, sizeof(server_t));
- server->server = server->path = NULL;
- server->protocol = NULL;
-
- p = strstr(ptr, "://");
- if(p == NULL) {
- fprintf(stderr, "config: line %d: bad server location\n", linenum);
- return(1);
- }
- *p = '\0';
- p++; p++; p++;
- if(p == NULL || *p == '\0') {
- fprintf(stderr, "config: line %d: bad server location\n", linenum);
- return(1);
- }
- server->protocol = strdup(ptr);
- if(!strcmp(server->protocol, "ftp") || !strcmp(server->protocol, "http")) {
- char *slash;
- /* split the url into domain and path */
- slash = strchr(p, '/');
- if(slash == NULL) {
- /* no path included, default to / */
- server->path = strdup("/");
- } else {
- /* add a trailing slash if we need to */
- if(slash[strlen(slash)-1] == '/') {
- server->path = strdup(slash);
- } else {
- MALLOC(server->path, strlen(slash)+2);
- sprintf(server->path, "%s/", slash);
- }
- *slash = '\0';
- }
- server->server = strdup(p);
- } else if(!strcmp(server->protocol, "file")){
- /* add a trailing slash if we need to */
- if(p[strlen(p)-1] == '/') {
- server->path = strdup(p);
- } else {
- MALLOC(server->path, strlen(p)+2);
- sprintf(server->path, "%s/", p);
- }
- } else {
- fprintf(stderr, "config: line %d: protocol %s is not supported\n", linenum, ptr);
- return(1);
- }
- /* add to the list */
- vprint("config: %s: server: %s %s %s\n", section, server->protocol, server->server, server->path);
- sync->servers = list_add(sync->servers, server);
- } else {
- fprintf(stderr, "config: line %d: syntax error\n", linenum);
- return(1);
- }
- }
- line[0] = '\0';
- }
- }
- }
- fclose(fp);
-
- return(0);
-}
-
-/* Display usage/syntax for the specified operation.
- * op: the operation code requested
- * myname: basename(argv[0])
- */
-void usage(int op, char *myname)
-{
- if(op == PM_MAIN) {
- printf("usage: %s {-h --help}\n", myname);
- printf(" %s {-V --version}\n", myname);
- printf(" %s {-A --add} [options] <file>\n", myname);
- printf(" %s {-R --remove} [options] <package>\n", myname);
- printf(" %s {-U --upgrade} [options] <file>\n", myname);
- printf(" %s {-F --freshen} [options] <file>\n", myname);
- printf(" %s {-Q --query} [options] [package]\n", myname);
- printf(" %s {-S --sync} [options] [package]\n", myname);
- printf("\nuse '%s --help' with other options for more syntax\n\n", myname);
- } else {
- if(op == PM_ADD) {
- printf("usage: %s {-A --add} [options] <file>\n", myname);
- printf("options:\n");
- printf(" -d, --nodeps skip dependency checks\n");
- printf(" -f, --force force install, overwrite conflicting files\n");
- } else if(op == PM_REMOVE) {
- printf("usage: %s {-R --remove} [options] <package>\n", myname);
- printf("options:\n");
- printf(" -c, --cascade remove packages and all packages that depend on them\n");
- printf(" -d, --nodeps skip dependency checks\n");
- printf(" -n, --nosave remove configuration files as well\n");
- } else if(op == PM_UPGRADE) {
- if(pmo_freshen) {
- printf("usage: %s {-F --freshen} [options] <file>\n", myname);
- } else {
- printf("usage: %s {-U --upgrade} [options] <file>\n", myname);
- }
- printf("options:\n");
- printf(" -d, --nodeps skip dependency checks\n");
- printf(" -f, --force force install, overwrite conflicting files\n");
- } else if(op == PM_QUERY) {
- printf("usage: %s {-Q --query} [options] [package]\n", myname);
- printf("options:\n");
- printf(" -i, --info view package information\n");
- printf(" -g, --groups view all members of a package group\n");
- printf(" -l, --list list the contents of the queried package\n");
- printf(" -o, --owns <file> query the package that owns <file>\n");
- printf(" -p, --file pacman will query the package file [package] instead of\n");
- printf(" looking in the database\n");
- } else if(op == PM_SYNC) {
- printf("usage: %s {-S --sync} [options] [package]\n", myname);
- printf("options:\n");
- printf(" -c, --clean remove packages from cache directory to free up diskspace\n");
- printf(" -d, --nodeps skip dependency checks\n");
- printf(" -f, --force force install, overwrite conflicting files\n");
- printf(" -g, --groups view all members of a package group\n");
- printf(" -s, --search search sync database for matching strings\n");
- printf(" -u, --sysupgrade upgrade all packages that are out of date\n");
- printf(" -w, --downloadonly download packages, but do not install/upgrade anything\n");
- printf(" -y, --refresh download a fresh package sync database from the server\n");
- }
- printf(" -v, --verbose be verbose\n");
- printf(" -r, --root <path> set an alternate installation root\n");
- printf(" -b, --dbpath <path> set an alternate database location\n");
- }
-}
-
-/* Version
- */
-void version(void)
-{
- printf("\n");
- printf(" .--. Pacman v%s\n", PACVER);
- printf("/ _.-' .-. .-. .-. Copyright (C) 2002-2003 Judd Vinet <jvinet@zeroflux.org>\n");
- printf("\\ '-. '-' '-' '-' \n");
- printf(" '--' This program may be freely redistributed under\n");
- printf(" the terms of the GNU General Public License\n\n");
-}
-
-/* Check verbosity option and, if set, print the
- * string to stdout
- */
-void vprint(char *fmt, ...)
-{
- va_list args;
- if(pmo_verbose) {
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
- fflush(stdout);
- }
-}
-
-/* Output a message to stderr, and (optionally) syslog and/or a logfile */
-void logaction(FILE *fp, char *fmt, ...)
-{
- char msg[1024];
- va_list args;
- va_start(args, fmt);
- vsnprintf(msg, 1024, fmt, args);
- va_end(args);
- if(fp) {
- fprintf(fp, "%s\n", msg);
- fflush(fp);
- }
- if(pmo_usesyslog) {
- syslog(LOG_WARNING, "%s", msg);
- }
- if(logfd) {
- time_t t;
- struct tm *tm;
- t = time(NULL);
- tm = localtime(&t);
-
- fprintf(logfd, "[%02d/%02d/%02d %02d:%02d] %s\n", tm->tm_mon+1, tm->tm_mday,
- tm->tm_year-100, tm->tm_hour, tm->tm_min, msg);
- }
-}
-
-/* Condense a list of strings into one long (space-delimited) string
- */
-char* buildstring(PMList *strlist)
-{
- char* str;
- int size = 1;
- PMList *lp;
-
- for(lp = strlist; lp; lp = lp->next) {
- size += strlen(lp->data) + 1;
- }
- MALLOC(str, size);
- str[0] = '\0';
- for(lp = strlist; lp; lp = lp->next) {
- strcat(str, lp->data);
- strcat(str, " ");
- }
- /* shave off the last space */
- str[strlen(str)-1] = '\0';
-
- return(str);
-}
-
-
-int lckmk(char *file, int retries, unsigned int sleep_secs)
-{
- int fd, count = 0;
-
- while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) {
- if(++count < retries) {
- sleep(sleep_secs);
- } else {
- return(-1);
- }
- }
- return(fd > 0 ? 0 : -1);
-}
-
-int lckrm(char *file)
-{
- return(unlink(file));
-}
-
-void cleanup(int signum)
-{
- PMList *lp;
-
- if(pm_access == READ_WRITE && lckrm(lckfile)) {
- logaction(stderr, "warning: could not remove lock file %s", lckfile);
- }
- if(workfile) {
- /* remove the current file being downloaded (as it's not complete) */
- unlink(workfile);
- FREE(workfile);
- }
- if(pmo_usesyslog) {
- closelog();
- }
- if(logfd) {
- fclose(logfd);
- }
-
- /* free memory */
- for(lp = pmc_syncs; lp; lp = lp->next) {
- sync_t *sync = (sync_t *)lp->data;
- PMList *i;
- for(i = sync->servers; i; i = i->next) {
- server_t *server = (server_t *)i->data;
- FREE(server->protocol);
- FREE(server->server);
- FREE(server->path);
- }
- FREELIST(sync->servers);
- FREE(sync->treename);
- }
- FREELIST(pmc_syncs);
- FREELIST(pmo_noupgrade);
- FREELIST(pmo_ignorepkg);
- FREE(pmo_root);
- FREE(pmo_dbpath);
-
- FREELIST(pm_targets);
-
- /* this is segfaulting... quick fix for now
- FREELISTPKGS(pm_packages);*/
-
- exit(signum);
-}
-
-/* vim: set ts=2 sw=2 noet: */
diff --git a/src/pacman.h b/src/pacman.h
index 4f64519d..9c693a69 100644
--- a/src/pacman.h
+++ b/src/pacman.h
@@ -22,7 +22,7 @@
#define _PAC_PACMAN_H
#ifndef PACVER
-#define PACVER "2.7.3"
+#define PACVER "2.7.4"
#endif
#ifndef PKGDIR