Imported from pacman-2.1.tar.gz

This commit is contained in:
Judd Vinet 2002-09-16 05:22:13 +00:00
parent 62a783a6bd
commit 6a654187b6
20 changed files with 951 additions and 425 deletions

View file

@ -34,7 +34,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
PACVER = 2.0
PACVER = 2.1
LIBTAR_VERSION = 1.2.5
TOPDIR = @srcdir@
@ -105,11 +105,13 @@ install: pacman convertdb man
$(INSTALL) -D -m0755 $(SCRDIR)makepkg $(DESTDIR)$(BINDIR)/makepkg
$(INSTALL) -D -m0755 $(SCRDIR)makeworld $(DESTDIR)$(BINDIR)/makeworld
$(INSTALL) -D -m0755 $(SCRDIR)abs $(DESTDIR)$(BINDIR)/abs
$(INSTALL) -D -m0755 $(SCRDIR)gensync $(DESTDIR)$(BINDIR)/gensync
$(INSTALL) -D -m0644 $(MANSRC)pacman.8 $(DESTDIR)$(MANDIR)/man8/pacman.8
$(INSTALL) -D -m0644 $(MANSRC)makepkg.8 $(DESTDIR)$(MANDIR)/man8/makepkg.8
$(INSTALL) -D -m0644 etc/pacman.conf $(DESTDIR)/etc/pacman.conf
$(INSTALL) -D -m0644 etc/makepkg.conf $(DESTDIR)/etc/makepkg.conf
$(INSTALL) -D -m0644 etc/supfile $(DESTDIR)/etc/abs/supfile
$(INSTALL) -D -m0644 etc/supfile.arch $(DESTDIR)/etc/abs/supfile.arch
$(INSTALL) -D -m0644 etc/supfile.unofficial $(DESTDIR)/etc/abs/supfile.unofficial
clean:
rm -f *~ $(OBJDIR)*.o $(MANSRC)*.8

17
TODO
View file

@ -1,7 +1,14 @@
- have "group" designations
- use 'set -e' in makepkg?
- if a package fails, ask before aborting the full operation
- ask, then remove conflicting packages with --sync
- use a provides tag (instead of an OR operator in depends)
- add a freshen operation
- add a 'cascade' option to --remove that will remove a package and
all requiredby packages under it
- check $PACCONF env var
- ftp transfer progress bar breaks after ~42000 K
- use a 'trust pacman' config option for downgrading?
- use a provides tag (instead of an OR operator in depends)
- instead of 'conflicts' use a ! operator in depends
- add a --pretend option
- add a consistency/sanity check operation
@ -11,12 +18,10 @@
- use package caches more for performance
+ add an "ignore package" option in either pacman.conf or in each package
record. this will prevent it from being upgraded from the sync set
- if a package is removed with --nodeps and re-installed, the requiredby
fields of it's required packages are not updated
- duplicate dep checks occur with sync (one in sync, one in add)
- clean up output a bit (message queue?)
- add an OR operator to dependencies or allow a sibling tag (ie, mawk, gawk)
- run ldd on every executable in a newly built package to find required so's
- add a freshen operation
- allow multiple ftp servers to be defined and fallback to backups on failure
- use a files.cache gdbm (or whatever) for --owns and db_find_conflicts
- things like 'groupadd' and 'useradd' in the install scriptlets will affect
the real root, not the one specified with -r

View file

@ -1,4 +1,4 @@
.TH pacman 8 "July 18, 2002" "pacman #VERSION#" ""
.TH pacman 8 "August 18, 2002" "pacman #VERSION#" ""
.SH NAME
pacman \- package manager utility
.SH SYNOPSIS
@ -149,21 +149,55 @@ All three files are different. So we install the new file, but back up the
old one to a .pacsave extension. This way the user can move the old configuration
file back into place if he wishes.
.SH CONFIGURATION
pacman will attempt to read \fI/etc/pacman.conf\fP each time it is invoked. Currently
the only options in it are for the --sync operation, but more may be added later.
pacman will attempt to read \fI/etc/pacman.conf\fP each time it is invoked. This
configuration file is divided into sections or \fIrepositories\fP. Each section
defines a package repository that pacman can use when searching for packages in
--sync mode. The exception to this is the \fIoptions\fP section, which defines
global options.
.TP
.B "Sync_Tree_Name"
Sets the name of the package set you wish to follow. The common choices are \fIcurrent\fP
and \fIstable\fP. You could also specify a specific package version, eg, 0.3.
.TP
.B "Sync_Server"
This is the hostname of the ftp server that will be used for downloading lists and
packages. eg, \fIftp.ibiblio.org\fP.
.TP
.B "Sync_Tree_Path"
This is the full path name (on the ftp server) to the package tree you are following.
So if you are following \fIcurrent\fP, on \fIftp.ibiblio.org\fP, you would use
\fI/pub/linux/distributions/archlinux/current\fP.
.SH Example:
.RS
.nf
[options]
NoUpgrade = etc/passed etc/group etc/shadow
NoUpgrade = etc/fstab
[current]
Server = ftp://ftp.server.org/linux/archlinux/current
Server = ftp://ftp.mirror.com/arch/current
[custom]
Server = local:///home/pkgs
.fi
.RE
All files listed with a \fINoUpgrade\fP directive will never be touched during a package
install/upgrade. This directive is only valid in the options section.
Each repository section defines a section name and at least one location where the packages
can be found. The section name is defined by the string within square brackets (eg, the two
above are 'current' and 'custom'). Locations are defined with the \fIServer\fP directive and
follow a URL naming structure. Currently only ftp is supported for remote servers. If you
want to use a local directory, you can specify the full path with a 'local://' prefix, as
shown above.
.SH USING YOUR OWN REPOSITORY
Let's say you have a bunch of custom packages in \fI/home/pkgs\fP and their respective PKGBUILD
files are all in \fI/usr/abs/local\fP. All you need to do is generate a compressed package database
in the \fI/home/pkgs\fP directory so pacman can find it when run with --refresh.
.RS
.nf
# gensync /usr/abs/local /home/pkgs/custom.db.tar.gz
.fi
.RE
The above command will read all PKGBUILD files in /usr/abs/local and generate a compressed
database called /home/pkgs/custom.db.tar.gz. Note that the database must be of the form
\fI{treename}.db.tar.gz\fP, where {treename} is the name of the section defined in the
configuration file.
That's it! Now configure your \fIcustom\fP section in the configuration file as shown in the
config example above. Pacman will now use your package repository. If you add new packages to
the repository, remember to re-generate the database and use pacman's --refresh option.
.SH SEE ALSO
\fBmakepkg\fP is the package-building tool that comes with pacman.
.SH AUTHOR

View file

@ -2,34 +2,78 @@
# /etc/pacman.conf
#
# name of the tree you want to follow (eg: stable, current, 0.2, 0.3, ...)
Sync_Tree_Name = current
# Currently the only option directive is NoUpgrade. Use this with a
# space-delimited list of files that should never be touched by pacman
# during an install/upgrade. (note: do not include the leading slash)
[options]
NoUpgrade = etc/passwd etc/group etc/shadow
NoUpgrade = etc/fstab
# ftp server
Sync_Server = ftp.ibiblio.org
[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://gd.tuwien.ac.at/opsys/linux/archlinux/current
Server = ftp://ftp2.archlinux.org/current
Server = ftp://ftp3.archlinux.org/current
Server = ftp://ftp.archlinux.org/current
# full path to sync tree
Sync_Tree_Path = /pub/linux/distributions/archlinux/current
# Uncomment this block to access the 'unofficial' package set
#
#[unofficial]
#Server = ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/unofficial
#Server = ftp://ftp.mpi-sb.mpg.de/pub/linux/mirror/ftp.ibiblio.org/pub/Linux/distributions/archlinux/unofficial
#Server = ftp://ftp.oit.unc.edu/pub/Linux/distributions/archlinux/unofficial
#Server = ftp://ftp.tu-chemnitz.de/pub/linux/sunsite.unc-mirror/distributions/archlinux/unofficial
#Server = ftp://gd.tuwien.ac.at/opsys/linux/archlinux/unofficial
#Server = ftp://ftp2.archlinux.org/unofficial
#Server = ftp://ftp3.archlinux.org/unofficial
#Server = ftp://ftp.archlinux.org/unofficial
###
### MIRRORS
#########################
# If you use the 'stable' tree, you should disable the 'current'
# tree to avoid conflicts
#
#[stable]
#Server = ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/stable
#Server = ftp://ftp.mpi-sb.mpg.de/pub/linux/mirror/ftp.ibiblio.org/pub/Linux/distributions/archlinux/stable
#Server = ftp://ftp.oit.unc.edu/pub/Linux/distributions/archlinux/stable
#Server = ftp://ftp.tu-chemnitz.de/pub/linux/sunsite.unc-mirror/distributions/archlinux/stable
#Server = ftp://ftp.archlinux.org/stable
#Server = ftp://ftp.oit.unc.edu/pub/Linux/distributions/archlinux/stable
#Server = ftp://ftp2.archlinux.org/stable
#Server = ftp://ftp3.archlinux.org/stable
# Sync_Server = ftp.mpi-sb.mpg.de
# Sync_Tree_Path = /pub/linux/mirror/ftp.ibiblio.org/pub/Linux/distributions/archlinux/current
# Sync_Server = ftp2.archlinux.org
# Sync_Tree_Path = /current
# Sync_Server = ftp.oit.unc.edu
# Sync_Tree_Path = /pub/Linux/distributions/archlinux/current
# Sync_Server = ftp.tu-chemnitz.de
# Sync_Tree_Path = /pub/linux/sunsite.unc-mirror/distributions/archlinux/current
# Sync_Server = ftp.archlinux.org
# Sync_Tree_Path = /current
# Sync_Server = ftp.oit.unc.edu
# Sync_Tree_Path = /pub/Linux/distributions/archlinux/current
# This is a typical setup for a local package repository. To have pacman
# resolve dependencies and install your custom packages with the --sync
# operation, you must generate a sync db from your custom PKGBUILDs and
# place it in the directory specified by the Server directive.
#
# # gensync /usr/abs/local /home/custompkgs/custom.db.tar.gz
#
# The sync database must be of the form {treename}.db.gz, where treename
# is the name of the package tree (in this case, 'custom').
#
# Then you can activate this custom repository by uncommenting the last
# two lines and using pacman as usual:
#
# # pacman -S --refresh
# :: Synchronizing package databases...
# current.db.tar.gz [#################################] 100% | 20K
# custom.db.tar.gz [/home/custompkgs/ ] 100% | LOCAL
#
# # pacman -S my_custom_pkg
#
# Targets: my_custom_pkg-0.12-1
#
# Do you want to install/upgrade these packages? [Y/n]
#
# :: Retrieving packages from custom...
# my_custom_pkg-0.12-1.pkg [/home/custompkgs/ ] 100% | LOCAL
#
# checking for conflicts... done.
# installing my_custom_pkg... done.
#
#[custom]
#Server = local:///home/custompkgs

View file

@ -3,7 +3,7 @@
#
# this is the host containing the master ABS files
*default host=archlinux.org
*default host=cvs.archlinux.org
*default base=/usr/abs
*default prefix=/usr/abs
@ -20,4 +20,4 @@
#
*default tag=CURRENT
abs
arch

16
etc/supfile.unofficial Normal file
View file

@ -0,0 +1,16 @@
#
# /etc/abs/supfile.unofficial
#
# this is the host containing the unofficial PKGBUILD files
*default host=unofficial.archlinux.org
*default base=/usr/abs
*default prefix=/usr/abs
*default release=cvs
*default delete
*default use-rel-suffix
*default compress
*default tag=CURRENT
unofficial

View file

@ -1,6 +1,6 @@
#!/bin/bash
myver='2.0'
myver='2.1'
ABS_ROOT=/usr/abs
usage() {
@ -9,7 +9,7 @@ usage() {
echo
echo "abs will synchronize PKGBUILD scripts from the CVS repository"
echo "into /usr/abs. You can follow different package trees by editing"
echo "/etc/abs/supfile"
echo "/etc/abs/supfile.arch"
echo
exit 0
}
@ -25,17 +25,14 @@ update() {
exit 1
fi
if [ ! -r /etc/abs/supfile ]; then
echo "abs: missing config file /etc/abs/supfile"
exit 1
fi
if [ "`id -u`" != "0" ]; then
echo "abs: you must be root to update your ABS tree"
exit 1
fi
cd $ABS_ROOT && cvsup -L 1 -r 0 -g -c .sup /etc/abs/supfile
for sup in `find /etc/abs -name "supfile.*"`; do
cd $ABS_ROOT && cvsup -L 1 -r 0 -g -c .sup $sup
done
}
for opt in "$@"; do

104
scripts/gensync Executable file
View file

@ -0,0 +1,104 @@
#!/bin/bash
myver='2.1'
usage() {
echo "gensync $myver"
echo "usage: $0 <root> <destfile>"
echo
echo "gensync will generate a sync database by reading all PKGBUILD files"
echo "from <root>. gensync builds the database in /tmp/.gensync and then"
echo "compresses it to <destfile>."
echo
echo "note: The <destfile> name is important. It must be of the form"
echo " {treename}.db.tar.gz where {treename} is the name of the custom"
echo " package repository you configured in /etc/pacman.conf. The"
echo " generated database must reside in the same directory as your"
echo " custom packages (also configured in /etc/pacman.conf)"
echo
echo "example: gensync /usr/abs/local /home/mypkgs/custom.db.tar.gz"
echo
echo
exit 0
}
db_write_entry()
{
unset pkgname pkgver pkgrel
unset depends conflicts
source $1 || return 1
cd /tmp/.gensync
mkdir $pkgname-$pkgver-$pkgrel
cd $pkgname-$pkgver-$pkgrel
# desc
echo "%NAME%" >desc
echo "$pkgname" >>desc
echo "" >>desc
echo "%VERSION%" >>desc
echo "$pkgver-$pkgrel" >>desc
echo "" >>desc
echo "%DESC%" >>desc
echo "$pkgdesc" >>desc
echo "" >>desc
# depends
echo "%DEPENDS%" >depends
for depend in "${depends[@]}"; do
echo "$depend" >>depends
done
echo "" >>depends
echo "%CONFLICTS%" >>depends
for conflict in "${conflicts[@]}"; do
echo "$conflict" >>depends
done
echo "" >>depends
}
if [ $# -lt 2 ]; then
usage
exit 0
fi
if [ "$1" = "-h" -o "$1" = "--help" ]; then
usage
exit 0
fi
d=`dirname $1`
rootdir=`cd $d && pwd`
rootdir="$rootdir/`basename $1`"
d=`dirname $2`
destfile=`cd $d && pwd`
destfile="$destfile/`basename $2`"
rm -rf /tmp/.gensync || exit 1
mkdir -p /tmp/.gensync || exit 1
if [ ! -d $rootdir ]; then
echo "gensync: invalid root dir: $rootdir" >&2
rm -rf /tmp/.gensync
exit 1
fi
echo "gensync: building database entries..." >&2
#for category in `find $rootdir/* -type d -maxdepth 0`; do
for file in `find $rootdir/* -name PKGBUILD`; do
db_write_entry $file
if [ $? -gt 0 ]; then
echo "gensync: error writing entry for $file" >&2
rm -rf /tmp/.gensync
exit 1
fi
done
echo "gensync: compressing to $destfile..." >&2
cd /tmp/.gensync
tar c * | gzip -9 >$destfile
if [ $? -gt 0 ]; then
echo "gensync: error writing to $destfile" >&2
rm -rf /tmp/.gensync
exit 1
fi
rm -rf /tmp/.gensync
exit 0

View file

@ -1,6 +1,6 @@
#!/bin/bash
myver='2.0'
myver='2.1'
startdir=`pwd`
[ -f /etc/makepkg.conf ] && source /etc/makepkg.conf
@ -30,21 +30,26 @@ fi
CLEANUP=0
INSTALL=0
BUILDSCRIPT="./PKGBUILD"
if [ "$1" = "-c" -o "$1" = "--clean" ]; then
shift
for arg in $*; do
case $arg in
-c|--clean)
CLEANUP=1
fi
if [ "$1" = "-i" -o "$1" = "--install" ]; then
shift
;;
-i|--install)
INSTALL=1
fi
;;
*)
BUILDSCRIPT=$arg
;;
esac
done
unset pkgname pkgver pkgrel pkgdesc
unset depends conflicts backup source install build
umask 0022
# check for a download utility
if [ -x /usr/bin/wget ]; then
ftpagent="/usr/bin/wget --passive-ftp --tries=3 --waitretry=3"
@ -57,11 +62,6 @@ else
exit 1
fi
BUILDSCRIPT="./PKGBUILD"
if [ "$1" != "" ]; then
BUILDSCRIPT=$1
fi
if [ ! -f $BUILDSCRIPT ]; then
msg "==> ERROR: $BUILDSCRIPT does not exist."
exit 1
@ -147,8 +147,8 @@ for netfile in ${source[@]}; do
cmd="tar -xf $file" ;;
*.zip)
cmd="unzip -qq $file" ;;
*)
cmd="cp ../$file ." ;;
*.gz)
cmd="gunzip $file" ;;
esac
msg "==> $cmd"
$cmd

View file

@ -1,9 +1,9 @@
#!/bin/bash
toplevel=`pwd`
version="2.0"
version="2.1"
if [ $# -lt 2 -o "$1" = "--help" -o "$1" = "-h" ]; then
usage() {
echo "makeworld version $version"
echo "usage: $0 [options] <destdir> <category> [category] ..."
echo "options:"
@ -11,25 +11,42 @@ if [ $# -lt 2 -o "$1" = "--help" -o "$1" = "-h" ]; then
echo " -i, --install Install package after successful build"
echo " -h, --help This help"
echo
echo " where <category> is one or more of base, opt, contrib"
echo " eg: makeworld /packages base opt"
echo " where <category> is one or more directory names under the ABS root"
echo " eg: makeworld -c /packages base lib editors"
echo
echo " this should be run from the toplevel directory of ABS (usually /usr/abs)"
}
if [ $# -lt 2 -o "$1" = "--help" -o "$1" = "-h" ]; then
usage
exit 1
fi
MAKEPKG_OPTS=
if [ "$1" = "-c" -o "$1" = "--clean" ]; then
shift
for arg in $*; do
case $arg in
-c|--clean)
MAKEPKG_OPTS="$MAKEPKG_OPTS -c"
fi
if [ "$1" = "-i" -o "$1" = "--install" ]; then
shift
;;
-i|--install)
MAKEPKG_OPTS="$MAKEPKG_OPTS -i"
fi
dest=$1
;;
*)
dest=$arg
shift
break
;;
esac
shift
if [ "$dest" != "" ]; then
break;
fi
done
if [ "$dest" = "" ]; then
usage
exit 1
fi
sd=`date +"[%b %d %H:%M]"`

View file

@ -1,6 +1,6 @@
#!/bin/sh
echo
echo "Pacman 2.0 no longer comes with pacsync. Use 'pacman -S' instead."
echo "Pacman 2.0+ no longer comes with pacsync. Use 'pacman -S' instead."
echo " (see 'pacman -S --help' or the manpage for syntax)"
echo

View file

@ -31,6 +31,7 @@
#include "package.h"
#include "db.h"
#include "util.h"
#include "pacsync.h"
#include "pacman.h"
extern PMList *pm_packages;

View file

@ -93,6 +93,18 @@ int list_count(PMList *list)
return(i);
}
int list_isin(PMList *haystack, void *needle)
{
PMList *lp;
for(lp = haystack; lp; lp = lp->next) {
if(lp->data == needle) {
return(1);
}
}
return(0);
}
/* List one is extended and returned
* List two is freed (but not its data)
*/

View file

@ -12,6 +12,7 @@ PMList* list_new();
void list_free(PMList* list);
PMList* list_add(PMList* list, void* data);
int list_count(PMList* list);
int list_isin(PMList *haystack, void *needle);
PMList* list_merge(PMList *one, PMList *two);
PMList* list_last(PMList* list);

View file

@ -30,6 +30,7 @@
#include "package.h"
#include "db.h"
#include "util.h"
#include "pacsync.h"
#include "pacman.h"
extern tartype_t gztype;

View file

@ -72,25 +72,24 @@ unsigned short pmo_s_upgrade = 0;
unsigned short pmo_s_sync = 0;
unsigned short pmo_s_search = 0;
unsigned short pmo_s_clean = 0;
PMList *pmo_noupgrade = NULL;
/* configuration options */
char pmc_syncserver[512] = "";
char pmc_syncpath[512] = "";
char pmc_syncname[512] = "";
char *lckfile = "/tmp/pacman.lck";
/* 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;
char *lckfile = "/tmp/pacman.lck";
int main(int argc, char *argv[])
{
int ret = 0;
char *ptr = NULL;
char *dbpath = NULL;
char path[PATH_MAX];
pacdb_t *db_local = NULL;
PMList *lp;
@ -141,6 +140,12 @@ int main(int argc, char *argv[])
signal(SIGINT, cleanup);
signal(SIGTERM, cleanup);
/* parse the system-wide config file */
snprintf(path, PATH_MAX, "/%s", PACCONF);
if(parseconfig(path)) {
cleanup(1);
}
/* check for db existence */
/* add a trailing '/' if there isn't one */
if(pmo_root[strlen(pmo_root)-1] != '/') {
@ -249,37 +254,18 @@ int pacman_deptest(pacdb_t *db, PMList *targets)
int pacman_sync(pacdb_t *db, PMList *targets)
{
char url[1024];
char *dbpath = NULL;
char dbpath[PATH_MAX];
int allgood = 1, confirm = 0;
pacdb_t *db_sync = NULL;
PMList *pkgcache = NULL;
PMList *i, *j;
int cols;
PMList *i, *j, *k;
PMList *final = NULL;
PMList *trail = NULL;
PMList *deps = NULL;
int cols;
PMList *databases = NULL;
/* parse the system-wide config file */
snprintf(url, 511, "/%s", PACCONF);
if(parseconfig(url)) {
if(!list_count(pmc_syncs)) {
fprintf(stderr, "error: no usable package repositories configured.\n");
return(1);
}
if(!strlen(pmc_syncserver)) {
fprintf(stderr, "error: no Sync_Server specified in %s\n", url);
return(1);
}
if(!strlen(pmc_syncname)) {
fprintf(stderr, "error: no Sync_Tree_Name specified in %s\n", url);
return(1);
}
if(!strlen(pmc_syncpath)) {
fprintf(stderr, "error: no Sync_Tree_Path specified in %s\n", url);
return(1);
}
if(pmc_syncpath[0] != '/') {
sprintf(pmc_syncpath, "/%s", pmc_syncpath);
}
if(pmo_s_clean) {
mode_t oldmask;
@ -303,38 +289,44 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(pmo_s_sync && !pmo_s_search) {
/* grab a fresh package list */
printf(":: Synchronizing remote package tree... \n");
printf(":: Synchronizing package databases... \n");
sync_synctree();
printf("\n");
}
/* open the sync db */
MALLOC(dbpath, PATH_MAX);
snprintf(dbpath, PATH_MAX-1, "%s%s", pmo_root, PKGDIR);
db_sync = db_open(dbpath, pmc_syncname);
/* 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;
snprintf(dbpath, PATH_MAX, "%s%s", pmo_root, PKGDIR);
db_sync = db_open(dbpath, sync->treename);
if(db_sync == NULL) {
fprintf(stderr, "error: could not open the sync database.\n");
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 */
pkgcache = db_loadpkgs(db_sync, pkgcache);
if(db_sync == NULL) {
fprintf(stderr, "error: could not open sync database (%s/%s)\n", dbpath, pmc_syncname);
return(1);
dbs->pkgcache = NULL;
dbs->pkgcache = db_loadpkgs(db_sync, dbs->pkgcache);
databases = list_add(databases, dbs);
}
final = list_new();
trail = list_new();
if(pmo_s_search) {
/* search sync db */
/* search sync databases */
for(i = targets; i; i = i->next) {
char *targ = strdup(i->data);
strtoupper(targ);
for(j = pkgcache; j; j = j->next) {
pkginfo_t *pkg = (pkginfo_t*)j->data;
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);
@ -352,6 +344,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
FREE(haystack);
}
}
FREE(targ);
}
} else if(pmo_s_upgrade) {
@ -359,18 +352,18 @@ int pacman_sync(pacdb_t *db, PMList *targets)
for(i = pm_packages; i && allgood; i = i->next) {
int cmp, found = 0;
pkginfo_t *local = (pkginfo_t*)i->data;
pkginfo_t *sync = NULL;
syncpkg_t *sync = NULL;
MALLOC(sync, sizeof(syncpkg_t));
for(j = pkgcache; !found && j; j = j->next) {
sync = (pkginfo_t*)j->data;
if(local == NULL || local->name == NULL) {
vprint("local is NULL!\n");
}
if(sync == NULL || sync->name == NULL) {
vprint("sync is NULL!\n");
}
if(!strcmp(local->name, sync->name)) {
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) {
@ -378,7 +371,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
continue;
}
/* compare versions and see if we need to upgrade */
cmp = rpmvercmp(local->version, sync->version);
cmp = rpmvercmp(local->version, sync->pkg->version);
if(cmp > 0) {
/* local version is newer */
fprintf(stderr, ":: %s-%s: local version is newer\n",
@ -390,12 +383,12 @@ int pacman_sync(pacdb_t *db, PMList *targets)
continue;
} else {
/* re-fetch the package record with dependency info */
sync = db_scan(db_sync, sync->name, INFRQ_DESC | INFRQ_DEPENDS);
sync->pkg = db_scan(sync->dbs->db, sync->pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
/* add to the targets list */
if(!is_pkgin(sync, final)) {
allgood = !resolvedeps(db, db_sync, sync, final, trail);
if(!list_isin(final, sync)) {
allgood = !resolvedeps(db, databases, sync, final, trail);
/* check again, as resolvedeps could have added our target for us */
if(!is_pkgin(sync, final)) {
if(!list_isin(final, sync)) {
final = list_add(final, sync);
}
}
@ -408,19 +401,35 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* process targets */
for(i = targets; i && allgood; i = i->next) {
if(i->data) {
int cmp;
int cmp, found = 0;
pkginfo_t *local;
pkginfo_t *sync;
syncpkg_t *sync = NULL;
MALLOC(sync, sizeof(syncpkg_t));
local = db_scan(db, (char*)i->data, INFRQ_DESC);
sync = db_scan(db_sync, (char*)i->data, INFRQ_DESC | INFRQ_DEPENDS);
if(sync == NULL) {
fprintf(stderr, ":: %s: not found in sync db\n", (char*)i->data);
//sync = db_scan(db_sync, (char*)i->data, INFRQ_DESC | INFRQ_DEPENDS);
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((char*)i->data, pkg->name)) {
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) {
fprintf(stderr, "%s: not found in sync db\n", (char*)i->data);
continue;
}
if(local) {
/* this is an upgrade, compare versions and determine if it is necessary */
cmp = rpmvercmp(local->version, sync->version);
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)) {
@ -434,10 +443,24 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
}
/* add to targets list */
if(!is_pkgin(sync, final)) {
allgood = !resolvedeps(db, db_sync, sync, final, trail);
found = 0;
for(j = final; j; j = j->next) {
syncpkg_t *tmp = (syncpkg_t*)j->data;
if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) {
found = 1;
}
}
if(!found) {
allgood = !resolvedeps(db, databases, sync, final, trail);
/* check again, as resolvedeps could have added our target for us */
if(!is_pkgin(sync, final)) {
found = 0;
for(j = final; j; j = j->next) {
syncpkg_t *tmp = (syncpkg_t*)j->data;
if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) {
found = 1;
}
}
if(!found) {
final = list_add(final, sync);
}
}
@ -447,7 +470,16 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(allgood) {
/* check for inter-conflicts and whatnot */
deps = checkdeps(db, PM_UPGRADE, final);
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) {
fprintf(stderr, "error: unresolvable conflicts/dependencies:\n");
for(i = deps; i; i = i->next) {
@ -474,6 +506,12 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* abort mission */
allgood = 0;
}
/* cleanup */
for(i = list; i; i = i->next) {
i->data = NULL;
}
list_free(list);
list = NULL;
/* list targets */
if(final && final->data) {
@ -481,18 +519,18 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
cols = 9;
for(i = final; allgood && i; i = i->next) {
pkginfo_t *p = (pkginfo_t*)i->data;
if(p) {
syncpkg_t *s = (syncpkg_t*)i->data;
if(s && s->pkg) {
char t[PATH_MAX];
int s;
snprintf(t, PATH_MAX, "%s-%s ", p->name, p->version);
s = strlen(t);
if(s+cols > 78) {
int len;
snprintf(t, PATH_MAX, "%s-%s ", s->pkg->name, s->pkg->version);
len = strlen(t);
if(len+cols > 78) {
cols = 9;
fprintf(stderr, "\n%9s", " ");
}
fprintf(stderr, "%s", t);
cols += s;
cols += len;
}
}
printf("\n");
@ -504,24 +542,41 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
}
if(allgood && confirm) {
PMList *files = NULL;
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;
/* download targets */
/* 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) {
pkginfo_t *p = (pkginfo_t*)i->data;
if(p) {
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, "%svar/cache/pacman/pkg/%s-%s.pkg.tar.gz",
pmo_root, p->name, p->version);
pmo_root, 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", p->name, p->version);
snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version);
files = list_add(files, strdup(path));
} else {
count++;
}
}
}
@ -530,7 +585,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(files) {
struct stat buf;
printf("\n:: Downloading packages...\n"); fflush(stdout);
printf("\n:: Retrieving packages from %s...\n", current->treename);
fflush(stdout);
if(stat(ldir, &buf)) {
mode_t oldmask;
char parent[PATH_MAX];
@ -539,7 +595,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
snprintf(parent, PATH_MAX, "%svar/cache/pacman", pmo_root);
fprintf(stderr, "warning: no %s cache exists. creating...\n", ldir);
oldmask = umask(0000);
if(mkdir(parent, 0755) || mkdir(ldir, 0755)) {
mkdir(parent, 0755);
if(mkdir(ldir, 0755)) {
/* couldn't mkdir the cache directory, so fall back to /tmp and unlink
* the package afterwards.
*/
@ -549,21 +606,32 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
umask(oldmask);
}
if(downloadfiles(pmc_syncserver, pmc_syncpath, ldir, files)) {
fprintf(stderr, "error: ftp transfer failed.\n");
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);
list_free(files);
files = NULL;
}
if(count == list_count(final)) {
done = 1;
}
}
printf("\n");
/* double-check */
if(files) {
list_free(files);
files = NULL;
}
/* install targets */
for(i = final; allgood && i; i = i->next) {
char *str;
pkginfo_t *p = (pkginfo_t*)i->data;
if(p) {
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, p->name, p->version);
snprintf(str, PATH_MAX, "%s/%s-%s.pkg.tar.gz", ldir, sync->pkg->name, sync->pkg->version);
files = list_add(files, str);
}
}
@ -580,22 +648,26 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
/* cleanup */
for(i = pkgcache; i; i = i->next) {
if(i->data) freepkg((pkginfo_t*)i->data);
i->data = NULL;
}
for(i = final; i; i = i->next) {
if(i->data) freepkg((pkginfo_t*)i->data);
syncpkg_t *sync = (syncpkg_t*)i->data;
if(sync) freepkg(sync->pkg);
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;
}
list_free(pkgcache);
for(i = databases; i; i = i->next) {
dbsync_t *dbs = (dbsync_t*)i->data;
db_close(dbs->db);
list_free(dbs->pkgcache);
free(dbs);
i->data = NULL;
}
list_free(databases);
list_free(final);
list_free(trail);
db_close(db_sync);
return(!allgood);
}
@ -726,6 +798,7 @@ int pacman_add(pacdb_t *db, PMList *targets)
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);
@ -746,6 +819,9 @@ int pacman_add(pacdb_t *db, PMList *targets)
if(!stat(expath, &buf) && !S_ISDIR(buf.st_mode)) {
/* file already exists */
if(is_in(pathname, pmo_noupgrade)) {
notouch = 1;
} else {
if(!pmo_upgrade) {
nb = is_in(pathname, info->backup);
} else {
@ -756,6 +832,7 @@ int pacman_add(pacdb_t *db, PMList *targets)
}
}
}
}
if(nb) {
char *temp;
@ -857,7 +934,14 @@ int pacman_add(pacdb_t *db, PMList *targets)
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);
fprintf(stderr, "warning: extracting %s%s as %s\n", pmo_root, pathname, expath);
/*tar_skip_regfile(tar);*/
}
if(tar_extract_file(tar, expath)) {
fprintf(stderr, "could not extract %s: %s\n", pathname, strerror(errno));
errors++;
@ -1026,6 +1110,12 @@ int pacman_remove(pacdb_t *db, PMList *targets)
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);
@ -1312,31 +1402,53 @@ int pacman_upgrade(pacdb_t *db, PMList *targets)
}
/* populates *list with packages that need to be installed to satisfy all
* dependencies (recursive) for *package
* dependencies (recursive) for *syncpkg->pkg
*
* make sure *list and *trail are already initialized
*/
int resolvedeps(pacdb_t *local, pacdb_t *sync, pkginfo_t *package, PMList *list, PMList *trail)
int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *list, PMList *trail)
{
pkginfo_t *info;
PMList *i;
PMList *i, *j, *k;
PMList *targ = NULL;
PMList *deps = NULL;
targ = list_new();
targ = list_add(targ, package);
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;
syncpkg_t *sync = NULL;
depmissing_t *miss = (depmissing_t*)i->data;
info = db_scan(sync, miss->depend.name, INFRQ_DESC | INFRQ_DEPENDS);
if(info == NULL) {
MALLOC(sync, sizeof(syncpkg_t));
/* find the package in one of the repositories */
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(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;
}
}
}
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);
}
if(is_pkgin(info, list) == 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;
}
@ -1344,13 +1456,21 @@ int resolvedeps(pacdb_t *local, pacdb_t *sync, pkginfo_t *package, PMList *list,
fprintf(stderr, "error: %s conflicts with %s\n", miss->target, miss->depend.name);
return(1);
} else if(miss->type == DEPEND) {
/*printf("resolving %s\n", info->name); fflush(stdout);*/
if(!is_pkgin(info, trail)) {
list_add(trail, info);
if(resolvedeps(local, sync, info, list, trail)) {
/*printf("resolving %s\n", sync->pkg->name); fflush(stdout);*/
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);
}
list_add(list, info);
vprint("adding %s-%s\n", sync->pkg->name, sync->pkg->version);
list_add(list, sync);
} else {
/* cycle detected -- skip it */
/*printf("cycle detected\n"); fflush(stdout);*/
@ -1398,7 +1518,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
if((p = db_scan(db, j->data, INFRQ_DESC | INFRQ_DEPENDS)) == NULL) {
continue;
}
for(k = p->depends; k; k = k->next) {
for(k = p->depends; k && !found; k = k->next) {
if(splitdep(k->data, &depend)) {
continue;
}

View file

@ -22,7 +22,7 @@
#define _PAC_PACMAN_H
#ifndef PACVER
#define PACVER "2.0"
#define PACVER "2.1"
#endif
#ifndef PKGDIR
@ -50,7 +50,7 @@ int pacman_sync(pacdb_t *db, PMList *targets);
int pacman_deptest(pacdb_t *db, PMList *targets);
PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets);
int resolvedeps(pacdb_t *local, pacdb_t *sync, pkginfo_t *package, PMList *list, PMList *trail);
int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *sync, PMList *list, PMList *trail);
int splitdep(char *depstr, depend_t *depend);
int lckmk(char *file, int retries, unsigned int sleep_secs);

View file

@ -41,23 +41,41 @@ static char sync_fnm[25];
/* pacman options */
extern char *pmo_root;
/* configuration options */
extern char pmc_syncserver[512];
extern char pmc_syncpath[512];
extern char pmc_syncname[512];
/* sync servers */
extern PMList *pmc_syncs;
int sync_synctree()
{
char ldir[PATH_MAX] = "";
char path[PATH_MAX];
mode_t oldmask;
char *str;
PMList *files = NULL;
PMList *i;
int success = 0;
snprintf(ldir, PATH_MAX, "%s%s/%s", pmo_root, PKGDIR, pmc_syncname);
for(i = pmc_syncs; i; i = i->next) {
sync_t *sync = (sync_t*)i->data;
snprintf(ldir, PATH_MAX, "%s%s", pmo_root, PKGDIR);
/* build a one-element list */
snprintf(path, PATH_MAX, "%s.db.tar.gz", sync->treename);
files = list_add(files, strdup(path));
success = 1;
if(downloadfiles(sync->servers, ldir, files)) {
fprintf(stderr, "failed to synchronize %s\n", sync->treename);
success = 0;
}
/*printf("\n");*/
list_free(files);
files = NULL;
snprintf(path, PATH_MAX, "%s/%s.db.tar.gz", ldir, sync->treename);
if(success) {
snprintf(ldir, PATH_MAX, "%s%s/%s", pmo_root, PKGDIR, sync->treename);
/* remove the old dir */
vprint("Removing %s (if it exists)\n", ldir);
vprint("removing %s (if it exists)\n", ldir);
rmrf(ldir);
/* make the new dir */
@ -65,101 +83,129 @@ int sync_synctree()
mkdir(ldir, 0755);
umask(oldmask);
/* build out list of one */
snprintf(path, PATH_MAX, "%s.db.tar.gz", pmc_syncname);
str = strdup(path);
files = list_add(files, str);
if(downloadfiles(pmc_syncserver, pmc_syncpath, ldir, files)) {
list_free(files);
return(1);
}
/* uncompress the sync database */
snprintf(path, PATH_MAX, "%s/%s", ldir, (char*)files->data);
list_free(files);
vprint("Unpacking %s...\n", path);
if(unpack(path, ldir)) {
return(1);
}
}
/* remove the .tar.gz */
unlink(path);
return(0);
}
int downloadfiles(char *server, char *remotepath, char *localpath, PMList *files)
return(!success);
}
int downloadfiles(PMList *servers, char *localpath, PMList *files)
{
int fsz;
netbuf *control = NULL;
PMList *lp;
int ret = 0;
int done = 0;
PMList *complete = NULL;
PMList *i;
if(files == NULL) {
return(0);
}
for(i = servers; i && !done; i = i->next) {
server_t *server = (server_t*)i->data;
if(!server->islocal) {
FtpInit();
if(!FtpConnect(server, &control)) {
fprintf(stderr, "error: cannot connect to %s\n", server);
return(1);
if(!FtpConnect(server->server, &control)) {
fprintf(stderr, "error: cannot connect to %s\n", server->server);
continue;
}
if(!FtpLogin("anonymous", "arch@guest", control)) {
fprintf(stderr, "error: anonymous login failed\n");
FtpQuit(control);
return(1);
continue;
}
if(!FtpChdir(remotepath, control)) {
fprintf(stderr, "error: could not cwd to %s: %s\n", remotepath,
if(!FtpChdir(server->path, control)) {
fprintf(stderr, "error: could not cwd to %s: %s\n", server->path,
FtpLastResponse(control));
return(1);
continue;
}
}
/* get each file in the list */
for(lp = files; lp; lp = lp->next) {
char output[PATH_MAX];
int j;
char *fn = (char*)lp->data;
snprintf(output, PATH_MAX, "%s/%s", localpath, (char*)lp->data);
if(is_in(fn, complete)) {
continue;
}
snprintf(output, PATH_MAX, "%s/%s", localpath, fn);
strncpy(sync_fnm, lp->data, 24);
for(j = strlen(sync_fnm); j < 24; j++) {
sync_fnm[j] = ' ';
}
sync_fnm[24] = '\0';
if(!server->islocal) {
/* passive mode */
/* TODO: make passive ftp an option */
if(!FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, control)) {
fprintf(stderr, "warning: failed to set passive mode\n");
}
if(!FtpSize((char*)lp->data, &fsz, FTPLIB_IMAGE, control)) {
fprintf(stderr, "warning: failed to get filesize for %s\n", (char*)lp->data);
if(!FtpSize(fn, &fsz, FTPLIB_IMAGE, control)) {
fprintf(stderr, "warning: failed to get filesize for %s\n", fn);
}
/* set up our progress bar's callback */
FtpOptions(FTPLIB_CALLBACK, (long)log_progress, control);
FtpOptions(FTPLIB_IDLETIME, (long)1000, control);
FtpOptions(FTPLIB_CALLBACKARG, (long)&fsz, control);
FtpOptions(FTPLIB_CALLBACKBYTES, (10*1024), control);
strncpy(sync_fnm, lp->data, 24);
for(j = strlen(sync_fnm); j < 24; j++) {
sync_fnm[j] = ' ';
}
sync_fnm[24] = '\0';
if(!FtpGet(output, lp->data, FTPLIB_IMAGE, control)) {
fprintf(stderr, "\nerror: could not download %s: %s\n", (char*)lp->data,
FtpLastResponse(control));
fprintf(stderr, "\nfailed downloading %s from %s: %s\n",
fn, server->server, FtpLastResponse(control));
/* unlink the file */
unlink(output);
ret = 1;
} else {
log_progress(control, fsz, &fsz);
complete = list_add(complete, fn);
}
printf("\n");
fflush(stdout);
} else {
/* local repository, just copy the file */
char src[PATH_MAX], dest[PATH_MAX];
snprintf(src, PATH_MAX, "%s%s", server->path, fn);
snprintf(dest, PATH_MAX, "%s/%s", localpath, fn);
vprint("copying %s to %s\n", src, dest);
if(copyfile(src, dest)) {
fprintf(stderr, "failed copying %s\n", src);
} else {
char out[56];
printf("%s [", sync_fnm);
strncpy(out, server->path, 33);
printf("%s", out);
for(j = strlen(out); j < 33; j++) {
printf(" ");
}
fputs("] 100% | LOCAL\n", stdout);
fflush(stdout);
complete = list_add(complete, fn);
}
}
}
if(list_count(complete) == list_count(files)) {
done = 1;
}
if(!server->islocal) {
FtpQuit(control);
return(ret);
}
}
return(!done);
}
static int log_progress(netbuf *ctl, int xfered, void *arg)

View file

@ -21,8 +21,31 @@
#ifndef _PAC_PACSYNC_H
#define _PAC_PACSYNC_H
typedef struct __server_t {
unsigned short islocal;
char* server;
char* path;
} server_t;
typedef struct __sync_t {
char* treename;
PMList *servers;
} sync_t;
/* linking structs */
typedef struct __dbsync_t {
pacdb_t *db;
sync_t *sync;
PMList *pkgcache;
} dbsync_t;
typedef struct __syncpkg_t {
pkginfo_t *pkg;
dbsync_t *dbs;
} syncpkg_t;
int sync_synctree();
int downloadfiles(char *server, char *remotepath, char *localpath, PMList *files);
int downloadfiles(PMList *servers, char *localpath, PMList *files);
#endif

View file

@ -34,6 +34,7 @@
#include "package.h"
#include "db.h"
#include "util.h"
#include "pacsync.h"
#include "pacman.h"
extern char* pmo_root;
@ -54,11 +55,9 @@ extern unsigned short pmo_s_sync;
extern unsigned short pmo_s_search;
extern unsigned short pmo_s_clean;
extern unsigned short pmo_s_upgrade;
extern PMList *pmo_noupgrade;
extern char pmc_syncserver[512];
extern char pmc_syncname[512];
extern char pmc_syncpath[512];
extern PMList *pmc_syncs;
extern PMList *pm_targets;
/* borrowed and modifed from Per Liden's pkgutils (http://crux.nu) */
@ -221,6 +220,7 @@ int parseargs(int op, int argc, char **argv)
return(0);
}
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
int parseconfig(char *configfile)
{
FILE *fp = NULL;
@ -228,6 +228,8 @@ int parseconfig(char *configfile)
char *ptr = NULL;
char *key = NULL;
int linenum = 0;
char section[256] = "";
sync_t *sync = NULL;
if((fp = fopen(configfile, "r")) == NULL) {
perror(configfile);
@ -243,26 +245,127 @@ int parseconfig(char *configfile)
if(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 || ptr == NULL) {
fprintf(stderr, "syntax error in config file (line %d)\n", linenum);
fprintf(stderr, "config: line %d: syntax error\n", linenum);
return(1);
} else {
trim(key);
key = strtoupper(key);
trim(ptr);
if(!strcmp(key, "SYNC_SERVER")) {
strncpy(pmc_syncserver, ptr, sizeof(pmc_syncserver)-1);
} else if(!strcmp(key, "SYNC_TREE_PATH")) {
strncpy(pmc_syncpath, ptr, sizeof(pmc_syncpath)-1);
} else if(!strcmp(key, "SYNC_TREE_NAME")) {
strncpy(pmc_syncname, ptr, sizeof(pmc_syncname)-1);
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 {
fprintf(stderr, "Syntax error in description file line %d\n", linenum);
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->islocal = 0;
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->islocal = !strcmp(ptr, "local");
if(!server->islocal) {
char *slash;
/* no http support yet */
if(strcmp(ptr, "ftp")) {
fprintf(stderr, "config: line %d: protocol %s is not supported\n", linenum, ptr);
return(1);
}
/* 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 {
/* 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);
}
}
/* add to the list */
vprint("config: %s: server: %s %s\n", section, 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);
@ -272,7 +375,7 @@ int copyfile(char *src, char *dest)
{
FILE *in, *out;
size_t len;
char buf[1025];
char buf[4097];
in = fopen(src, "r");
if(in == NULL) {
@ -283,7 +386,7 @@ int copyfile(char *src, char *dest)
return(1);
}
while((len = fread(buf, 1, 1024, in))) {
while((len = fread(buf, 1, 4096, in))) {
fwrite(buf, 1, len, out);
}