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 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.1 - Fixed a bug in makepkg's option parsing
2.4 - Added getopt-style options to makeworld 2.4 - Added getopt-style options to makeworld
- Added -w <destdir> to makepkg - Added -w <destdir> to makepkg

View file

@ -34,7 +34,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
PACVER = 2.4.1 PACVER = 2.5
TOPDIR = @srcdir@ TOPDIR = @srcdir@
SRCDIR = $(TOPDIR)/src/ SRCDIR = $(TOPDIR)/src/
@ -43,7 +43,7 @@ MANSRC = $(TOPDIR)/doc/
SCRDIR = $(TOPDIR)/scripts/ SCRDIR = $(TOPDIR)/scripts/
CXX = @CC@ 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 -D_GNU_SOURCE -DPACVER=\"$(PACVER)\" -I. -Ilibftp
LDFLAGS += @LDFLAGS@ -static -Llibftp -lftp -ltar -lz LDFLAGS += @LDFLAGS@ -static -Llibftp -lftp -ltar -lz
@ -53,9 +53,10 @@ SRCS = $(SRCDIR)pacman.c \
$(SRCDIR)list.c \ $(SRCDIR)list.c \
$(SRCDIR)package.c \ $(SRCDIR)package.c \
$(SRCDIR)pacsync.c \ $(SRCDIR)pacsync.c \
$(SRCDIR)rpmvercmp.c \
$(SRCDIR)md5.c \ $(SRCDIR)md5.c \
$(SRCDIR)md5driver.c $(SRCDIR)md5driver.c \
$(SRCDIR)vercmp.c \
$(SRCDIR)rpmvercmp.c
OBJECTS = $(OBJDIR)pacman.o \ OBJECTS = $(OBJDIR)pacman.o \
$(OBJDIR)db.o \ $(OBJDIR)db.o \
@ -63,20 +64,20 @@ OBJECTS = $(OBJDIR)pacman.o \
$(OBJDIR)list.o \ $(OBJDIR)list.o \
$(OBJDIR)package.o \ $(OBJDIR)package.o \
$(OBJDIR)pacsync.o \ $(OBJDIR)pacsync.o \
$(OBJDIR)rpmvercmp.o \
$(OBJDIR)md5.o \ $(OBJDIR)md5.o \
$(OBJDIR)md5driver.o $(OBJDIR)md5driver.o \
$(OBJDIR)rpmvercmp.o
all: ftplib pacman vercmp convertdb man all: ftplib pacman vercmp convertdb man
pacman: $(OBJECTS) pacman: $(OBJECTS)
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS) $(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
vercmp: $(OBJDIR)rpmvercmp.o $(OBJDIR)vercmp.o vercmp: $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o
$(CXX) $(OBJDIR)rpmvercmp.o $(OBJDIR)vercmp.o -o $@ $(CXX) $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o $(CXXFLAGS) -o $@
convertdb: $(SRCDIR)convertdb.c $(SRCDIR)list.c convertdb: $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o
$(CXX) -o convertdb $(SRCDIR)convertdb.c $(SRCDIR)list.c $(CXXFLAGS) $(CXX) $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o $(CXXFLAGS) -lz -ltar -o $@
.c.o: $(SRCS) .c.o: $(SRCS)
$(CXX) $(CXXFLAGS) -o $@ -c $< $(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 .SH NAME
makepkg \- package build utility makepkg \- package build utility
.SH SYNOPSIS .SH SYNOPSIS
@ -34,6 +34,7 @@ pkgname=modutils
pkgver=2.4.13 pkgver=2.4.13
pkgrel=1 pkgrel=1
pkgdesc="Utilities for inserting and removing modules from the linux kernel" pkgdesc="Utilities for inserting and removing modules from the linux kernel"
url="http://www.kernel.org"
backup=(etc/modules.conf) backup=(etc/modules.conf)
depends=('glibc>=2.2.5' 'bash' 'zlib') depends=('glibc>=2.2.5' 'bash' 'zlib')
source=(ftp://ftp.server.com/$pkgname-$pkgver.tar.gz modules.conf) 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 .B pkgdesc
This should be a brief description of the package and its functionality. 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 .TP
.B backup .B backup
A space-delimited array of filenames (without a preceding slash). The A space-delimited array of filenames (without a preceding slash). The
@ -226,21 +232,6 @@ by wget.
.SH MAKEPKG OPTIONS .SH MAKEPKG OPTIONS
.TP .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" .B "\-b, \-\-builddeps"
Build missing dependencies from source. When makepkg finds missing Build missing dependencies from source. When makepkg finds missing
dependencies, it will look for the dependencies' PKGBUILD files under 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. 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. The child makepkg calls will be made with the \fB-b\fP and \fB-i\fP options.
.TP .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" .B "\-d, \-\-nodeps"
Do not perform any dependency checks. This will let you override/ignore any 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 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 file already exists in the build directory. You can override this behaviour with
the \fB--force\fP switch. the \fB--force\fP switch.
.TP .TP
.B "\-w <destdir>" .B "\-i, \-\-install"
Write the resulting package file to the directory \fI<destdir>\fP instead of the Install/Upgrade the package after a successful build.
current working directory.
.TP .TP
.B "\-p <buildscript>" .B "\-p <buildscript>"
Read the package script \fI<buildscript>\fP instead of the default (\fIPKGBUILD\fP). 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 .SH CONFIGURATION
Configuration options are stored in \fI/etc/makepkg.conf\fP. This file is parsed 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 .SH NAME
pacman \- package manager utility pacman \- package manager utility
.SH SYNOPSIS .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 Add a package to the system. Package will be uncompressed
into the installation root and the database will be updated. into the installation root and the database will be updated.
.TP .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" .B "\-F, \-\-freshen"
This is like --upgrade except that, unlike --upgrade, this will only This is like --upgrade except that, unlike --upgrade, this will only
upgrade packages that are already installed on your system. 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 database or can be used on individual .tar.gz packages. See
\fBQUERY OPTIONS\fP below. \fBQUERY OPTIONS\fP below.
.TP .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" .B "\-S, \-\-sync"
Synchronize packages. With this function you can install packages Synchronize packages. With this function you can install packages
directly from the ftp servers, complete with all dependencies required 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 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). \fBpacman -Su\fP to upgrade all packages that are out of date (see below).
.TP .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" .B "\-V, \-\-version"
Display version and exit. Display version and exit.
.TP .TP
@ -53,14 +53,10 @@ Display syntax for the given operation. If no operation was
supplied then the general syntax is shown. supplied then the general syntax is shown.
.SH OPTIONS .SH OPTIONS
.TP .TP
.B "\-v, \-\-verbose" .B "\-c, \-\-cascade"
Output more status and error messages. (only used with \fB--remove\fP)
.TP Remove all target packages, as well as all packages that depend on one
.B "\-f, \-\-force" or more target packages. This operation is recursive.
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 .TP
.B "\-d, \-\-nodeps" .B "\-d, \-\-nodeps"
Skips all dependency checks. Normally, pacman will always check 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 installed and there are no package conflicts in the system. This
switch disables these checks. switch disables these checks.
.TP .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" .B "\-n, \-\-nosave"
(only used with \fB--remove\fP) (only used with \fB--remove\fP)
Instructs pacman to ignore file backup designations. Normally, when 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 \fB--nosave\fP is used, these designations are ignored and the files are
removed. removed.
.TP .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>" .B "\-r, \-\-root <path>"
Specify alternative installation root (default is "/"). This Specify alternative installation root (default is "/"). This
should \fInot\fP be used as a way to install software into 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 which is "owned" by another system. By using this option you not only
specify where the software should be installed, but you also specify where the software should be installed, but you also
specify which package database to use. specify which package database to use.
.TP
.B "\-v, \-\-verbose"
Output more status and error messages.
.SH SYNC OPTIONS .SH SYNC OPTIONS
.TP .TP
.B "\-y, \-\-refresh" .B "\-c, \-\-clean"
Download a fresh copy of the master package list from the ftp server Remove packages from the cache. When pacman downloads packages,
defined in \fI/etc/pacman.conf\fP. This should typically be used each it saves them in \fI/var/cache/pacman/pkg\fP. If you need to free up
time you use \fB--sysupgrade\fP. 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 .TP
.B "\-u, \-\-sysupgrade" .B "\-u, \-\-sysupgrade"
Upgrades all packages that are out of date. pacman will examine every 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 Dependencies are automatically resolved at this level and will be
installed/upgraded if necessary. installed/upgraded if necessary.
.TP .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" .B "\-w, \-\-downloadonly"
Retrieve all packages from the server, but do not install/upgrade anything. Retrieve all packages from the server, but do not install/upgrade anything.
.TP .TP
.B "\-c, \-\-clean" .B "\-y, \-\-refresh"
Remove packages from the cache. When pacman downloads packages, Download a fresh copy of the master package list from the ftp server
it saves them in \fI/var/cache/pacman/pkg\fP. If you need to free up defined in \fI/etc/pacman.conf\fP. This should typically be used each
diskspace, you can remove these packages by using the --clean option. time you use \fB--sysupgrade\fP.
.SH QUERY OPTIONS .SH QUERY OPTIONS
.TP .TP
.B "\-o, \-\-owns <file>" .B "\-i, \-\-info"
Search for the package that owns <file>. Display information on a given package. If it is used with the \fB-p\fP
option then the .PKGINFO file will be printed.
.TP .TP
.B "\-l, \-\-list" .B "\-l, \-\-list"
List all files owned by <package>. Multiple packages can be specified on List all files owned by <package>. Multiple packages can be specified on
the command line. the command line.
.TP .TP
.B "\-i, \-\-info" .B "\-o, \-\-owns <file>"
Display information on a given package. If it is used with the \fB-p\fP Search for the package that owns <file>.
option then the .PKGINFO file will be printed.
.TP .TP
.B "\-p, \-\-file" .B "\-p, \-\-file"
Tells pacman that the package supplied on the command line is a Tells pacman that the package supplied on the command line is a
@ -185,9 +185,9 @@ Server = local:///home/pkgs
.RE .RE
.SH CONFIG: OPTIONS .SH CONFIG: OPTIONS
.TP .TP
.B "NoUpgrade = <file> [file] ..." .B "DBPath = /path/to/db/dir"
All files listed with a \fBNoUpgrade\fP directive will never be touched during a package Overrides the default location of the toplevel database directory. The default is
install/upgrade. \fINote:\fP do not include the leading slash when specifying files. \fI/var/lib/pacman\fP.
.TP .TP
.B "IgnorePkg = <package> [package] ..." .B "IgnorePkg = <package> [package] ..."
Instructs pacman to ignore any upgrades for this package when performing a 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 .TP
.B "NoPassiveFtp" .B "NoPassiveFtp"
Disables passive ftp connections when downloading packages. (aka Active Mode) 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 .SH CONFIG: REPOSITORIES
Each repository section defines a section name and at least one location where the packages Each repository section defines a section name and at least one location where the packages

View file

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

View file

@ -1,12 +1,12 @@
#!/bin/bash #!/bin/bash
myver='2.4.1' myver='2.5'
startdir=`pwd` startdir=`pwd`
[ -f /etc/makepkg.conf ] && source /etc/makepkg.conf [ -f /etc/makepkg.conf ] && source /etc/makepkg.conf
strip_url() { strip_url() {
echo $1 | sed 's|^.*://.*/||g' echo $1 | sed 's|^.*://.*/||g'
} }
msg() { msg() {
@ -14,57 +14,57 @@ msg() {
} }
checkdeps() { checkdeps() {
local missdep=`pacman -T $*` local missdep=`pacman -T $*`
local deplist="" local deplist=""
missdep=`pacman -T $*` missdep=`pacman -T $*`
ret=$? ret=$?
if [ "$ret" != "0" ]; then if [ "$ret" != "0" ]; then
if [ "$ret" = "127" ]; then if [ "$ret" = "127" ]; then
msg "==> Missing Dependencies:" msg "==> Missing Dependencies:"
msg "" msg ""
nl=0 nl=0
for dep in $missdep; do for dep in $missdep; do
echo -ne "$dep " >&2 echo -ne "$dep " >&2
if [ "$nl" = "1" ]; then if [ "$nl" = "1" ]; then
nl=0 nl=0
echo -ne "\n" >&2 echo -ne "\n" >&2
# add this dep to the list # add this dep to the list
depname=`echo $dep | sed 's|=.*$||' | sed 's|>.*$||' | sed 's|<.*$||'` depname=`echo $dep | sed 's|=.*$||' | sed 's|>.*$||' | sed 's|<.*$||'`
deplist="$deplist $depname" deplist="$deplist $depname"
continue continue
fi fi
nl=1 nl=1
done done
msg "" msg ""
else else
msg "==> ERROR: pacman returned a fatal error." msg "==> ERROR: pacman returned a fatal error."
exit 1 exit 1
fi fi
fi fi
echo $deplist echo $deplist
} }
usage() { usage() {
echo "makepkg version $myver" echo "makepkg version $myver"
echo "usage: $0 [options]" echo "usage: $0 [options]"
echo "options:" echo "options:"
echo " -c, --clean Clean up work files after build" echo " -c, --clean Clean up work files after build"
echo " -C, --cleancache Clean up source files from the cache" echo " -C, --cleancache Clean up source files from the cache"
echo " -s, --syncdeps Install missing dependencies with pacman" echo " -s, --syncdeps Install missing dependencies with pacman"
echo " -b, --builddeps Build missing dependencies from source" echo " -b, --builddeps Build missing dependencies from source"
echo " -d, --nodeps Skip all dependency checks" echo " -d, --nodeps Skip all dependency checks"
echo " -i, --install Install package after successful build" echo " -i, --install Install package after successful build"
echo " -f, --force Overwrite existing package" echo " -f, --force Overwrite existing package"
echo " -w <destdir> Write package to <destdir> instead of the working dir" echo " -w <destdir> Write package to <destdir> instead of the working dir"
echo " -p <buildscript> Use an alternate build script (instead of PKGBUILD)" echo " -p <buildscript> Use an alternate build script (instead of PKGBUILD)"
echo " -h, --help This help" echo " -h, --help This help"
echo 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 " file in the current directory."
echo echo
exit 0 exit 0
} }
# Options # Options
@ -79,139 +79,135 @@ PKGDEST=$startdir
BUILDSCRIPT="./PKGBUILD" BUILDSCRIPT="./PKGBUILD"
while [ "$#" -ne "0" ]; do while [ "$#" -ne "0" ]; do
case $1 in case $1 in
--clean) CLEANUP=1 ;; --clean) CLEANUP=1 ;;
--cleancache) CLEANCACHE=1 ;; --cleancache) CLEANCACHE=1 ;;
--syncdeps) DEP_BIN=1 ;; --syncdeps) DEP_BIN=1 ;;
--builddeps) DEP_SRC=1 ;; --builddeps) DEP_SRC=1 ;;
--nodeps) NODEPS=1 ;; --nodeps) NODEPS=1 ;;
--install) INSTALL=1 ;; --install) INSTALL=1 ;;
--force) FORCE=1 ;; --force) FORCE=1 ;;
--*) --*)
usage usage
exit 1 exit 1
;; ;;
-*) -*)
while getopts "cCsbdifp:w:-" opt; do while getopts "cCsbdifp:w:-" opt; do
case $opt in case $opt in
c) CLEANUP=1 ;; c) CLEANUP=1 ;;
C) CLEANCACHE=1 ;; C) CLEANCACHE=1 ;;
s) DEP_BIN=1 ;; s) DEP_BIN=1 ;;
b) DEP_SRC=1 ;; b) DEP_SRC=1 ;;
d) NODEPS=1 ;; d) NODEPS=1 ;;
i) INSTALL=1 ;; i) INSTALL=1 ;;
f) FORCE=1 ;; f) FORCE=1 ;;
w) w) PKGDEST=$OPTARG ;;
PKGDEST=$OPTARG p) BUILDSCRIPT=$OPTARG ;;
;; -)
p) OPTIND=0
BUILDSCRIPT=$OPTARG break
;; ;;
-) *)
OPTIND=0 usage
break exit 1
;; ;;
*) esac
usage done
exit 1 ;;
;; *)
esac true
done ;;
;; esac
*) shift
true
;;
esac
shift
done done
if [ "$CLEANCACHE" = "1" ]; then if [ "$CLEANCACHE" = "1" ]; then
msg "==> Cleaning up source files from the cache" msg "==> Cleaning up source files from the cache"
rm -rf /var/cache/pacman/src/* rm -rf /var/cache/pacman/src/*
exit 0 exit 0
fi fi
unset pkgname pkgver pkgrel pkgdesc unset pkgname pkgver pkgrel pkgdesc url
unset depends conflicts backup source install build unset depends conflicts backup source install build
umask 0022 umask 0022
if [ ! -f $BUILDSCRIPT ]; then if [ ! -f $BUILDSCRIPT ]; then
msg "==> ERROR: $BUILDSCRIPT does not exist." msg "==> ERROR: $BUILDSCRIPT does not exist."
exit 1 exit 1
fi fi
source $BUILDSCRIPT source $BUILDSCRIPT
# check for no-no's # check for no-no's
if [ `echo $pkgver | grep '-'` ]; then if [ `echo $pkgver | grep '-'` ]; then
msg "==> ERROR: pkgver is not allowed to contain hyphens." msg "==> ERROR: pkgver is not allowed to contain hyphens."
exit 1 exit 1
fi fi
if [ `echo $pkgrel | grep '-'` ]; then if [ `echo $pkgrel | grep '-'` ]; then
msg "==> ERROR: pkgrel is not allowed to contain hyphens." msg "==> ERROR: pkgrel is not allowed to contain hyphens."
exit 1 exit 1
fi fi
if [ -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}.pkg.tar.gz -a "$FORCE" = "0" ]; then if [ -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}.pkg.tar.gz -a "$FORCE" = "0" ]; then
msg "==> ERROR: a package has already been built. (use -f to overwrite)" msg "==> ERROR: a package has already been built. (use -f to overwrite)"
exit 1 exit 1
fi fi
unset deplist unset deplist
if [ `type -p pacman` -a "$NODEPS" = "0" ]; then if [ `type -p pacman` -a "$NODEPS" = "0" ]; then
msg "==> Checking Dependencies..." msg "==> Checking Dependencies..."
deplist=`checkdeps ${depends[@]}` deplist=`checkdeps ${depends[@]}`
if [ "$deplist" != "" ]; then if [ "$deplist" != "" ]; then
if [ "$DEP_BIN" = "1" ]; then if [ "$DEP_BIN" = "1" ]; then
# install missing deps from binary packages (using pacman -S) # install missing deps from binary packages (using pacman -S)
msg "==> Installing missing dependencies..." msg "==> Installing missing dependencies..."
pacman -D $deplist pacman -D $deplist
if [ "$?" = "127" ]; then if [ "$?" = "127" ]; then
msg "==> ERROR: Failed to install missing dependencies." msg "==> ERROR: Failed to install missing dependencies."
exit 1 exit 1
fi fi
# TODO: check deps again to make sure they were resolved # TODO: check deps again to make sure they were resolved
elif [ "$DEP_SRC" = "1" ]; then elif [ "$DEP_SRC" = "1" ]; then
# install missing deps by building them from source. # install missing deps by building them from source.
# we look for each package name in $ABSROOT and build it. # we look for each package name in $ABSROOT and build it.
if [ "$ABSROOT" = "" ]; then if [ "$ABSROOT" = "" ]; then
msg "==> ERROR: The ABSROOT environment variable is not defined." msg "==> ERROR: The ABSROOT environment variable is not defined."
exit 1 exit 1
fi fi
# TODO: handle version comparators (eg, glibc>=2.2.5) # TODO: handle version comparators (eg, glibc>=2.2.5)
msg "==> Building missing dependencies..." msg "==> Building missing dependencies..."
for dep in $deplist; do for dep in $deplist; do
candidates=`find $ABSROOT -type d -name "$dep"` candidates=`find $ABSROOT -type d -name "$dep"`
if [ "$candidates" = "" ]; then if [ "$candidates" = "" ]; then
msg "==> ERROR: Could not find \"$dep\" under $ABSROOT" msg "==> ERROR: Could not find \"$dep\" under $ABSROOT"
exit 1 exit 1
fi fi
success=0 success=0
for pkgdir in $candidates; do for pkgdir in $candidates; do
if [ -f $pkgdir/PKGBUILD ]; then if [ -f $pkgdir/PKGBUILD ]; then
cd $pkgdir cd $pkgdir
echo makepkg -i -c -b -w $PKGDEST echo makepkg -i -c -b -w $PKGDEST
makepkg -i -c -b -w $PKGDEST makepkg -i -c -b -w $PKGDEST
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
success=1 success=1
break break
fi fi
fi fi
done done
if [ "$success" = "0" ]; then if [ "$success" = "0" ]; then
msg "==> ERROR: Failed to build \"$dep\"" msg "==> ERROR: Failed to build \"$dep\""
exit 1 exit 1
fi fi
done done
# TODO: check deps again to make sure they were resolved # TODO: check deps again to make sure they were resolved
else else
exit 1 exit 1
fi fi
fi fi
elif [ "$NODEPS" = "1" ]; then elif [ "$NODEPS" = "1" ]; then
msg "==> WARNING: skipping dependency checks." msg "==> WARNING: skipping dependency checks."
else else
msg "==> WARNING: pacman was not found in PATH. skipping dependency checks." msg "==> WARNING: pacman was not found in PATH. skipping dependency checks."
fi fi
d=`date` d=`date`
@ -223,69 +219,69 @@ msg "==> Acquiring/Extracting Sources..."
mkdir -p src mkdir -p src
cd $startdir/src cd $startdir/src
for netfile in ${source[@]}; do for netfile in ${source[@]}; do
file=`strip_url $netfile` file=`strip_url $netfile`
if [ -f ../$file ]; then if [ -f ../$file ]; then
msg "==> Found $file in build dir" msg "==> Found $file in build dir"
cp ../$file . cp ../$file .
elif [ -f /var/cache/pacman/src/$file ]; then elif [ -f /var/cache/pacman/src/$file ]; then
msg "==> Using local copy of $file" msg "==> Using local copy of $file"
cp /var/cache/pacman/src/$file . cp /var/cache/pacman/src/$file .
else else
# check for a download utility # check for a download utility
if [ -z "$FTPAGENT" ]; then if [ -z "$FTPAGENT" ]; then
msg "==> ERROR: FTPAGENT is not configured. Check the /etc/makepkg.conf file." msg "==> ERROR: FTPAGENT is not configured. Check the /etc/makepkg.conf file."
msg "==> Aborting..." msg "==> Aborting..."
exit 1 exit 1
fi fi
ftpclient=`echo $FTPAGENT | awk {'print $1'}` ftpclient=`echo $FTPAGENT | awk {'print $1'}`
if [ ! -x $ftpclient ]; then if [ ! -x $ftpclient ]; then
msg "==> ERROR: ftpclient `basename $ftpclient` is not installed." msg "==> ERROR: ftpclient `basename $ftpclient` is not installed."
msg "==> Aborting..." msg "==> Aborting..."
exit 1 exit 1
fi fi
proto=`echo $netfile | sed 's|://.*||'` proto=`echo $netfile | sed 's|://.*||'`
if [ "$proto" != "ftp" -a "$proto" != "http" ]; then if [ "$proto" != "ftp" -a "$proto" != "http" ]; then
msg "==> ERROR: $netfile was not found in the build directory and is not a proper URL." msg "==> ERROR: $netfile was not found in the build directory and is not a proper URL."
msg "==> Aborting..." msg "==> Aborting..."
exit 1 exit 1
fi fi
msg "==> Downloading $file" msg "==> Downloading $file"
$FTPAGENT $netfile 2>&1 $FTPAGENT $netfile 2>&1
if [ ! -f $file ]; then if [ ! -f $file ]; then
msg "==> ERROR: Failed to download $file" msg "==> ERROR: Failed to download $file"
msg "==> Aborting..." msg "==> Aborting..."
exit 1 exit 1
fi fi
mkdir -p /var/cache/pacman/src && cp $file /var/cache/pacman/src mkdir -p /var/cache/pacman/src && cp $file /var/cache/pacman/src
fi fi
unset cmd unset cmd
case $file in case $file in
*.tar.gz|*.tar.Z|*.tgz) *.tar.gz|*.tar.Z|*.tgz)
cmd="tar --use-compress-program=gzip -xf $file" ;; cmd="tar --use-compress-program=gzip -xf $file" ;;
*.tar.bz2) *.tar.bz2)
cmd="tar --use-compress-program=bzip2 -xf $file" ;; cmd="tar --use-compress-program=bzip2 -xf $file" ;;
*.tar) *.tar)
cmd="tar -xf $file" ;; cmd="tar -xf $file" ;;
*.zip) *.zip)
cmd="unzip -qq $file" ;; cmd="unzip -qq $file" ;;
*.gz) *.gz)
cmd="gunzip $file" ;; cmd="gunzip $file" ;;
esac esac
if [ "$cmd" != "" ]; then if [ "$cmd" != "" ]; then
msg "==> $cmd" msg "==> $cmd"
$cmd $cmd
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
msg "==> ERROR: Failed to extract $file" msg "==> ERROR: Failed to extract $file"
msg "==> Aborting..." msg "==> Aborting..."
exit 1 exit 1
fi fi
fi fi
done done
# check for existing pkg directory # check for existing pkg directory
if [ -d $startdir/pkg ]; then if [ -d $startdir/pkg ]; then
msg "==> Removing existing pkg directory..." msg "==> Removing existing pkg directory..."
rm -rf $startdir/pkg rm -rf $startdir/pkg
fi fi
mkdir -p $startdir/pkg mkdir -p $startdir/pkg
@ -293,8 +289,8 @@ mkdir -p $startdir/pkg
msg "==> Building Package..." msg "==> Building Package..."
build 2>&1 build 2>&1
if [ $? -gt 0 ]; then if [ $? -gt 0 ]; then
msg "==> Build Failed. Aborting..." msg "==> Build Failed. Aborting..."
exit 2 exit 2
fi fi
# remove info/doc files # remove info/doc files
@ -304,30 +300,36 @@ rm -rf pkg/usr/doc pkg/usr/share/doc
# move /usr/share/man files to /usr/man # move /usr/share/man files to /usr/man
if [ -d pkg/usr/share/man ]; then if [ -d pkg/usr/share/man ]; then
mkdir -p pkg/usr/man mkdir -p pkg/usr/man
cp -a pkg/usr/share/man/* pkg/usr/man/ cp -a pkg/usr/share/man/* pkg/usr/man/
rm -rf pkg/usr/share/man 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 fi
# compress man pages # compress man pages
if [ -d pkg/usr/man ]; then if [ -d pkg/usr/man ]; then
msg "==> Compressing man pages..." msg "==> Compressing man pages..."
for i in `find pkg/usr/man -type f`; do for i in `find pkg/usr/man -type f`; do
ext=`echo $i | sed 's|.*\.||g'` ext=`echo $i | sed 's|.*\.||g'`
fn=`echo $i | sed 's|.*/||g'` fn=`echo $i | sed 's|.*/||g'`
if [ "$ext" != "gz" ]; then if [ "$ext" != "gz" ]; then
# update symlinks to this manpage # update symlinks to this manpage
for ln in `find pkg/usr/man -lname "$fn"`; do for ln in `find pkg/usr/man -lname "$fn"`; do
rm -f $ln rm -f $ln
ln -sf ${fn}.gz ${ln}.gz ln -sf ${fn}.gz ${ln}.gz
done done
# compress the original # compress the original
gzip -9 $i gzip -9 $i
fi fi
done done
fi fi
# strip binaries # strip binaries
cd $startdir cd $startdir
msg "==> Stripping debugging symbols from libraries..." msg "==> Stripping debugging symbols from libraries..."
@ -338,9 +340,9 @@ find pkg/{,usr,usr/local,opt/*}/{bin,sbin} -type f -exec /usr/bin/strip '{}' ';'
# get some package meta info # get some package meta info
builddate=`date -u "+%a %b %d %k:%M:%S %Y"` builddate=`date -u "+%a %b %d %k:%M:%S %Y"`
if [ "$PACKAGER" != "" ]; then if [ "$PACKAGER" != "" ]; then
packager="$PACKAGER" packager="$PACKAGER"
else else
packager="Arch Linux (http://www.archlinux.org)" packager="Arch Linux (http://www.archlinux.org)"
fi fi
size=`du -cb $startdir/pkg | tail -1 | awk '{print $1}'` size=`du -cb $startdir/pkg | tail -1 | awk '{print $1}'`
@ -353,47 +355,53 @@ date >>.PKGINFO
echo "pkgname = $pkgname" >>.PKGINFO echo "pkgname = $pkgname" >>.PKGINFO
echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO
echo "pkgdesc = $pkgdesc" >>.PKGINFO echo "pkgdesc = $pkgdesc" >>.PKGINFO
echo "url = $url" >>.PKGINFO
echo "builddate = $builddate" >>.PKGINFO echo "builddate = $builddate" >>.PKGINFO
echo "packager = $packager" >>.PKGINFO echo "packager = $packager" >>.PKGINFO
echo "size = $size" >>.PKGINFO echo "size = $size" >>.PKGINFO
for depend in "${depends[@]}"; do for depend in "${depends[@]}"; do
echo "depend = $depend" >>.PKGINFO echo "depend = $depend" >>.PKGINFO
done done
for conflict in "${conflicts[@]}"; do for conflict in "${conflicts[@]}"; do
echo "conflict = $conflict" >>.PKGINFO echo "conflict = $conflict" >>.PKGINFO
done done
for bakfile in "${backup[@]}"; do for bakfile in "${backup[@]}"; do
echo "backup = $bakfile" >>.PKGINFO echo "backup = $bakfile" >>.PKGINFO
done done
# check for an install script # check for an install script
if [ "$install" != "" ]; then if [ "$install" != "" ]; then
msg "==> Copying install script..." msg "==> Copying install script..."
cp $startdir/$install $startdir/pkg/._install cp $startdir/$install $startdir/pkg/.INSTALL
fi fi
# build a filelist
msg "==> Building filelist..."
cd $startdir/pkg
tar cv * >/dev/null 2>.FILELIST
# tar it up # tar it up
msg "==> Compressing package..." msg "==> Compressing package..."
cd $startdir/pkg cd $startdir/pkg
if [ -f $startdir/pkg/._install ]; then if [ -f $startdir/pkg/.INSTALL ]; then
tar czvf $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO ._install * >../filelist cmd="tar czvf $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO .FILELIST .INSTALL *"
else 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 fi
$cmd >../filelist
cd $startdir cd $startdir
if [ "$CLEANUP" = "1" ]; then if [ "$CLEANUP" = "1" ]; then
msg "==> Cleaning up" msg "==> Cleaning up"
rm -rf src pkg filelist rm -rf src pkg filelist
fi fi
d=`date` msg "==> Finished making $pkgname (`date`)"
msg "==> Finished making $pkgname ($d)"
if [ "$INSTALL" = "1" ]; then if [ "$INSTALL" = "1" ]; then
msg "==> Running pacman --upgrade" msg "==> Running pacman --upgrade"
pacman --upgrade $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz pacman --upgrade $PKGDEST/$pkgname-$pkgver-$pkgrel.pkg.tar.gz
fi fi
exit 0 exit 0

View file

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

View file

@ -29,8 +29,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "list.h" #include "list.h"
#include "util.h"
char* trim(char *str);
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
@ -139,25 +138,4 @@ int main(int argc, char* argv[])
return(0); 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: */ /* vim: set ts=2 sw=2 noet: */

View file

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

View file

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

View file

@ -20,14 +20,9 @@
*/ */
#include "config.h" #include "config.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include "list.h" #include "list.h"
PMList* list_new() PMList* list_new()
@ -105,6 +100,20 @@ int list_isin(PMList *haystack, void *needle)
return(0); 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 one is extended and returned
* List two is freed (but not its data) * List two is freed (but not its data)
*/ */
@ -131,4 +140,77 @@ PMList* list_last(PMList *list)
return(ptr); 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: */ /* 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 #ifndef _PAC_LIST_H
#define _PAC_LIST_H #define _PAC_LIST_H
@ -13,8 +33,12 @@ void list_free(PMList* list);
PMList* list_add(PMList* list, void* data); PMList* list_add(PMList* list, void* data);
int list_count(PMList* list); int list_count(PMList* list);
int list_isin(PMList *haystack, void *needle); int list_isin(PMList *haystack, void *needle);
int is_in(char *needle, PMList *haystack);
PMList* list_merge(PMList *one, PMList *two); PMList* list_merge(PMList *one, PMList *two);
PMList* list_last(PMList* list); 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 #endif

View file

@ -45,4 +45,7 @@ void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, unsigned char *, unsigned int); void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
void MD5Final(unsigned char [16], MD5_CTX *); void MD5Final(unsigned char [16], MD5_CTX *);
char* MDFile(char *);
void MDPrint(unsigned char [16]);
/* vim: set ts=2 sw=2 noet: */ /* 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_LEN 1000
#define TEST_BLOCK_COUNT 1000 #define TEST_BLOCK_COUNT 1000
char* MDFile(char *);
void MDPrint(unsigned char [16]);
#define MD_CTX MD5_CTX #define MD_CTX MD5_CTX
#define MDInit MD5Init #define MDInit MD5Init
#define MDUpdate MD5Update #define MDUpdate MD5Update

View file

@ -24,39 +24,45 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include "list.h" #include <libtar.h>
#include "package.h" #include <zlib.h>
#include "db.h"
#include "util.h" #include "util.h"
#include "pacsync.h" #include "package.h"
#include "pacman.h"
extern tartype_t gztype;
pkginfo_t* load_pkg(char *pkgfile, unsigned short output) pkginfo_t* load_pkg(char *pkgfile, unsigned short output)
{ {
char *expath; char *expath;
char *descfile;
int i; int i;
int config = 0;
int filelist = 0;
TAR *tar; TAR *tar;
pkginfo_t *info = NULL; pkginfo_t *info = NULL;
PMList *backup = NULL; PMList *backup = NULL;
PMList *lp; PMList *lp;
tartype_t gztype = {
(openfunc_t) gzopen_frontend,
(closefunc_t)gzclose,
(readfunc_t) gzread,
(writefunc_t)gzwrite
};
info = newpkg(); info = newpkg();
descfile = strdup("/tmp/pacman_XXXXXX");
if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
perror("could not open package"); perror("could not open package");
return(NULL); return(NULL);
} }
vprint("load_pkg: loading filelist from package...\n");
for(i = 0; !th_read(tar); i++) { for(i = 0; !th_read(tar); i++) {
if(config && filelist) {
/* we have everything we need */
break;
}
if(!strcmp(th_get_pathname(tar), ".PKGINFO")) { if(!strcmp(th_get_pathname(tar), ".PKGINFO")) {
char *descfile;
/* extract this file into /tmp. it has info for us */ /* 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); mkstemp(descfile);
tar_extract_file(tar, descfile); tar_extract_file(tar, descfile);
/* parse the info file */ /* parse the info file */
@ -74,14 +80,43 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output)
info->backup = list_add(info->backup, lp->data); info->backup = list_add(info->backup, lp->data);
} }
} }
config = 1;
FREE(descfile);
continue; continue;
} } else if(!strcmp(th_get_pathname(tar), "._install") || !strcmp(th_get_pathname(tar), ".INSTALL")) {
if(!strcmp(th_get_pathname(tar), "._install")) {
info->scriptlet = 1; 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;
}
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 { } else {
expath = strdup(th_get_pathname(tar)); if(!filelist) {
/* add the path to the list */ /* no .FILELIST present in this package.. build the filelist the */
info->files = list_add(info->files, expath); /* old-fashioned way, one at a time */
expath = strdup(th_get_pathname(tar));
info->files = list_add(info->files, expath);
}
} }
if(TH_ISREG(tar) && tar_skip_regfile(tar)) { if(TH_ISREG(tar) && tar_skip_regfile(tar)) {
@ -93,9 +128,8 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output)
expath = NULL; expath = NULL;
} }
tar_close(tar); 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); fprintf(stderr, "load_pkg: missing package info file in %s\n", pkgfile);
return(NULL); 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)); strncpy(info->version, ptr, sizeof(info->version));
} else if(!strcmp(key, "PKGDESC")) { } else if(!strcmp(key, "PKGDESC")) {
strncpy(info->desc, ptr, sizeof(info->desc)); strncpy(info->desc, ptr, sizeof(info->desc));
} else if(!strcmp(key, "URL")) {
strncpy(info->url, ptr, sizeof(info->url));
} else if(!strcmp(key, "BUILDDATE")) { } else if(!strcmp(key, "BUILDDATE")) {
strncpy(info->builddate, ptr, sizeof(info->builddate)); strncpy(info->builddate, ptr, sizeof(info->builddate));
} else if(!strcmp(key, "INSTALLDATE")) { } else if(!strcmp(key, "INSTALLDATE")) {
@ -188,6 +224,7 @@ pkginfo_t* newpkg()
pkg->name[0] = '\0'; pkg->name[0] = '\0';
pkg->version[0] = '\0'; pkg->version[0] = '\0';
pkg->desc[0] = '\0'; pkg->desc[0] = '\0';
pkg->url[0] = '\0';
pkg->builddate[0] = '\0'; pkg->builddate[0] = '\0';
pkg->installdate[0] = '\0'; pkg->installdate[0] = '\0';
pkg->packager[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)); 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: */ /* vim: set ts=2 sw=2 noet: */

View file

@ -21,6 +21,8 @@
#ifndef _PAC_PACKAGE_H #ifndef _PAC_PACKAGE_H
#define _PAC_PACKAGE_H #define _PAC_PACKAGE_H
#include "list.h"
/* mods for depend_t.mod */ /* mods for depend_t.mod */
#define DEP_ANY 0 #define DEP_ANY 0
#define DEP_EQ 1 #define DEP_EQ 1
@ -33,6 +35,7 @@ typedef struct __pkginfo_t {
char name[256]; char name[256];
char version[64]; char version[64];
char desc[512]; char desc[512];
char url[255];
char builddate[32]; char builddate[32];
char installdate[32]; char installdate[32];
char packager[64]; char packager[64];
@ -62,6 +65,8 @@ int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output)
pkginfo_t* newpkg(); pkginfo_t* newpkg();
void freepkg(pkginfo_t *pkg); void freepkg(pkginfo_t *pkg);
int pkgcmp(const void *p1, const void *p2); int pkgcmp(const void *p1, const void *p2);
int is_pkgin(pkginfo_t *needle, PMList *haystack);
void dump_pkg(pkginfo_t *info);
#endif #endif
/* vim: set ts=2 sw=2 noet: */ /* vim: set ts=2 sw=2 noet: */

View file

@ -24,30 +24,26 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <limits.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <dirent.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include <getopt.h>
#include <zlib.h>
#include <libtar.h>
/* pacman */ /* pacman */
#include "list.h" #include "rpmvercmp.h"
#include "md5.h" #include "md5.h"
#include "list.h"
#include "package.h" #include "package.h"
#include "db.h"
#include "util.h" #include "util.h"
#include "db.h"
#include "pacsync.h" #include "pacsync.h"
#include "pacman.h" #include "pacman.h"
extern tartype_t gztype;
/* other prototypes */
int rpmvercmp(const char *a, const char *b);
char* MDFile(char *);
/* /*
* GLOBALS * GLOBALS
* *
@ -77,6 +73,7 @@ unsigned short pmo_s_sync = 0;
unsigned short pmo_s_search = 0; unsigned short pmo_s_search = 0;
unsigned short pmo_s_clean = 0; unsigned short pmo_s_clean = 0;
/* configuration file options */ /* configuration file options */
char *pmo_dbpath = NULL;
PMList *pmo_noupgrade = NULL; PMList *pmo_noupgrade = NULL;
PMList *pmo_ignorepkg = NULL; PMList *pmo_ignorepkg = NULL;
unsigned short pmo_nopassiveftp = 0; unsigned short pmo_nopassiveftp = 0;
@ -91,57 +88,57 @@ PMList *pm_targets = NULL;
char *lckfile = "/tmp/pacman.lck"; char *lckfile = "/tmp/pacman.lck";
char *workfile = NULL; char *workfile = NULL;
enum {READ_ONLY, READ_WRITE} pm_access;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int ret = 0; int ret = 0;
char *ptr = NULL; char *ptr = NULL;
char *dbpath = NULL;
char path[PATH_MAX]; char path[PATH_MAX];
pacdb_t *db_local = NULL; pacdb_t *db_local = NULL;
PMList *lp;
/* default root */ /* default root */
MALLOC(pmo_root, PATH_MAX); MALLOC(pmo_root, PATH_MAX);
strcpy(pmo_root, "/"); strcpy(pmo_root, "/");
/* default dbpath */
MALLOC(pmo_dbpath, PATH_MAX);
strcpy(pmo_dbpath, PKGDIR);
if(argc < 2) { if(argc < 2) {
usage(PM_MAIN, (char*)basename(argv[0])); usage(PM_MAIN, (char*)basename(argv[0]));
return(0); return(0);
} }
/* parse the command line */
ret = parseargs(PM_ADD, argc, argv); ret = parseargs(PM_ADD, argc, argv);
if(ret) { if(ret) {
return(ret); return(ret);
} }
/* check for permission */ /* check for permission */
pm_access = READ_ONLY;
if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) { if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) {
if(pmo_op == PM_SYNC && pmo_s_search) { if(pmo_op == PM_SYNC && pmo_s_search) {
/* special case: PM_SYNC can be used w/ pmo_s_search by any user */ /* special case: PM_SYNC can be used w/ pmo_s_search by any user */
} else { } else {
uid_t uid = geteuid(); if(geteuid() != 0) {
if(uid != 0) {
fprintf(stderr, "error: you cannot perform this operation unless you are root.\n"); fprintf(stderr, "error: you cannot perform this operation unless you are root.\n");
return(1); return(1);
} }
pm_access = READ_WRITE;
/* lock */
if(lckmk(lckfile, 1, 1) == -1) {
fprintf(stderr, "error: unable to lock pacman database.\n");
fprintf(stderr, " if you're sure pacman is not already running, you\n");
fprintf(stderr, " can remove %s\n", lckfile);
return(32);
}
} }
} }
vprint("Installation Root: %s\n", pmo_root); vprint("Installation Root: %s\n", pmo_root);
if(pm_targets) { if(pmo_verbose) {
vprint("Targets:\n"); list_display("Targets: ", pm_targets);
for(lp = pm_targets; lp; lp = lp->next) {
vprint(" %s\n", lp->data);
}
}
/* lock */
if(lckmk(lckfile, 1, 1) == -1) {
fprintf(stderr, "error: unable to lock pacman database.\n");
fprintf(stderr, " if you're sure pacman is not already running, you\n");
fprintf(stderr, " can remove %s\n", lckfile);
return(32);
} }
/* set signal handlers */ /* set signal handlers */
@ -164,28 +161,27 @@ int main(int argc, char *argv[])
pmo_root = ptr; pmo_root = ptr;
} }
/* db location */ /* db location */
MALLOC(dbpath, PATH_MAX); vprint("Top-level DB Path: %s%s\n", pmo_root, pmo_dbpath);
snprintf(dbpath, PATH_MAX-1, "%s%s", pmo_root, PKGDIR);
vprint("Top-level DB Path: %s\n", dbpath);
db_local = db_open(dbpath, "local"); db_local = db_open(pmo_root, pmo_dbpath, "local");
if(db_local == NULL) { if(db_local == NULL) {
/* couldn't open the db directory - try creating it */ /* couldn't open the db directory - try creating it */
char path[PATH_MAX]; char path[PATH_MAX];
snprintf(path, PATH_MAX, "%s/local", dbpath); snprintf(path, PATH_MAX, "%s%s/local", pmo_root, pmo_dbpath);
vprint("initializing database...\n", path); vprint("initializing database %s...\n", path);
ret = makepath(path); ret = makepath(path);
if(ret) { if(ret) {
fprintf(stderr, "error: could not create database.\n"); fprintf(stderr, "error: could not create database.\n");
cleanup(1); 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"); fprintf(stderr, "error: could not open database.\n");
cleanup(1); cleanup(1);
} }
} }
/* load pm_packages cache */ /* load pm_packages cache */
pm_packages = db_loadpkgs(db_local, pm_packages); pm_packages = db_loadpkgs(db_local, pm_packages);
@ -203,7 +199,7 @@ int main(int argc, char *argv[])
} }
db_close(db_local); db_close(db_local);
FREE(pmo_root); FREE(pmo_root);
FREE(dbpath); FREE(pmo_dbpath);
cleanup(ret); cleanup(ret);
/* not reached */ /* not reached */
return(0); return(0);
@ -284,7 +280,6 @@ int pacman_deptest(pacdb_t *db, PMList *targets)
int pacman_sync(pacdb_t *db, PMList *targets) int pacman_sync(pacdb_t *db, PMList *targets)
{ {
char dbpath[PATH_MAX];
int allgood = 1, confirm = 0; int allgood = 1, confirm = 0;
int cols; int cols;
PMList *i, *j, *k; PMList *i, *j, *k;
@ -329,8 +324,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
dbsync_t *dbs = NULL; dbsync_t *dbs = NULL;
sync_t *sync = (sync_t*)i->data; sync_t *sync = (sync_t*)i->data;
snprintf(dbpath, PATH_MAX, "%s%s", pmo_root, PKGDIR); db_sync = db_open(pmo_root, PKGDIR, sync->treename);
db_sync = db_open(dbpath, sync->treename);
if(db_sync == NULL) { if(db_sync == NULL) {
fprintf(stderr, "error: could not open sync database: %s\n", sync->treename); fprintf(stderr, "error: could not open sync database: %s\n", sync->treename);
fprintf(stderr, " have you used --refresh yet?\n"); fprintf(stderr, " have you used --refresh yet?\n");
@ -403,6 +397,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
} }
if(!found) { if(!found) {
/*fprintf(stderr, "%s: not found in sync db. skipping.", local->name);*/ /*fprintf(stderr, "%s: not found in sync db. skipping.", local->name);*/
FREE(sync);
continue; continue;
} }
/* compare versions and see if we need to upgrade */ /* compare versions and see if we need to upgrade */
@ -412,40 +407,32 @@ int pacman_sync(pacdb_t *db, PMList *targets)
fprintf(stderr, ":: %s-%s: local version is newer\n", fprintf(stderr, ":: %s-%s: local version is newer\n",
local->name, local->version); local->name, local->version);
newer = 1; newer = 1;
FREE(sync);
continue; continue;
} else if(cmp == 0) { } else if(cmp == 0) {
/* versions are identical */ /* versions are identical */
FREE(sync);
continue; continue;
} else if(is_in((char*)i->data, pmo_ignorepkg)) { } else if(is_in((char*)i->data, pmo_ignorepkg)) {
/* package should be ignored (IgnorePkg) */ /* package should be ignored (IgnorePkg) */
fprintf(stderr, ":: %s-%s: ignoring package upgrade (%s)\n", fprintf(stderr, ":: %s-%s: ignoring package upgrade (%s)\n",
local->name, local->version, sync->pkg->version); local->name, local->version, sync->pkg->version);
ignore = 1; ignore = 1;
FREE(sync);
continue; continue;
} else { }
PMList *lp = NULL;
int found = 0; /* re-fetch the package record with dependency info */
/* re-fetch the package record with dependency info */ sync->pkg = db_scan(sync->dbs->db, sync->pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
sync->pkg = db_scan(sync->dbs->db, sync->pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
/* add to the targets list */ /* add to the targets list */
for(found = 0, lp = final; lp && !found; lp = lp->next) { found = is_pkginsync(sync, final);
syncpkg_t *s = (syncpkg_t*)lp->data; if(!found) {
if(s && !strcmp(s->pkg->name, sync->pkg->name)) { allgood = !resolvedeps(db, databases, sync, final, trail);
found = 1; /* check again, as resolvedeps could have added our target for us */
} found = is_pkginsync(sync, final);
}
if(!found) { if(!found) {
allgood = !resolvedeps(db, databases, sync, final, trail); final = list_add(final, sync);
/* 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;
}
}
if(!found) {
final = list_add(final, sync);
}
} }
} }
} }
@ -480,6 +467,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(!found) { if(!found) {
fprintf(stderr, "%s: not found in sync db\n", (char*)i->data); fprintf(stderr, "%s: not found in sync db\n", (char*)i->data);
allgood = 0; allgood = 0;
freepkg(local);
FREE(sync);
continue; continue;
} }
if(local && !pmo_s_downloadonly) { if(local && !pmo_s_downloadonly) {
@ -488,36 +477,31 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(cmp > 0) { if(cmp > 0) {
/* local version is newer - get confirmation first */ /* local version is newer - get confirmation first */
if(!yesno(":: %s-%s: local version is newer. Upgrade anyway? [Y/n] ", local->name, local->version)) { if(!yesno(":: %s-%s: local version is newer. Upgrade anyway? [Y/n] ", local->name, local->version)) {
freepkg(local);
freepkg(sync->pkg);
FREE(sync);
continue; continue;
} }
} else if(cmp == 0) { } else if(cmp == 0) {
/* versions are identical */ /* versions are identical */
if(!yesno(":: %s-%s: is up to date. Upgrade anyway? [Y/n] ", local->name, local->version)) { if(!yesno(":: %s-%s: is up to date. Upgrade anyway? [Y/n] ", local->name, local->version)) {
freepkg(local);
freepkg(sync->pkg);
FREE(sync);
continue; continue;
} }
} }
} }
/* add to targets list */ freepkg(local);
found = 0;
for(j = final; j; j = j->next) { found = is_pkginsync(sync, final);
syncpkg_t *tmp = (syncpkg_t*)j->data; if(!found && !pmo_nodeps) {
if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) {
found = 1;
}
}
if(!found) {
allgood = !resolvedeps(db, databases, sync, final, trail); allgood = !resolvedeps(db, databases, sync, final, trail);
/* check again, as resolvedeps could have added our target for us */ /* check again, as resolvedeps could have added our target for us */
found = 0; found = is_pkginsync(sync, final);
for(j = final; j; j = j->next) { }
syncpkg_t *tmp = (syncpkg_t*)j->data; if(!found) {
if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) { final = list_add(final, sync);
found = 1;
}
}
if(!found) {
final = list_add(final, sync);
}
} }
} }
} }
@ -535,33 +519,36 @@ int pacman_sync(pacdb_t *db, PMList *targets)
} }
} }
deps = checkdeps(db, PM_UPGRADE, list); if(!pmo_nodeps && !pmo_s_upgrade) {
if(deps) { deps = checkdeps(db, PM_UPGRADE, list);
fprintf(stderr, "error: unresolvable conflicts/dependencies:\n"); if(deps) {
for(i = deps; i; i = i->next) { fprintf(stderr, "error: unresolvable conflicts/dependencies:\n");
depmissing_t *miss = (depmissing_t*)i->data; for(i = deps; i; i = i->next) {
if(miss->type == CONFLICT) { depmissing_t *miss = (depmissing_t*)i->data;
fprintf(stderr, " %s: conflicts with %s\n", miss->target, miss->depend.name); if(miss->type == CONFLICT) {
} else if(miss->type == DEPEND || miss->type == REQUIRED) { fprintf(stderr, " %s: conflicts with %s\n", miss->target, miss->depend.name);
fprintf(stderr, " %s: requires %s", miss->target, miss->depend.name); } else if(miss->type == DEPEND || miss->type == REQUIRED) {
switch(miss->depend.mod) { fprintf(stderr, " %s: requires %s", miss->target, miss->depend.name);
case DEP_EQ: fprintf(stderr, "=%s", miss->depend.version); break; switch(miss->depend.mod) {
case DEP_GE: fprintf(stderr, ">=%s", miss->depend.version); break; case DEP_EQ: fprintf(stderr, "=%s", miss->depend.version); break;
case DEP_LE: fprintf(stderr, "<=%s", miss->depend.version); break; case DEP_GE: fprintf(stderr, ">=%s", miss->depend.version); break;
} case DEP_LE: fprintf(stderr, "<=%s", miss->depend.version); break;
if(miss->type == DEPEND) { }
fprintf(stderr, " but it is not in the sync db\n"); if(miss->type == DEPEND) {
} else { fprintf(stderr, " but it is not in the sync db\n");
fprintf(stderr, "\n"); } else {
fprintf(stderr, "\n");
}
} }
FREE(miss);
i->data = NULL;
} }
FREE(miss); list_free(deps);
i->data = NULL; /* abort mission */
allgood = 0;
} }
list_free(deps);
/* abort mission */
allgood = 0;
} }
/* cleanup */ /* cleanup */
for(i = list; i; i = i->next) { for(i = list; i; i = i->next) {
i->data = NULL; 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); snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version);
files = list_add(files, strdup(path)); files = list_add(files, strdup(path));
} else { } else {
vprint(" %s-%s.pkg.tar.gz is already in the cache\n", sync->pkg->name, sync->pkg->version);
count++; count++;
} }
} }
@ -719,7 +707,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
for(i = final; i; i = i->next) { for(i = final; i; i = i->next) {
syncpkg_t *sync = (syncpkg_t*)i->data; syncpkg_t *sync = (syncpkg_t*)i->data;
if(sync) freepkg(sync->pkg); if(sync) freepkg(sync->pkg);
free(sync); FREE(sync);
i->data = NULL; i->data = NULL;
} }
for(i = trail; i; i = i->next) { 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; dbsync_t *dbs = (dbsync_t*)i->data;
db_close(dbs->db); db_close(dbs->db);
list_free(dbs->pkgcache); list_free(dbs->pkgcache);
free(dbs); FREE(dbs);
i->data = NULL; i->data = NULL;
} }
list_free(databases); list_free(databases);
@ -751,6 +739,12 @@ int pacman_add(pacdb_t *db, PMList *targets)
PMList *alltargs = NULL; PMList *alltargs = NULL;
PMList *filenames = NULL; PMList *filenames = NULL;
unsigned short real_pmo_upgrade; unsigned short real_pmo_upgrade;
tartype_t gztype = {
(openfunc_t) gzopen_frontend,
(closefunc_t)gzclose,
(readfunc_t) gzread,
(writefunc_t)gzwrite
};
if(targets == NULL) { if(targets == NULL) {
return(0); return(0);
@ -766,13 +760,14 @@ int pacman_add(pacdb_t *db, PMList *targets)
return(1); return(1);
} }
if(pmo_freshen) { 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); pkginfo_t *dummy = db_scan(db, info->name, INFRQ_DESC);
if(dummy == NULL) { if(dummy == NULL || rpmvercmp(dummy->version, info->version) >= 0) {
freepkg(info); freepkg(info);
info = NULL; info = NULL;
continue; continue;
} }
freepkg(dummy);
} }
alltargs = list_add(alltargs, info); alltargs = list_add(alltargs, info);
filenames = list_add(filenames, strdup(targ->data)); filenames = list_add(filenames, strdup(targ->data));
@ -810,7 +805,7 @@ int pacman_add(pacdb_t *db, PMList *targets)
if(!pmo_force) { if(!pmo_force) {
printf("checking for conflicts... "); printf("checking for conflicts... ");
fflush(stdout); fflush(stdout);
lp = db_find_conflicts(db, alltargs); lp = db_find_conflicts(db, alltargs, pmo_root);
if(lp) { if(lp) {
printf("\nerror: the following file conflicts were found:\n"); printf("\nerror: the following file conflicts were found:\n");
for(j = lp; j; j = j->next) { for(j = lp; j; j = j->next) {
@ -884,12 +879,12 @@ int pacman_add(pacdb_t *db, PMList *targets)
char pathname[PATH_MAX]; char pathname[PATH_MAX];
strncpy(pathname, th_get_pathname(tar), 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); tar_skip_regfile(tar);
continue; continue;
} }
if(!strcmp(pathname, "._install")) { if(!strcmp(pathname, "._install") || !strcmp(pathname, ".INSTALL")) {
/* the install script goes inside the db */ /* the install script goes inside the db */
snprintf(expath, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root, snprintf(expath, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root,
PKGDIR, db->treename, info->name, info->version); PKGDIR, db->treename, info->name, info->version);
@ -1279,7 +1274,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
} }
} }
} else { } else {
/*vprint(" unlinking %s\n", line);*/ vprint(" unlinking %s\n", line);
if(unlink(line)) { if(unlink(line)) {
perror("cannot remove file"); perror("cannot remove file");
} }
@ -1389,13 +1384,12 @@ int pacman_query(pacdb_t *db, PMList *targets)
printf("\n"); printf("\n");
} else if(pmo_q_list) { } else if(pmo_q_list) {
for(lp = info->files; lp; lp = lp->next) { for(lp = info->files; lp; lp = lp->next) {
if(strcmp(lp->data, ".PKGINFO")) { printf("%s %s\n", info->name, (char*)lp->data);
printf("%s %s\n", info->name, (char*)lp->data);
}
} }
} else if(!pmo_q_info) { } else {
printf("%s %s\n", info->name, info->version); printf("%s %s\n", info->name, info->version);
} }
freepkg(info);
continue; continue;
} }
@ -1417,6 +1411,7 @@ int pacman_query(pacdb_t *db, PMList *targets)
gotcha = 1; gotcha = 1;
} }
} }
freepkg(info);
} }
if(!gotcha) { if(!gotcha) {
fprintf(stderr, "No package owns %s\n", package); 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) { for(q = info->files; q; q = q->next) {
printf("%s %s%s\n", info->name, pmo_root, (char*)q->data); printf("%s %s%s\n", info->name, pmo_root, (char*)q->data);
} }
freepkg(info);
} else { } else {
printf("%s %s\n", tmpp->name, tmpp->version); printf("%s %s\n", tmpp->name, tmpp->version);
} }
@ -1449,70 +1445,12 @@ int pacman_query(pacdb_t *db, PMList *targets)
} else { } else {
/* find a target */ /* find a target */
if(pmo_q_info) { if(pmo_q_info) {
int cols;
info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS); info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS);
if(info == NULL) { if(info == NULL) {
fprintf(stderr, "Package \"%s\" was not found.\n", package); fprintf(stderr, "Package \"%s\" was not found.\n", package);
return(2); return(2);
} }
dump_pkg(info);
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);
printf("\n"); printf("\n");
} else if(pmo_q_list) { } else if(pmo_q_list) {
info = db_scan(db, package, INFRQ_DESC | INFRQ_FILES); 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); printf("%s %s\n", info->name, info->version);
} }
freepkg(info);
} }
} }
if(info) {
freepkg(info);
}
return(0); return(0);
} }
int pacman_upgrade(pacdb_t *db, PMList *targets) 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 */ /* handle it */
pmo_upgrade = 1; pmo_upgrade = 1;
return(pacman_add(db, targets)); return(pacman_add(db, targets));
@ -1907,6 +1842,405 @@ int splitdep(char *depstr, depend_t *depend)
return(0); 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 lckmk(char *file, int retries, unsigned int sleep_secs)
{ {
int fd, count = 0; int fd, count = 0;
@ -1928,7 +2262,7 @@ int lckrm(char *file)
void cleanup(int signum) 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); fprintf(stderr, "warning: could not remove lock file %s\n", lckfile);
} }
if(workfile) { if(workfile) {

View file

@ -22,7 +22,7 @@
#define _PAC_PACMAN_H #define _PAC_PACMAN_H
#ifndef PACVER #ifndef PACVER
#define PACVER "2.4.1" #define PACVER "2.5"
#endif #endif
#ifndef PKGDIR #ifndef PKGDIR
@ -42,6 +42,8 @@
#define PM_SYNC 6 #define PM_SYNC 6
#define PM_DEPTEST 7 #define PM_DEPTEST 7
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
int pacman_add(pacdb_t *db, PMList *targets); int pacman_add(pacdb_t *db, PMList *targets);
int pacman_remove(pacdb_t *db, PMList *targets); int pacman_remove(pacdb_t *db, PMList *targets);
int pacman_upgrade(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 resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *sync, PMList *list, PMList *trail);
int splitdep(char *depstr, depend_t *depend); 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 lckmk(char *file, int retries, unsigned int sleep_secs);
int lckrm(char *lckfile); int lckrm(char *lckfile);
void cleanup(int signum); void cleanup(int signum);

View file

@ -21,11 +21,8 @@
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <ftplib.h> #include <ftplib.h>
/* pacman */ /* pacman */
@ -42,7 +39,7 @@ static int offset;
/* pacman options */ /* pacman options */
extern char *pmo_root; extern char *pmo_root;
extern unsigned char pmo_nopassiveftp; extern unsigned short pmo_nopassiveftp;
/* sync servers */ /* sync servers */
extern PMList *pmc_syncs; extern PMList *pmc_syncs;
@ -130,6 +127,13 @@ int downloadfiles(PMList *servers, char *localpath, PMList *files)
FtpLastResponse(control)); FtpLastResponse(control));
continue; 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 */ /* get each file in the list */
@ -151,13 +155,6 @@ int downloadfiles(PMList *servers, char *localpath, PMList *files)
sync_fnm[24] = '\0'; sync_fnm[24] = '\0';
if(!server->islocal) { 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)) { if(!FtpSize(fn, &fsz, FTPLIB_IMAGE, control)) {
fprintf(stderr, "warning: failed to get filesize for %s\n", fn); 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); 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: */ /* vim: set ts=2 sw=2 noet: */

View file

@ -21,12 +21,14 @@
#ifndef _PAC_PACSYNC_H #ifndef _PAC_PACSYNC_H
#define _PAC_PACSYNC_H #define _PAC_PACSYNC_H
/* Servers */
typedef struct __server_t { typedef struct __server_t {
unsigned short islocal; unsigned short islocal;
char* server; char* server;
char* path; char* path;
} server_t; } server_t;
/* Repositories */
typedef struct __sync_t { typedef struct __sync_t {
char* treename; char* treename;
PMList *servers; PMList *servers;
@ -46,6 +48,7 @@ typedef struct __syncpkg_t {
int sync_synctree(); int sync_synctree();
int downloadfiles(PMList *servers, char *localpath, PMList *files); int downloadfiles(PMList *servers, char *localpath, PMList *files);
int is_pkginsync(syncpkg_t *needle, PMList *haystack);
#endif #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 <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <libgen.h>
#include <getopt.h>
#include <ctype.h> #include <ctype.h>
#include "list.h" #include <dirent.h>
#include "package.h" #include <zlib.h>
#include "db.h" #include <libtar.h>
#include "util.h" #include "util.h"
#include "pacsync.h"
#include "pacman.h"
/* command line options */ /* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */
extern char* pmo_root; int gzopen_frontend(char *pathname, int oflags, int mode)
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)
{ {
char* gzoflags; char* gzoflags;
int fd; int fd;
@ -102,17 +66,16 @@ static int gzopen_frontend(char *pathname, int oflags, int mode)
return (int)gzf; 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) int unpack(char *archive, char *prefix)
{ {
TAR *tar = NULL; TAR *tar = NULL;
char expath[PATH_MAX]; 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 */ /* open the .tar.gz package */
if(tar_open(&tar, archive, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { if(tar_open(&tar, archive, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
@ -130,280 +93,6 @@ int unpack(char *archive, char *prefix)
return(0); 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) int copyfile(char *src, char *dest)
{ {
FILE *in, *out; FILE *in, *out;
@ -501,94 +190,6 @@ int rmrf(char *path)
return(0); 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, ...) int yesno(char *fmt, ...)
{ {
char response[32]; 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 /* Convert a string to uppercase
*/ */
char* strtoupper(char *str) char* strtoupper(char *str)

View file

@ -21,30 +21,20 @@
#ifndef _PAC_UTIL_H #ifndef _PAC_UTIL_H
#define _PAC_UTIL_H #define _PAC_UTIL_H
#include <libtar.h>
#include <zlib.h>
#define MALLOC(p, b) { if((b) > 0) { \ #define MALLOC(p, b) { if((b) > 0) { \
p = malloc(b); if (!(p)) { \ 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; } exit(1); }} else p = NULL; }
#define FREE(p) { if (p) { free(p); (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 unpack(char *archive, char *prefix);
int parseargs(int op, int argc, char **argv);
int parseconfig(char *configfile);
int copyfile(char *src, char *dest); int copyfile(char *src, char *dest);
int makepath(char *path); int makepath(char *path);
int rmrf(char *path); int rmrf(char *path);
int vprint(char *fmt, ...);
void indentprint(char *str, int indent); void indentprint(char *str, int indent);
int yesno(char* fmt, ...); 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* trim(char *str);
char* strtoupper(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 <stdio.h>
#include <string.h> #include <string.h>
#include "rpmvercmp.h"
int rpmvercmp(const char *a, const char *b);
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {