Imported from pacman-2.0.tar.gz

This commit is contained in:
Judd Vinet 2002-08-09 18:03:48 +00:00
parent 20b7462293
commit 62a783a6bd
50 changed files with 15380 additions and 2069 deletions

View file

@ -1,5 +1,14 @@
VERSION DESCRIPTION
------------------------------------------------------------------
- Improved dependency resolution and sorting
2.0 - Added dependency functionality
- Completely new database format, similar to FreeBSD
- Better internal data structures
- Merged pacsync functionality into pacman
- Now uses libftp for all file retrieval (currently only ftp)
- Automatic dependency resolution, a la apt-get
- Moved config stuff from /etc/pacsync.conf to /etc/pacman.conf
- Much better backup file handling, now uses md5 hashes a la rpm
1.23 - Added install/upgrade/remove scripting control
1.22 - Some manpage typo fixes
- Added --root switch to pacsync

View file

@ -1,82 +0,0 @@
#
# 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.
#
# NOTE: Since pacman is compiled statically, you will need the static
# libraries for zlib and glibc.
DESTDIR =
BINDIR = /usr/bin
MANDIR = /usr/man
ETCDIR = /etc
VERSION = 1.23
LIBTAR_VERSION = 1.2.4
CXX = gcc
CXXFLAGS += -DNDEBUG -O2 -Wall -pedantic -fno-exceptions -fno-rtti \
-D_GNU_SOURCE -DVERSION=\"$(VERSION)\" -Ilibtar-$(LIBTAR_VERSION)/lib
LDFLAGS += -static -Llibtar-$(LIBTAR_VERSION)/lib -ltar -lz
OBJECTS = pacman.o
all: libtar pacman man
pacman: $(OBJECTS)
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
pacman.o: pacman.c pacman.h
$(CXX) $(CXXFLAGS) -c pacman.c
man: pacman.8 pacsync.8 makepkg.8
%: %.in
sed -e "s/#VERSION#/$(VERSION)/" $< > $@
dist: distclean
(cd ..; tar czvf pacman-$(VERSION).tar.gz pacman-$(VERSION))
libtar:
(tar xzf libtar-$(LIBTAR_VERSION).tar.gz; \
cd libtar-$(LIBTAR_VERSION); \
LDFLAGS="" ./configure --disable-encap --disable-encap-install; \
make;)
install: all
install -D -m0755 pacman $(DESTDIR)$(BINDIR)/pacman
install -D -m0644 pacman.8 $(DESTDIR)$(MANDIR)/man8/pacman.8
install -D -m0644 pacsync.8 $(DESTDIR)$(MANDIR)/man8/pacsync.8
install -D -m0644 makepkg.8 $(DESTDIR)$(MANDIR)/man8/makepkg.8
install -D -m0755 makepkg $(DESTDIR)$(BINDIR)/makepkg
install -D -m0755 makeworld $(DESTDIR)$(BINDIR)/makeworld
install -D -m0755 pacsync $(DESTDIR)$(BINDIR)/pacsync
@echo ""
@echo "*** If this is a first-time install, you should copy makepkg.conf"
@echo "*** and pacsync.conf to /etc now."
@echo ""
clean:
rm -f *~ *.o *.8
distclean: clean
rm -f pacman
rm -rf libtar-$(LIBTAR_VERSION)
# End of file

122
Makefile.in Normal file
View file

@ -0,0 +1,122 @@
#
# 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.
#
# NOTE: Since pacman is compiled statically, you will need the static
# libraries for zlib and glibc.
DESTDIR =
prefix = @prefix@
exec_prefix = @prefix@
BINDIR = @bindir@
MANDIR = @mandir@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
PACVER = 2.0
LIBTAR_VERSION = 1.2.5
TOPDIR = @srcdir@
SRCDIR = $(TOPDIR)/src/
OBJDIR = $(TOPDIR)/src/
MANSRC = $(TOPDIR)/doc/
SCRDIR = $(TOPDIR)/scripts/
CXX = @CC@
CXXFLAGS += @CFLAGS@ -Wall -pedantic -fno-exceptions -fno-rtti \
-D_GNU_SOURCE -DPACVER=\"$(PACVER)\" -I. \
-Ilibtar-$(LIBTAR_VERSION)/lib -Ilibftp
LDFLAGS += @LDFLAGS@ -static -Llibtar-$(LIBTAR_VERSION)/lib -Llibftp \
-lftp -ltar -lz
SRCS = $(SRCDIR)pacman.c \
$(SRCDIR)db.c \
$(SRCDIR)util.c \
$(SRCDIR)list.c \
$(SRCDIR)package.c \
$(SRCDIR)pacsync.c \
$(SRCDIR)rpmvercmp.c \
$(SRCDIR)md5.c \
$(SRCDIR)md5driver.c
OBJECTS = $(OBJDIR)pacman.o \
$(OBJDIR)db.o \
$(OBJDIR)util.o \
$(OBJDIR)list.o \
$(OBJDIR)package.o \
$(OBJDIR)pacsync.o \
$(OBJDIR)rpmvercmp.o \
$(OBJDIR)md5.o \
$(OBJDIR)md5driver.o
all: libtar ftplib pacman convertdb man
pacman: $(OBJECTS)
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
convertdb: $(SRCDIR)convertdb.c $(SRCDIR)list.c
$(CXX) -o convertdb $(SRCDIR)convertdb.c $(SRCDIR)list.c $(CXXFLAGS)
.c.o: $(SRCS)
$(CXX) $(CXXFLAGS) -o $@ -c $<
man: $(MANSRC)pacman.8 \
$(MANSRC)makepkg.8
%.8: %.8.in
sed -e "s/#VERSION#/$(PACVER)/" $< > $@
dist: distclean
(cd ..; tar czvf pacman-$(PACVER).tar.gz pacman-$(PACVER))
ftplib:
(cd libftp; make libftp.a)
libtar:
(tar xzf libtar-$(LIBTAR_VERSION).tar.gz; \
cd libtar-$(LIBTAR_VERSION); \
LDFLAGS="" ./configure --disable-encap --disable-encap-install; \
make;)
install: pacman convertdb man
$(INSTALL) -D -m0755 pacman $(DESTDIR)$(BINDIR)/pacman
$(INSTALL) -D -m0755 convertdb $(DESTDIR)$(BINDIR)/convertdb
$(INSTALL) -D -m0755 $(SCRDIR)makepkg $(DESTDIR)$(BINDIR)/makepkg
$(INSTALL) -D -m0755 $(SCRDIR)makeworld $(DESTDIR)$(BINDIR)/makeworld
$(INSTALL) -D -m0755 $(SCRDIR)abs $(DESTDIR)$(BINDIR)/abs
$(INSTALL) -D -m0644 $(MANSRC)pacman.8 $(DESTDIR)$(MANDIR)/man8/pacman.8
$(INSTALL) -D -m0644 $(MANSRC)makepkg.8 $(DESTDIR)$(MANDIR)/man8/makepkg.8
$(INSTALL) -D -m0644 etc/pacman.conf $(DESTDIR)/etc/pacman.conf
$(INSTALL) -D -m0644 etc/makepkg.conf $(DESTDIR)/etc/makepkg.conf
$(INSTALL) -D -m0644 etc/supfile $(DESTDIR)/etc/abs/supfile
clean:
rm -f *~ $(OBJDIR)*.o $(MANSRC)*.8
(cd libftp; make clobber)
distclean: clean
rm -f pacman convertdb
rm -rf libtar-$(LIBTAR_VERSION)
# End of file

21
README
View file

@ -7,24 +7,23 @@ DESCRIPTION:
------------
pacman is a utility which manages software packages in Linux. It uses
simple .tar.gz files as a package format, and maintains a text-based
package database, just in case some hand tweaking is necessary.
package database (more of a hierarchy), just in case some hand tweaking
is necessary.
pacman does not strive to "do everything." It will add, remove and
upgrade packages in the system, and it will allow you to query the
package database for installed packages, files and owners.
package database for installed packages, files and owners. It also
attempts to handle dependencies automatically and can
Although the package manager itself is quite simple, the pacman tarball
also comes with scripts that help automate building and installing
packages. These are used extensively in the Arch Build System (ABS),
used in Arch Linux <http://www.archlinux.org>. See ABS.txt for more
information.
used in Arch Linux <http://www.archlinux.org>.
As of version 1.2, pacsync is included as well. This performs an
apt-like function, keeping your system's packages in sync with the
packages on a remote server.
Plans exist for dependency checking as I approach version 2.0.
See TODO for more info.
As of version 2.0, pacman can also keep your system's packages in
sync with a master server. You can follow CURRENT and STABLE trees,
or lock yourself into a specific version. See the pacman manpage
for more info on this (--sync operation).
INSTALL:
@ -44,7 +43,7 @@ BUGS:
-----
If you find bugs (which is quite likely), please submit them to
<jvinet@zeroflux.org> with specific information, such as your
commandline, the nature of the bug, and even the package database, if
commandline, the nature of the bug, and even the package database if
it helps.

31
TODO
View file

@ -1,11 +1,22 @@
- add a [sibling] option to .PKGINFO -- used when only one of
the siblings can be installed at a time (eg, bsdinit,sysvinit)
- sort packages by package name in pacman.db
? manage conditional file installs (ie, 'info' pages)
- maybe add a 'confirm every action' option for doing paranoid installs
- add a consistency check operation
- add file locking to db
- check $PACCONF env var
- ftp transfer progress bar breaks after ~42000 K
- use a 'trust pacman' config option for downgrading?
- use a provides tag (instead of an OR operator in depends)
- instead of 'conflicts' use a ! operator in depends
- add a --pretend option
- add a consistency/sanity check operation
- add a --dbpath option
+ dependency checking
- upgrade currently does a double db backup; not really desirable
- build-time (source) dependencies in makepkg
- auto-resolve dependencies in makepkg
- use package caches more for performance
+ add an "ignore package" option in either pacman.conf or in each package
record. this will prevent it from being upgraded from the sync set
- duplicate dep checks occur with sync (one in sync, one in add)
- clean up output a bit (message queue?)
- add an OR operator to dependencies or allow a sibling tag (ie, mawk, gawk)
- run ldd on every executable in a newly built package to find required so's
- add a freshen operation
- allow multiple ftp servers to be defined and fallback to backups on failure
- use a files.cache gdbm (or whatever) for --owns and db_find_conflicts
- things like 'groupadd' and 'useradd' in the install scriptlets will affect
the real root, not the one specified with -r

0
acconfig.h Normal file
View file

1321
config.guess vendored Executable file

File diff suppressed because it is too large Load diff

153
config.h.in Normal file
View file

@ -0,0 +1,153 @@
/* config.h.in. Generated from configure.in by autoheader. */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#undef CRAY_STACKSEG_END
/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA
/* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#undef HAVE_DIRENT_H
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `getpass' function. */
#undef HAVE_GETPASS
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if `lstat' has the bug that it succeeds when given the
zero-length file name argument. */
#undef HAVE_LSTAT_EMPTY_STRING_BUG
/* Define to 1 if your system has a working `malloc' function. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mkdir' function. */
#undef HAVE_MKDIR
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
/* Define to 1 if you have the `rmdir' function. */
#undef HAVE_RMDIR
/* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */
#undef HAVE_STAT_EMPTY_STRING_BUG
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the `strverscmp' function. */
#undef HAVE_STRVERSCMP
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_DIR_H
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_NDIR_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t

1443
config.sub vendored Executable file

File diff suppressed because it is too large Load diff

5573
configure vendored Executable file

File diff suppressed because it is too large Load diff

35
configure.in Normal file
View file

@ -0,0 +1,35 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([acconfig.h])
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_CXX
# Checks for libraries.
# AC_CHECK_LIB([tar], [tar_open])
AC_CHECK_LIB([z], [gzread])
# Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h limits.h stdlib.h string.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_MODE_T
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_ALLOCA
AC_FUNC_LSTAT
AC_FUNC_MALLOC
AC_TYPE_SIGNAL
AC_FUNC_STAT
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([getpass memmove mkdir realpath rmdir strdup strerror strstr strverscmp])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View file

@ -1,4 +1,4 @@
.TH makepkg 8 "Mar 17, 2002" "makepkg #VERSION#" ""
.TH makepkg 8 "July 18, 2002" "makepkg #VERSION#" ""
.SH NAME
makepkg \- package build utility
.SH SYNOPSIS
@ -8,9 +8,10 @@ makepkg \- package build utility
a build-capable linux platform, wget, and some build scripts. The advantage
to a script-based build is that you only really do the work once. Once you
have the build script for a package, you just need to run makepkg and it
will do the rest: download source files, configure the buildtime settings,
build the package, install the package into a temporary root, make
customizations, and package the whole thing up for pacman to use.
will do the rest: download source files, check dependencies,
configure the buildtime settings, build the package, install the package
into a temporary root, make customizations, generate meta-info, and package
the whole thing up for \fBpacman\fP to use.
\fBmakeworld\fP can be used to rebuild an entire package group, or the
entire build tree.
@ -19,6 +20,11 @@ Start in an isolated directory (ie, it's not used for anything other
than building this package). The build script should be called PKGBUILD
and it should bear resemblance to the example below.
\fBNOTE:\fP If you have a local copy of the Arch Build System (ABS) tree
on your computer, you can copy the PKGBUILD.proto file to your new package
build directory and edit it from there. To acquire/sync the ABS tree, use
the \fBabs\fP script included with pacman/makepkg.
.TP
.TP
.SH PKGBUILD Example:
@ -27,7 +33,9 @@ and it should bear resemblance to the example below.
pkgname=modutils
pkgver=2.4.13
pkgrel=1
pkgdesc="Utilities for inserting and removing modules from the linux kernel"
backup=(etc/modules.conf)
depends=('glibc>=2.2.5' 'bash' 'zlib')
source=(ftp://ftp.server.com/$pkgname-$pkgver.tar.gz modules.conf)
build() {
@ -43,11 +51,26 @@ build() {
.RE
As you can see, the setup is fairly simple. The first three lines define
the package name and version info. They also define the final package name,
which will be of the form $pkgname-$pkgver-$pkgrel.pkg.tar.gz
the package name and version info. They also define the final package name
which will be of the form \fI$pkgname-$pkgver-$pkgrel.pkg.tar.gz\fP. The fourth
line provides a brief description of the package. These four lines should
be present in every PKGBUILD script.
The sources are then decompressed (if necessary) into a directory called ./src.
Then the \fIbuild\fP function is called. This is where all package configuration,
The line with \fIbackup=\fP specifies files that should be treated specially
when removing or upgrading packages. See \fBHANDLING CONFIG FILES\fP in
the \fIpacman\fP manpage for more information on this.
The sixth line lists the dependencies for this package. In order to build/run
the package, all dependencies must be satisifed first. makepkg will check this
before attempting to build the package.
Once your PKGBUILD is created, you can run \fImakepkg\fP from the build directory.
makepkg will then check dependencies and look for the source files required to
build. If some are missing it will attempt to download them, provided there is
a fully-qualified URL in the \fIsource\fP array.
The sources are then extracted into a directory called ./src and
the \fIbuild\fP function is called. This is where all package configuration,
building, and installing should be done. Any customization will likely take
place here.
@ -65,13 +88,14 @@ make prefix=$startdir/pkg/usr install
.fi
.RE
Notice that the "/usr" portion should be present with "prefix", but not "DESTDIR."
Notice that the "/usr" portion should be present with "prefix", but not "DESTDIR".
Once the package is successfully installed into the package root, \fImakepkg\fP
will remove some directories (as per Arch Linux package guidelines; if you use
this elsewhere, feel free to change it) like /usr/doc and /usr/info. It will
then strip debugging info from libraries and binaries and compress everything
into a .pkg.tar.gz file in the directory you ran \fBmakepkg\fP from.
then strip debugging info from libraries and binaries and generate a meta-info
file. Finally, it will compress everything into a .pkg.tar.gz file and leave it
in the directory you ran \fBmakepkg\fP from.
At this point you should have a package file in the current directory, named
something like name-version-release.pkg.tar.gz. Done!
@ -95,11 +119,15 @@ script is run after all files have been upgraded.
script is run right before files are removed.
.RE
In order to use this feature, your build function should put the script in
$startdir/pkg/var/lib/pacman/scripts and it must be named exactly the same
as the \fI$pkgname\fP variable in the PKGBUILD script. For example, an
install script for grep will be $startdir/pkg/var/lib/pacman/scripts/grep.
Note that the scripts should be 644, not 755 (we don't need execute permission).
To use this feature, just create a file (eg, pkgname.install) and put it in
the same directory as the PKGBUILD script. Then use the \fIinstall\fP directive:
.RS
.nf
install=pkgname.install
.fi
.RE
The install script does not need to be specified in the \fIsource\fP array.
.TP
.TP
@ -111,6 +139,7 @@ post_install() {
#
# do post-install stuff here
#
/bin/true
}
# arg 1: the new package version
@ -119,6 +148,7 @@ post_upgrade() {
#
# do post-upgrade stuff here
#
/bin/true
}
# arg 1: the old package version
@ -126,6 +156,7 @@ pre_remove() {
#
# do pre-remove stuff here
#
/bin/true
}
op=$1
@ -151,12 +182,39 @@ This is the version of the software as released from the author (eg, 2.7.1).
.B pkgrel
This is the release number specific to Arch Linux packages.
.TP
.B pkgdesc
This should be a brief description of the package and its functionality.
.TP
.B backup
A space-delimited array of filenames (without a preceding slash). The
\fIbackup\fP line will be propagated to the package meta-info file for
pacman. This will designate all files listed there to be backed up if this
package is ever removed from a system.
package is ever removed from a system. See \fBHANDLING CONFIG FILES\fP in
the \fIpacman\fP manpage for more information.
.TP
.B install
Specified a special install script that is to be included in the package.
This file should reside in the same directory as the PKGBUILD, and will be
copied into the package by makepkg. It does not need to be included in the
\fIsource\fP array. (eg, install=modutils.install)
.TP
.B depends
An array of packages that this package depends on to build and run. Packages
in this list should be surrounded with single quotes and contain at least the
package name. They can also include a version requirement of the form
\fBname<>version\fP, where <> is one of these three comparisons: \fB>=\fP
(greater than equal to), \fB<=\fP (less than or equal to), or \fB=\fP (equal to).
See the PKGBUILD example above for an example of the \fIdepends\fP directive.
.TP
.B conflicts
An array of packages that will conflict with this package (ie, they cannot both
be installed at the same time). This directive follows the same format as
\fIdepends\fP except you cannot specify versions here, only package names.
.TP
.B source
@ -166,14 +224,27 @@ file, unless they have a fully-qualified URL. Then if the source file
does not already exist in /var/cache/pacman/src, the file is downloaded
by wget.
.SH MAKEPKG OPTIONS
.TP
.B "\-c, \-\-clean"
Clean up leftover work files/directories after a successful build.
.TP
.B "\-i, \-\-install"
Install/Upgrade the package after a successful build.
.SH CONFIGURATION
Configuration options are stored in /etc/makepkg.conf. This file is parsed
Configuration options are stored in \fI/etc/makepkg.conf\fP. This file is parsed
as a bash script, so you can export any special compiler flags you wish
to use. This is helpful for building for different architectures, or with
different optimizations.
\fBNOTE:\fP This does not guarantee that all package Makefiles will use
your exported variables. Some of them are flaky...
.SH SEE ALSO
\fBpacman\fP is the package manager that uses packages built by makepkg.
See the Arch Linux Documentation for package-building guidelines if you wish
to contribute packages to the Arch Linux project.
.SH AUTHOR
.nf
Judd Vinet <jvinet@zeroflux.org>

172
doc/pacman.8.in Normal file
View file

@ -0,0 +1,172 @@
.TH pacman 8 "July 18, 2002" "pacman #VERSION#" ""
.SH NAME
pacman \- package manager utility
.SH SYNOPSIS
\fBpacman <operation> [options] <package> [package] ...\fP
.SH DESCRIPTION
\fBpacman\fP is a \fIpackage management\fP utility that tracks installed
packages on a linux system. It has simple dependency support and the ability
to connect to a remote ftp server and automatically upgrade packages on
the local system. pacman package are \fIgzipped tar\fP format.
.SH OPERATIONS
.TP
.B "\-A, \-\-add"
Add a package to the system. Package will be uncompressed
into the installation root and the database will be updated.
.TP
.B "\-R, \-\-remove"
Remove a package from the system. Files belonging to the
specified package will be deleted, and the database will
be updated. Most configuration files will be saved with a
\fI.pacsave\fP extension unless the \fB--nosave\fP option was
used.
.TP
.B "\-U, \-\-upgrade"
Upgrade a package. This is essentially a "remove-then-add"
process. See \fBHANDLING CONFIG FILES\fP for an explanation
on how pacman takes care of config files.
.TP
.B "\-Q, \-\-query"
Query the package database. This operation allows you to
view installed packages and their files, as well as meta-info
about individual packages (dependencies, conflicts, install date,
build date, size). This can be run against the local package
database or can be used on individual .tar.gz packages. See
\fBQUERY OPTIONS\fP below.
.TP
.B "\-S, \-\-sync"
Synchronize packages. With this function you can install packages
directly from the ftp servers, complete with all dependencies required
to run the packages. For example, \fBpacman -S qt\fP will download
qt and all the packages it depends on and install them. You could also use
\fBpacman -Su\fP to upgrade all packages that are out of date (see below).
.TP
.B "\-V, \-\-version"
Display version and exit.
.TP
.B "\-h, \-\-help"
Display syntax for the given operation. If no operation was
supplied then the general syntax is shown.
.SH OPTIONS
.TP
.B "\-v, \-\-verbose"
Output more status and error messages.
.TP
.B "\-f, \-\-force"
Bypass file conflict checks,, overwriting conflicting files. If the
package that is about to be installed contains files that are already
installed, this option will cause all those files to be overwritten.
This option should be used with care, ideally not at all.
.TP
.B "\-d, \-\-nodeps"
Skips all dependency checks. Normally, pacman will always check
a package's dependency fields to ensure that all dependencies are
installed and there are no package conflicts in the system. This
switch disables these checks.
.TP
.B "\-n, \-\-nosave"
(only used with \fB--remove\fP)
Instructs pacman to ignore file backup designations. Normally, when
a file is about to be \fIremoved\fP from the system the database is first
checked to see if the file should be renamed to a .pacsave extension. If
\fB--nosave\fP is used, these designations are ignored and the files are
removed.
.TP
.B "\-r, \-\-root <path>"
Specify alternative installation root (default is "/"). This
should \fInot\fP be used as a way to install software into
e.g. /usr/local instead of /usr. Instead this should be used
if you want to install a package on a temporary mounted partition,
which is "owned" by another system. By using this option you not only
specify where the software should be installed, but you also
specify which package database to use.
.SH SYNC OPTIONS
.TP
.B "\-y, \-\-refresh"
Download a fresh copy of the master package list from the ftp server
defined in \fI/etc/pacman.conf\fP. This should typically be used each
time you use \fB--sysupgrade\fP.
.TP
.B "\-u, \-\-sysupgrade"
Upgrades all packages that are out of date. pacman will examine every
package installed on the system, and if a newer package exists on the
server it will upgrade. pacman will present a report of all packages
it wants to upgrade and will not proceed without user confirmation.
Dependencies are automatically resolved at this level and will be
installed/upgraded if necessary.
.TP
.B "\-s, \-\-search <string>"
This will search each package in the package list for names or descriptions
that contains <string>.
.TP
.B "\-c, \-\-clean"
Remove packages from the cache. When pacman downloads packages,
it saves them in \fI/var/cache/pacman/pkg\fP. If you need to free up
diskspace, you can remove these packages by using the --clean option.
.SH QUERY OPTIONS
.TP
.B "\-o, \-\-owns <file>"
Search for the package that owns <file>.
.TP
.B "\-l, \-\-list"
List all files owned by <package>. Multiple packages can be specified on
the command line.
.TP
.B "\-i, \-\-info"
Display information on a given package. If it is used with the \fB-p\fP
option then the .PKGINFO file will be printed.
.TP
.B "\-p, \-\-file"
Tells pacman that the package supplied on the command line is a
file, not an entry in the database. Pacman will decompress the
file and query it. This is useful with \fB--info\fP and \fB--list\fP.
.SH HANDLING CONFIG FILES
pacman uses the same logic as rpm to determine action against files
that are designated to be backed up. During an upgrade, it uses 3
md5 hashes for each backup file to determine the required action:
one for the original file installed, one for the new file that's about
to be installed, and one for the actual file existing on the filesystem.
After comparing these 3 hashes, the follow scenarios can result:
.TP
original=\fBX\fP, current=\fBX\fP, new=\fBX\fP
All three files are the same, so we win either way. Install the new file.
.TP
original=\fBX\fP, current=\fBX\fP, new=\fBY\fP
The current file is un-altered from the original but the new one is
different. Since the user did not ever modify the file, and the new
one may contain improvements/bugfixes, we install the new file.
.TP
original=\fBX\fP, current=\fBY\fP, new=\fBX\fP
Both package versions contain the exact same file, but the one
on the filesystem has been modified since. In this case, we leave
the current file in place.
.TP
original=\fBX\fP, current=\fBY\fP, new=\fBY\fP
The new one is identical to the current one. Win win. Install the new file.
.TP
original=\fBX\fP, current=\fBY\fP, new=\fBZ\fP
All three files are different. So we install the new file, but back up the
old one to a .pacsave extension. This way the user can move the old configuration
file back into place if he wishes.
.SH CONFIGURATION
pacman will attempt to read \fI/etc/pacman.conf\fP each time it is invoked. Currently
the only options in it are for the --sync operation, but more may be added later.
.TP
.B "Sync_Tree_Name"
Sets the name of the package set you wish to follow. The common choices are \fIcurrent\fP
and \fIstable\fP. You could also specify a specific package version, eg, 0.3.
.TP
.B "Sync_Server"
This is the hostname of the ftp server that will be used for downloading lists and
packages. eg, \fIftp.ibiblio.org\fP.
.TP
.B "Sync_Tree_Path"
This is the full path name (on the ftp server) to the package tree you are following.
So if you are following \fIcurrent\fP, on \fIftp.ibiblio.org\fP, you would use
\fI/pub/linux/distributions/archlinux/current\fP.
.SH SEE ALSO
\fBmakepkg\fP is the package-building tool that comes with pacman.
.SH AUTHOR
.nf
Judd Vinet <jvinet@zeroflux.org>
.fi

View file

@ -1,8 +1,9 @@
#
# /etc/pkgmake.conf
# /etc/makepkg.conf
#
export CFLAGS="-O2 -march=i686 -pipe"
export CXXFLAGS="-O2 -march=i686 -pipe"
# End of file
#export MAKEFLAGS="-j 2"

35
etc/pacman.conf Normal file
View file

@ -0,0 +1,35 @@
#
# /etc/pacman.conf
#
# name of the tree you want to follow (eg: stable, current, 0.2, 0.3, ...)
Sync_Tree_Name = current
# ftp server
Sync_Server = ftp.ibiblio.org
# full path to sync tree
Sync_Tree_Path = /pub/linux/distributions/archlinux/current
###
### MIRRORS
#########################
# Sync_Server = ftp.mpi-sb.mpg.de
# Sync_Tree_Path = /pub/linux/mirror/ftp.ibiblio.org/pub/Linux/distributions/archlinux/current
# Sync_Server = ftp2.archlinux.org
# Sync_Tree_Path = /current
# Sync_Server = ftp.oit.unc.edu
# Sync_Tree_Path = /pub/Linux/distributions/archlinux/current
# Sync_Server = ftp.tu-chemnitz.de
# Sync_Tree_Path = /pub/linux/sunsite.unc-mirror/distributions/archlinux/current
# Sync_Server = ftp.archlinux.org
# Sync_Tree_Path = /current
# Sync_Server = ftp.oit.unc.edu
# Sync_Tree_Path = /pub/Linux/distributions/archlinux/current

23
etc/supfile Normal file
View file

@ -0,0 +1,23 @@
#
# /etc/abs/supfile
#
# this is the host containing the master ABS files
*default host=archlinux.org
*default base=/usr/abs
*default prefix=/usr/abs
*default release=cvs
*default delete
*default use-rel-suffix
*default compress
#
# Set tag equal to the package tree you wish to follow. CURRENT and
# STABLE are the most commonly used, but you can specify specific
# versions or tag names. Examples are RELEASE_0_2, VEGA, RELEASE_0_3,
# FIREFLY, etc.
#
*default tag=CURRENT
abs

251
install-sh Executable file
View file

@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
:
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
:
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
:
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

68
libftp/Makefile Normal file
View file

@ -0,0 +1,68 @@
#
# This makefile contains modifications submitted by Richard Braakman
# (dark@xs4all.nl) for the shared library generation.
#
# By default, ftplib uses PASV. If you need it to use PORT
# instead, uncomment the next line
DEFINES = -DFTPLIB_DEFMODE=FTPLIB_PORT
SONAME = 3
SOVERSION = $(SONAME).1
TARGETS = qftp libftp.a libftp.so
OBJECTS = qftp.o ftplib.o
SOURCES = qftp.c ftplib.c
CFLAGS = -Wall $(DEBUG) -I. $(INCLUDES) $(DEFINES)
LDFLAGS = -L.
DEPFLAGS =
all : $(TARGETS)
clean :
rm -f $(OBJECTS) core *.bak
rm -rf unshared
clobber : clean
rm -f $(TARGETS) .depend
rm -f libftp.so.*
install : all
install qftp /usr/local/bin
install -m 644 libftp.so.$(SOVERSION) /usr/local/lib
install -m 644 ftplib.h /usr/local/include
(cd /usr/local/lib && \
ln -sf libftp.so.$(SOVERSION) libftp.so.$(SONAME) && \
ln -sf libftp.so.$(SONAME) libftp.so)
-(cd /usr/local/bin && \
for f in ftpdir ftpget ftplist ftprm ftpsend; \
do ln -s qftp $$f; done)
depend :
$(CC) $(CFLAGS) -M $(SOURCES) > .depend
# build without -fPIC
unshared/ftplib.o: ftplib.c ftplib.h
-mkdir unshared
$(CC) -c $(CFLAGS) -D_REENTRANT $< -o $@
ftplib.o: ftplib.c ftplib.h
$(CC) -c $(CFLAGS) -fPIC -D_REENTRANT $< -o $@
libftp.a: unshared/ftplib.o
ar -rcs $@ $<
libftp.so.$(SOVERSION): ftplib.o
$(CC) -shared -Wl,-soname,libftp.so.$(SONAME) -lc -o $@ $<
libftp.so: libftp.so.$(SOVERSION)
ln -sf $< libftp.so.$(SONAME)
ln -sf $< $@
qftp : qftp.o libftp.so ftplib.h
$(CC) $(LDFLAGS) -o $@ $< -lftp
ifeq (.depend,$(wildcard .depend))
include .depend
endif

1295
libftp/ftplib.c Normal file

File diff suppressed because it is too large Load diff

125
libftp/ftplib.h Normal file
View file

@ -0,0 +1,125 @@
/***************************************************************************/
/* */
/* ftplib.h - header file for callable ftp access routines */
/* Copyright (C) 1996, 1997 Thomas Pfau, pfau@cnj.digex.net */
/* 73 Catherine Street, South Bound Brook, NJ, 08880 */
/* */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Library General Public */
/* License as published by the Free Software Foundation; either */
/* version 2 of the License, or (at your option) any later version. */
/* */
/* This library 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 */
/* Library General Public License for more details. */
/* */
/* You should have received a copy of the GNU Library General Public */
/* License along with this progam; if not, write to the */
/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
/* Boston, MA 02111-1307, USA. */
/* */
/***************************************************************************/
#if !defined(__FTPLIB_H)
#define __FTPLIB_H
#if defined(__unix__) || defined(VMS)
#define GLOBALDEF
#define GLOBALREF extern
#elif defined(_WIN32)
#if defined BUILDING_LIBRARY
#define GLOBALDEF __declspec(dllexport)
#define GLOBALREF __declspec(dllexport)
#else
#define GLOBALREF __declspec(dllimport)
#endif
#endif
/* FtpAccess() type codes */
#define FTPLIB_DIR 1
#define FTPLIB_DIR_VERBOSE 2
#define FTPLIB_FILE_READ 3
#define FTPLIB_FILE_WRITE 4
/* FtpAccess() mode codes */
#define FTPLIB_ASCII 'A'
#define FTPLIB_IMAGE 'I'
#define FTPLIB_TEXT FTPLIB_ASCII
#define FTPLIB_BINARY FTPLIB_IMAGE
/* connection modes */
#define FTPLIB_PASSIVE 1
#define FTPLIB_PORT 2
/* connection option names */
#define FTPLIB_CONNMODE 1
#define FTPLIB_CALLBACK 2
#define FTPLIB_IDLETIME 3
#define FTPLIB_CALLBACKARG 4
#define FTPLIB_CALLBACKBYTES 5
#ifdef __cplusplus
extern "C" {
#endif
typedef struct NetBuf netbuf;
typedef int (*FtpCallback)(netbuf *nControl, int xfered, void *arg);
/* v1 compatibility stuff */
#if !defined(_FTPLIB_NO_COMPAT)
netbuf *DefaultNetbuf;
#define ftplib_lastresp FtpLastResponse(DefaultNetbuf)
#define ftpInit FtpInit
#define ftpOpen(x) FtpConnect(x, &DefaultNetbuf)
#define ftpLogin(x,y) FtpLogin(x, y, DefaultNetbuf)
#define ftpSite(x) FtpSite(x, DefaultNetbuf)
#define ftpMkdir(x) FtpMkdir(x, DefaultNetbuf)
#define ftpChdir(x) FtpChdir(x, DefaultNetbuf)
#define ftpRmdir(x) FtpRmdir(x, DefaultNetbuf)
#define ftpNlst(x, y) FtpNlst(x, y, DefaultNetbuf)
#define ftpDir(x, y) FtpDir(x, y, DefaultNetbuf)
#define ftpGet(x, y, z) FtpGet(x, y, z, DefaultNetbuf)
#define ftpPut(x, y, z) FtpPut(x, y, z, DefaultNetbuf)
#define ftpRename(x, y) FtpRename(x, y, DefaultNetbuf)
#define ftpDelete(x) FtpDelete(x, DefaultNetbuf)
#define ftpQuit() FtpQuit(DefaultNetbuf)
#endif /* (_FTPLIB_NO_COMPAT) */
/* end v1 compatibility stuff */
GLOBALREF int ftplib_debug;
GLOBALREF void FtpInit(void);
GLOBALREF char *FtpLastResponse(netbuf *nControl);
GLOBALREF int FtpConnect(const char *host, netbuf **nControl);
GLOBALREF int FtpOptions(int opt, long val, netbuf *nControl);
GLOBALREF int FtpLogin(const char *user, const char *pass, netbuf *nControl);
GLOBALREF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl,
netbuf **nData);
GLOBALREF int FtpRead(void *buf, int max, netbuf *nData);
GLOBALREF int FtpWrite(void *buf, int len, netbuf *nData);
GLOBALREF int FtpClose(netbuf *nData);
GLOBALREF int FtpSite(const char *cmd, netbuf *nControl);
GLOBALREF int FtpSysType(char *buf, int max, netbuf *nControl);
GLOBALREF int FtpMkdir(const char *path, netbuf *nControl);
GLOBALREF int FtpChdir(const char *path, netbuf *nControl);
GLOBALREF int FtpCDUp(netbuf *nControl);
GLOBALREF int FtpRmdir(const char *path, netbuf *nControl);
GLOBALREF int FtpPwd(char *path, int max, netbuf *nControl);
GLOBALREF int FtpNlst(const char *output, const char *path, netbuf *nControl);
GLOBALREF int FtpDir(const char *output, const char *path, netbuf *nControl);
GLOBALREF int FtpSize(const char *path, int *size, char mode, netbuf *nControl);
GLOBALREF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl);
GLOBALREF int FtpGet(const char *output, const char *path, char mode,
netbuf *nControl);
GLOBALREF int FtpPut(const char *input, const char *path, char mode,
netbuf *nControl);
GLOBALREF int FtpRename(const char *src, const char *dst, netbuf *nControl);
GLOBALREF int FtpDelete(const char *fnm, netbuf *nControl);
GLOBALREF void FtpQuit(netbuf *nControl);
#ifdef __cplusplus
};
#endif
#endif /* __FTPLIB_H */

Binary file not shown.

BIN
libtar-1.2.5.tar.gz Normal file

Binary file not shown.

140
makepkg
View file

@ -1,140 +0,0 @@
#!/bin/bash
myver='1.23'
startdir=`pwd`
[ -f /etc/makepkg.conf ] && . /etc/makepkg.conf
strip_url() {
echo $1 | sed 's|^.*://.*/||g'
}
if [ "$1" = "--help" -o "$1" = "-h" ]; then
shift
echo "makepkg version $myver"
echo "usage: $0 [build_script]"
echo
echo " if build_script is not specified, makepkg will look for a PKGBUILD"
echo " file in the current directory."
echo
exit 1
fi
BUILDSCRIPT="`pwd`/PKGBUILD"
if [ "$1" != "" ]; then
BUILDSCRIPT=$1
fi
if [ ! -f $BUILDSCRIPT ]; then
echo "==> ERROR: $BUILDSCRIPT does not exist!" >&2
exit 1
fi
. $BUILDSCRIPT
# check for no-no's
if [ `echo $pkgver | grep '-'` ]; then
echo "==> ERROR: pkgver is not allowed to contain hyphens." >&2
exit 1
fi
echo
d=`date`
echo "==> Building package $pkgname ($d)" >&2
# extract source
echo "==> Acquiring/Extracting Sources..." >&2
mkdir -p src pkg
cd $startdir/src
for netfile in ${source[@]}; do
file=`strip_url $netfile`
if [ -f ../$file ]; then
echo "==> Found $file in build dir" >&2
cp ../$file .
elif [ -f /var/cache/pacman/src/$file ]; then
echo "==> Using local copy of $file" >&2
cp /var/cache/pacman/src/$file .
else
proto=`echo $netfile | sed 's|://.*||'`
if [ "$proto" != "ftp" -a "$proto" != "http" ]; then
echo "==> ERROR: $netfile was not found in the build directory and is not a proper URL."
echo "==> Aborting..." >&2
exit 1
fi
# check for a download utility
if [ -x /usr/bin/snarf ]; then
ftpagent="/usr/bin/snarf"
elif [ -x /usr/bin/lftpget -a "$proto" = "ftp" ]; then
ftpagent="/usr/bin/lftpget"
elif [ -x /usr/bin/wget ]; then
ftpagent="/usr/bin/wget --passive-ftp --tries=3 --waitretry=3"
else
echo "==> ERROR: You need an ftp client installed (snarf/lftp/wget) in /usr/bin" >&2
exit 1
fi
echo "==> Downloading $file" >&2
$ftpagent $netfile 2>&1
if [ ! -f $file ]; then
echo "==> ERROR: Failed to download $file" >&2
echo "==> Aborting..." >&2
exit 1
fi
mkdir -p /var/cache/pacman/src && cp $file /var/cache/pacman/src
fi
case $file in
*.tar.gz|*.tar.Z|*.tgz)
cmd="tar --use-compress-program=gzip -xf $file" ;;
*.tar.bz2)
cmd="tar --use-compress-program=bzip2 -xf $file" ;;
*.zip)
cmd="unzip -qq $file" ;;
*)
cmd="cp ../$file ." ;;
esac
echo "==> $cmd" >&2
$cmd
done
# build
echo "==> Building Package..." >&2
build 2>&1
if [ $? -gt 0 ]; then
echo "==> Build Failed. Aborting..." >&2
exit 2
fi
# write the .PKGINFO file
echo "==> Generating .PKGINFO file..." >&2
cd $startdir/pkg
echo "# Generated by makepkg $myver" >.PKGINFO
echo -n "# " >>.PKGINFO
date >>.PKGINFO
echo "pkgname = $pkgname" >>.PKGINFO
echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO
for bakfile in "${backup[@]}"; do
echo "backup = $bakfile" >>.PKGINFO
done
# remove info/doc files
cd $startdir
rm -rf pkg/usr/info pkg/usr/share/info
rm -rf pkg/usr/doc pkg/usr/share/doc
# strip binaries
cd $startdir
echo "==> Stripping debugging symbols from libraries..." >&2
find pkg/{,usr,usr/local}/lib -type f \
-exec /usr/bin/strip --strip-debug '{}' ';' 2>&1
echo "==> Stripping symbols from binaries..." >&2
find pkg/{,usr,usr/local}/{bin,sbin} -type f \
-exec /usr/bin/strip '{}' ';' 2>&1
# tar it up
echo "==> Compressing package..." >&2
cd $startdir/pkg
tar czvf $startdir/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO * >../filelist
cd $startdir
d=`date`
echo "==> Finished ($d)" >&2
exit 0

View file

@ -1,87 +0,0 @@
.TH pacman 8 "Mar 17, 2002" "pacman #VERSION#" ""
.SH NAME
pacman \- package manager utility
.SH SYNOPSIS
\fBpacman <operation> [options] <package> [package] ...\fP
.SH DESCRIPTION
\fBpacman\fP is a \fIpackage management\fP utility. Package
information is maintained in a basic text format for easy
tweaking, if necessary, and packages are in a standard
\fIgzipped tar\fP format.
.SH OPERATIONS
.TP
.B "\-A, \-\-add"
Add a package to the system. Package will be uncompressed
into the installation root and the database will be updated.
.TP
.B "\-R, \-\-remove"
Remove a package from the system. Files belonging to the
specified package will be deleted, and the database will
be updated. Note that most configuration files will be
be renamed with \fI.pacsave\fP extensions.
.TP
.B "\-U, \-\-upgrade"
Upgrade a package. This is essentially a "remove-then-install"
process. Most configuration files will be not be overwritten.
.TP
.B "\-Q, \-\-query"
Query the package database. This operation allows you to
view installed packages and their files. See \fBQUERY OPTIONS\fP
below.
.TP
.B "\-V, \-\-version"
Display version and exit.
.TP
.B "\-h, \-\-help"
Display syntax for the given operation. If no operation was
supplied, then the general syntax is shown.
.SH QUERY OPTIONS
.TP
.B "\-o, \-\-owns <file>"
Output the name of the package that owns <file>.
.TP
.B "\-l, \-\-list"
Instead of outputting the package name, output the list of
files owned by the package.
.TP
.B "\-i, \-\-info"
Output the .PKGINFO file contained in <package>. This option
can only be used with the \fB-p\fP option.
.TP
.B "\-p, \-\-file"
Tells pacman that the package supplied on the command line is a
file, not an entry in the database. Pacman will decompress the
file and query it. This is useful with \fB--info\fP and \fB--list\fP.
.SH OPTIONS
.TP
.B "\-v, \-\-verbose"
Output more status and error messages.
.TP
.B "\-f, \-\-force"
Force installation, 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, preferably not at all.
.TP
.B "\-n, \-\-nosave"
Instructs pacman to ignore file backup designations. Normally, when
a file is about to be \fIremoved\fP from the system the database is first
checked to see if the file should be renamed to a .pacsave extension
(indicated by a '\fB*\fP' prefix in the pacman database). The \fB--nosave\fP
will turn off these file backups. Normally, when a file is about to be \fIadded\fP
or \fIupgraded\fP and a starred file already exists, pacman will write
the new file to a .pacnew extension and keep the old one in place. In this
case, \fB--nosave\fP instructs pacman to overwrite the existing file.
.TP
.B "\-r, \-\-root <path>"
Specify alternative installation root (default is "/"). This
should \fInot\fP be used as a way to install software into
e.g. /usr/local instead of /usr. Instead this should be used
if you want to install a package on a temporary mounted partition,
which is "owned" by another system. By using this option you not only
specify where the software should be installed, but you also
specify which package database to use.
.SH AUTHOR
.nf
Judd Vinet <jvinet@zeroflux.org>
.fi

1202
pacman.c

File diff suppressed because it is too large Load diff

View file

@ -1,69 +0,0 @@
/*
* 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 PACMAN_H
#define PACMAN_H
#define VERSION "1.23"
#define PKGEXT ".tar.gz"
#define PKGDIR "/var/lib/pacman"
#define PKGDB "pacman.db"
/* Operations */
#define PM_MAIN 0
#define PM_ADD 1
#define PM_REMOVE 2
#define PM_QUERY 3
#define PM_UPGRADE 4
typedef int (*pm_opfunc_t)(char*);
typedef char** fileset_t;
typedef struct __pkginfo_t {
char version[64];
char name[256];
} pkginfo_t;
int pacman_add(char* pkgfile);
int pacman_remove(char* pkgfile);
int pacman_query(char* pkgfile);
int pacman_upgrade(char* pkgfile);
int db_open(char* path);
int db_update(fileset_t files, unsigned int filecount);
int db_find_conflicts(fileset_t files, unsigned int filecount);
int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output);
int parseargs(int op, int argc, char** argv);
int parse_descfile(char* descfile, unsigned short output, fileset_t* bakptr,
unsigned int* bakct);
int vprint(char* fmt, ...);
void usage(int op, char* myname);
void version(void);
int is_in(char* needle, fileset_t haystack, unsigned int hayct);
int needbackup(char* file, fileset_t files, unsigned int filect);
char* trim(char* str);
char* strtoupper(char* str);
static int gzopen_frontend(char *pathname, int oflags, int mode);
#endif /* PACMAN_H */
/* vim: set ts=2 noet: */

332
pacsync
View file

@ -1,332 +0,0 @@
#!/bin/bash
version="1.23"
tanpath="/var/lib/pacman"
tandb="pacsync.db"
errors=0
upgrade=0
INSTALL_ROOT="/"
IGNORE_PKG=
message() {
echo "==> $1" >&2
}
usage() {
echo "pacsync version $version"
echo "usage: $0 [--root <root>] [--ignore <pkg>] <operation> [package]"
echo ""
echo "operations:"
echo " sync Download a fresh package list from the server"
echo " install <pkg> Download and install <pkg>"
echo " upgrade <pkg> Download and upgrade <pkg>"
echo " report Generate a report of all packages that could be upgraded"
echo " sysupgrade Same as \"report\", but actually do the upgrades"
echo " clean Removes all files from package cache to clear up diskspace"
echo ""
echo "options:"
echo " --root <root> Set installation root to <root>"
echo " --ignore <pkg> Ignore packages that have <pkg> in their names when doing"
echo " sysupgrades. (--ignore can be used multiple times)"
echo ""
}
checkdb() {
if [ ! -f $INSTALL_ROOT/$tanpath/$tandb ]; then
message "missing package list. (use \"sync\" first)"
exit 1
fi
}
download() {
targ=$1
shift
cl=
for file in $*; do
# snarf returns a nonzero error code when the file already exists, which
# confuses pacsync, so for now, no resume action...
rm -f $file
cl="$cl $SYNC_SERVER/$file"
done
message "Downloading $targ"
$ftpagent $cl 2>&1
if [ $? -gt 0 ]; then
message "error: could not download $targ"
return 1
fi
return 0
}
dosync() {
download "package list" pacsync/$tandb
if [ $? -gt 0 ]; then
exit 1
fi
rm -f $INSTALL_ROOT/$tanpath/$tandb
mv $tandb $INSTALL_ROOT/$tanpath/$tandb
message "Done."
}
doinstall() {
pkg2dl=
pkg2inst=
for pkgname in $*; do
line=`egrep "^[a-z]+/$pkgname-[a-zA-Z0-9\.]+-[0-9]+\.pkg\.tar\.gz$" $INSTALL_ROOT/$tanpath/$tandb`
if [ $? -gt 0 ]; then
message "package $pkgname not found"
exit 1
fi
pacman=`pacman -Q -r $INSTALL_ROOT $pkgname 2>/dev/null`
if [ $? -eq 0 ]; then
message "$pkgname is already installed (try using \"upgrade\")"
exit 1
fi
filename=`echo $line | sed 's|^[a-z]*/||g'`
pkg2inst="$pkg2inst $filename"
if [ ! -f $INSTALL_ROOT/var/cache/pacman/pkg/$filename ]; then
pkg2dl="$pkg2dl $filename"
fi
done
# download packages that aren't already cached
if [ "$pkg2dl" != "" ]; then
download "packages" $pkg2dl
if [ $? -gt 0 ]; then
exit 1
fi
if [ `pwd` != "$INSTALL_ROOT/var/cache/pacman/pkg" ]; then
# move downloaded files into cache
mkdir -p $INSTALL_ROOT/var/cache/pacman/pkg
mv $pkg2dl $INSTALL_ROOT/var/cache/pacman/pkg/
fi
fi
# install packages
message "Installing packages"
cd $INSTALL_ROOT/var/cache/pacman/pkg
pacman -A -r $INSTALL_ROOT $pkg2inst
if [ $? -gt 0 ]; then
message "error: some packages failed to install"
exit 1
fi
message "Done"
exit 0
}
doupgrade() {
pkg2dl=
pkg2up=
for pkgname in $*; do
line=`egrep "^[a-z]+/$pkgname-[a-zA-Z0-9\.]+-[0-9]+\.pkg\.tar\.gz$" $INSTALL_ROOT/$tanpath/$tandb`
if [ $? -gt 0 ]; then
message "package $pkgname not found"
exit 1
fi
pacman=`pacman -Q -r $INSTALL_ROOT $pkgname 2>/dev/null`
if [ $? -gt 0 ]; then
message "$pkgname is not installed (use \"install\" first)"
exit 1
fi
pkgver=`echo $pacman | awk '{print $2}'`
package="$pkgname-$pkgver"
filename=`echo $line | sed 's|^[a-z]*/||g'`
# compare filename and package. if they are at all different, we
# assume that the newer version is on the server and do the upgrade
if [ "$filename" = "$package.pkg.tar.gz" ]; then
message "$pkgname is already up to date (skipping)"
else
pkg2up="$pkg2up $filename"
if [ ! -f $INSTALL_ROOT/var/cache/pacman/pkg/$filename ]; then
pkg2dl="$pkg2dl $filename"
fi
fi
done
# download packages that aren't already cached
if [ "$pkg2dl" != "" ]; then
download "packages" $pkg2dl
if [ $? -gt 0 ]; then
exit 1
fi
if [ `pwd` != "$INSTALL_ROOT/var/cache/pacman/pkg" ]; then
# move downloaded files into cache
mkdir -p $INSTALL_ROOT/var/cache/pacman/pkg
mv $pkg2dl $INSTALL_ROOT/var/cache/pacman/pkg/
fi
fi
# install packages
if [ "$pkg2up" != "" ]; then
message "Upgrading packages"
cd $INSTALL_ROOT/var/cache/pacman/pkg
pacman -U -r $INSTALL_ROOT $pkg2up
if [ $? -gt 0 ]; then
message "error: some packages failed to upgrade"
exit 1
fi
message "Done"
fi
exit 0
}
doreport() {
headers=0
newkernel=0
pkg2up=
for pkgfile in `cat $INSTALL_ROOT/$tanpath/$tandb | sed "s|^[a-z]*/||g"`; do
pkgname=`echo $pkgfile | sed 's|-[a-zA-Z0-9\.]*-[0-9]*\.pkg\.tar\.gz||g'`
pacman=`pacman -Q -r $INSTALL_ROOT $pkgname 2>/dev/null`
if [ $? -gt 0 ]; then
# skip this one, it's not installed
continue
fi
pkgver=`echo $pacman | awk '{print $2}'`
locfile="$pkgname-$pkgver"
remfile=`echo $pkgfile | sed 's|^[a-zA-Z]*/||g' | sed 's|\.pkg\.tar\.gz||g'`
# compare locfile and remfile
if [ "$locfile" = "$remfile" ]; then
# this package is up to date
continue
else
if [ `echo "$locfile" | egrep '^kernel-[a-zA-Z0-9\.]+-[0-9]+$'` ]; then
# this is the kernel pacakge -- we handle this one specially
newkernel=1
continue
fi
if [ "$IGNORE_PKG" != "" ]; then
if [ `echo "$locfile" | egrep "$IGNORE_PKG"` ]; then
# ignore this package as per user's request
continue
fi
fi
if [ "$headers" = "0" ]; then
echo "+--------------------------------------+--------------------------------------+"
echo "| LOCAL | REMOTE |"
echo "+--------------------------------------+--------------------------------------+"
headers=1
fi
echo -n "| $locfile"
awk "BEGIN { for (j=length(\"$locfile\"); j<36; j++) printf \" \" }"
echo -n " | "
awk "BEGIN { for (j=length(\"$remfile\"); j<36; j++) printf \" \" }"
echo "$remfile |"
pkg2up="$pkg2up $pkgname"
fi
done
if [ "$headers" = "1" ]; then
echo "+--------------------------------------+--------------------------------------+"
fi
if [ "$newkernel" = "1" ]; then
echo
echo "NOTICE: A new kernel is available for upgrade, but this process will not"
echo " upgrade it for you. If you wish to upgrade, you must explicitly"
echo " request it by running 'pacsync upgrade kernel'. If you choose to"
echo " upgrade, make sure you re-run 'lilo' as well!"
echo
fi
# do we upgrade?
if [ "$upgrade" = "1" -a "$pkg2up" != "" ]; then
echo ""
echo -n "Do you want to upgrade these packages? [Y/n] "
read answer
echo ""
if [ "$answer" = "y" -o "$answer" = "Y" -o "$answer" = "" ]; then
doupgrade $pkg2up
fi
fi
exit 0
}
cd /tmp
if [ $# -lt 1 ]; then
usage
exit 0
fi
if [ "$1" = "--root" ]; then
shift
INSTALL_ROOT=$1
shift
fi
while [ "$1" = "--ignore" ]; do
shift
if [ "$IGNORE_PKG" = "" ]; then
IGNORE_PKG="$1"
else
IGNORE_PKG="$IGNORE_PKG|$1"
fi
shift
done
if [ -f /etc/pacsync.conf ]; then
. /etc/pacsync.conf
else
message "error: Missing /etc/pacsync.conf configuration file!"
exit 1
fi
proto=`echo $SYNC_SERVER | sed 's|://.*||'`
# check for a download utility
if [ -x /usr/bin/snarf ]; then
ftpagent="/usr/bin/snarf"
elif [ -x /usr/bin/lftpget -a "$proto" = "ftp" ]; then
ftpagent="/usr/bin/lftpget"
elif [ -x /usr/bin/wget ]; then
ftpagent="/usr/bin/wget --passive-ftp --tries=3 --waitretry=3"
else
message "error: you need an ftp client installed (snarf/lftp/wget) in /usr/bin"
exit 1
fi
op=$1
shift
if [ "$1" = "-v" ]; then
verbose=1
shift
fi
case $op in
sync)
dosync
;;
install)
checkdb
if [ "$1" = "" ]; then
message "error: no package specified"
exit 1
fi
doinstall $*
;;
upgrade)
checkdb
if [ "$1" = "" ]; then
message "error: no package specified"
exit 1
fi
doupgrade $*
;;
report)
checkdb
doreport
;;
sysupgrade)
checkdb
upgrade=1
doreport
;;
clean)
message "Removing packages from cache"
rm -f $INSTALL_ROOT/var/cache/pacman/pkg/*
;;
*)
message "error: invalid operation"
exit 1
;;
esac

View file

@ -1,53 +0,0 @@
.TH pacsync 8 "Mar 17, 2002" "pacsync #VERSION#" ""
.SH NAME
pacsync \- package update frontend for pacman
.SH SYNOPSIS
\fBpacsync [--root <root>] <operation> [package] [package] ...\fP
.SH DESCRIPTION
\fBpacsync\fP is a \fIpackage update\fP frontend for the
\fIpacman\fP package manager. It keeps track of the versions
of packages installed on the local system and the versions of
packages on a remote server. This allows you to issue a single
command and have you system's packages brought into sync.
.SH OPERATIONS
.TP
.B "sync"
Download a new copy of the package list from the server. This
should be done regularly, usually before an "install", "upgrade"
or "sysupgrade" command.
.TP
.B "install <package>"
Install a new package. \fBpacsync\fP will first look for the package
in the cache directory. If it is not there, it will attempt to
download the file from the server. On success, the package will
be installed. (Note that the downloaded file is also copied to
a cache directory on your filesystem. You can delete it with
"clean").
.TP
.B "upgrade <package>"
Upgrade a package. This is the same as \fIinstall\fP, except a package
is upgraded (ie, it is already installed in the system).
.TP
.B "report"
Generate an upgrade report. This operation will compare all local
package versions to remote versions, and then show you a report of
the differences.
.TP
.B "sysupgrade"
Full system upgrade. This is the same as report except after confirmation,
\fBpacsync\fP will upgrade all packages that are not up to date.
.TP
.B "clean"
This will remove all downloaded packages from the cache directory. This
can/should be used regularly to free up diskspace.
.SH CONFIGURATION
Configuration options are stored in /etc/pacsync.conf. Currently there is only
one directive.
.TP
.B "SYNC_SERVER"
This should be set to the full URL of the download server closest to you.
FTP is preferred, but HTTP is supported also, provided you have wget.
.SH AUTHOR
.nf
Judd Vinet <jvinet@zeroflux.org>
.fi

View file

@ -1,58 +0,0 @@
#
# /etc/pacsync.conf
#
#
# From here you can configure pacsync to follow a certain package tree.
# Typically this is either 'stable' or 'current', but you can pick
# specific versions as well (eg, '0.2'). Read below for the structure.
#
# Arch Linux servers follow this directory structure:
#
# 0.1
# |- iso
# | |- i686
# |- os
# | |- i686
# 0.2
# |- iso
# | |- i686
# |- os
# | |- i686
# 0.3
# |- iso
# | |- i686
# |- os
# | |- i686
# current -> 0.3/os/i686
# stable -> 0.2/os/i686
#
#
# Set your SYNC_SERVER according to the version you wish to follow. For
# example, if you simply wish to follow the stable branch (whatever version
# it may be), then you can set SYNC_SERVER as follows:
#
# SYNC_SERVER="ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/stable"
#
# Other examples:
# SYNC_SERVER="ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/0.2/os/i686"
# SYNC_SERVER="ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/0.3/os/i686"
# SYNC_SERVER="ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/current"
#
#
# SYNC_SERVER: the full location of the package repository (ftp or http)
#
SYNC_SERVER="ftp://ftp.ibiblio.org/pub/linux/distributions/archlinux/current"
#
# OTHER LOCATIONS (MIRRORS)
#
# Note: ibiblio.org will typically be fastest. Please stick with them unless
# you've got a good reason to change.
#
#SYNC_SERVER="http://www.ibiblio.org/pub/linux/distributions/archlinux/current"
#SYNC_SERVER="ftp://ftp2.archlinux.org/current"
#SYNC_SERVER="ftp://ftp.archlinux.org/current"

54
scripts/abs Executable file
View file

@ -0,0 +1,54 @@
#!/bin/bash
myver='2.0'
ABS_ROOT=/usr/abs
usage() {
echo "abs $myver"
echo "usage: $0"
echo
echo "abs will synchronize PKGBUILD scripts from the CVS repository"
echo "into /usr/abs. You can follow different package trees by editing"
echo "/etc/abs/supfile"
echo
exit 0
}
update() {
if [ ! `type -p cvsup` ]; then
echo "abs: cvsup was not found in PATH. Install cvsup"
exit 1
fi
if [ ! -d "$ABS_ROOT" ]; then
echo "abs: directory $ABS_ROOT does not exist"
exit 1
fi
if [ ! -r /etc/abs/supfile ]; then
echo "abs: missing config file /etc/abs/supfile"
exit 1
fi
if [ "`id -u`" != "0" ]; then
echo "abs: you must be root to update your ABS tree"
exit 1
fi
cd $ABS_ROOT && cvsup -L 1 -r 0 -g -c .sup /etc/abs/supfile
}
for opt in "$@"; do
case $opt in
-h|--help)
usage
exit 0 ;;
*)
echo "abs: invalid option \"$opt\""
exit 1 ;;
esac
done
update
exit 0

252
scripts/makepkg Executable file
View file

@ -0,0 +1,252 @@
#!/bin/bash
myver='2.0'
startdir=`pwd`
[ -f /etc/makepkg.conf ] && source /etc/makepkg.conf
strip_url() {
echo $1 | sed 's|^.*://.*/||g'
}
msg() {
echo $* >&2
}
if [ "$1" = "--help" -o "$1" = "-h" ]; then
shift
echo "makepkg version $myver"
echo "usage: $0 [options] [build_script]"
echo "options:"
echo " -c, --clean Clean up work files after build"
echo " -i, --install Install package after successful build"
echo " -h, --help This help"
echo
echo " if build_script is not specified, makepkg will look for a PKGBUILD"
echo " file in the current directory."
echo
exit 0
fi
CLEANUP=0
INSTALL=0
if [ "$1" = "-c" -o "$1" = "--clean" ]; then
shift
CLEANUP=1
fi
if [ "$1" = "-i" -o "$1" = "--install" ]; then
shift
INSTALL=1
fi
unset pkgname pkgver pkgrel pkgdesc
unset depends conflicts backup source install build
umask 0022
# check for a download utility
if [ -x /usr/bin/wget ]; then
ftpagent="/usr/bin/wget --passive-ftp --tries=3 --waitretry=3"
elif [ -x /usr/bin/snarf ]; then
ftpagent="/usr/bin/snarf"
elif [ -x /usr/bin/lftpget -a "$proto" = "ftp" ]; then
ftpagent="/usr/bin/lftpget"
else
msg "==> ERROR: You need an ftp client installed (snarf/lftp/wget) in /usr/bin"
exit 1
fi
BUILDSCRIPT="./PKGBUILD"
if [ "$1" != "" ]; then
BUILDSCRIPT=$1
fi
if [ ! -f $BUILDSCRIPT ]; then
msg "==> ERROR: $BUILDSCRIPT does not exist."
exit 1
fi
source $BUILDSCRIPT
# check for no-no's
if [ `echo $pkgver | grep '-'` ]; then
msg "==> ERROR: pkgver is not allowed to contain hyphens."
exit 1
fi
if [ `echo $pkgrel | grep '-'` ]; then
msg "==> ERROR: pkgrel is not allowed to contain hyphens."
exit 1
fi
if [ `type -p pacman` ]; then
msg "==> Checking Dependencies..."
missdep=`pacman -T ${depends[@]}`
ret=$?
if [ "$ret" != "0" ]; then
if [ "$ret" = "127" ]; then
msg "==> ERROR: Dependency Check Failed:"
msg ""
nl=0
for dep in $missdep; do
echo -ne "$dep " >&2
if [ "$nl" = "1" ]; then
nl=0
echo -ne "\n" >&2
continue
fi
nl=1
done
msg ""
else
msg "==> ERROR: pacman returned a fatal error."
fi
exit 1
fi
else
msg "==> WARNING: pacman was not found in PATH. skipping dependency checks."
fi
d=`date`
msg "==> Making package $pkgname ($d)"
# extract source
msg "==> Acquiring/Extracting Sources..."
mkdir -p src
cd $startdir/src
for netfile in ${source[@]}; do
file=`strip_url $netfile`
if [ -f ../$file ]; then
msg "==> Found $file in build dir"
cp ../$file .
elif [ -f /var/cache/pacman/src/$file ]; then
msg "==> Using local copy of $file"
cp /var/cache/pacman/src/$file .
else
proto=`echo $netfile | sed 's|://.*||'`
if [ "$proto" != "ftp" -a "$proto" != "http" ]; then
msg "==> ERROR: $netfile was not found in the build directory and is not a proper URL."
msg "==> Aborting..."
exit 1
fi
msg "==> Downloading $file"
$ftpagent $netfile 2>&1
if [ ! -f $file ]; then
msg "==> ERROR: Failed to download $file"
msg "==> Aborting..."
exit 1
fi
mkdir -p /var/cache/pacman/src && cp $file /var/cache/pacman/src
fi
case $file in
*.tar.gz|*.tar.Z|*.tgz)
cmd="tar --use-compress-program=gzip -xf $file" ;;
*.tar.bz2)
cmd="tar --use-compress-program=bzip2 -xf $file" ;;
*.tar)
cmd="tar -xf $file" ;;
*.zip)
cmd="unzip -qq $file" ;;
*)
cmd="cp ../$file ." ;;
esac
msg "==> $cmd"
$cmd
done
# check for existing pkg directory
if [ -d $startdir/pkg ]; then
msg "==> Removing existing pkg directory..."
rm -rf $startdir/pkg
fi
mkdir -p $startdir/pkg
# build
msg "==> Building Package..."
build 2>&1
if [ $? -gt 0 ]; then
msg "==> Build Failed. Aborting..."
exit 2
fi
# get some package meta info
builddate=`date -u "+%a %b %d %k:%M:%S %Y"`
if [ "$PACKAGER" != "" ]; then
packager="$PACKAGER"
else
packager="Arch Linux (http://www.archlinux.org)"
fi
size=`du -cb $startdir/pkg | tail -1 | awk '{print $1}'`
# write the .PKGINFO file
msg "==> Generating .PKGINFO file..."
cd $startdir/pkg
echo "# Generated by makepkg $myver" >.PKGINFO
echo -n "# " >>.PKGINFO
date >>.PKGINFO
echo "pkgname = $pkgname" >>.PKGINFO
echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO
echo "pkgdesc = $pkgdesc" >>.PKGINFO
echo "builddate = $builddate" >>.PKGINFO
echo "packager = $packager" >>.PKGINFO
echo "size = $size" >>.PKGINFO
for depend in "${depends[@]}"; do
echo "depend = $depend" >>.PKGINFO
done
for conflict in "${conflicts[@]}"; do
echo "conflict = $conflict" >>.PKGINFO
done
for bakfile in "${backup[@]}"; do
echo "backup = $bakfile" >>.PKGINFO
done
# check for an install script
if [ "$install" != "" ]; then
msg "==> Copying install script..."
cp $startdir/$install $startdir/pkg/._install
fi
# remove info/doc files
cd $startdir
rm -rf pkg/usr/info pkg/usr/share/info
rm -rf pkg/usr/doc pkg/usr/share/doc
# move /usr/share/man files to /usr/man
if [ -d pkg/usr/share/man ]; then
mkdir -p pkg/usr/man
cp -a pkg/usr/share/man/* pkg/usr/man/
rm -rf pkg/usr/share/man
fi
# strip binaries
cd $startdir
msg "==> Stripping debugging symbols from libraries..."
find pkg/{,usr,usr/local}/lib -type f -exec /usr/bin/strip --strip-debug '{}' ';' 2>&1
msg "==> Stripping symbols from binaries..."
find pkg/{,usr,usr/local}/{bin,sbin} -type f -exec /usr/bin/strip '{}' ';' 2>&1
# tar it up
msg "==> Compressing package..."
cd $startdir/pkg
if [ -f $startdir/pkg/._install ]; then
tar czvf $startdir/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO ._install * >../filelist
else
tar czvf $startdir/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO * >../filelist
fi
cd $startdir
if [ "$CLEANUP" = "1" ]; then
msg "==> Cleaning up"
rm -rf src pkg
fi
d=`date`
msg "==> Finished making $pkgname ($d)"
if [ "$INSTALL" = "1" ]; then
msg "==> Running pacman --upgrade"
pacman --upgrade $pkgname-$pkgver-$pkgrel.pkg.tar.gz
fi
exit 0

View file

@ -1,11 +1,16 @@
#!/bin/bash
toplevel=`pwd`
version="1.23"
version="2.0"
if [ $# -lt 2 ]; then
echo "makepkg version $version"
echo "usage: $0 <destdir> <category> [category] ..."
if [ $# -lt 2 -o "$1" = "--help" -o "$1" = "-h" ]; then
echo "makeworld version $version"
echo "usage: $0 [options] <destdir> <category> [category] ..."
echo "options:"
echo " -c, --clean Clean up work files after build"
echo " -i, --install Install package after successful build"
echo " -h, --help This help"
echo
echo " where <category> is one or more of base, opt, contrib"
echo " eg: makeworld /packages base opt"
echo
@ -13,6 +18,16 @@ if [ $# -lt 2 ]; then
exit 1
fi
MAKEPKG_OPTS=
if [ "$1" = "-c" -o "$1" = "--clean" ]; then
shift
MAKEPKG_OPTS="$MAKEPKG_OPTS -c"
fi
if [ "$1" = "-i" -o "$1" = "--install" ]; then
shift
MAKEPKG_OPTS="$MAKEPKG_OPTS -i"
fi
dest=$1
shift
@ -25,7 +40,7 @@ for category in $*; do
. PKGBUILD
buildstatus=0
if [ ! -f $dest/$pkgname-$pkgver-$pkgrel.pkg.tar.gz ]; then
makepkg
makepkg $MAKEPKG_OPTS 2>>$toplevel/makepkg.log
if [ $? -gt 0 ]; then
buildstatus=2
else

6
scripts/pacsync Executable file
View file

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

163
src/convertdb.c Normal file
View file

@ -0,0 +1,163 @@
/*
* 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 <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "list.h"
char* trim(char *str);
int main(int argc, char* argv[])
{
FILE* db = NULL;
FILE* fp = NULL;
char* ptr = NULL;
char* dbdir = "/var/lib/pacman/pacman.db";
char name[256];
char ver[256];
char line[PATH_MAX+1];
char topdir[PATH_MAX+1];
char path[PATH_MAX+1];
mode_t oldumask;
struct stat buf;
if(argc < 2) {
printf("converts a pacman 1.x database to a pacman 2.0 format\n");
printf("usage: %s <target_dir>\n\n", basename(argv[0]));
printf("convertdb will convert all package data from /var/lib/pacman/pacman.db\n");
printf("to a 2.0 format and place it in target_dir.\n\n");
return(0);
}
db = fopen(dbdir, "r");
if(db == NULL) {
perror(dbdir);
return(1);
}
oldumask = umask(0000);
while(fgets(name, 255, db)) {
PMList *backup = NULL;
PMList *lp;
if(!fgets(ver, 255, db)) {
perror(dbdir);
return(1);
}
trim(name);
trim(ver);
fprintf(stderr, "converting %s\n", name);
/* package directory */
snprintf(topdir, PATH_MAX, "%s/%s-%s", argv[1], name, ver);
mkdir(topdir, 0755);
/* DESC */
snprintf(path, PATH_MAX, "%s/desc", topdir);
if(!(fp = fopen(path, "w"))) {
perror(path);
return(1);
}
fputs("%NAME%\n", fp);
fprintf(fp, "%s\n\n", name);
fputs("%VERSION%\n", fp);
fprintf(fp, "%s\n\n", ver);
fputs("%DESC%\n\n", fp);
fclose(fp);
/* DEPENDS */
snprintf(path, PATH_MAX, "%s/depends", topdir);
if(!(fp = fopen(path, "w"))) {
perror(path);
return(1);
}
fputs("%DEPENDS%\n\n", fp);
fputs("%REQUIREDBY%\n\n", fp);
fputs("%CONFLICTS%\n\n", fp);
fclose(fp);
/* FILES */
snprintf(path, PATH_MAX, "%s/files", topdir);
if(!(fp = fopen(path, "w"))) {
perror(path);
return(1);
}
fputs("%FILES%\n", fp);
while(fgets(line, 255, db) && strcmp(trim(line), "")) {
trim(line);
ptr = line;
/* check for backup designation and frontslashes that shouldn't be there */
if(line[0] == '*') ptr++;
if(*ptr == '/') ptr++;
if(line[0] == '*') backup = list_add(backup, strdup(ptr));
fprintf(fp, "%s\n", ptr);
}
fprintf(fp, "\n");
fputs("%BACKUP%\n", fp);
for(lp = backup; lp; lp = lp->next) {
/* print the filename and a bad md5 hash. we just use 32 f's cuz we can't
* md5 the original file since we don't have it
*/
fprintf(fp, "%s\tffffffffffffffffffffffffffffffff\n", (char*)lp->data);
}
fputs("\n", fp);
fclose(fp);
snprintf(path, PATH_MAX, "/var/lib/pacman/scripts/%s", name);
if(!stat(path, &buf)) {
snprintf(line, PATH_MAX, "/bin/cp %s %s/install", path, topdir);
system(line);
}
list_free(backup);
}
umask(oldumask);
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: */

508
src/db.c Normal file
View file

@ -0,0 +1,508 @@
/*
* 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "list.h"
#include "package.h"
#include "db.h"
#include "util.h"
#include "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
* installed packages
*
* returns: 0 on success
* 1 if db is not initialized
* 2 if db is corrupt
*/
pacdb_t* db_open(char *dbpath, char *treename)
{
pacdb_t *db = NULL;
char path[PATH_MAX];
MALLOC(db, sizeof(pacdb_t));
snprintf(path, PATH_MAX-1, "%s/%s", dbpath, treename);
db->dir = opendir(path);
if(db->dir == NULL) {
return(NULL);
}
strncpy(db->treename, treename, 128);
return(db);
}
void db_close(pacdb_t* db)
{
closedir(db->dir);
return;
}
/* frees pkgcache if necessary and returns a new package
* cache from db
*/
PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache)
{
pkginfo_t *info;
PMList *lp;
pkginfo_t **arr = NULL;
unsigned int arrct = 0;
int i;
PMList *cache = NULL;
/* if pm_packages already contains data, free it first */
for(lp = pkgcache; lp; lp = lp->next) {
if(lp->data) {
freepkg(lp->data);
lp->data = NULL;
}
}
list_free(pkgcache);
rewinddir(db->dir);
while((info = db_scan(db, NULL, INFRQ_DESC)) != NULL) {
/* add to the collective */
/* we load all package names into a linear array first, so qsort can handle it */
if(arr == NULL) {
arr = (pkginfo_t**)malloc(sizeof(pkginfo_t*));
arrct++;
} else {
arr = (pkginfo_t**)realloc(arr, (++arrct)*sizeof(pkginfo_t*));
}
if(arr == NULL) {
fprintf(stderr, "error: out of memory\n");
exit(1);
}
arr[arrct-1] = info;
}
/* sort the package list */
qsort(arr, (size_t)arrct, sizeof(pkginfo_t*), pkgcmp);
/* now load them into the proper PMList */
for(i = 0; i < arrct; i++) {
cache = list_add(cache, arr[i]);
}
return(cache);
}
pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq)
{
struct dirent *ent = NULL;
char name[256];
char *ptr = NULL;
int found = 0;
if(target != NULL) {
/* search for a specific package (by name only) */
rewinddir(db->dir);
/* read the . and .. first */
ent = readdir(db->dir);
ent = readdir(db->dir);
ent = readdir(db->dir);
while(!found && ent != NULL) {
strncpy(name, ent->d_name, 255);
/* truncate the string at the second-to-last hyphen, */
/* which will give us the package name */
if((ptr = rindex(name, '-'))) {
*ptr = '\0';
}
if((ptr = rindex(name, '-'))) {
*ptr = '\0';
}
if(!strcmp(name, target)) {
found = 1;
continue;
}
ent = readdir(db->dir);
}
if(!found) {
return(NULL);
}
} else {
/* normal iteration */
ent = readdir(db->dir);
if(ent && !strcmp(ent->d_name, ".")) {
ent = readdir(db->dir);
}
if(ent && !strcmp(ent->d_name, "..")) {
ent = readdir(db->dir);
}
if(ent == NULL) {
return(NULL);
}
}
return(db_read(db, ent, inforeq));
}
pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
{
FILE *fp = NULL;
struct stat buf;
pkginfo_t *info = NULL;
char path[PATH_MAX];
char topdir[PATH_MAX];
char line[512];
if(ent == NULL) {
return(NULL);
}
snprintf(topdir, PATH_MAX, "%s%s/%s", pmo_root, PKGDIR, db->treename);
info = newpkg();
/* we always load DESC */
inforeq |= INFRQ_DESC;
snprintf(path, PATH_MAX, "%s/%s", topdir, ent->d_name);
if(stat(path, &buf)) {
/* directory doesn't exist or can't be opened */
return(NULL);
}
/* DESC */
if(inforeq & INFRQ_DESC) {
snprintf(path, PATH_MAX, "%s/%s/desc", topdir, ent->d_name);
fp = fopen(path, "r");
if(fp == NULL) {
fprintf(stderr, "error: %s: %s\n", path, strerror(errno));
return(NULL);
}
while(!feof(fp)) {
if(fgets(line, 256, fp) == NULL) {
break;
}
trim(line);
if(!strcmp(line, "%NAME%")) {
if(fgets(info->name, 256, fp) == NULL) {
return(NULL);
}
trim(info->name);
} else if(!strcmp(line, "%VERSION%")) {
if(fgets(info->version, 64, fp) == NULL) {
return(NULL);
}
trim(info->version);
} else if(!strcmp(line, "%DESC%")) {
if(fgets(info->desc, 512, fp) == NULL) {
return(NULL);
}
trim(info->desc);
} else if(!strcmp(line, "%BUILDDATE%")) {
if(fgets(info->builddate, 32, fp) == NULL) {
return(NULL);
}
trim(info->builddate);
} else if(!strcmp(line, "%INSTALLDATE%")) {
if(fgets(info->installdate, 32, fp) == NULL) {
return(NULL);
}
trim(info->installdate);
} else if(!strcmp(line, "%PACKAGER%")) {
if(fgets(info->packager, 64, fp) == NULL) {
return(NULL);
}
trim(info->packager);
} else if(!strcmp(line, "%SIZE%")) {
char tmp[32];
if(fgets(tmp, sizeof(tmp), fp) == NULL) {
return(NULL);
}
trim(tmp);
info->size = atol(tmp);
}
}
fclose(fp);
}
/* FILES */
if(inforeq & INFRQ_FILES) {
snprintf(path, PATH_MAX, "%s/%s/files", topdir, ent->d_name);
fp = fopen(path, "r");
if(fp == NULL) {
fprintf(stderr, "error: %s: %s\n", path, strerror(errno));
return(NULL);
}
while(fgets(line, 256, fp)) {
trim(line);
if(!strcmp(line, "%FILES%")) {
while(fgets(line, 512, fp) && strlen(trim(line))) {
char *s = strdup(line);
info->files = list_add(info->files, s);
}
}
if(!strcmp(line, "%BACKUP%")) {
while(fgets(line, 512, fp) && strlen(trim(line))) {
char *s = strdup(line);
info->backup = list_add(info->backup, s);
}
}
}
fclose(fp);
}
/* DEPENDS */
if(inforeq & INFRQ_DEPENDS) {
snprintf(path, PATH_MAX, "%s/%s/depends", topdir, ent->d_name);
fp = fopen(path, "r");
if(fp == NULL) {
fprintf(stderr, "db_read: error: %s: %s\n", path, strerror(errno));
return(NULL);
}
while(!feof(fp)) {
fgets(line, 255, fp);
trim(line);
if(!strcmp(line, "%DEPENDS%")) {
while(fgets(line, 512, fp) && strlen(trim(line))) {
char *s = strdup(line);
info->depends = list_add(info->depends, s);
}
}
if(!strcmp(line, "%REQUIREDBY%")) {
while(fgets(line, 512, fp) && strlen(trim(line))) {
char *s = strdup(line);
info->requiredby = list_add(info->requiredby, s);
}
}
if(!strcmp(line, "%CONFLICTS%")) {
while(fgets(line, 512, fp) && strlen(trim(line))) {
char *s = strdup(line);
info->conflicts = list_add(info->conflicts, s);
}
}
}
fclose(fp);
}
/* INSTALL */
snprintf(path, PATH_MAX, "%s/%s/install", topdir, ent->d_name);
if(!stat(path, &buf)) {
info->scriptlet = 1;
}
return(info);
}
int db_write(pacdb_t *db, pkginfo_t *info)
{
FILE *fp = NULL;
char topdir[PATH_MAX];
char path[PATH_MAX];
mode_t oldmask;
PMList *lp = NULL;
if(info == NULL) {
return(1);
}
snprintf(topdir, PATH_MAX, "%s%s/%s/%s-%s", pmo_root, PKGDIR, db->treename,
info->name, info->version);
oldmask = umask(0000);
mkdir(topdir, 0755);
umask(oldmask);
/* DESC */
snprintf(path, PATH_MAX, "%s/desc", topdir);
fp = fopen(path, "w");
if(fp == NULL) {
perror("db_write");
return(1);
}
fputs("%NAME%\n", fp);
fprintf(fp, "%s\n\n", info->name);
fputs("%VERSION%\n", fp);
fprintf(fp, "%s\n\n", info->version);
fputs("%DESC%\n", fp);
fprintf(fp, "%s\n\n", info->desc);
fputs("%BUILDDATE%\n", fp);
fprintf(fp, "%s\n\n", info->builddate);
fputs("%INSTALLDATE%\n", fp);
fprintf(fp, "%s\n\n", info->installdate);
fputs("%PACKAGER%\n", fp);
fprintf(fp, "%s\n\n", info->packager);
fputs("%SIZE%\n", fp);
fprintf(fp, "%ld\n\n", info->size);
fclose(fp);
/* FILES */
snprintf(path, PATH_MAX, "%s/files", topdir);
fp = fopen(path, "w");
if(fp == NULL) {
perror("db_write");
return(1);
}
fputs("%FILES%\n", fp);
for(lp = info->files; lp; lp = lp->next) {
fprintf(fp, "%s\n", (char*)lp->data);
}
fprintf(fp, "\n");
fputs("%BACKUP%\n", fp);
for(lp = info->backup; lp; lp = lp->next) {
fprintf(fp, "%s\n", (char*)lp->data);
}
fprintf(fp, "\n");
fclose(fp);
/* DEPENDS */
snprintf(path, PATH_MAX, "%s/depends", topdir);
fp = fopen(path, "w");
if(fp == NULL) {
perror("db_write");
return(1);
}
fputs("%DEPENDS%\n", fp);
for(lp = info->depends; lp; lp = lp->next) {
fprintf(fp, "%s\n", (char*)lp->data);
}
fprintf(fp, "\n");
fputs("%REQUIREDBY%\n", fp);
for(lp = info->requiredby; lp; lp = lp->next) {
fprintf(fp, "%s\n", (char*)lp->data);
}
fprintf(fp, "\n");
fputs("%CONFLICTS%\n", fp);
for(lp = info->conflicts; lp; lp = lp->next) {
fprintf(fp, "%s\n", (char*)lp->data);
}
fprintf(fp, "\n");
fclose(fp);
/* INSTALL */
/* nothing needed here (script is automatically extracted) */
return(0);
}
PMList* db_find_conflicts(pacdb_t *db, PMList *targets)
{
PMList *i, *j, *k;
char *filestr = NULL;
char path[PATH_MAX+1];
char *str = NULL;
struct stat buf;
PMList *conflicts = NULL;
/* CHECK 1: check every db package against every target package */
/* XXX: I've disabled the database-against-targets check for now, as the
* many many strcmp() calls slow it down heavily and most of the
* checking is redundant to the targets-against-filesystem check.
* This will be re-enabled if I can improve performance significantly.
*
pkginfo_t *info = NULL;
char *dbstr = NULL;
vprint("Checking database against targets...\n");
rewinddir(db->dir);
while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_FILES)) != NULL) {
for(i = info->files; i; i = i->next) {
if(i->data == NULL) continue;
dbstr = (char*)i->data;
for(j = targets; j; j = j->next) {
pkginfo_t *targ = (pkginfo_t*)j->data;
if(strcmp(info->name, targ->name)) {
for(k = targ->files; k; k = k->next) {
filestr = (char*)k->data;
if(!strcmp(dbstr, filestr)) {
if(rindex(k->data, '/') == filestr+strlen(filestr)-1) {
continue;
}
MALLOC(str, 512);
snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (installed)", dbstr,
targ->name, info->name);
conflicts = list_add(conflicts, str);
}
}
}
}
}
}*/
/* CHECK 2: check every target against every target */
vprint("Checking targets against targets...\n");
for(i = targets; i; i = i->next) {
pkginfo_t *p1 = (pkginfo_t*)i->data;
for(j = i; j; j = j->next) {
pkginfo_t *p2 = (pkginfo_t*)j->data;
if(strcmp(p1->name, p2->name)) {
for(k = p1->files; k; k = k->next) {
filestr = k->data;
if(!strcmp(filestr, "._install")) {
continue;
}
if(rindex(filestr, '/') == filestr+strlen(filestr)-1) {
/* this filename has a trailing '/', so it's a directory -- skip it. */
continue;
}
if(is_in(filestr, p2->files)) {
MALLOC(str, 512);
snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (target)",
filestr, p1->name, p2->name);
conflicts = list_add(conflicts, str);
}
}
}
}
}
/* CHECK 3: check every target against the filesystem */
vprint("Checking targets against filesystem...\n");
for(i = targets; i; i = i->next) {
pkginfo_t *p = (pkginfo_t*)i->data;
pkginfo_t *dbpkg = NULL;
for(j = p->files; j; j = j->next) {
filestr = (char*)j->data;
snprintf(path, PATH_MAX, "%s%s", pmo_root, filestr);
if(!stat(path, &buf) && !S_ISDIR(buf.st_mode)) {
int ok = 0;
if(dbpkg == NULL) {
dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES);
}
if(dbpkg && is_in(j->data, dbpkg->files)) {
ok = 1;
}
if(!ok) {
MALLOC(str, 512);
snprintf(str, 512, "%s: exists in filesystem", path);
conflicts = list_add(conflicts, str);
}
}
}
freepkg(dbpkg);
dbpkg = NULL;
}
return(conflicts);
}
/* vim: set ts=2 sw=2 noet: */

46
src/db.h Normal file
View file

@ -0,0 +1,46 @@
/*
* 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_DB_H
#define _PAC_DB_H
#include <dirent.h>
/* info requests for db_read */
#define INFRQ_DESC 0x01
#define INFRQ_DEPENDS 0x02
#define INFRQ_FILES 0x04
#define INFRQ_ALL 0xFF
typedef struct __pacdb_t {
char treename[128];
DIR* dir;
} pacdb_t;
pacdb_t* db_open(char *dbpath, char *treename);
void db_close(pacdb_t *db);
PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache);
pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq);
pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq);
int db_write(pacdb_t *db, pkginfo_t *info);
PMList* db_find_conflicts(pacdb_t *db, PMList* targets);
#endif
/* vim: set ts=2 sw=2 noet: */

122
src/list.c Normal file
View file

@ -0,0 +1,122 @@
/*
* 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "list.h"
PMList* list_new()
{
PMList *list = NULL;
list = (PMList*)malloc(sizeof(PMList));
if(list == NULL) {
return(NULL);
}
list->data = NULL;
list->prev = NULL;
list->next = NULL;
return(list);
}
void list_free(PMList *list)
{
if(list == NULL) {
return;
}
if(list->data != NULL) {
free(list->data);
list->data = NULL;
}
if(list->next != NULL) {
list_free(list->next);
}
free(list);
return;
}
PMList* list_add(PMList *list, void *data)
{
PMList *ptr, *lp;
ptr = list;
if(ptr == NULL) {
ptr = list_new();
}
lp = list_last(ptr);
if(lp == ptr && lp->data == NULL) {
/* nada */
} else {
lp->next = list_new();
if(lp->next == NULL) {
return(NULL);
}
lp->next->prev = lp;
lp = lp->next;
}
lp->data = data;
return(ptr);
}
int list_count(PMList *list)
{
int i;
PMList *lp;
for(lp = list, i = 0; lp; lp = lp->next, i++);
return(i);
}
/* List one is extended and returned
* List two is freed (but not its data)
*/
PMList* list_merge(PMList *one, PMList *two)
{
PMList *lp;
for(lp = two; lp; lp = lp->next) {
if(lp->data) {
list_add(one, lp->data);
lp->data = NULL;
}
}
list_free(two);
return(one);
}
PMList* list_last(PMList *list)
{
PMList *ptr;
for(ptr = list; ptr && ptr->next; ptr = ptr->next);
return(ptr);
}
/* vim: set ts=2 sw=2 noet: */

20
src/list.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef _PAC_LIST_H
#define _PAC_LIST_H
/* your average linked list */
typedef struct __pmlist_t {
void* data;
struct __pmlist_t* prev;
struct __pmlist_t* next;
} PMList;
PMList* list_new();
void list_free(PMList* list);
PMList* list_add(PMList* list, void* data);
int list_count(PMList* list);
PMList* list_merge(PMList *one, PMList *two);
PMList* list_last(PMList* list);
#endif
/* vim: set ts=2 sw=2 noet: */

338
src/md5.c Normal file
View file

@ -0,0 +1,338 @@
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include "md5.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform(UINT4 [4], unsigned char [64]);
static void Encode(unsigned char *, UINT4 *, unsigned int);
static void Decode(UINT4 *, unsigned char *, unsigned int);
static void MD5_memcpy(POINTER, POINTER, unsigned int);
static void MD5_memset(POINTER, int, unsigned int);
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (context)
MD5_CTX *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (context, input, inputLen)
MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (digest, context)
unsigned char digest[16]; /* message digest */
MD5_CTX *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (state, block)
UINT4 state[4];
unsigned char block[64];
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (output, input, len)
unsigned char *output;
UINT4 *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (output, input, len)
UINT4 *output;
unsigned char *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}
/* vim: set ts=2 sw=2 noet: */

48
src/md5.h Normal file
View file

@ -0,0 +1,48 @@
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
void MD5Final(unsigned char [16], MD5_CTX *);
/* vim: set ts=2 sw=2 noet: */

83
src/md5driver.c Normal file
View file

@ -0,0 +1,83 @@
/* MD5DRIVER.C - taken and modified from MDDRIVER.C (license below) */
/* for use in pacman. */
/*********************************************************************/
/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
rights reserved.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* The following makes MD default to MD5 if it has not already been
defined with C compiler flags.
*/
#define MD MD5
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "md5.h"
/* Length of test block, number of test blocks.
*/
#define TEST_BLOCK_LEN 1000
#define TEST_BLOCK_COUNT 1000
char* MDFile(char *);
void MDPrint(unsigned char [16]);
#define MD_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final
char* MDFile(char *filename)
{
FILE *file;
MD_CTX context;
int len;
unsigned char buffer[1024], digest[16];
if((file = fopen(filename, "rb")) == NULL) {
printf ("%s can't be opened\n", filename);
} else {
char *ret;
int i;
MDInit(&context);
while((len = fread(buffer, 1, 1024, file))) {
MDUpdate(&context, buffer, len);
}
MDFinal(digest, &context);
fclose(file);
/*printf("MD5 (%s) = ", filename);
MDPrint(digest);
printf("\n");*/
ret = (char*)malloc(33);
ret[0] = '\0';
for(i = 0; i < 16; i++) {
sprintf(ret, "%s%02x", ret, digest[i]);
}
return(ret);
}
return(NULL);
}
/* Prints a message digest in hexadecimal.
*/
void MDPrint(unsigned char digest[16])
{
unsigned int i;
for (i = 0; i < 16; i++)
printf ("%02x", digest[i]);
}
/* vim: set ts=2 sw=2 noet: */

228
src/package.c Normal file
View file

@ -0,0 +1,228 @@
/*
* 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "list.h"
#include "package.h"
#include "db.h"
#include "util.h"
#include "pacman.h"
extern tartype_t gztype;
pkginfo_t* load_pkg(char *pkgfile, unsigned short output)
{
char *expath;
char *descfile;
int i;
TAR *tar;
pkginfo_t *info = NULL;
PMList *backup = NULL;
PMList *lp;
info = newpkg();
descfile = strdup("/tmp/pacman_XXXXXX");
if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
perror("could not open package");
return(NULL);
}
vprint("load_pkg: loading filelist from package...\n");
for(i = 0; !th_read(tar); i++) {
if(!strcmp(th_get_pathname(tar), ".PKGINFO")) {
/* extract this file into /tmp. it has info for us */
vprint("load_pkg: found package description file.\n");
mkstemp(descfile);
tar_extract_file(tar, descfile);
/* parse the info file */
parse_descfile(descfile, info, &backup, output);
if(!strlen(info->name)) {
fprintf(stderr, "error: missing package name in description file.\n");
return(NULL);
}
if(!strlen(info->version)) {
fprintf(stderr, "error: missing package version in description file.\n");
return(NULL);
}
for(lp = backup; lp; lp = lp->next) {
if(lp->data) {
info->backup = list_add(info->backup, lp->data);
}
}
continue;
}
if(!strcmp(th_get_pathname(tar), "._install")) {
info->scriptlet = 1;
} else {
expath = strdup(th_get_pathname(tar));
/* add the path to the list */
info->files = list_add(info->files, expath);
}
if(TH_ISREG(tar) && tar_skip_regfile(tar)) {
perror("bad package file");
return(NULL);
}
expath = NULL;
}
tar_close(tar);
FREE(descfile);
if(!strlen(info->name) || !strlen(info->version)) {
fprintf(stderr, "Error: Missing .PKGINFO file in %s\n", pkgfile);
return(NULL);
}
return(info);
}
/* Parses the package description file for the current package
*
* Returns: 0 on success, 1 on error
*
*/
int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output)
{
FILE* fp = NULL;
char line[PATH_MAX+1];
char* ptr = NULL;
char* key = NULL;
int linenum = 0;
PMList* bak = NULL;
if((fp = fopen(descfile, "r")) == NULL) {
perror(descfile);
return(1);
}
while(!feof(fp)) {
fgets(line, PATH_MAX, fp);
if(output) {
printf("%s", line);
}
linenum++;
trim(line);
if(line[0] == '#') {
continue;
}
if(strlen(line) == 0) {
continue;
}
ptr = line;
key = strsep(&ptr, "=");
if(key == NULL || ptr == NULL) {
fprintf(stderr, "Syntax error in description file line %d\n", linenum);
} else {
trim(key);
key = strtoupper(key);
trim(ptr);
if(!strcmp(key, "PKGNAME")) {
strncpy(info->name, ptr, sizeof(info->name));
} else if(!strcmp(key, "PKGVER")) {
strncpy(info->version, ptr, sizeof(info->version));
} else if(!strcmp(key, "PKGDESC")) {
strncpy(info->desc, ptr, sizeof(info->desc));
} else if(!strcmp(key, "BUILDDATE")) {
strncpy(info->builddate, ptr, sizeof(info->builddate));
} else if(!strcmp(key, "INSTALLDATE")) {
strncpy(info->installdate, ptr, sizeof(info->installdate));
} else if(!strcmp(key, "PACKAGER")) {
strncpy(info->packager, ptr, sizeof(info->packager));
} else if(!strcmp(key, "SIZE")) {
char tmp[32];
strncpy(tmp, ptr, sizeof(tmp));
info->size = atol(tmp);
} else if(!strcmp(key, "DEPEND")) {
char *s = strdup(ptr);
info->depends = list_add(info->depends, s);
} else if(!strcmp(key, "CONFLICT")) {
char *s = strdup(ptr);
info->conflicts = list_add(info->conflicts, s);
} else if(!strcmp(key, "BACKUP")) {
char *s = strdup(ptr);
bak = list_add(bak, s);
} else {
fprintf(stderr, "Syntax error in description file line %d\n", linenum);
}
}
line[0] = '\0';
}
fclose(fp);
unlink(descfile);
*backup = bak;
return(0);
}
pkginfo_t* newpkg()
{
pkginfo_t* pkg = NULL;
MALLOC(pkg, sizeof(pkginfo_t));
pkg->name[0] = '\0';
pkg->version[0] = '\0';
pkg->desc[0] = '\0';
pkg->builddate[0] = '\0';
pkg->installdate[0] = '\0';
pkg->packager[0] = '\0';
pkg->size = 0;
pkg->scriptlet = 0;
pkg->requiredby = NULL;
pkg->conflicts = NULL;
pkg->files = NULL;
pkg->backup = NULL;
pkg->depends = NULL;
return(pkg);
}
void freepkg(pkginfo_t *pkg)
{
if(pkg == NULL) {
return;
}
list_free(pkg->files);
list_free(pkg->backup);
list_free(pkg->depends);
list_free(pkg->conflicts);
list_free(pkg->requiredby);
FREE(pkg);
return;
}
/* Helper function for sorting packages
*/
int pkgcmp(const void *p1, const void *p2)
{
pkginfo_t **pkg1 = (pkginfo_t**)p1;
pkginfo_t **pkg2 = (pkginfo_t**)p2;
return(strcmp(pkg1[0]->name, pkg2[0]->name));
}
/* vim: set ts=2 sw=2 noet: */

67
src/package.h Normal file
View file

@ -0,0 +1,67 @@
/*
* 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_PACKAGE_H
#define _PAC_PACKAGE_H
/* mods for depend_t.mod */
#define DEP_ANY 0
#define DEP_EQ 1
#define DEP_GE 2
#define DEP_LE 3
/* Package Structures */
typedef char** fileset_t;
typedef struct __pkginfo_t {
char name[256];
char version[64];
char desc[512];
char builddate[32];
char installdate[32];
char packager[64];
unsigned long size;
unsigned short scriptlet;
PMList *files;
PMList *backup;
PMList *depends;
PMList *requiredby;
PMList *conflicts;
} pkginfo_t;
typedef struct __depend_t {
unsigned short mod;
char name[256];
char version[64];
} depend_t;
typedef struct __depmissing_t {
enum {DEPEND, REQUIRED, CONFLICT} type;
char target[256];
depend_t depend;
} depmissing_t;
pkginfo_t* load_pkg(char *pkgfile, unsigned short output);
int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output);
pkginfo_t* newpkg();
void freepkg(pkginfo_t *pkg);
int pkgcmp(const void *p1, const void *p2);
#endif
/* vim: set ts=2 sw=2 noet: */

1660
src/pacman.c Normal file

File diff suppressed because it is too large Load diff

62
src/pacman.h Normal file
View file

@ -0,0 +1,62 @@
/*
* 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_PACMAN_H
#define _PAC_PACMAN_H
#ifndef PACVER
#define PACVER "2.0"
#endif
#ifndef PKGDIR
#define PKGDIR "var/lib/pacman"
#endif
#ifndef PACCONF
#define PACCONF "etc/pacman.conf"
#endif
/* Operations */
#define PM_MAIN 1
#define PM_ADD 2
#define PM_REMOVE 3
#define PM_QUERY 4
#define PM_UPGRADE 5
#define PM_SYNC 6
#define PM_DEPTEST 7
int pacman_add(pacdb_t *db, PMList *targets);
int pacman_remove(pacdb_t *db, PMList *targets);
int pacman_upgrade(pacdb_t *db, PMList *targets);
int pacman_query(pacdb_t *db, PMList *targets);
int pacman_sync(pacdb_t *db, PMList *targets);
int pacman_deptest(pacdb_t *db, PMList *targets);
PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets);
int resolvedeps(pacdb_t *local, pacdb_t *sync, pkginfo_t *package, PMList *list, PMList *trail);
int splitdep(char *depstr, depend_t *depend);
int lckmk(char *file, int retries, unsigned int sleep_secs);
int lckrm(char *lckfile);
void cleanup(int signum);
#endif /* PACMAN_H */
/* vim: set ts=2 sw=2 noet: */

183
src/pacsync.c Normal file
View file

@ -0,0 +1,183 @@
/*
* 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <ftplib.h>
/* pacman */
#include "list.h"
#include "package.h"
#include "db.h"
#include "util.h"
#include "pacsync.h"
#include "pacman.h"
static int log_progress(netbuf *ctl, int xfered, void *arg);
static char sync_fnm[25];
/* pacman options */
extern char *pmo_root;
/* configuration options */
extern char pmc_syncserver[512];
extern char pmc_syncpath[512];
extern char pmc_syncname[512];
int sync_synctree()
{
char ldir[PATH_MAX] = "";
char path[PATH_MAX];
mode_t oldmask;
char *str;
PMList *files = NULL;
snprintf(ldir, PATH_MAX, "%s%s/%s", pmo_root, PKGDIR, pmc_syncname);
/* remove the old dir */
vprint("Removing %s (if it exists)\n", ldir);
rmrf(ldir);
/* make the new dir */
oldmask = umask(0000);
mkdir(ldir, 0755);
umask(oldmask);
/* build out list of one */
snprintf(path, PATH_MAX, "%s.db.tar.gz", pmc_syncname);
str = strdup(path);
files = list_add(files, str);
if(downloadfiles(pmc_syncserver, pmc_syncpath, ldir, files)) {
list_free(files);
return(1);
}
/* uncompress the sync database */
snprintf(path, PATH_MAX, "%s/%s", ldir, (char*)files->data);
list_free(files);
vprint("Unpacking %s...\n", path);
if(unpack(path, ldir)) {
return(1);
}
/* remove the .tar.gz */
unlink(path);
return(0);
}
int downloadfiles(char *server, char *remotepath, char *localpath, PMList *files)
{
int fsz;
netbuf *control = NULL;
PMList *lp;
int ret = 0;
if(files == NULL) {
return(0);
}
FtpInit();
if(!FtpConnect(server, &control)) {
fprintf(stderr, "error: cannot connect to %s\n", server);
return(1);
}
if(!FtpLogin("anonymous", "arch@guest", control)) {
fprintf(stderr, "error: anonymous login failed\n");
FtpQuit(control);
return(1);
}
if(!FtpChdir(remotepath, control)) {
fprintf(stderr, "error: could not cwd to %s: %s\n", remotepath,
FtpLastResponse(control));
return(1);
}
/* get each file in the list */
for(lp = files; lp; lp = lp->next) {
char output[PATH_MAX];
int j;
snprintf(output, PATH_MAX, "%s/%s", localpath, (char*)lp->data);
/* passive mode */
/* TODO: make passive ftp an option */
if(!FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, control)) {
fprintf(stderr, "warning: failed to set passive mode\n");
}
if(!FtpSize((char*)lp->data, &fsz, FTPLIB_IMAGE, control)) {
fprintf(stderr, "warning: failed to get filesize for %s\n", (char*)lp->data);
}
/* set up our progress bar's callback */
FtpOptions(FTPLIB_CALLBACK, (long)log_progress, control);
FtpOptions(FTPLIB_IDLETIME, (long)1000, control);
FtpOptions(FTPLIB_CALLBACKARG, (long)&fsz, control);
FtpOptions(FTPLIB_CALLBACKBYTES, (10*1024), control);
strncpy(sync_fnm, lp->data, 24);
for(j = strlen(sync_fnm); j < 24; j++) {
sync_fnm[j] = ' ';
}
sync_fnm[24] = '\0';
if(!FtpGet(output, lp->data, FTPLIB_IMAGE, control)) {
fprintf(stderr, "\nerror: could not download %s: %s\n", (char*)lp->data,
FtpLastResponse(control));
/* unlink the file */
unlink(output);
ret = 1;
} else {
log_progress(control, fsz, &fsz);
}
printf("\n");
fflush(stdout);
}
FtpQuit(control);
return(ret);
}
static int log_progress(netbuf *ctl, int xfered, void *arg)
{
int fsz = *(int*)arg;
int pct = (unsigned int)(xfered * 100) / fsz;
int i;
printf("%s [", sync_fnm);
for(i = 0; i < (int)(pct/3); i++) {
printf("#");
}
for(i = (int)(pct/3); i < (int)(100/3); i++) {
printf(" ");
}
printf("] %3d%% | %6dK\r", pct, (xfered/1024));
fflush(stdout);
return(1);
}
/* vim: set ts=2 sw=2 noet: */

29
src/pacsync.h Normal file
View file

@ -0,0 +1,29 @@
/*
* 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_PACSYNC_H
#define _PAC_PACSYNC_H
int sync_synctree();
int downloadfiles(char *server, char *remotepath, char *localpath, PMList *files);
#endif
/* vim: set ts=2 sw=2 noet: */

120
src/rpmvercmp.c Normal file
View file

@ -0,0 +1,120 @@
/*
* 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 <ctype.h>
#include <string.h>
/* this function was taken from rpm 4.0.4 and rewritten */
int rpmvercmp(const char *a, const char *b)
{
char *str1, *str2;
char *one, *two;
char *rel1 = NULL, *rel2 = NULL;
char oldch1, oldch2;
int is1num, is2num;
int rc;
if(!strcmp(a,b)) {
return(0);
}
str1 = strdup(a);
str2 = strdup(b);
/* lose the release number */
for(one = str1; *one && *one != '-'; one++);
if(one) {
*one = '\0';
rel1 = ++one;
}
for(two = str2; *two && *two != '-'; two++);
if(two) {
*two = '\0';
rel2 = ++two;
}
one = str1;
two = str2;
while(*one || *two) {
while(*one && !isalnum(*one)) one++;
while(*two && !isalnum(*two)) two++;
str1 = one;
str2 = two;
/* find the next segment for each string */
if(isdigit(*str1)) {
is1num = 1;
while(*str1 && isdigit(*str1)) str1++;
} else {
is1num = 0;
while(*str1 && isalpha(*str1)) str1++;
}
if(isdigit(*str2)) {
is2num = 1;
while(*str2 && isdigit(*str2)) str2++;
} else {
is2num = 0;
while(*str2 && isalpha(*str2)) str2++;
}
oldch1 = *str1;
*str1 = '\0';
oldch2 = *str2;
*str2 = '\0';
/* see if we ran out of segments on one string */
if(one == str1 && two != str2) {
return(is2num ? -1 : 1);
}
if(one != str1 && two == str2) {
return(is1num ? 1 : -1);
}
/* see if we have a type mismatch (ie, one is alpha and one is digits) */
if(is1num && !is2num) return(1);
if(!is1num && is2num) return(-1);
if(is1num) while(*one == '0') one++;
if(is2num) while(*two == '0') two++;
rc = strverscmp(one, two);
if(rc) return(rc);
*str1 = oldch1;
*str2 = oldch2;
one = str1;
two = str2;
}
if((!*one) && (!*two)) {
/* compare release numbers */
if(rel1 && rel2) return(rpmvercmp(rel1, rel2));
return(0);
}
return(*one ? 1 : -1);
}
/* vim: set ts=2 sw=2 noet: */

571
src/util.c Normal file
View file

@ -0,0 +1,571 @@
/*
* 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <getopt.h>
#include <ctype.h>
#include "list.h"
#include "package.h"
#include "db.h"
#include "util.h"
#include "pacman.h"
extern char* pmo_root;
extern unsigned short pmo_op;
extern unsigned short pmo_version;
extern unsigned short pmo_verbose;
extern unsigned short pmo_help;
extern unsigned short pmo_force;
extern unsigned short pmo_nodeps;
extern unsigned short pmo_upgrade;
extern unsigned short pmo_nosave;
extern unsigned short pmo_vertest;
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_s_sync;
extern unsigned short pmo_s_search;
extern unsigned short pmo_s_clean;
extern unsigned short pmo_s_upgrade;
extern char pmc_syncserver[512];
extern char pmc_syncname[512];
extern char pmc_syncpath[512];
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;
int fd;
gzFile gzf;
switch (oflags & O_ACCMODE) {
case O_WRONLY:
gzoflags = "w";
break;
case O_RDONLY:
gzoflags = "r";
break;
case O_RDWR:
default:
errno = EINVAL;
return -1;
}
if((fd = open(pathname, oflags, mode)) == -1) {
return -1;
}
if((oflags & O_CREAT) && fchmod(fd, mode)) {
return -1;
}
if(!(gzf = gzdopen(fd, gzoflags))) {
errno = ENOMEM;
return -1;
}
return (int)gzf;
}
tartype_t gztype = {
(openfunc_t) gzopen_frontend,
(closefunc_t)gzclose,
(readfunc_t) gzread,
(writefunc_t)gzwrite
};
int unpack(char *archive, char *prefix)
{
TAR *tar = NULL;
char expath[PATH_MAX];
/* open the .tar.gz package */
if(tar_open(&tar, archive, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
perror(archive);
return(1);
}
while(!th_read(tar)) {
snprintf(expath, PATH_MAX, "%s/%s", prefix, th_get_pathname(tar));
if(tar_extract_file(tar, expath)) {
fprintf(stderr, "could not extract %s: %s\n", th_get_pathname(tar), strerror(errno));
}
}
tar_close(tar);
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'},
{"query", no_argument, 0, 'Q'},
{"sync", no_argument, 0, 'S'},
{"deptest", no_argument, 0, 'T'},
{"vertest", no_argument, 0, 'Y'},
{"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'},
{"refresh", no_argument, 0, 'y'},
{0, 0, 0, 0}
};
while((opt = getopt_long(argc, argv, "ARUQSTYr:vhscVfnoldpiuy", 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 '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_vertest = 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 'y': pmo_s_sync = 1; break;
case 's': pmo_s_search = 1; break;
case 'c': pmo_s_clean = 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;
if((fp = fopen(configfile, "r")) == NULL) {
perror(configfile);
return(1);
}
while(fgets(line, PATH_MAX, fp)) {
linenum++;
trim(line);
if(strlen(line) == 0) {
continue;
}
if(line[0] == '#') {
continue;
}
ptr = line;
key = strsep(&ptr, "=");
if(key == NULL || ptr == NULL) {
fprintf(stderr, "syntax error in config file (line %d)\n", linenum);
} else {
trim(key);
key = strtoupper(key);
trim(ptr);
if(!strcmp(key, "SYNC_SERVER")) {
strncpy(pmc_syncserver, ptr, sizeof(pmc_syncserver)-1);
} else if(!strcmp(key, "SYNC_TREE_PATH")) {
strncpy(pmc_syncpath, ptr, sizeof(pmc_syncpath)-1);
} else if(!strcmp(key, "SYNC_TREE_NAME")) {
strncpy(pmc_syncname, ptr, sizeof(pmc_syncname)-1);
} else {
fprintf(stderr, "Syntax error in description file line %d\n", linenum);
}
}
line[0] = '\0';
}
fclose(fp);
return(0);
}
int copyfile(char *src, char *dest)
{
FILE *in, *out;
size_t len;
char buf[1025];
in = fopen(src, "r");
if(in == NULL) {
return(1);
}
out = fopen(dest, "w");
if(out == NULL) {
return(1);
}
while((len = fread(buf, 1, 1024, in))) {
fwrite(buf, 1, len, out);
}
fclose(in);
fclose(out);
return(0);
}
int makepath(char *path)
{
char *orig, *str, *ptr;
char full[PATH_MAX] = "";
mode_t oldmask;
oldmask = umask(0000);
orig = strdup(path);
str = orig;
while((ptr = strsep(&str, "/"))) {
if(strlen(ptr)) {
struct stat buf;
strcat(full, "/");
strcat(full, ptr);
if(stat(full, &buf)) {
if(mkdir(full, 0755)) {
free(orig);
return(1);
}
}
}
}
free(orig);
umask(oldmask);
return(0);
}
int rmrf(char *path)
{
int errflag = 0;
struct dirent *dp;
DIR *dirp;
char name[PATH_MAX];
extern int errno;
if(!unlink(path)) {
return(0);
} else {
if (errno == ENOENT) {
return(0);
} else if (errno == EPERM) {
/* fallthrough */
} else if (errno == EISDIR) {
/* fallthrough */
} else if (errno == ENOTDIR) {
return(1);
} else {
/* not a directory */
return(1);
}
if((dirp = opendir(path)) == (DIR *)-1) {
return(1);
}
for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
if (dp->d_ino) {
sprintf(name, "%s/%s", path, dp->d_name);
if(strcmp(dp->d_name, "..") && strcmp(dp->d_name, ".")) {
errflag += rmrf(name);
}
}
}
closedir(dirp);
if(rmdir(path)) {
errflag++;
}
return(errflag);
}
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 {-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");
} else if(op == PM_UPGRADE) {
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(" -c, --clean remove packages from cache directory to free up diskspace\n");
}
printf(" -v, --verbose be verbose\n");
printf(" -r, --root <path> set an alternate installation root\n");
}
}
/* Version
*/
void version(void)
{
printf("\n");
printf(" .--. Pacman v%s\n", PACVER);
printf("/ _.-' .-. .-. .-. Copyright (C) 2002 Judd Vinet <jvinet@zeroflux.org>\n");
printf("\\ '-. '-' '-' '-' \n");
printf(" '--' This program may be freely redistributed under\n");
printf(" the terms of the GNU GPL\n\n");
}
/* Check verbosity option and, if set, print the
* string to stdout
*/
int vprint(char *fmt, ...)
{
va_list args;
if(pmo_verbose) {
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
return(0);
}
int yesno(char *fmt, ...)
{
char response[32];
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
if(fgets(response, 32, stdin)) {
trim(response);
if(!strcasecmp(response, "Y") || !strcasecmp(response, "YES") || !strlen(response)) {
return(1);
}
}
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);
}
/* Look for a filename in a pkginfo_t.backup list. If we find it,
* then we return the md5 hash (parsed from the same line)
*/
char* needbackup(char* file, PMList *backup)
{
PMList *lp;
/* run through the backup list and parse out the md5 hash for our file */
for(lp = backup; lp; lp = lp->next) {
char* str = strdup(lp->data);
char* ptr;
/* tab delimiter */
ptr = index(str, '\t');
if(ptr == NULL) {
FREE(str);
continue;
}
*ptr = '\0';
ptr++;
/* now str points to the filename and ptr points to the md5 hash */
if(!strcmp(file, str)) {
char *md5 = strdup(ptr);
FREE(str);
return(md5);
}
FREE(str);
}
return(NULL);
}
/* Test for existence of a package in a PMList*
* of pkginfo_t*
*
* returns: 0 for no match
* 1 for identical match
* -1 for name-only match (version mismatch)
*/
int is_pkgin(pkginfo_t *needle, PMList *haystack)
{
PMList *lp;
pkginfo_t *info;
for(lp = haystack; lp; lp = lp->next) {
info = (pkginfo_t*)lp->data;
if(info && !strcmp(info->name, needle->name)) {
if(!strcmp(info->version, needle->version)) {
return(1);
}
return(-1);
}
}
return(0);
}
/* Convert a string to uppercase
*/
char* strtoupper(char *str)
{
char *ptr = str;
while(*ptr) {
(*ptr) = toupper(*ptr);
ptr++;
}
return str;
}
/* 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: */

52
src/util.h Normal file
View file

@ -0,0 +1,52 @@
/*
* 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_UTIL_H
#define _PAC_UTIL_H
#include <libtar.h>
#include <zlib.h>
#define MALLOC(p, b) { if((b) > 0) { \
p = malloc(b); if (!(p)) { \
fprintf(stderr, "malloc failure: could not allocate %d byets\n", b); \
exit(1); }} else p = NULL; }
#define FREE(p) { if (p) { free(p); (p)= NULL; }}
int unpack(char *archive, char *prefix);
int parseargs(int op, int argc, char **argv);
int parseconfig(char *configfile);
int copyfile(char *src, char *dest);
int makepath(char *path);
int rmrf(char *path);
int vprint(char *fmt, ...);
int yesno(char* fmt, ...);
void usage(int op, char *myname);
void version(void);
char* needbackup(char *file, PMList *backup);
int is_in(char *needle, PMList *haystack);
int is_pkgin(pkginfo_t *needle, PMList *haystack);
char* trim(char *str);
char* strtoupper(char *str);
#endif
/* vim: set ts=2 sw=2 noet: */