Imported from pacman-1.2.tar.gz

This commit is contained in:
Judd Vinet 2002-03-18 09:36:01 +00:00
parent 8cf35f551f
commit 931506031b
12 changed files with 692 additions and 128 deletions

View file

@ -1,5 +1,10 @@
VERSION DESCRIPTION VERSION DESCRIPTION
------------------------------------------------------------------ ------------------------------------------------------------------
-
1.1 - Fixed some string-handling bugs
- Added better handling of configuration files and the like.
If "file" is about to be removed, but it is designated to
be backed up, then it will be copied to "file.save"
- Changed db_find_conflicts() to ignore directories - Changed db_find_conflicts() to ignore directories
1.0 - Initial Release 1.0 - Initial Release

View file

@ -27,7 +27,7 @@ BINDIR = /usr/bin
MANDIR = /usr/man MANDIR = /usr/man
ETCDIR = /etc ETCDIR = /etc
VERSION = 1.1 VERSION = 1.2
LIBTAR_VERSION = 1.2.4 LIBTAR_VERSION = 1.2.4
CXX = gcc CXX = gcc
@ -45,7 +45,7 @@ pacman: $(OBJECTS)
pacman.o: pacman.c pacman.h pacman.o: pacman.c pacman.h
$(CXX) $(CXXFLAGS) -c pacman.c $(CXX) $(CXXFLAGS) -c pacman.c
man: pacman.8 man: pacman.8 pacsync.8 makepkg.8
%: %.in %: %.in
sed -e "s/#VERSION#/$(VERSION)/" $< > $@ sed -e "s/#VERSION#/$(VERSION)/" $< > $@
@ -62,11 +62,14 @@ libtar:
install: all install: all
install -D -m0755 pacman $(DESTDIR)$(BINDIR)/pacman install -D -m0755 pacman $(DESTDIR)$(BINDIR)/pacman
install -D -m0644 pacman.8 $(DESTDIR)$(MANDIR)/man8/pacman.8 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 makepkg $(DESTDIR)$(BINDIR)/makepkg
install -D -m0755 makeworld $(DESTDIR)$(BINDIR)/makeworld install -D -m0755 makeworld $(DESTDIR)$(BINDIR)/makeworld
install -D -m0755 pacsync $(DESTDIR)$(BINDIR)/pacsync
@echo "" @echo ""
@echo "*** If this is a first-time install, you should copy makepkg.conf" @echo "*** If this is a first-time install, you should copy makepkg.conf"
@echo "*** to /etc now." @echo "*** and pacsync.conf to /etc now."
@echo "" @echo ""
clean: clean:

18
README
View file

@ -13,7 +13,17 @@ DESCRIPTION:
upgrade packages in the system, and it will allow you to query the 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.
Plans exist for dependency checking and remote file fetching, as well. 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.
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. See TODO for more info.
@ -32,15 +42,15 @@ Note: Since pacman is compiled statically, you will need the static libraries
BUGS: BUGS:
----- -----
If you find bugs (which is quite likely at version 1.0), please submit If you find bugs (which is quite likely), please submit them to
them to <jvinet@zeroflux.org> with specific information, such as your <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. it helps.
COPYRIGHT: COPYRIGHT:
---------- ----------
pacman is Copyright (c) 2002 Judd vinet <jvinet@zeroflux.org> and is pacman is Copyright (c) 2002 Judd Vinet <jvinet@zeroflux.org> and is
licensed through the GNU General Public License (see COPYING). licensed through the GNU General Public License (see COPYING).
pacman uses "libtar", a library for reading/writing tar-files. This pacman uses "libtar", a library for reading/writing tar-files. This

14
makepkg
View file

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
me=`basename $0` me=`basename $0`
myver='1.1' myver='1.2'
startdir=`pwd` startdir=`pwd`
[ -f /etc/makepkg.conf ] && . /etc/makepkg.conf [ -f /etc/makepkg.conf ] && . /etc/makepkg.conf
@ -30,9 +30,9 @@ for netfile in ${source[@]}; do
if [ -f ../$file ]; then if [ -f ../$file ]; then
echo "==> Found $file in build dir" >&2 echo "==> Found $file in build dir" >&2
cp ../$file . cp ../$file .
elif [ -f /var/cache/pkg/$file ]; then elif [ -f /var/cache/pacman/src/$file ]; then
echo "==> Using local copy of $file" >&2 echo "==> Using local copy of $file" >&2
cp /var/cache/pkg/$file . cp /var/cache/pacman/src/$file .
else else
echo "==> Downloading $file" >&2 echo "==> Downloading $file" >&2
wget --passive-ftp --no-directories --tries=3 --waitretry=3 $netfile 2>&1 wget --passive-ftp --no-directories --tries=3 --waitretry=3 $netfile 2>&1
@ -41,7 +41,7 @@ for netfile in ${source[@]}; do
echo "==> Aborting..." >&2 echo "==> Aborting..." >&2
exit 1 exit 1
fi fi
mkdir -p /var/cache/pkg && cp $file /var/cache/pkg mkdir -p /var/cache/pacman/src && cp $file /var/cache/pacman/src
fi fi
case $file in case $file in
*.tar.gz|*.tar.Z|*.tgz) *.tar.gz|*.tar.Z|*.tgz)
@ -76,6 +76,12 @@ echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO
for bakfile in "${backup[@]}"; do for bakfile in "${backup[@]}"; do
echo "backup = $bakfile" >>.PKGINFO echo "backup = $bakfile" >>.PKGINFO
done done
if [ "$install" != "" ]; then
cat $startdir/$install | egrep '^[^$]' | sed 's/^/install = /g' >>.PKGINFO
fi
if [ "$remove" != "" ]; then
cat $startdir/$remove | egrep '^[^$]' | sed 's/^/remove = /g' >>.PKGINFO
fi
# remove info/doc files # remove info/doc files
cd $startdir cd $startdir

110
makepkg.8.in Executable file
View file

@ -0,0 +1,110 @@
.TH makepkg 8 "Mar 17, 2002" "makepkg #VERSION#" ""
.SH NAME
makepkg \- package build utility
.SH SYNOPSIS
\fBmakepkg\fP
.SH DESCRIPTION
\fBmakepkg\fP will build packages for you. All it needs is
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.
\fBmakeworld\fP can be used to rebuild an entire package group, or the
entire build tree.
.SH BUILD PROCESS (or How To Build Your Own Packages)
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.
.TP
.TP
.SH PKGBUILD Example:
.RS
.nf
pkgname=modutils
pkgver=2.4.13
pkgrel=1
backup=(etc/modules.conf)
source=(ftp://ftp.server.com/$pkgname-$pkgver.tar.gz modules.conf)
build() {
cd $startdir/src/$pkgname-$pkgver
./configure --prefix=/usr
make || return 1
make prefix=$startdir/pkg/usr install
# copy our custom modules.conf into the package root
mkdir -p $startdir/pkg/etc
cp ../modules.conf $startdir/pkg/etc
}
.fi
.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 sources are then decompressed (if necessary) into a directory called ./src.
Then 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.
After a package is built, the \fIbuild\fP function must install the package
files into a special package root, which can be referenced by \fB$startdir/pkg\fP
in the \fIbuild\fP function. The typical way to do this is one of the following:
.RS
.nf
make DESTDIR=$startdir/pkg install
or
make prefix=$startdir/pkg/usr install
.fi
.RE
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
.SH PKGBUILD Directives
.TP
.B backup
A space-delimited array of filenames (without a preceiding 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.
.TP
.B source
The \fIsource\fP line is an array of source files required to build the
package. Source files must reside in the same directory as the PKGBUILD
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.
.TP
.B install
There is also an \fIinstall\fP directive that is not used in the example
above. If \fIinstall\fP is set to the name of a file in the package build
directory (but \fBnot\fP listed in the source line), then it will be
copied to the package meta-info file and designated as a post-install script.
This will be run by pacman whenever it installs the package.
.SH CONFIGURATION
Configuration options are stored in /etc/makepkg.conf. 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 AUTHOR
.nf
Judd Vinet <jvinet@zeroflux.org>
.fi

View file

@ -1,11 +1,15 @@
#!/bin/bash #!/bin/bash
toplevel=`pwd` toplevel=`pwd`
version="1.2"
if [ $# -lt 2 ]; then if [ $# -lt 2 ]; then
echo "makepkg version $version"
echo "usage: $0 <destdir> <category> [category] ..." echo "usage: $0 <destdir> <category> [category] ..."
echo " where <category> is base, opt, etc." echo " where <category> is base, opt, etc."
echo " eg: makeworld /packages base opt extra" echo " eg: makeworld /packages base opt extra"
echo
echo " this should be run from the toplevel directory of ABS (usually /usr/abs)"
exit 1 exit 1
fi fi

View file

@ -1,8 +1,8 @@
.TH pacman 8 "Feb 10, 2002" "pacman #VERSION#" "" .TH pacman 8 "Mar 17, 2002" "pacman #VERSION#" ""
.SH NAME .SH NAME
pacman \- package manager utility pacman \- package manager utility
.SH SYNOPSIS .SH SYNOPSIS
\fBpacman <operation> [options] <package>\fP \fBpacman <operation> [options] <package> [package] ...\fP
.SH DESCRIPTION .SH DESCRIPTION
\fBpacman\fP is a \fIpackage management\fP utility. Package \fBpacman\fP is a \fIpackage management\fP utility. Package
information is maintained in a basic text format for easy information is maintained in a basic text format for easy

304
pacman.c
View file

@ -95,15 +95,21 @@ unsigned short pmo_q_info = 0;
unsigned short pmo_q_list = 0; unsigned short pmo_q_list = 0;
char* pmo_q_owns = NULL; char* pmo_q_owns = NULL;
pkginfo_t** packages = NULL; /* list of installed packages */
unsigned int pkgcount = 0; pkginfo_t** pm_packages = NULL;
unsigned int pm_pkgcount = 0;
/* list of targets specified on command line */
fileset_t pm_targets = NULL;
unsigned int pm_targct = 0;
/* path to post-install script, if any */
char* pm_install = NULL;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
pm_opfunc_t op_func; pm_opfunc_t op_func;
char* funcvar = NULL; int i, ret = 0;
int ret = 0;
/* default root */ /* default root */
pmo_root = (char*)malloc(2); pmo_root = (char*)malloc(2);
@ -118,16 +124,16 @@ int main(int argc, char* argv[])
/* the handler function */ /* the handler function */
if(!strcmp(argv[1], "-A") || !strcmp(argv[1], "--add")) { if(!strcmp(argv[1], "-A") || !strcmp(argv[1], "--add")) {
op_func = pacman_add; op_func = pacman_add;
funcvar = parseargs(PM_ADD, argc, argv); ret = parseargs(PM_ADD, argc, argv);
} else if(!strcmp(argv[1], "-R") || !strcmp(argv[1], "--remove")) { } else if(!strcmp(argv[1], "-R") || !strcmp(argv[1], "--remove")) {
op_func = pacman_remove; op_func = pacman_remove;
funcvar = parseargs(PM_REMOVE, argc, argv); ret = parseargs(PM_REMOVE, argc, argv);
} else if(!strcmp(argv[1], "-Q") || !strcmp(argv[1], "--query")) { } else if(!strcmp(argv[1], "-Q") || !strcmp(argv[1], "--query")) {
op_func = pacman_query; op_func = pacman_query;
funcvar = parseargs(PM_QUERY, argc, argv); ret = parseargs(PM_QUERY, argc, argv);
} else if(!strcmp(argv[1], "-U") || !strcmp(argv[1], "--upgrade")) { } else if(!strcmp(argv[1], "-U") || !strcmp(argv[1], "--upgrade")) {
op_func = pacman_upgrade; op_func = pacman_upgrade;
funcvar = parseargs(PM_UPGRADE, argc, argv); ret = parseargs(PM_UPGRADE, argc, argv);
} else if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { } else if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
usage(PM_MAIN, (char*)basename(argv[0])); usage(PM_MAIN, (char*)basename(argv[0]));
return(1); return(1);
@ -135,16 +141,21 @@ int main(int argc, char* argv[])
version(); version();
return(1); return(1);
} else { } else {
printf("error: invalid operation\n\n"); fprintf(stderr, "error: invalid operation\n\n");
usage(PM_MAIN, (char*)basename(argv[0])); usage(PM_MAIN, (char*)basename(argv[0]));
return(1); return(1);
} }
if(funcvar == NULL && op_func != pacman_query) { if(ret || (pm_targct < 1 && op_func != pacman_query)) {
return(1); return(1);
} }
vprint("Installation Root: %s\n", pmo_root); vprint("Installation Root: %s\n", pmo_root);
vprint("Package Name: %s\n", funcvar); if(pm_targct) {
vprint("Targets:\n");
for(i = 0; i < pm_targct; i++) {
vprint(" %s\n", pm_targets[i]);
}
}
/* check for db existence */ /* check for db existence */
if(pmo_root != NULL) { if(pmo_root != NULL) {
@ -161,27 +172,40 @@ int main(int argc, char* argv[])
ret = db_open(dbpath); ret = db_open(dbpath);
if(ret == 1) { if(ret == 1) {
printf("error: Could not open package database file!\n"); fprintf(stderr, "error: Could not open package database file!\n");
printf(" Check to see that %s exists.\n", dbpath); fprintf(stderr, " Check to see that %s exists.\n", dbpath);
printf(" If not, you may simply create it by \"touch\"-ing it.\n"); fprintf(stderr, " If not, you may simply create it by \"touch\"-ing it.\n");
return(1); return(1);
} }
if(ret == 2) { if(ret == 2) {
printf("error: Database is corrupt! You may need to use the backup database.\n"); fprintf(stderr, "error: Database is corrupt! You may need to use the backup database.\n");
printf(" I hope you like tweaking... ;-)\n"); fprintf(stderr, " I hope you like tweaking... ;-)\n");
return(1); return(1);
} }
/* start the requested operation */ /* start the requested operation */
if(!pmo_nofunc) { if(!pmo_nofunc) {
ret = op_func(funcvar); for(i = 0; i < pm_targct; i++) {
if(ret) { if(op_func(pm_targets[i])) {
printf("There were errors\n"); ret = 1;
}
}
if(op_func == pacman_query && pm_targct == 0) {
ret = op_func(NULL);
} }
} }
if(op_func == pacman_remove) {
/* the remove function no longer updates the db itself. we do it here
* instead, in an effort to save some expensive file rewrites. note that we
* can't do this for pacman_add() yet, as he's gotta call db_find_conflicts
* for each package.
*/
ret = db_update(NULL, 0);
}
fclose(dbfp); fclose(dbfp);
return(0); return(ret);
} }
int pacman_add(char* pkgfile) int pacman_add(char* pkgfile)
@ -206,13 +230,13 @@ int pacman_add(char* pkgfile)
vprint("Looking for DB conflicts...\n"); vprint("Looking for DB conflicts...\n");
if((i = db_find_conflicts(files, filecount)) == 1) { if((i = db_find_conflicts(files, filecount)) == 1) {
if(pmo_force) { if(pmo_force) {
printf("\nInstalling package anyway...\n"); fprintf(stderr, "\nInstalling package anyway...\n");
printf(" You might have duplicate entries in your package\n"); fprintf(stderr, " You might have duplicate entries in your package\n");
printf(" database now. You may want to edit it and remove\n"); fprintf(stderr, " database now. You may want to edit it and remove\n");
printf(" one of the copies.\n\n"); fprintf(stderr, " one of the copies.\n\n");
} else { } else {
printf("Aborting...\n"); fprintf(stderr, "Aborting...\n");
printf(" (use -f to override)\n\n"); fprintf(stderr, " (use -f to override)\n\n");
return(1); return(1);
} }
} else if(i == 2) { } else if(i == 2) {
@ -225,7 +249,11 @@ int pacman_add(char* pkgfile)
if(pmo_upgrade) { if(pmo_upgrade) {
vprint("Removing old package first...\n"); vprint("Removing old package first...\n");
if(pacman_remove(pkgname)) { if(pacman_remove(pkgname)) {
printf("\nUpgrade aborted.\n"); fprintf(stderr, "\nUpgrade aborted.\n");
return(1);
}
if(db_update(NULL, 0)) {
fprintf(stderr, "\nError updating database. Upgrade aborted.\n");
return(1); return(1);
} }
} }
@ -257,11 +285,11 @@ int pacman_add(char* pkgfile)
strcpy(newpath, expath); strcpy(newpath, expath);
strcat(newpath, ".save"); strcat(newpath, ".save");
rename(expath, newpath); rename(expath, newpath);
printf("%s renamed to %s\n", expath, newpath); fprintf(stderr, "%s renamed to %s\n", expath, newpath);
} }
if(tar_extract_file(tar, expath)) { if(tar_extract_file(tar, expath)) {
errmsg = strerror(errno); errmsg = strerror(errno);
printf("could not extract %s: %s\n", th_get_pathname(tar), errmsg); fprintf(stderr, "could not extract %s: %s\n", th_get_pathname(tar), errmsg);
errors = 1; errors = 1;
} }
free(expath); free(expath);
@ -269,16 +297,29 @@ int pacman_add(char* pkgfile)
tar_close(tar); tar_close(tar);
vprint("Done.\n"); vprint("Done.\n");
if(errors) { if(errors) {
printf("There were errors. No database update was performed.\n"); fprintf(stderr, "There were errors. No database update was performed.\n");
return(1);
} else { } else {
vprint("Updating database...\n"); vprint("Updating database...\n");
if(db_update(files, filecount)) { if(db_update(files, filecount)) {
printf("error: Could not update database! The database may not\n"); fprintf(stderr, "error: Could not update database! The database may not\n");
printf(" be in a sane state!\n"); fprintf(stderr, " be in a sane state!\n");
return(1); return(1);
} }
vprint("Done.\n"); vprint("Done.\n");
} }
/* run the script in pm_install */
if(pm_install != NULL) {
vprint("Executing post-install script...\n");
expath = (char*)malloc(256);
snprintf(expath, 255, "/bin/bash %s", pm_install);
system(expath);
free(expath);
unlink(pm_install);
free(pm_install);
}
return(0); return(0);
} }
@ -286,7 +327,7 @@ int pacman_remove(char* pkgfile)
{ {
int found = 0, done = 0; int found = 0, done = 0;
int i; int i;
char line[255]; char line[PATH_MAX+1];
fileset_t files = NULL; fileset_t files = NULL;
unsigned int filecount = 0, nb = 0; unsigned int filecount = 0, nb = 0;
struct stat buf; struct stat buf;
@ -304,17 +345,17 @@ int pacman_remove(char* pkgfile)
strcpy(line, trim(line)); strcpy(line, trim(line));
if(!strcmp(line, pkgfile)) { if(!strcmp(line, pkgfile)) {
/* read the version */ /* read the version */
fgets(line, 255, dbfp); fgets(line, 63, dbfp);
found = 1; found = 1;
} }
} }
if(!found) { if(!found) {
printf("Cannot remove %s: Package was not found.\n", pkgfile); fprintf(stderr, "Cannot remove %s: Package was not found.\n", pkgfile);
return(1); return(1);
} }
while(!done) { while(!done) {
fgets(line, 255, dbfp); fgets(line, PATH_MAX, dbfp);
strcpy(line, trim(line)); strcpy(line, trim(line));
if(strlen(line)) { if(strlen(line)) {
/* add the path to the list */ /* add the path to the list */
@ -347,13 +388,13 @@ int pacman_remove(char* pkgfile)
/* perror("cannot remove directory"); */ /* perror("cannot remove directory"); */
} }
} else { } else {
/* if the file ends in .conf, back it up */ /* if the file is flagged, back it up to .save */
if(!pmo_nosave && nb) { if(!pmo_nosave && nb) {
newpath = (char*)realloc(newpath, strlen(file)+6); newpath = (char*)realloc(newpath, strlen(file)+6);
strcpy(newpath, file); strcpy(newpath, file);
strcat(newpath, ".save"); strcat(newpath, ".save");
rename(file, newpath); rename(file, newpath);
printf("%s renamed to %s\n", file, newpath); fprintf(stderr, "%s renamed to %s\n", file, newpath);
} else { } else {
vprint(" unlinking %s\n", file); vprint(" unlinking %s\n", file);
if(unlink(file)) { if(unlink(file)) {
@ -365,31 +406,31 @@ int pacman_remove(char* pkgfile)
/* now splice this name out of the packages list */ /* now splice this name out of the packages list */
found = 0; found = 0;
for(i = 0; i < pkgcount-1; i++) { for(i = 0; i < pm_pkgcount-1; i++) {
if(found) { if(found) {
packages[i] = packages[i+1]; pm_packages[i] = pm_packages[i+1];
} else { } else {
if(!strcmp(packages[i]->name, pkgfile)) { if(!strcmp(pm_packages[i]->name, pkgfile)) {
found = 1; found = 1;
if(i < pkgcount-1) { if(i < pm_pkgcount-1) {
packages[i] = packages[i+1]; pm_packages[i] = pm_packages[i+1];
} }
} }
} }
} }
/* drop the last item */ /* drop the last item */
packages = (pkginfo_t**)realloc(packages, (--pkgcount)*sizeof(pkginfo_t*)); pm_packages = (pkginfo_t**)realloc(pm_packages, (--pm_pkgcount)*sizeof(pkginfo_t*));
/* and commit the db */ /* the db will be commited back up in main() */
return(db_update(NULL, 0)); return(0);
} }
int pacman_query(char* pkgfile) int pacman_query(char* pkgfile)
{ {
char *str = NULL; char *str = NULL;
char name[255]; char name[256];
char ver[255]; char ver[64];
char line[255]; char line[PATH_MAX+1];
int found = 0; int found = 0;
int done = 0; int done = 0;
int i; int i;
@ -422,22 +463,25 @@ int pacman_query(char* pkgfile)
while(!found && !feof(dbfp)) { while(!found && !feof(dbfp)) {
fgets(name, 255, dbfp); fgets(name, 255, dbfp);
strcpy(name, trim(name)); strcpy(name, trim(name));
fgets(ver, 255, dbfp); fgets(ver, 63, dbfp);
strcpy(ver, trim(ver)); strcpy(ver, trim(ver));
strcpy(line, " "); strcpy(line, " ");
while(strlen(line) && !feof(dbfp)) { while(strlen(line) && !feof(dbfp)) {
fgets(line, 255, dbfp); fgets(line, PATH_MAX, dbfp);
strcpy(line, trim(line)); strcpy(line, trim(line));
str = line; str = line;
if(line[0] == '*') {
str++;
}
str += strlen(pmo_root); str += strlen(pmo_root);
if(!strcmp(line, pmo_q_owns)) { if(!strcmp(str, pmo_q_owns)) {
printf("%s %s\n", name, ver); printf("%s %s\n", name, ver);
return(0); return(0);
} }
} }
} }
printf("No package owns this file.\n"); fprintf(stderr, "No package owns this file.\n");
return(0); return(2);
} }
/* find packages in the db */ /* find packages in the db */
@ -449,7 +493,7 @@ int pacman_query(char* pkgfile)
strcpy(name, trim(name)); strcpy(name, trim(name));
if(pkgfile == NULL || (pkgfile != NULL && !strcmp(name, pkgfile))) { if(pkgfile == NULL || (pkgfile != NULL && !strcmp(name, pkgfile))) {
/* read the version */ /* read the version */
fgets(ver, 255, dbfp); fgets(ver, 63, dbfp);
strcpy(ver, trim(ver)); strcpy(ver, trim(ver));
found = 1; found = 1;
if(pkgfile != NULL) { if(pkgfile != NULL) {
@ -459,13 +503,14 @@ int pacman_query(char* pkgfile)
} }
if(feof(dbfp)) { if(feof(dbfp)) {
if(pkgfile != NULL && !found) { if(pkgfile != NULL && !found) {
printf("Package was not found in database.\n"); fprintf(stderr, "Package \"%s\" was not found in database.\n", pkgfile);
return(2);
} }
break; break;
} }
found = 0; found = 0;
while(!found) { while(!found) {
fgets(line, 255, dbfp); fgets(line, PATH_MAX, dbfp);
strcpy(line, trim(line)); strcpy(line, trim(line));
if(strlen(line)) { if(strlen(line)) {
if(pmo_q_list) { if(pmo_q_list) {
@ -495,8 +540,7 @@ int pacman_upgrade(char* pkgfile)
/* this is basically just a remove,add process. pacman_add() will */ /* this is basically just a remove,add process. pacman_add() will */
/* handle it */ /* handle it */
pmo_upgrade = 1; pmo_upgrade = 1;
pacman_add(pkgfile); return pacman_add(pkgfile);
return(0);
} }
/* /*
@ -559,10 +603,10 @@ int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output)
} }
tar_close(tar); tar_close(tar);
free(descfile);
if(pkgname == NULL || pkgver == NULL) { if(pkgname == NULL || pkgver == NULL) {
printf("The current version of Pacman requires a .PKGINFO file\n"); fprintf(stderr, "Error: Missing .PKGINFO file in %s\n", pkgfile);
printf("present in the .tar.gz archive. This package does not\n");
printf("have one.\n");
return(0); return(0);
} }
@ -575,26 +619,38 @@ int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output)
*/ */
int db_open(char* path) int db_open(char* path)
{ {
char line[255]; char line[PATH_MAX+1];
int i;
pkginfo_t* info; pkginfo_t* info;
/* if pm_packages already contains data, free it first */
if(pm_pkgcount) {
for(i = 0; i < pm_pkgcount; i++) {
free(pm_packages[i]);
}
free(pm_packages);
pm_packages = NULL;
pm_pkgcount = 0;
}
dbfp = fopen(path, "r"); dbfp = fopen(path, "r");
if(dbfp == NULL) { if(dbfp == NULL) {
return(1); return(1);
} }
while(!feof(dbfp)) { while(!feof(dbfp)) {
info = (pkginfo_t*)malloc(sizeof(pkginfo_t)); info = (pkginfo_t*)malloc(sizeof(pkginfo_t));
fgets(line, 64, dbfp); fgets(line, sizeof(info->name)-1, dbfp);
if(feof(dbfp)) { if(feof(dbfp)) {
break; break;
} }
strcpy(info->name, trim(line)); strcpy(info->name, trim(line));
fgets(line, 32, dbfp); fgets(line, sizeof(info->version)-1, dbfp);
strcpy(info->version, trim(line)); strcpy(info->version, trim(line));
/* add to the collective */ /* add to the collective */
packages = (pkginfo_t**)realloc(packages, (++pkgcount) * sizeof(pkginfo_t*)); pm_packages = (pkginfo_t**)realloc(pm_packages, (++pm_pkgcount) * sizeof(pkginfo_t*));
packages[pkgcount-1] = info; pm_packages[pm_pkgcount-1] = info;
for(;;) { for(;;) {
fgets(line, 255, dbfp); fgets(line, PATH_MAX, dbfp);
if(feof(dbfp)) { if(feof(dbfp)) {
return(2); return(2);
} }
@ -617,12 +673,12 @@ int db_open(char* path)
*/ */
int db_update(fileset_t files, unsigned int filecount) int db_update(fileset_t files, unsigned int filecount)
{ {
FILE* olddb; FILE* olddb = NULL;
char* newpath = NULL; char* newpath = NULL;
char* str = NULL; char* str = NULL;
char name[64]; char name[256];
char ver[32]; char ver[64];
char line[255]; char line[PATH_MAX+1];
int i = 0, found = 0, done = 0; int i = 0, found = 0, done = 0;
/* build the backup pathname */ /* build the backup pathname */
@ -643,21 +699,21 @@ int db_update(fileset_t files, unsigned int filecount)
rewind(olddb); rewind(olddb);
while(!feof(olddb)) { while(!feof(olddb)) {
if(!fgets(name, 64, olddb)) { if(!fgets(name, 255, olddb)) {
break; break;
} }
strcpy(name, trim(name)); strcpy(name, trim(name));
fgets(ver, 32, olddb); fgets(ver, 63, olddb);
found = 0; found = 0;
for(i = 0; i < pkgcount && !found; i++) { for(i = 0; i < pm_pkgcount && !found; i++) {
if(!strcmp(packages[i]->name, name)) { if(!strcmp(pm_packages[i]->name, name)) {
/* it's there... copy the entries over */ /* it's there... copy the entries over */
found = 1; found = 1;
fputs(name, dbfp); fputs(name, dbfp);
fputc('\n', dbfp); fputc('\n', dbfp);
fputs(ver, dbfp); fputs(ver, dbfp);
for(done = 0; !done;) { for(done = 0; !done;) {
fgets(line, 255, olddb); fgets(line, PATH_MAX, olddb);
if(found) { if(found) {
fputs(line, dbfp); fputs(line, dbfp);
} }
@ -670,7 +726,7 @@ int db_update(fileset_t files, unsigned int filecount)
if(!found) { if(!found) {
/* skip through filelist for this package */ /* skip through filelist for this package */
for(done = 0; !done;) { for(done = 0; !done;) {
fgets(line, 255, olddb); fgets(line, PATH_MAX, olddb);
if(strlen(trim(line)) == 0 || feof(olddb)) { if(strlen(trim(line)) == 0 || feof(olddb)) {
done = 1; done = 1;
} }
@ -713,8 +769,8 @@ int db_update(fileset_t files, unsigned int filecount)
int db_find_conflicts(fileset_t files, unsigned int filecount) int db_find_conflicts(fileset_t files, unsigned int filecount)
{ {
int i; int i;
char line[255]; char line[PATH_MAX+1];
char name[255]; char name[256];
char* dbstr = NULL; char* dbstr = NULL;
char* filestr = NULL; char* filestr = NULL;
struct stat buf; struct stat buf;
@ -726,13 +782,13 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
fgets(name, 255, dbfp); fgets(name, 255, dbfp);
strcpy(name, trim(name)); strcpy(name, trim(name));
if(!pmo_upgrade && !strcmp(name, pkgname)) { if(!pmo_upgrade && !strcmp(name, pkgname)) {
printf("error: This package is already installed.\n"); fprintf(stderr, "error: This package is already installed.\n");
printf(" Maybe you should be using --upgrade.\n"); fprintf(stderr, " Maybe you should be using --upgrade.\n");
return(2); return(2);
} }
fgets(line, 255, dbfp); fgets(line, 64, dbfp);
while(!feof(dbfp)) { while(!feof(dbfp)) {
fgets(line, 255, dbfp); fgets(line, PATH_MAX, dbfp);
strcpy(line, trim(line)); strcpy(line, trim(line));
dbstr = line; dbstr = line;
if(dbstr[0] == '*') { if(dbstr[0] == '*') {
@ -742,6 +798,7 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
break; break;
} }
if(index(dbstr, '/') == dbstr && (!pmo_upgrade || strcmp(name,pkgname))) { if(index(dbstr, '/') == dbstr && (!pmo_upgrade || strcmp(name,pkgname))) {
/* we're looking at a file in the db that belongs to a different package */
for(i = 0; i < filecount; i++) { for(i = 0; i < filecount; i++) {
filestr = files[i]; filestr = files[i];
if(filestr[0] == '*') { if(filestr[0] == '*') {
@ -752,7 +809,7 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
/* this filename has a trailing '/', so it's a directory -- skip it. */ /* this filename has a trailing '/', so it's a directory -- skip it. */
continue; continue;
} }
printf("conflict: %s already exists in package \"%s\"\n", dbstr, name); fprintf(stderr, "conflict: %s already exists in package \"%s\"\n", dbstr, name);
conflicts = 1; conflicts = 1;
} }
} }
@ -768,7 +825,7 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
filestr++; filestr++;
} }
if(!stat(filestr, &buf) && !S_ISDIR(buf.st_mode)) { if(!stat(filestr, &buf) && !S_ISDIR(buf.st_mode)) {
printf("conflict: %s already exists in filesystem\n", filestr); fprintf(stderr, "conflict: %s already exists in filesystem\n", filestr);
conflicts = 1; conflicts = 1;
} }
} }
@ -785,8 +842,9 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr, int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr,
unsigned int* bakct) unsigned int* bakct)
{ {
FILE* fp; FILE* fp = NULL;
char line[255]; FILE* inst = NULL;
char line[PATH_MAX+1];
char* ptr = NULL; char* ptr = NULL;
char* key = NULL; char* key = NULL;
int linenum = 0; int linenum = 0;
@ -799,7 +857,7 @@ int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr,
} }
while(!feof(fp)) { while(!feof(fp)) {
fgets(line, 255, fp); fgets(line, PATH_MAX, fp);
if(output) { if(output) {
printf("%s", line); printf("%s", line);
} }
@ -814,7 +872,7 @@ int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr,
ptr = line; ptr = line;
key = strsep(&ptr, "="); key = strsep(&ptr, "=");
if(key == NULL || ptr == NULL) { if(key == NULL || ptr == NULL) {
printf("Syntax error in description file line %d\n", linenum); fprintf(stderr, "Syntax error in description file line %d\n", linenum);
} else { } else {
key = trim(key); key = trim(key);
key = strtoupper(key); key = strtoupper(key);
@ -827,12 +885,25 @@ int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr,
strcpy(pkgver, ptr); strcpy(pkgver, ptr);
} else if(!strcmp(key, "PKGDESC")) { } else if(!strcmp(key, "PKGDESC")) {
/* Not used yet */ /* Not used yet */
} else if(!strcmp(key, "INSTALL")) {
if(inst == NULL) {
pm_install = (char*)malloc(strlen("/tmp/pacman_XXXXXX")+1);
strcpy(pm_install, "/tmp/pacman_XXXXXX");
mkstemp(pm_install);
inst = fopen(pm_install, "w");
if(inst == NULL) {
perror("fopen");
return(1);
}
}
fputs(ptr, inst);
fputc('\n', inst);
} else if(!strcmp(key, "BACKUP")) { } else if(!strcmp(key, "BACKUP")) {
backup = (fileset_t)realloc(backup, (++count) * sizeof(char*)); backup = (fileset_t)realloc(backup, (++count) * sizeof(char*));
backup[count-1] = (char*)malloc(strlen(ptr)+1); backup[count-1] = (char*)malloc(strlen(ptr)+1);
strcpy(backup[count-1], ptr); strcpy(backup[count-1], ptr);
} else { } else {
printf("Syntax error in description file line %d\n", linenum); fprintf(stderr, "Syntax error in description file line %d\n", linenum);
} }
} }
line[0] = '\0'; line[0] = '\0';
@ -840,6 +911,11 @@ int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr,
fclose(fp); fclose(fp);
unlink(descfile); unlink(descfile);
if(inst != NULL) {
fputs("exit 0\n", inst);
fclose(inst);
}
if(count > 0) { if(count > 0) {
(*bakptr) = backup; (*bakptr) = backup;
(*bakct) = count; (*bakct) = count;
@ -853,19 +929,21 @@ int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr,
* argc: argc * argc: argc
* argv: argv * argv: argv
* *
* Returns: the functional variable for that operation * Returns: 0 on success, 1 on error
* (eg, the package file name for PM_ADD)
*/ */
char* parseargs(int op, int argc, char** argv) int parseargs(int op, int argc, char** argv)
{ {
char* pkg = NULL;
int i; int i;
for(i = 2; i < argc; i++) { for(i = 2; i < argc; i++) {
if(strlen(argv[i]) > PATH_MAX) {
fprintf(stderr, "error: argument %d is too long.\n", i);
return(1);
}
if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
pmo_nofunc = 1; pmo_nofunc = 1;
usage(op, (char*)basename(argv[0])); usage(op, (char*)basename(argv[0]));
return(NULL); return(1);
} else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) { } else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) {
pmo_verbose = 1; pmo_verbose = 1;
} else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force")) { } else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force")) {
@ -873,14 +951,14 @@ char* parseargs(int op, int argc, char** argv)
} else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--root")) { } else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--root")) {
i++; i++;
if(i >= argc) { if(i >= argc) {
printf("error: missing argument for %s\n", argv[i-1]); fprintf(stderr, "error: missing argument for %s\n", argv[i-1]);
return(NULL); return(1);
} }
free(pmo_root); free(pmo_root);
pmo_root = (char*)malloc(PATH_MAX); pmo_root = (char*)malloc(PATH_MAX);
if(realpath(argv[i], pmo_root) == NULL) { if(realpath(argv[i], pmo_root) == NULL) {
perror("bad root path"); perror("bad root path");
return(NULL); return(1);
} }
} else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--nosave")) { } else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--nosave")) {
pmo_nosave = 1; pmo_nosave = 1;
@ -888,15 +966,19 @@ char* parseargs(int op, int argc, char** argv)
/* PM_QUERY only */ /* PM_QUERY only */
i++; i++;
if(i >= argc) { if(i >= argc) {
printf("error: missing argument for %s\n", argv[i-1]); fprintf(stderr, "error: missing argument for %s\n", argv[i-1]);
return(NULL); return(1);
}
if(strlen(argv[i]) > PATH_MAX) {
fprintf(stderr, "error: argument %d is too long.\n", i);
return(1);
} }
free(pmo_q_owns); free(pmo_q_owns);
pmo_q_owns = (char*)malloc(PATH_MAX); pmo_q_owns = (char*)malloc(PATH_MAX);
if(realpath(argv[i], pmo_q_owns) == NULL) { if(realpath(argv[i], pmo_q_owns) == NULL) {
perror("bad path specified for --owns"); perror("bad path specified for --owns");
pmo_nofunc = 1; pmo_nofunc = 1;
return(NULL); return(1);
} }
} else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) { } else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) {
/* PM_QUERY only */ /* PM_QUERY only */
@ -908,20 +990,22 @@ char* parseargs(int op, int argc, char** argv)
/* PM_QUERY only */ /* PM_QUERY only */
pmo_q_info = 1; pmo_q_info = 1;
} else { } else {
pkg = argv[i]; /* add the target to our pseudo linked list */
pm_targets = (fileset_t)realloc(pm_targets, (++pm_targct) * sizeof(char*));
pm_targets[pm_targct-1] = argv[i];
} }
} }
if(op != PM_QUERY && pkg == NULL) { if(op != PM_QUERY && pm_targct < 1) {
printf("error: no package specified\n\n"); fprintf(stderr, "error: no package specified\n\n");
usage(op, (char*)basename(argv[0])); usage(op, (char*)basename(argv[0]));
return(NULL); return(1);
} }
if(op == PM_QUERY && pmo_q_isfile && pkg == NULL) { if(op == PM_QUERY && pmo_q_isfile && pm_targct < 1) {
printf("error: no package file specified\n\n"); fprintf(stderr, "error: no package file specified\n\n");
return(NULL); return(1);
} }
return(pkg); return(0);
} }
/* Display usage/syntax for the specified operation. /* Display usage/syntax for the specified operation.

View file

@ -21,7 +21,7 @@
#ifndef PACMAN_H #ifndef PACMAN_H
#define PACMAN_H #define PACMAN_H
#define VERSION "1.1" #define VERSION "1.2"
#define PKGEXT ".tar.gz" #define PKGEXT ".tar.gz"
#define PKGDB "/var/lib/pacman/pacman.db" #define PKGDB "/var/lib/pacman/pacman.db"
@ -36,8 +36,8 @@
typedef int (*pm_opfunc_t)(char*); typedef int (*pm_opfunc_t)(char*);
typedef char** fileset_t; typedef char** fileset_t;
typedef struct __pkginfo_t { typedef struct __pkginfo_t {
char version[32]; char version[64];
char name[64]; char name[256];
} pkginfo_t; } pkginfo_t;
int pacman_add(char* pkgfile); int pacman_add(char* pkgfile);
@ -50,7 +50,7 @@ int db_update(fileset_t files, unsigned int filecount);
int db_find_conflicts(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 load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output);
char* parseargs(int op, int argc, char** argv); int parseargs(int op, int argc, char** argv);
int parse_descfile(char* descfile, unsigned short output, fileset_t* bakptr, int parse_descfile(char* descfile, unsigned short output, fileset_t* bakptr,
unsigned int* bakct); unsigned int* bakct);

281
pacsync Executable file
View file

@ -0,0 +1,281 @@
#!/bin/bash
version="1.2"
tanpath="/var/lib/pacman"
tandb="pacsync.db"
errors=0
upgrade=0
message() {
echo "==> $1" >&2
}
usage() {
echo "pacsync version $version"
echo "usage: $0 <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 ""
}
checkdb() {
if [ ! -f $tanpath/$tandb ]; then
message "missing package list. (use \"sync\" first)"
exit 1
fi
}
download() {
targ=$1
shift
cl=
for file in $*; do
cl="$cl $SYNC_SERVER/$file"
done
message "Downloading $targ"
$ftpagent $cl
if [ $? -gt 0 ]; then
message "ERROR: could not download $targ"
return 1
fi
return 0
}
dosync() {
cd /tmp
download "package list" $tandb
if [ $? -gt 0 ]; then
exit 1
fi
rm -f $tanpath/$tandb
mv /tmp/$tandb $tanpath/$tandb
message "Done."
}
doinstall() {
pkg2dl=
pkg2inst=
for pkgname in $*; do
line=`egrep "^[a-z]+/$pkgname-[a-z0-9\.]+-[0-9]+\.pkg\.tar\.gz$" $tanpath/$tandb`
if [ $? -gt 0 ]; then
message "package $pkgname not found"
exit 1
fi
pacman=`pacman -Q $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 /var/cache/pacman/pkg/$filename ]; then
pkg2dl="$pkg2dl arch/$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` != "/var/cache/pacman/pkg" ]; then
# move downloaded files into cache
mkdir -p /var/cache/pacman/pkg
mv `echo $pkg2dl | sed 's|arch/||g'` /var/cache/pacman/pkg/
fi
fi
# install packages
message "Installing packages"
cd /var/cache/pacman/pkg
pacman -A $pkg2inst
if [ $? -gt 0 ]; then
echo "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-z0-9\.]+-[0-9]+\.pkg\.tar\.gz$" $tanpath/$tandb`
if [ $? -gt 0 ]; then
message "package $pkgname not found"
exit 1
fi
pacman=`pacman -Q $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 /var/cache/pacman/pkg/$filename ]; then
pkg2dl="$pkg2dl arch/$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` != "/var/cache/pacman/pkg" ]; then
# move downloaded files into cache
mkdir -p /var/cache/pacman/pkg
mv `echo $pkg2dl | sed 's|arch/||g'` /var/cache/pacman/pkg/
fi
fi
# install packages
if [ "$pkg2up" != "" ]; then
message "Upgrading packages"
cd /var/cache/pacman/pkg
pacman -U $pkg2up
if [ $? -gt 0 ]; then
echo "ERROR: some packages failed to upgrade"
exit 1
fi
message "Done"
fi
exit 0
}
doreport() {
headers=0
pkg2up=
for pkgfile in `cat $tanpath/$tandb | sed "s|^[a-z]*/||g"`; do
pkgname=`echo $pkgfile | sed 's|-[a-z0-9\.]*-[0-9]*\.pkg\.tar\.gz||g'`
pacman=`pacman -Q $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-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 [ "$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
# 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
}
if [ $# -lt 1 ]; then
usage
exit 0
fi
if [ -f /etc/pacsync.conf ]; then
. /etc/pacsync.conf
else
message "error: missing configuration file!"
exit 1
fi
proto=`echo $SYNC_SERVER | sed 's|://.*||'`
# check for a download utility
if [ -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 (lftp or 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 /var/cache/pacman/pkg/*
;;
*)
message "error: invalid operation"
exit 1
;;
esac

53
pacsync.8.in Normal file
View file

@ -0,0 +1,53 @@
.TH pacsync 8 "Mar 17, 2002" "pacsync #VERSION#" ""
.SH NAME
pacsync \- package update frontend for pacman
.SH SYNOPSIS
\fBpacsync <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

8
pacsync.conf Normal file
View file

@ -0,0 +1,8 @@
#
# /etc/pacsync.conf
#
# the full URL of the server (up to the /arch package directory)
SYNC_SERVER="ftp://ftp.archlinux.org"
#SYNC_SERVER="http://www.archlinux.org/pub"