Imported from pacman-2.5.tar.gz

This commit is contained in:
Judd Vinet 2003-05-30 19:56:46 +00:00
parent e9c6f3b213
commit 636c641119
25 changed files with 1270 additions and 1106 deletions

View file

@ -1,5 +1,15 @@
VERSION DESCRIPTION
------------------------------------------------------------------
2.5 - Added an URL tag to package info
- Sped up package load times by about 500% by introducing
a .FILELIST into the package
- Renamed the install scriptlet from ._install to .INSTALL
- Added patch from Aurlien Foret:
- Better lock handling (RW and RO)
- Sorted package order in -Qi's dependency lists
- Added a DBPath option to pacman.conf
- Fixed memory leaks
- Added the --nodeps option to -S
2.4.1 - Fixed a bug in makepkg's option parsing
2.4 - Added getopt-style options to makeworld
- Added -w <destdir> to makepkg

View file

@ -34,7 +34,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
PACVER = 2.4.1
PACVER = 2.5
TOPDIR = @srcdir@
SRCDIR = $(TOPDIR)/src/
@ -43,7 +43,7 @@ MANSRC = $(TOPDIR)/doc/
SCRDIR = $(TOPDIR)/scripts/
CXX = @CC@
CXXFLAGS += @CFLAGS@ -g -Wall -pedantic -fno-exceptions -fno-rtti \
CXXFLAGS += @CFLAGS@ -g -Wall -pedantic -fno-exceptions \
-D_GNU_SOURCE -DPACVER=\"$(PACVER)\" -I. -Ilibftp
LDFLAGS += @LDFLAGS@ -static -Llibftp -lftp -ltar -lz
@ -53,9 +53,10 @@ SRCS = $(SRCDIR)pacman.c \
$(SRCDIR)list.c \
$(SRCDIR)package.c \
$(SRCDIR)pacsync.c \
$(SRCDIR)rpmvercmp.c \
$(SRCDIR)md5.c \
$(SRCDIR)md5driver.c
$(SRCDIR)md5driver.c \
$(SRCDIR)vercmp.c \
$(SRCDIR)rpmvercmp.c
OBJECTS = $(OBJDIR)pacman.o \
$(OBJDIR)db.o \
@ -63,20 +64,20 @@ OBJECTS = $(OBJDIR)pacman.o \
$(OBJDIR)list.o \
$(OBJDIR)package.o \
$(OBJDIR)pacsync.o \
$(OBJDIR)rpmvercmp.o \
$(OBJDIR)md5.o \
$(OBJDIR)md5driver.o
$(OBJDIR)md5driver.o \
$(OBJDIR)rpmvercmp.o
all: ftplib pacman vercmp convertdb man
pacman: $(OBJECTS)
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
vercmp: $(OBJDIR)rpmvercmp.o $(OBJDIR)vercmp.o
$(CXX) $(OBJDIR)rpmvercmp.o $(OBJDIR)vercmp.o -o $@
vercmp: $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o
$(CXX) $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o $(CXXFLAGS) -o $@
convertdb: $(SRCDIR)convertdb.c $(SRCDIR)list.c
$(CXX) -o convertdb $(SRCDIR)convertdb.c $(SRCDIR)list.c $(CXXFLAGS)
convertdb: $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o
$(CXX) $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o $(CXXFLAGS) -lz -ltar -o $@
.c.o: $(SRCS)
$(CXX) $(CXXFLAGS) -o $@ -c $<

19
cnvpkg Executable file
View file

@ -0,0 +1,19 @@
#!/bin/bash
TMPDIR=/tmp/.pkgcnv
TMPFILE=/tmp/.pkgcnvf
tl=`pwd`
for fn in $*; do
rm -rf $TMPDIR;
mkdir -p $TMPDIR;
echo "Converting $fn"
cd $TMPDIR
tar zxvf $tl/$fn | grep -v '^.PKGINFO' | grep -v '._install' >$TMPFILE
mv $TMPFILE ./.FILELIST
if [ -f ._install ]; then
tar cfz /new/$fn .PKGINFO .FILELIST ._install *
else
tar cfz /new/$fn .PKGINFO .FILELIST *
fi
done

View file

@ -1,4 +1,4 @@
.TH makepkg 8 "April 19, 2003" "makepkg #VERSION#" ""
.TH makepkg 8 "May 27, 2003" "makepkg #VERSION#" ""
.SH NAME
makepkg \- package build utility
.SH SYNOPSIS
@ -34,6 +34,7 @@ pkgname=modutils
pkgver=2.4.13
pkgrel=1
pkgdesc="Utilities for inserting and removing modules from the linux kernel"
url="http://www.kernel.org"
backup=(etc/modules.conf)
depends=('glibc>=2.2.5' 'bash' 'zlib')
source=(ftp://ftp.server.com/$pkgname-$pkgver.tar.gz modules.conf)
@ -186,6 +187,11 @@ This is the release number specific to Arch Linux packages.
.B pkgdesc
This should be a brief description of the package and its functionality.
.TP
.B url
This field contains an optional URL that is associated with the piece of software
being packaged. This is typically the project's website.
.TP
.B backup
A space-delimited array of filenames (without a preceding slash). The
@ -226,21 +232,6 @@ by wget.
.SH MAKEPKG OPTIONS
.TP
.B "\-c, \-\-clean"
Clean up leftover work files/directories after a successful build.
.TP
.B "\-C, \-\-cleancache"
Removes all source files from the cache directory to free up diskspace.
.TP
.B "\-i, \-\-install"
Install/Upgrade the package after a successful build.
.TP
.B "\-s, \-\-syncdeps"
Install missing dependencies using pacman. When makepkg finds missing
dependencies, it will run pacman to try and resolve them. If successful,
pacman will download the missing packages from a package repository and
install them for you.
.TP
.B "\-b, \-\-builddeps"
Build missing dependencies from source. When makepkg finds missing
dependencies, it will look for the dependencies' PKGBUILD files under
@ -248,6 +239,12 @@ $ABSROOT (set in your /etc/makepkg.conf). If it finds them it will
run another copy of makepkg to build and install the missing dependencies.
The child makepkg calls will be made with the \fB-b\fP and \fB-i\fP options.
.TP
.B "\-c, \-\-clean"
Clean up leftover work files/directories after a successful build.
.TP
.B "\-C, \-\-cleancache"
Removes all source files from the cache directory to free up diskspace.
.TP
.B "\-d, \-\-nodeps"
Do not perform any dependency checks. This will let you override/ignore any
dependencies required. There's a good chance this option will break the build
@ -258,12 +255,21 @@ process if all of the dependencies aren't installed.
file already exists in the build directory. You can override this behaviour with
the \fB--force\fP switch.
.TP
.B "\-w <destdir>"
Write the resulting package file to the directory \fI<destdir>\fP instead of the
current working directory.
.B "\-i, \-\-install"
Install/Upgrade the package after a successful build.
.TP
.B "\-p <buildscript>"
Read the package script \fI<buildscript>\fP instead of the default (\fIPKGBUILD\fP).
.TP
.B "\-s, \-\-syncdeps"
Install missing dependencies using pacman. When makepkg finds missing
dependencies, it will run pacman to try and resolve them. If successful,
pacman will download the missing packages from a package repository and
install them for you.
.TP
.B "\-w <destdir>"
Write the resulting package file to the directory \fI<destdir>\fP instead of the
current working directory.
.SH CONFIGURATION
Configuration options are stored in \fI/etc/makepkg.conf\fP. This file is parsed

View file

@ -1,4 +1,4 @@
.TH pacman 8 "April 10, 2003" "pacman #VERSION#" ""
.TH pacman 8 "May 27, 2003" "pacman #VERSION#" ""
.SH NAME
pacman \- package manager utility
.SH SYNOPSIS
@ -14,18 +14,6 @@ the local system. pacman package are \fIgzipped tar\fP format.
Add a package to the system. Package will be uncompressed
into the installation root and the database will be updated.
.TP
.B "\-R, \-\-remove"
Remove a package from the system. Files belonging to the
specified package will be deleted, and the database will
be updated. Most configuration files will be saved with a
\fI.pacsave\fP extension unless the \fB--nosave\fP option was
used.
.TP
.B "\-U, \-\-upgrade"
Upgrade a package. This is essentially a "remove-then-add"
process. See \fBHANDLING CONFIG FILES\fP for an explanation
on how pacman takes care of config files.
.TP
.B "\-F, \-\-freshen"
This is like --upgrade except that, unlike --upgrade, this will only
upgrade packages that are already installed on your system.
@ -38,6 +26,13 @@ build date, size). This can be run against the local package
database or can be used on individual .tar.gz packages. See
\fBQUERY OPTIONS\fP below.
.TP
.B "\-R, \-\-remove"
Remove a package from the system. Files belonging to the
specified package will be deleted, and the database will
be updated. Most configuration files will be saved with a
\fI.pacsave\fP extension unless the \fB--nosave\fP option was
used.
.TP
.B "\-S, \-\-sync"
Synchronize packages. With this function you can install packages
directly from the ftp servers, complete with all dependencies required
@ -45,6 +40,11 @@ to run the packages. For example, \fBpacman -S qt\fP will download
qt and all the packages it depends on and install them. You could also use
\fBpacman -Su\fP to upgrade all packages that are out of date (see below).
.TP
.B "\-U, \-\-upgrade"
Upgrade a package. This is essentially a "remove-then-add"
process. See \fBHANDLING CONFIG FILES\fP for an explanation
on how pacman takes care of config files.
.TP
.B "\-V, \-\-version"
Display version and exit.
.TP
@ -53,14 +53,10 @@ Display syntax for the given operation. If no operation was
supplied then the general syntax is shown.
.SH OPTIONS
.TP
.B "\-v, \-\-verbose"
Output more status and error messages.
.TP
.B "\-f, \-\-force"
Bypass file conflict checks,, overwriting conflicting files. If the
package that is about to be installed contains files that are already
installed, this option will cause all those files to be overwritten.
This option should be used with care, ideally not at all.
.B "\-c, \-\-cascade"
(only used with \fB--remove\fP)
Remove all target packages, as well as all packages that depend on one
or more target packages. This operation is recursive.
.TP
.B "\-d, \-\-nodeps"
Skips all dependency checks. Normally, pacman will always check
@ -68,6 +64,12 @@ a package's dependency fields to ensure that all dependencies are
installed and there are no package conflicts in the system. This
switch disables these checks.
.TP
.B "\-f, \-\-force"
Bypass file conflict checks,, overwriting conflicting files. If the
package that is about to be installed contains files that are already
installed, this option will cause all those files to be overwritten.
This option should be used with care, ideally not at all.
.TP
.B "\-n, \-\-nosave"
(only used with \fB--remove\fP)
Instructs pacman to ignore file backup designations. Normally, when
@ -76,11 +78,6 @@ checked to see if the file should be renamed to a .pacsave extension. If
\fB--nosave\fP is used, these designations are ignored and the files are
removed.
.TP
.B "\-c, \-\-cascade"
(only used with \fB--remove\fP)
Remove all target packages, as well as all packages that depend on one
or more target packages. This operation is recursive.
.TP
.B "\-r, \-\-root <path>"
Specify alternative installation root (default is "/"). This
should \fInot\fP be used as a way to install software into
@ -89,12 +86,19 @@ if you want to install a package on a temporary mounted partition,
which is "owned" by another system. By using this option you not only
specify where the software should be installed, but you also
specify which package database to use.
.TP
.B "\-v, \-\-verbose"
Output more status and error messages.
.SH SYNC OPTIONS
.TP
.B "\-y, \-\-refresh"
Download a fresh copy of the master package list from the ftp server
defined in \fI/etc/pacman.conf\fP. This should typically be used each
time you use \fB--sysupgrade\fP.
.B "\-c, \-\-clean"
Remove packages from the cache. When pacman downloads packages,
it saves them in \fI/var/cache/pacman/pkg\fP. If you need to free up
diskspace, you can remove these packages by using the --clean option.
.TP
.B "\-s, \-\-search <string>"
This will search each package in the package list for names or descriptions
that contains <string>.
.TP
.B "\-u, \-\-sysupgrade"
Upgrades all packages that are out of date. pacman will examine every
@ -104,29 +108,25 @@ it wants to upgrade and will not proceed without user confirmation.
Dependencies are automatically resolved at this level and will be
installed/upgraded if necessary.
.TP
.B "\-s, \-\-search <string>"
This will search each package in the package list for names or descriptions
that contains <string>.
.TP
.B "\-w, \-\-downloadonly"
Retrieve all packages from the server, but do not install/upgrade anything.
.TP
.B "\-c, \-\-clean"
Remove packages from the cache. When pacman downloads packages,
it saves them in \fI/var/cache/pacman/pkg\fP. If you need to free up
diskspace, you can remove these packages by using the --clean option.
.B "\-y, \-\-refresh"
Download a fresh copy of the master package list from the ftp server
defined in \fI/etc/pacman.conf\fP. This should typically be used each
time you use \fB--sysupgrade\fP.
.SH QUERY OPTIONS
.TP
.B "\-o, \-\-owns <file>"
Search for the package that owns <file>.
.B "\-i, \-\-info"
Display information on a given package. If it is used with the \fB-p\fP
option then the .PKGINFO file will be printed.
.TP
.B "\-l, \-\-list"
List all files owned by <package>. Multiple packages can be specified on
the command line.
.TP
.B "\-i, \-\-info"
Display information on a given package. If it is used with the \fB-p\fP
option then the .PKGINFO file will be printed.
.B "\-o, \-\-owns <file>"
Search for the package that owns <file>.
.TP
.B "\-p, \-\-file"
Tells pacman that the package supplied on the command line is a
@ -185,9 +185,9 @@ Server = local:///home/pkgs
.RE
.SH CONFIG: OPTIONS
.TP
.B "NoUpgrade = <file> [file] ..."
All files listed with a \fBNoUpgrade\fP directive will never be touched during a package
install/upgrade. \fINote:\fP do not include the leading slash when specifying files.
.B "DBPath = /path/to/db/dir"
Overrides the default location of the toplevel database directory. The default is
\fI/var/lib/pacman\fP.
.TP
.B "IgnorePkg = <package> [package] ..."
Instructs pacman to ignore any upgrades for this package when performing a
@ -195,6 +195,10 @@ Instructs pacman to ignore any upgrades for this package when performing a
.TP
.B "NoPassiveFtp"
Disables passive ftp connections when downloading packages. (aka Active Mode)
.TP
.B "NoUpgrade = <file> [file] ..."
All files listed with a \fBNoUpgrade\fP directive will never be touched during a package
install/upgrade. \fINote:\fP do not include the leading slash when specifying files.
.SH CONFIG: REPOSITORIES
Each repository section defines a section name and at least one location where the packages

View file

@ -1,6 +1,6 @@
#!/bin/bash
myver='2.4.1'
myver='2.5'
usage() {
echo "gensync $myver"

View file

@ -1,6 +1,6 @@
#!/bin/bash
myver='2.4.1'
myver='2.5'
startdir=`pwd`
[ -f /etc/makepkg.conf ] && source /etc/makepkg.conf
@ -61,7 +61,7 @@ usage() {
echo " -p <buildscript> Use an alternate build script (instead of PKGBUILD)"
echo " -h, --help This help"
echo
echo " if build_script is not specified, makepkg will look for a PKGBUILD"
echo " if -p is not specified, makepkg will look for a PKGBUILD"
echo " file in the current directory."
echo
exit 0
@ -101,12 +101,8 @@ while [ "$#" -ne "0" ]; do
d) NODEPS=1 ;;
i) INSTALL=1 ;;
f) FORCE=1 ;;
w)
PKGDEST=$OPTARG
;;
p)
BUILDSCRIPT=$OPTARG
;;
w) PKGDEST=$OPTARG ;;
p) BUILDSCRIPT=$OPTARG ;;
-)
OPTIND=0
break
@ -131,7 +127,7 @@ if [ "$CLEANCACHE" = "1" ]; then
exit 0
fi
unset pkgname pkgver pkgrel pkgdesc
unset pkgname pkgver pkgrel pkgdesc url
unset depends conflicts backup source install build
umask 0022
@ -309,6 +305,13 @@ if [ -d pkg/usr/share/man ]; then
rm -rf pkg/usr/share/man
fi
# remove /usr/share directory if empty
if [ -d pkg/usr/share ]; then
if [ -z "`ls -1 pkg/usr/share`" ]; then
rm -r pkg/usr/share
fi
fi
# compress man pages
if [ -d pkg/usr/man ]; then
msg "==> Compressing man pages..."
@ -327,7 +330,6 @@ if [ -d pkg/usr/man ]; then
done
fi
# strip binaries
cd $startdir
msg "==> Stripping debugging symbols from libraries..."
@ -353,6 +355,7 @@ date >>.PKGINFO
echo "pkgname = $pkgname" >>.PKGINFO
echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO
echo "pkgdesc = $pkgdesc" >>.PKGINFO
echo "url = $url" >>.PKGINFO
echo "builddate = $builddate" >>.PKGINFO
echo "packager = $packager" >>.PKGINFO
echo "size = $size" >>.PKGINFO
@ -370,17 +373,23 @@ done
# check for an install script
if [ "$install" != "" ]; then
msg "==> Copying install script..."
cp $startdir/$install $startdir/pkg/._install
cp $startdir/$install $startdir/pkg/.INSTALL
fi
# build a filelist
msg "==> Building filelist..."
cd $startdir/pkg
tar cv * >/dev/null 2>.FILELIST
# tar it up
msg "==> Compressing package..."
cd $startdir/pkg
if [ -f $startdir/pkg/._install ]; then
tar czvf $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO ._install * >../filelist
if [ -f $startdir/pkg/.INSTALL ]; then
cmd="tar czvf $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO .FILELIST .INSTALL *"
else
tar czvf $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO * >../filelist
cmd="tar czvf $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO .FILELIST *"
fi
$cmd >../filelist
cd $startdir
if [ "$CLEANUP" = "1" ]; then
@ -388,8 +397,7 @@ if [ "$CLEANUP" = "1" ]; then
rm -rf src pkg filelist
fi
d=`date`
msg "==> Finished making $pkgname ($d)"
msg "==> Finished making $pkgname (`date`)"
if [ "$INSTALL" = "1" ]; then
msg "==> Running pacman --upgrade"

View file

@ -1,19 +1,19 @@
#!/bin/bash
toplevel=`pwd`
version="2.4.1"
version="2.5"
usage() {
echo "makeworld version $version"
echo "usage: $0 [options] <destdir> <category> [category] ..."
echo "options:"
echo " -c, --clean Clean up work files after build"
echo " -s, --syncdeps Install missing dependencies with pacman"
echo " -b, --builddeps Build missing dependencies from source"
echo " -c, --clean Clean up work files after build"
echo " -d, --nodeps Skip all dependency checks"
echo " -i, --install Install package after successful build"
echo " -f, --force Overwrite existing packages"
echo " -i, --install Install package after successful build"
echo " -h, --help This help"
echo " -s, --syncdeps Install missing dependencies with pacman"
echo
echo " where <category> is one or more directory names under the ABS root"
echo " eg: makeworld -c /packages base lib editors"

View file

@ -29,8 +29,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include "list.h"
char* trim(char *str);
#include "util.h"
int main(int argc, char* argv[])
{
@ -139,25 +138,4 @@ int main(int argc, char* argv[])
return(0);
}
/* Trim whitespace and newlines from a string
*/
char* trim(char *str)
{
char *pch = str;
while(isspace(*pch)) {
pch++;
}
if(pch != str) {
memmove(str, pch, (strlen(pch) + 1));
}
pch = (char*)(str + (strlen(str) - 1));
while(isspace(*pch)) {
pch--;
}
*++pch = '\0';
return str;
}
/* vim: set ts=2 sw=2 noet: */

View file

@ -24,21 +24,10 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "list.h"
#include "package.h"
#include "db.h"
#include "util.h"
#include "pacsync.h"
#include "pacman.h"
extern PMList *pm_packages;
extern char *pmo_root;
extern unsigned short pmo_upgrade;
extern int errno;
#include "db.h"
/* Verify database integrity and build a list of
* installed packages
@ -47,14 +36,14 @@ extern int errno;
* 1 if db is not initialized
* 2 if db is corrupt
*/
pacdb_t* db_open(char *dbpath, char *treename)
pacdb_t* db_open(char *root, char *pkgdir, char *treename)
{
pacdb_t *db = NULL;
char path[PATH_MAX];
MALLOC(db, sizeof(pacdb_t));
snprintf(path, PATH_MAX-1, "%s/%s", dbpath, treename);
db->dir = opendir(path);
MALLOC(db->path, strlen(root)+strlen(pkgdir)+strlen(treename)+2);
sprintf(db->path, "%s%s/%s", root, pkgdir, treename);
db->dir = opendir(db->path);
if(db->dir == NULL) {
return(NULL);
}
@ -65,7 +54,14 @@ pacdb_t* db_open(char *dbpath, char *treename)
void db_close(pacdb_t* db)
{
if(db) {
if(db->dir) {
closedir(db->dir);
}
FREE(db->path);
}
FREE(db);
return;
}
@ -115,6 +111,8 @@ PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache)
cache = list_add(cache, arr[i]);
}
free(arr);
return(cache);
}
@ -174,19 +172,17 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
struct stat buf;
pkginfo_t *info = NULL;
char path[PATH_MAX];
char topdir[PATH_MAX];
char line[512];
if(ent == NULL) {
return(NULL);
}
snprintf(topdir, PATH_MAX, "%s%s/%s", pmo_root, PKGDIR, db->treename);
info = newpkg();
/* we always load DESC */
inforeq |= INFRQ_DESC;
snprintf(path, PATH_MAX, "%s/%s", topdir, ent->d_name);
snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name);
if(stat(path, &buf)) {
/* directory doesn't exist or can't be opened */
return(NULL);
@ -194,7 +190,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
/* DESC */
if(inforeq & INFRQ_DESC) {
snprintf(path, PATH_MAX, "%s/%s/desc", topdir, ent->d_name);
snprintf(path, PATH_MAX, "%s/%s/desc", db->path, ent->d_name);
fp = fopen(path, "r");
if(fp == NULL) {
fprintf(stderr, "error: %s: %s\n", path, strerror(errno));
@ -206,32 +202,37 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
}
trim(line);
if(!strcmp(line, "%NAME%")) {
if(fgets(info->name, 256, fp) == NULL) {
if(fgets(info->name, sizeof(info->name), fp) == NULL) {
return(NULL);
}
trim(info->name);
} else if(!strcmp(line, "%VERSION%")) {
if(fgets(info->version, 64, fp) == NULL) {
if(fgets(info->version, sizeof(info->version), fp) == NULL) {
return(NULL);
}
trim(info->version);
} else if(!strcmp(line, "%DESC%")) {
if(fgets(info->desc, 512, fp) == NULL) {
if(fgets(info->desc, sizeof(info->desc), fp) == NULL) {
return(NULL);
}
trim(info->desc);
} else if(!strcmp(line, "%URL%")) {
if(fgets(info->url, sizeof(info->url), fp) == NULL) {
return(NULL);
}
trim(info->url);
} else if(!strcmp(line, "%BUILDDATE%")) {
if(fgets(info->builddate, 32, fp) == NULL) {
if(fgets(info->builddate, sizeof(info->builddate), fp) == NULL) {
return(NULL);
}
trim(info->builddate);
} else if(!strcmp(line, "%INSTALLDATE%")) {
if(fgets(info->installdate, 32, fp) == NULL) {
if(fgets(info->installdate, sizeof(info->installdate), fp) == NULL) {
return(NULL);
}
trim(info->installdate);
} else if(!strcmp(line, "%PACKAGER%")) {
if(fgets(info->packager, 64, fp) == NULL) {
if(fgets(info->packager, sizeof(info->packager), fp) == NULL) {
return(NULL);
}
trim(info->packager);
@ -249,7 +250,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
/* FILES */
if(inforeq & INFRQ_FILES) {
snprintf(path, PATH_MAX, "%s/%s/files", topdir, ent->d_name);
snprintf(path, PATH_MAX, "%s/%s/files", db->path, ent->d_name);
fp = fopen(path, "r");
if(fp == NULL) {
fprintf(stderr, "error: %s: %s\n", path, strerror(errno));
@ -275,7 +276,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
/* DEPENDS */
if(inforeq & INFRQ_DEPENDS) {
snprintf(path, PATH_MAX, "%s/%s/depends", topdir, ent->d_name);
snprintf(path, PATH_MAX, "%s/%s/depends", db->path, ent->d_name);
fp = fopen(path, "r");
if(fp == NULL) {
fprintf(stderr, "db_read: error: %s: %s\n", path, strerror(errno));
@ -307,7 +308,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
}
/* INSTALL */
snprintf(path, PATH_MAX, "%s/%s/install", topdir, ent->d_name);
snprintf(path, PATH_MAX, "%s/%s/install", db->path, ent->d_name);
if(!stat(path, &buf)) {
info->scriptlet = 1;
}
@ -317,8 +318,8 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
int db_write(pacdb_t *db, pkginfo_t *info)
{
FILE *fp = NULL;
char topdir[PATH_MAX];
FILE *fp = NULL;
char path[PATH_MAX];
mode_t oldmask;
PMList *lp = NULL;
@ -326,9 +327,9 @@ int db_write(pacdb_t *db, pkginfo_t *info)
if(info == NULL) {
return(1);
}
snprintf(topdir, PATH_MAX, "%s%s/%s/%s-%s", pmo_root, PKGDIR, db->treename,
info->name, info->version);
snprintf(topdir, PATH_MAX, "%s/%s-%s", db->path,
info->name, info->version);
oldmask = umask(0000);
mkdir(topdir, 0755);
umask(oldmask);
@ -346,6 +347,8 @@ int db_write(pacdb_t *db, pkginfo_t *info)
fprintf(fp, "%s\n\n", info->version);
fputs("%DESC%\n", fp);
fprintf(fp, "%s\n\n", info->desc);
fputs("%URL%\n", fp);
fprintf(fp, "%s\n\n", info->url);
fputs("%BUILDDATE%\n", fp);
fprintf(fp, "%s\n\n", info->builddate);
fputs("%INSTALLDATE%\n", fp);
@ -406,7 +409,7 @@ int db_write(pacdb_t *db, pkginfo_t *info)
}
PMList* db_find_conflicts(pacdb_t *db, PMList *targets)
PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
{
PMList *i, *j, *k;
char *filestr = NULL;
@ -450,7 +453,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets)
}*/
/* CHECK 2: check every target against every target */
vprint("Checking targets against targets...\n");
/* orelien - vprint("Checking targets against targets...\n"); */
for(i = targets; i; i = i->next) {
pkginfo_t *p1 = (pkginfo_t*)i->data;
for(j = i; j; j = j->next) {
@ -458,7 +461,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets)
if(strcmp(p1->name, p2->name)) {
for(k = p1->files; k; k = k->next) {
filestr = k->data;
if(!strcmp(filestr, "._install")) {
if(!strcmp(filestr, "._install") || !strcmp(filestr, ".INSTALL")) {
continue;
}
if(rindex(filestr, '/') == filestr+strlen(filestr)-1) {
@ -477,13 +480,13 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets)
}
/* CHECK 3: check every target against the filesystem */
vprint("Checking targets against filesystem...\n");
/* orelien - vprint("Checking targets against filesystem...\n"); */
for(i = targets; i; i = i->next) {
pkginfo_t *p = (pkginfo_t*)i->data;
pkginfo_t *dbpkg = NULL;
for(j = p->files; j; j = j->next) {
filestr = (char*)j->data;
snprintf(path, PATH_MAX, "%s%s", pmo_root, filestr);
snprintf(path, PATH_MAX, "%s%s", root, filestr);
if(!stat(path, &buf) && !S_ISDIR(buf.st_mode)) {
int ok = 0;
if(dbpkg == NULL) {

View file

@ -30,17 +30,18 @@
#define INFRQ_ALL 0xFF
typedef struct __pacdb_t {
char *path;
char treename[128];
DIR* dir;
} pacdb_t;
pacdb_t* db_open(char *dbpath, char *treename);
pacdb_t* db_open(char *root, char *dbpath, char *treename);
void db_close(pacdb_t *db);
PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache);
pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq);
pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq);
int db_write(pacdb_t *db, pkginfo_t *info);
PMList* db_find_conflicts(pacdb_t *db, PMList* targets);
PMList* db_find_conflicts(pacdb_t *db, PMList* targets, char *root);
#endif
/* vim: set ts=2 sw=2 noet: */

View file

@ -20,14 +20,9 @@
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include "list.h"
PMList* list_new()
@ -105,6 +100,20 @@ int list_isin(PMList *haystack, void *needle)
return(0);
}
/* Test for existence of a string in a PMList
*/
int is_in(char *needle, PMList *haystack)
{
PMList *lp;
for(lp = haystack; lp; lp = lp->next) {
if(lp->data && !strcmp(lp->data, needle)) {
return(1);
}
}
return(0);
}
/* List one is extended and returned
* List two is freed (but not its data)
*/
@ -131,4 +140,77 @@ PMList* list_last(PMList *list)
return(ptr);
}
/* Helper function for sorting a list of strings
*/
int list_strcmp(const void *s1, const void *s2)
{
char **str1 = (char **)s1;
char **str2 = (char **)s2;
return(strcmp(*str1, *str2));
}
PMList *list_sort(PMList *list)
{
char **arr = NULL;
PMList *lp;
unsigned int arrct;
int i;
if(list == NULL) {
return(NULL);
}
arrct = list_count(list);
arr = (char **)malloc(arrct*sizeof(char*));
for(lp = list, i = 0; lp; lp = lp->next) {
arr[i++] = (char *)lp->data;
}
qsort(arr, (size_t)arrct, sizeof(char *), list_strcmp);
lp = NULL;
for(i = 0; i < arrct; i++) {
lp = list_add(lp, strdup(arr[i]));
}
free(arr);
return(lp);
}
void list_display(const char *title, PMList *list)
{
PMList *lp;
int cols, len, maxcols = 80;
char *cenv = NULL;
cenv = getenv("COLUMNS");
if(cenv) {
maxcols = atoi(cenv);
}
len = strlen(title);
printf("%s", title);
if(list) {
for(lp = list, cols = len; lp; lp = lp->next) {
int s = strlen((char*)lp->data)+1;
if(s+cols >= maxcols) {
int i;
cols = len;
printf("\n");
for (i = 0; i < len; i++) {
printf(" ");
}
}
printf("%s ", (char*)lp->data);
cols += s;
}
printf("\n");
} else {
printf("None\n");
}
}
/* vim: set ts=2 sw=2 noet: */

View file

@ -1,3 +1,23 @@
/*
* pacman
*
* 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.
*/
#ifndef _PAC_LIST_H
#define _PAC_LIST_H
@ -13,8 +33,12 @@ void list_free(PMList* list);
PMList* list_add(PMList* list, void* data);
int list_count(PMList* list);
int list_isin(PMList *haystack, void *needle);
int is_in(char *needle, PMList *haystack);
PMList* list_merge(PMList *one, PMList *two);
PMList* list_last(PMList* list);
int list_strcmp(const void *s1, const void *s2);
PMList *list_sort(PMList *list);
void list_display(const char *title, PMList *list);
#endif

View file

@ -45,4 +45,7 @@ void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
void MD5Final(unsigned char [16], MD5_CTX *);
char* MDFile(char *);
void MDPrint(unsigned char [16]);
/* vim: set ts=2 sw=2 noet: */

View file

@ -29,9 +29,6 @@ documentation and/or software.
#define TEST_BLOCK_LEN 1000
#define TEST_BLOCK_COUNT 1000
char* MDFile(char *);
void MDPrint(unsigned char [16]);
#define MD_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update

View file

@ -24,39 +24,45 @@
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "list.h"
#include "package.h"
#include "db.h"
#include <libtar.h>
#include <zlib.h>
#include "util.h"
#include "pacsync.h"
#include "pacman.h"
extern tartype_t gztype;
#include "package.h"
pkginfo_t* load_pkg(char *pkgfile, unsigned short output)
{
char *expath;
char *descfile;
int i;
int config = 0;
int filelist = 0;
TAR *tar;
pkginfo_t *info = NULL;
PMList *backup = NULL;
PMList *lp;
tartype_t gztype = {
(openfunc_t) gzopen_frontend,
(closefunc_t)gzclose,
(readfunc_t) gzread,
(writefunc_t)gzwrite
};
info = newpkg();
descfile = strdup("/tmp/pacman_XXXXXX");
if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
perror("could not open package");
return(NULL);
}
vprint("load_pkg: loading filelist from package...\n");
for(i = 0; !th_read(tar); i++) {
if(config && filelist) {
/* we have everything we need */
break;
}
if(!strcmp(th_get_pathname(tar), ".PKGINFO")) {
char *descfile;
/* extract this file into /tmp. it has info for us */
vprint("load_pkg: found package description file.\n");
descfile = strdup("/tmp/pacman_XXXXXX");
mkstemp(descfile);
tar_extract_file(tar, descfile);
/* parse the info file */
@ -74,15 +80,44 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output)
info->backup = list_add(info->backup, lp->data);
}
}
config = 1;
FREE(descfile);
continue;
} else if(!strcmp(th_get_pathname(tar), "._install") || !strcmp(th_get_pathname(tar), ".INSTALL")) {
info->scriptlet = 1;
} else if(!strcmp(th_get_pathname(tar), ".FILELIST")) {
/* Build info->files from the filelist */
FILE *fp;
char *fn;
char *str;
MALLOC(str, PATH_MAX);
fn = strdup("/tmp/pacman_XXXXXX");
mkstemp(fn);
tar_extract_file(tar, fn);
fp = fopen(fn, "r");
while(!feof(fp)) {
if(fgets(str, PATH_MAX, fp) == NULL) {
continue;
}
if(!strcmp(th_get_pathname(tar), "._install")) {
info->scriptlet = 1;
trim(str);
info->files = list_add(info->files, strdup(str));
}
FREE(str);
fclose(fp);
if(unlink(fn)) {
fprintf(stderr, "warning: could not remove tempfile %s\n", fn);
}
FREE(fn);
filelist = 1;
} else {
if(!filelist) {
/* no .FILELIST present in this package.. build the filelist the */
/* old-fashioned way, one at a time */
expath = strdup(th_get_pathname(tar));
/* add the path to the list */
info->files = list_add(info->files, expath);
}
}
if(TH_ISREG(tar) && tar_skip_regfile(tar)) {
char errorstr[255];
@ -93,9 +128,8 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output)
expath = NULL;
}
tar_close(tar);
FREE(descfile);
if(!strlen(info->name) || !strlen(info->version)) {
if(!config) {
fprintf(stderr, "load_pkg: missing package info file in %s\n", pkgfile);
return(NULL);
}
@ -147,6 +181,8 @@ int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output)
strncpy(info->version, ptr, sizeof(info->version));
} else if(!strcmp(key, "PKGDESC")) {
strncpy(info->desc, ptr, sizeof(info->desc));
} else if(!strcmp(key, "URL")) {
strncpy(info->url, ptr, sizeof(info->url));
} else if(!strcmp(key, "BUILDDATE")) {
strncpy(info->builddate, ptr, sizeof(info->builddate));
} else if(!strcmp(key, "INSTALLDATE")) {
@ -188,6 +224,7 @@ pkginfo_t* newpkg()
pkg->name[0] = '\0';
pkg->version[0] = '\0';
pkg->desc[0] = '\0';
pkg->url[0] = '\0';
pkg->builddate[0] = '\0';
pkg->installdate[0] = '\0';
pkg->packager[0] = '\0';
@ -227,4 +264,58 @@ int pkgcmp(const void *p1, const void *p2)
return(strcmp(pkg1[0]->name, pkg2[0]->name));
}
/* Test for existence of a package in a PMList*
* of pkginfo_t*
*
* returns: 0 for no match
* 1 for identical match
* -1 for name-only match (version mismatch)
*/
int is_pkgin(pkginfo_t *needle, PMList *haystack)
{
PMList *lp;
pkginfo_t *info;
for(lp = haystack; lp; lp = lp->next) {
info = (pkginfo_t*)lp->data;
if(info && !strcmp(info->name, needle->name)) {
if(!strcmp(info->version, needle->version)) {
return(1);
}
return(-1);
}
}
return(0);
}
/* Display the content of a package
*/
void dump_pkg(pkginfo_t *info)
{
PMList *pm;
if(info == NULL) {
return;
}
printf("Name : %s\n", info->name);
printf("Version : %s\n", info->version);
printf("Packager : %s\n", info->packager);
printf("URL: : %s\n", info->url);
printf("Size : %ld\n", info->size);
printf("Build Date : %s %s\n", info->builddate, strlen(info->builddate) ? "UTC" : "");
printf("Install Date : %s %s\n", info->installdate, strlen(info->installdate) ? "UTC" : "");
printf("Install Script: %s\n", (info->scriptlet ? "yes" : "no"));
pm = list_sort(info->depends);
list_display("Depends On : ", pm);
FREE(pm);
pm = list_sort(info->requiredby);
list_display("Required By : ", pm);
FREE(pm);
pm = list_sort(info->conflicts);
list_display("Conflicts With: ", pm);
FREE(pm);
printf("Description : %s\n", info->desc);
}
/* vim: set ts=2 sw=2 noet: */

View file

@ -21,6 +21,8 @@
#ifndef _PAC_PACKAGE_H
#define _PAC_PACKAGE_H
#include "list.h"
/* mods for depend_t.mod */
#define DEP_ANY 0
#define DEP_EQ 1
@ -33,6 +35,7 @@ typedef struct __pkginfo_t {
char name[256];
char version[64];
char desc[512];
char url[255];
char builddate[32];
char installdate[32];
char packager[64];
@ -62,6 +65,8 @@ int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output)
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);
#endif
/* vim: set ts=2 sw=2 noet: */

View file

@ -24,30 +24,26 @@
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <zlib.h>
#include <libtar.h>
/* pacman */
#include "list.h"
#include "rpmvercmp.h"
#include "md5.h"
#include "list.h"
#include "package.h"
#include "db.h"
#include "util.h"
#include "db.h"
#include "pacsync.h"
#include "pacman.h"
extern tartype_t gztype;
/* other prototypes */
int rpmvercmp(const char *a, const char *b);
char* MDFile(char *);
/*
* GLOBALS
*
@ -77,6 +73,7 @@ unsigned short pmo_s_sync = 0;
unsigned short pmo_s_search = 0;
unsigned short pmo_s_clean = 0;
/* configuration file options */
char *pmo_dbpath = NULL;
PMList *pmo_noupgrade = NULL;
PMList *pmo_ignorepkg = NULL;
unsigned short pmo_nopassiveftp = 0;
@ -91,51 +88,44 @@ PMList *pm_targets = NULL;
char *lckfile = "/tmp/pacman.lck";
char *workfile = NULL;
enum {READ_ONLY, READ_WRITE} pm_access;
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;
/* default root */
MALLOC(pmo_root, PATH_MAX);
strcpy(pmo_root, "/");
/* default dbpath */
MALLOC(pmo_dbpath, PATH_MAX);
strcpy(pmo_dbpath, PKGDIR);
if(argc < 2) {
usage(PM_MAIN, (char*)basename(argv[0]));
return(0);
}
/* parse the command line */
ret = parseargs(PM_ADD, argc, argv);
if(ret) {
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_search) {
/* special case: PM_SYNC can be used w/ pmo_s_search by any user */
} else {
uid_t uid = geteuid();
if(uid != 0) {
if(geteuid() != 0) {
fprintf(stderr, "error: you cannot perform this operation unless you are root.\n");
return(1);
}
}
}
vprint("Installation Root: %s\n", pmo_root);
if(pm_targets) {
vprint("Targets:\n");
for(lp = pm_targets; lp; lp = lp->next) {
vprint(" %s\n", lp->data);
}
}
pm_access = READ_WRITE;
/* lock */
if(lckmk(lckfile, 1, 1) == -1) {
fprintf(stderr, "error: unable to lock pacman database.\n");
@ -143,6 +133,13 @@ int main(int argc, char *argv[])
fprintf(stderr, " can remove %s\n", lckfile);
return(32);
}
}
}
vprint("Installation Root: %s\n", pmo_root);
if(pmo_verbose) {
list_display("Targets: ", pm_targets);
}
/* set signal handlers */
signal(SIGINT, cleanup);
@ -164,28 +161,27 @@ int main(int argc, char *argv[])
pmo_root = ptr;
}
/* db location */
MALLOC(dbpath, PATH_MAX);
snprintf(dbpath, PATH_MAX-1, "%s%s", pmo_root, PKGDIR);
vprint("Top-level DB Path: %s\n", dbpath);
vprint("Top-level DB Path: %s%s\n", pmo_root, pmo_dbpath);
db_local = db_open(dbpath, "local");
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/local", dbpath);
vprint("initializing database...\n", path);
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(dbpath, "local")) == NULL) {
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, pm_packages);
@ -203,7 +199,7 @@ int main(int argc, char *argv[])
}
db_close(db_local);
FREE(pmo_root);
FREE(dbpath);
FREE(pmo_dbpath);
cleanup(ret);
/* not reached */
return(0);
@ -284,7 +280,6 @@ int pacman_deptest(pacdb_t *db, PMList *targets)
int pacman_sync(pacdb_t *db, PMList *targets)
{
char dbpath[PATH_MAX];
int allgood = 1, confirm = 0;
int cols;
PMList *i, *j, *k;
@ -329,8 +324,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
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);
db_sync = db_open(pmo_root, PKGDIR, 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");
@ -403,6 +397,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
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 */
@ -412,43 +407,35 @@ int pacman_sync(pacdb_t *db, PMList *targets)
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;
} else {
PMList *lp = NULL;
int found = 0;
}
/* 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 */
for(found = 0, lp = final; lp && !found; lp = lp->next) {
syncpkg_t *s = (syncpkg_t*)lp->data;
if(s && !strcmp(s->pkg->name, sync->pkg->name)) {
found = 1;
}
}
found = is_pkginsync(sync, final);
if(!found) {
allgood = !resolvedeps(db, databases, sync, final, trail);
/* check again, as resolvedeps could have added our target for us */
for(found = 0, lp = final; lp && !found; lp = lp->next) {
syncpkg_t *s = (syncpkg_t*)lp->data;
if(s && !strcmp(s->pkg->name, sync->pkg->name)) {
found = 1;
}
}
found = is_pkginsync(sync, final);
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");
}
@ -480,6 +467,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(!found) {
fprintf(stderr, "%s: not found in sync db\n", (char*)i->data);
allgood = 0;
freepkg(local);
FREE(sync);
continue;
}
if(local && !pmo_s_downloadonly) {
@ -488,32 +477,28 @@ int pacman_sync(pacdb_t *db, PMList *targets)
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);
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);
continue;
}
}
}
/* add to targets list */
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) {
freepkg(local);
found = is_pkginsync(sync, final);
if(!found && !pmo_nodeps) {
allgood = !resolvedeps(db, databases, sync, final, trail);
/* check again, as resolvedeps could have added our target for us */
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;
}
found = is_pkginsync(sync, final);
}
if(!found) {
final = list_add(final, sync);
@ -521,7 +506,6 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
}
}
}
if(allgood) {
/* check for inter-conflicts and whatnot */
@ -535,6 +519,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
}
if(!pmo_nodeps && !pmo_s_upgrade) {
deps = checkdeps(db, PM_UPGRADE, list);
if(deps) {
fprintf(stderr, "error: unresolvable conflicts/dependencies:\n");
@ -562,6 +547,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* abort mission */
allgood = 0;
}
}
/* cleanup */
for(i = list; i; i = i->next) {
i->data = NULL;
@ -641,6 +628,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
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++;
}
}
@ -719,7 +707,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
for(i = final; i; i = i->next) {
syncpkg_t *sync = (syncpkg_t*)i->data;
if(sync) freepkg(sync->pkg);
free(sync);
FREE(sync);
i->data = NULL;
}
for(i = trail; i; i = i->next) {
@ -730,7 +718,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
dbsync_t *dbs = (dbsync_t*)i->data;
db_close(dbs->db);
list_free(dbs->pkgcache);
free(dbs);
FREE(dbs);
i->data = NULL;
}
list_free(databases);
@ -751,6 +739,12 @@ int pacman_add(pacdb_t *db, PMList *targets)
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);
@ -766,13 +760,14 @@ int pacman_add(pacdb_t *db, PMList *targets)
return(1);
}
if(pmo_freshen) {
/* only upgrade/install this package if it is already installed */
/* 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) {
if(dummy == NULL || rpmvercmp(dummy->version, info->version) >= 0) {
freepkg(info);
info = NULL;
continue;
}
freepkg(dummy);
}
alltargs = list_add(alltargs, info);
filenames = list_add(filenames, strdup(targ->data));
@ -810,7 +805,7 @@ int pacman_add(pacdb_t *db, PMList *targets)
if(!pmo_force) {
printf("checking for conflicts... ");
fflush(stdout);
lp = db_find_conflicts(db, alltargs);
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) {
@ -884,12 +879,12 @@ int pacman_add(pacdb_t *db, PMList *targets)
char pathname[PATH_MAX];
strncpy(pathname, th_get_pathname(tar), PATH_MAX);
if(!strcmp(pathname, ".PKGINFO")) {
if(!strcmp(pathname, ".PKGINFO") || !strcmp(pathname, ".FILELIST")) {
tar_skip_regfile(tar);
continue;
}
if(!strcmp(pathname, "._install")) {
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,
PKGDIR, db->treename, info->name, info->version);
@ -1279,7 +1274,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
}
}
} else {
/*vprint(" unlinking %s\n", line);*/
vprint(" unlinking %s\n", line);
if(unlink(line)) {
perror("cannot remove file");
}
@ -1389,13 +1384,12 @@ int pacman_query(pacdb_t *db, PMList *targets)
printf("\n");
} else if(pmo_q_list) {
for(lp = info->files; lp; lp = lp->next) {
if(strcmp(lp->data, ".PKGINFO")) {
printf("%s %s\n", info->name, (char*)lp->data);
}
}
} else if(!pmo_q_info) {
} else {
printf("%s %s\n", info->name, info->version);
}
freepkg(info);
continue;
}
@ -1417,6 +1411,7 @@ int pacman_query(pacdb_t *db, PMList *targets)
gotcha = 1;
}
}
freepkg(info);
}
if(!gotcha) {
fprintf(stderr, "No package owns %s\n", package);
@ -1442,6 +1437,7 @@ int pacman_query(pacdb_t *db, PMList *targets)
for(q = info->files; q; q = q->next) {
printf("%s %s%s\n", info->name, pmo_root, (char*)q->data);
}
freepkg(info);
} else {
printf("%s %s\n", tmpp->name, tmpp->version);
}
@ -1449,70 +1445,12 @@ int pacman_query(pacdb_t *db, PMList *targets)
} else {
/* find a target */
if(pmo_q_info) {
int cols;
info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS);
if(info == NULL) {
fprintf(stderr, "Package \"%s\" was not found.\n", package);
return(2);
}
printf("Name : %s\n", info->name);
printf("Version : %s\n", info->version);
printf("Packager : %s\n", info->packager);
printf("Size : %ld\n", info->size);
printf("Build Date : %s %s\n", info->builddate, strlen(info->builddate) ? "UTC" : "");
printf("Install Date : %s %s\n", info->installdate, strlen(info->installdate) ? "UTC" : "");
printf("Install Script: %s\n", (info->scriptlet ? "yes" : "no"));
printf("Depends On : ");
if(info->depends) {
for(lp = info->depends, cols = 16; lp; lp = lp->next) {
int s = strlen((char*)lp->data)+1;
if(s+cols > 79) {
cols = 16;
printf("\n%16s%s ", " ", (char*)lp->data);
} else {
printf("%s ", (char*)lp->data);
}
cols += s;
}
printf("\n");
} else {
printf("None\n");
}
printf("Required By : ");
if(info->requiredby) {
for(lp = info->requiredby, cols = 16; lp; lp = lp->next) {
int s = strlen((char*)lp->data)+1;
if(s+cols > 79) {
cols = 16;
printf("\n%16s%s ", " ", (char*)lp->data);
} else {
printf("%s ", (char*)lp->data);
}
cols += s;
}
printf("\n");
} else {
printf("None\n");
}
printf("Conflicts With: ");
if(info->conflicts) {
for(lp = info->conflicts, cols = 16; lp; lp = lp->next) {
int s = strlen((char*)lp->data)+1;
if(s+cols > 79) {
cols = 16;
printf("\n%16s%s ", " ", (char*)lp->data);
} else {
printf("%s ", (char*)lp->data);
}
cols += s;
}
printf("\n");
} else {
printf("None\n");
}
printf("Description : %s\n", info->desc);
dump_pkg(info);
printf("\n");
} else if(pmo_q_list) {
info = db_scan(db, package, INFRQ_DESC | INFRQ_FILES);
@ -1531,19 +1469,16 @@ int pacman_query(pacdb_t *db, PMList *targets)
}
printf("%s %s\n", info->name, info->version);
}
}
}
if(info) {
freepkg(info);
}
}
return(0);
}
int pacman_upgrade(pacdb_t *db, PMList *targets)
{
/* this is basically just a remove,add process. pacman_add() will */
/* this is basically just a remove-then-add process. pacman_add() will */
/* handle it */
pmo_upgrade = 1;
return(pacman_add(db, targets));
@ -1907,6 +1842,405 @@ int splitdep(char *depstr, depend_t *depend)
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'},
{"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'},
{"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'},
{0, 0, 0, 0}
};
while((opt = getopt_long(argc, argv, "ARUFQSTDYr:vhscVfnoldpiuwy", 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 'v': pmo_verbose = 1; break;
case 'f': pmo_force = 1; break;
case 'd': pmo_nodeps = 1; break;
case 'n': pmo_nosave = 1; break;
case 'l': pmo_q_list = 1; break;
case 'p': pmo_q_isfile = 1; break;
case 'i': pmo_q_info = 1; break;
case 'o': pmo_q_owns = 1; break;
case 'u': pmo_s_upgrade = 1; break;
case 'w': pmo_s_downloadonly = 1; break;
case 'y': pmo_s_sync = 1; break;
case 's': pmo_s_search = 1; break;
case 'c': pmo_s_clean = 1; pmo_r_cascade = 1; break;
case 'r': if(realpath(optarg, pmo_root) == NULL) {
perror("bad root path");
return(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 {
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 {
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);
}
/* 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(" -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(" -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");
}
}
/* Version
*/
void version(void)
{
printf("\n");
printf(" .--. Pacman v%s\n", PACVER);
printf("/ _.-' .-. .-. .-. Copyright (C) 2002 Judd Vinet <jvinet@zeroflux.org>\n");
printf("\\ '-. '-' '-' '-' \n");
printf(" '--' This program may be freely redistributed under\n");
printf(" the terms of the GNU GPL\n\n");
}
/* Check verbosity option and, if set, print the
* string to stdout
*/
int vprint(char *fmt, ...)
{
va_list args;
if(pmo_verbose) {
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
return(0);
}
int lckmk(char *file, int retries, unsigned int sleep_secs)
{
int fd, count = 0;
@ -1928,7 +2262,7 @@ int lckrm(char *file)
void cleanup(int signum)
{
if(lckrm(lckfile)) {
if(pm_access == READ_WRITE && lckrm(lckfile)) {
fprintf(stderr, "warning: could not remove lock file %s\n", lckfile);
}
if(workfile) {

View file

@ -22,7 +22,7 @@
#define _PAC_PACMAN_H
#ifndef PACVER
#define PACVER "2.4.1"
#define PACVER "2.5"
#endif
#ifndef PKGDIR
@ -42,6 +42,8 @@
#define PM_SYNC 6
#define PM_DEPTEST 7
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
int pacman_add(pacdb_t *db, PMList *targets);
int pacman_remove(pacdb_t *db, PMList *targets);
int pacman_upgrade(pacdb_t *db, PMList *targets);
@ -53,6 +55,14 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets);
int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *sync, PMList *list, PMList *trail);
int splitdep(char *depstr, depend_t *depend);
char* needbackup(char *file, PMList *backup);
int parseargs(int op, int argc, char **argv);
int parseconfig(char *configfile);
void usage(int op, char *myname);
void version(void);
int vprint(char *fmt, ...);
int lckmk(char *file, int retries, unsigned int sleep_secs);
int lckrm(char *lckfile);
void cleanup(int signum);

View file

@ -21,11 +21,8 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ftplib.h>
/* pacman */
@ -42,7 +39,7 @@ static int offset;
/* pacman options */
extern char *pmo_root;
extern unsigned char pmo_nopassiveftp;
extern unsigned short pmo_nopassiveftp;
/* sync servers */
extern PMList *pmc_syncs;
@ -130,6 +127,13 @@ int downloadfiles(PMList *servers, char *localpath, PMList *files)
FtpLastResponse(control));
continue;
}
if(!pmo_nopassiveftp) {
if(!FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, control)) {
fprintf(stderr, "warning: failed to set passive mode\n");
}
} else {
vprint("FTP passive mode not set\n");
}
}
/* get each file in the list */
@ -151,13 +155,6 @@ int downloadfiles(PMList *servers, char *localpath, PMList *files)
sync_fnm[24] = '\0';
if(!server->islocal) {
if(!pmo_nopassiveftp) {
if(!FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, control)) {
fprintf(stderr, "warning: failed to set passive mode\n");
}
} else {
vprint("FTP passive mode not set\n");
}
if(!FtpSize(fn, &fsz, FTPLIB_IMAGE, control)) {
fprintf(stderr, "warning: failed to get filesize for %s\n", fn);
}
@ -246,4 +243,23 @@ static int log_progress(netbuf *ctl, int xfered, void *arg)
return(1);
}
/* Test for existence of a package in a PMList*
* of syncpkg_t*
*/
int is_pkginsync(syncpkg_t *needle, PMList *haystack)
{
PMList *lp;
syncpkg_t *sync;
int found = 0;
for(lp = haystack; lp && !found; lp = lp->next) {
sync = (syncpkg_t*)lp->data;
if(sync && !strcmp(sync->pkg->name, needle->pkg->name)) {
found = 1;
}
}
return found;
}
/* vim: set ts=2 sw=2 noet: */

View file

@ -21,12 +21,14 @@
#ifndef _PAC_PACSYNC_H
#define _PAC_PACSYNC_H
/* Servers */
typedef struct __server_t {
unsigned short islocal;
char* server;
char* path;
} server_t;
/* Repositories */
typedef struct __sync_t {
char* treename;
PMList *servers;
@ -46,6 +48,7 @@ typedef struct __syncpkg_t {
int sync_synctree();
int downloadfiles(PMList *servers, char *localpath, PMList *files);
int is_pkginsync(syncpkg_t *needle, PMList *haystack);
#endif

28
src/rpmvercmp.h Normal file
View file

@ -0,0 +1,28 @@
/*
* pacman
*
* 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.
*/
#ifndef _PAC_RPMVERCMP_H
#define _PAC_RPMVERCMP_H
int rpmvercmp(const char *a, const char *b);
#endif
/* vim: set ts=2 sw=2 noet: */

View file

@ -24,52 +24,16 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <getopt.h>
#include <ctype.h>
#include "list.h"
#include "package.h"
#include "db.h"
#include <dirent.h>
#include <zlib.h>
#include <libtar.h>
#include "util.h"
#include "pacsync.h"
#include "pacman.h"
/* command line options */
extern char* pmo_root;
extern unsigned short pmo_op;
extern unsigned short pmo_version;
extern unsigned short pmo_verbose;
extern unsigned short pmo_help;
extern unsigned short pmo_force;
extern unsigned short pmo_nodeps;
extern unsigned short pmo_upgrade;
extern unsigned short pmo_freshen;
extern unsigned short pmo_nosave;
extern unsigned short pmo_d_vertest;
extern unsigned short pmo_d_resolve;
extern unsigned short pmo_q_isfile;
extern unsigned short pmo_q_info;
extern unsigned short pmo_q_list;
extern unsigned short pmo_q_owns;
extern unsigned short pmo_r_cascade;
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 unsigned short pmo_s_downloadonly;
/* configuration file options */
extern PMList *pmo_noupgrade;
extern PMList *pmo_ignorepkg;
extern unsigned short pmo_nopassiveftp;
extern PMList *pmc_syncs;
extern PMList *pm_targets;
/* borrowed and modifed from Per Liden's pkgutils (http://crux.nu) */
static int gzopen_frontend(char *pathname, int oflags, int mode)
/* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */
int gzopen_frontend(char *pathname, int oflags, int mode)
{
char* gzoflags;
int fd;
@ -102,17 +66,16 @@ static int gzopen_frontend(char *pathname, int oflags, int mode)
return (int)gzf;
}
tartype_t gztype = {
(openfunc_t) gzopen_frontend,
(closefunc_t)gzclose,
(readfunc_t) gzread,
(writefunc_t)gzwrite
};
int unpack(char *archive, char *prefix)
{
TAR *tar = NULL;
char expath[PATH_MAX];
tartype_t gztype = {
(openfunc_t) gzopen_frontend,
(closefunc_t)gzclose,
(readfunc_t) gzread,
(writefunc_t)gzwrite
};
/* open the .tar.gz package */
if(tar_open(&tar, archive, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
@ -130,280 +93,6 @@ int unpack(char *archive, char *prefix)
return(0);
}
/* 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'},
{"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'},
{"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'},
{0, 0, 0, 0}
};
while((opt = getopt_long(argc, argv, "ARUFQSTDYr:vhscVfnoldpiuwy", 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 'v': pmo_verbose = 1; break;
case 'f': pmo_force = 1; break;
case 'd': pmo_nodeps = 1; break;
case 'n': pmo_nosave = 1; break;
case 'l': pmo_q_list = 1; break;
case 'p': pmo_q_isfile = 1; break;
case 'i': pmo_q_info = 1; break;
case 'o': pmo_q_owns = 1; break;
case 'u': pmo_s_upgrade = 1; break;
case 'w': pmo_s_downloadonly = 1; break;
case 'y': pmo_s_sync = 1; break;
case 's': pmo_s_search = 1; break;
case 'c': pmo_s_clean = 1; pmo_r_cascade = 1; break;
case 'r': if(realpath(optarg, pmo_root) == NULL) {
perror("bad root path");
return(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);
}
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
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 {
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 {
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);
}
int copyfile(char *src, char *dest)
{
FILE *in, *out;
@ -501,94 +190,6 @@ int rmrf(char *path)
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(" -f, --force force install, overwrite conflicting files\n");
printf(" -d, --nodeps skip dependency checks\n");
} else if(op == PM_REMOVE) {
printf("usage: %s {-R --remove} [options] <package>\n", myname);
printf("options:\n");
printf(" -d, --nodeps skip dependency checks\n");
printf(" -n, --nosave remove configuration files as well\n");
printf(" -c, --cascade remove packages and all packages that depend on them\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(" -f, --force force install, overwrite conflicting files\n");
printf(" -d, --nodeps skip dependency checks\n");
} else if(op == PM_QUERY) {
printf("usage: %s {-Q --query} [options] [package]\n", myname);
printf("options:\n");
printf(" -o, --owns <file> query the package that owns <file>\n");
printf(" -l, --list list the contents of the queried package\n");
printf(" -i, --info view package information\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(" -s, --search search sync database for matching strings\n");
printf(" -f, --force force install, overwrite conflicting files\n");
printf(" -d, --nodeps skip dependency checks\n");
printf(" -y, --refresh download a fresh package sync database from the server\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(" -c, --clean remove packages from cache directory to free up diskspace\n");
}
printf(" -v, --verbose be verbose\n");
printf(" -r, --root <path> set an alternate installation root\n");
}
}
/* Version
*/
void version(void)
{
printf("\n");
printf(" .--. Pacman v%s\n", PACVER);
printf("/ _.-' .-. .-. .-. Copyright (C) 2002 Judd Vinet <jvinet@zeroflux.org>\n");
printf("\\ '-. '-' '-' '-' \n");
printf(" '--' This program may be freely redistributed under\n");
printf(" the terms of the GNU GPL\n\n");
}
/* Check verbosity option and, if set, print the
* string to stdout
*/
int vprint(char *fmt, ...)
{
va_list args;
if(pmo_verbose) {
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
return(0);
}
int yesno(char *fmt, ...)
{
char response[32];
@ -651,76 +252,6 @@ void indentprint(char *str, int indent)
}
}
/* Test for existence of a string in a PMList
*/
int is_in(char *needle, PMList *haystack)
{
PMList *lp;
for(lp = haystack; lp; lp = lp->next) {
if(lp->data && !strcmp(lp->data, needle)) {
return(1);
}
}
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);
}
/* Test for existence of a package in a PMList*
* of pkginfo_t*
*
* returns: 0 for no match
* 1 for identical match
* -1 for name-only match (version mismatch)
*/
int is_pkgin(pkginfo_t *needle, PMList *haystack)
{
PMList *lp;
pkginfo_t *info;
for(lp = haystack; lp; lp = lp->next) {
info = (pkginfo_t*)lp->data;
if(info && !strcmp(info->name, needle->name)) {
if(!strcmp(info->version, needle->version)) {
return(1);
}
return(-1);
}
}
return(0);
}
/* Convert a string to uppercase
*/
char* strtoupper(char *str)

View file

@ -21,30 +21,20 @@
#ifndef _PAC_UTIL_H
#define _PAC_UTIL_H
#include <libtar.h>
#include <zlib.h>
#define MALLOC(p, b) { if((b) > 0) { \
p = malloc(b); if (!(p)) { \
fprintf(stderr, "malloc failure: could not allocate %d byets\n", b); \
fprintf(stderr, "malloc failure: could not allocate %d bytes\n", b); \
exit(1); }} else p = NULL; }
#define FREE(p) { if (p) { free(p); (p)= NULL; }}
int gzopen_frontend(char *pathname, int oflags, int mode);
int unpack(char *archive, char *prefix);
int parseargs(int op, int argc, char **argv);
int parseconfig(char *configfile);
int copyfile(char *src, char *dest);
int makepath(char *path);
int rmrf(char *path);
int vprint(char *fmt, ...);
void indentprint(char *str, int indent);
int yesno(char* fmt, ...);
void usage(int op, char *myname);
void version(void);
char* needbackup(char *file, PMList *backup);
int is_in(char *needle, PMList *haystack);
int is_pkgin(pkginfo_t *needle, PMList *haystack);
char* trim(char *str);
char* strtoupper(char *str);

View file

@ -1,7 +1,27 @@
/*
* pacman
*
* 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 <stdio.h>
#include <string.h>
int rpmvercmp(const char *a, const char *b);
#include "rpmvercmp.h"
int main(int argc, char *argv[])
{