Imported from pacman-1.1.tar.gz

This commit is contained in:
Judd Vinet 2002-03-10 22:34:15 +00:00
parent d53b2011b1
commit 8cf35f551f
8 changed files with 232 additions and 122 deletions

View file

@ -27,7 +27,7 @@ BINDIR = /usr/bin
MANDIR = /usr/man
ETCDIR = /etc
VERSION = 1.0
VERSION = 1.1
LIBTAR_VERSION = 1.2.4
CXX = gcc

19
TODO
View file

@ -1,24 +1,19 @@
These are things that should get done at some point. Some are simple,
others are more complex and could be a while in development.
Some of these items kinda belong on more of a wishlist than a todo list. ;)
> make sure program consistently returns a non-zero return code on
error, so scripts can rely on it
- add a [sibling] option to .PKGINFO -- used when only one of
the siblings can be installed at a time (eg, bsdinit,sysvinit)
- handle wildcards on the command line
> handle wildcards on the command line
- sort packages by package name in pacman.db
- manage conditional file installs (ie, 'info' pages)
- make sure program consistently returns a non-zero return code on
error, so scripts can rely on it
? manage conditional file installs (ie, 'info' pages)
- maybe add a 'confirm every action' option for doing paranoid installs
- add better directory tracking
- use crux's pkgmk technique. $(make prefix=$PKG/usr install) then just
$(cd $PKG; tar czf $pkg.tar.gz *)
- add a consistency check operation
- change char[xxx] to char[PATH_MAX]
- add file locking to db
- add a --dbpath option
- dependency checking
- fetch files via ftp
+ dependency checking
+ fetch files via ftp
- need to manage foreign package lists like apt
- handle .save files better (for more than just .conf files)
- upgrade currently does a double db backup; not really desirable

View file

@ -1,25 +0,0 @@
#!/bin/bash
if [ "$1" = "" ]; then
echo "usage: $0 <pkg_directory>"
echo ""
echo "call this while in the root of the install tree and"
echo "pass it the path of the directory containing packages"
echo "to be installed"
echo ""
exit
fi
echo "Initializing pacman database..."
mkdir -p var/lib/pacman && touch var/lib/pacman/pacman.db
for pkg in `find $1/*`; do
echo "==> $pkg" >>install.log
echo "==> $pkg"
pacman -A -r . $pkg 2>&1 >>install.log
done
echo "Syncing..."
sync
echo "Done."

56
makepkg
View file

@ -1,7 +1,7 @@
#!/bin/bash
me=`basename $0`
myver='1.0'
myver='1.1'
startdir=`pwd`
[ -f /etc/makepkg.conf ] && . /etc/makepkg.conf
@ -11,30 +11,34 @@ strip_url() {
}
if [ ! -f $startdir/PKGBUILD ]; then
echo "error: $startdir/PKGBUILD does not exist!"
exit
echo "error: $startdir/PKGBUILD does not exist!" >&2
exit 1
fi
. $startdir/PKGBUILD
echo
d=`date`
echo "==> Building package $pkgname ($d)" >&2
# extract source
echo "==> Acquiring/Extracting Sources..."
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"
echo "==> Found $file in build dir" >&2
cp ../$file .
elif [ -f /var/cache/pkg/$file ]; then
echo "==> Using local copy of $file"
echo "==> Using local copy of $file" >&2
cp /var/cache/pkg/$file .
else
echo "==> Downloading $file"
wget --passive-ftp --no-directories --tries=3 --waitretry=3 $netfile
echo "==> Downloading $file" >&2
wget --passive-ftp --no-directories --tries=3 --waitretry=3 $netfile 2>&1
if [ ! -f $file ]; then
echo "==> ERROR: Failed to download $file"
echo "==> Aborting..."
echo "==> ERROR: Failed to download $file" >&2
echo "==> Aborting..." >&2
exit 1
fi
mkdir -p /var/cache/pkg && cp $file /var/cache/pkg
@ -49,40 +53,50 @@ for netfile in ${source[@]}; do
*)
cmd="cp ../$file ." ;;
esac
echo "$cmd"
echo "==> $cmd" >&2
$cmd
done
# build
echo "==> Building Package..."
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..."
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 files
# 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..."
echo "==> Stripping debugging symbols from libraries..." >&2
find pkg/{,usr,usr/local}/lib -type f \
-exec /usr/bin/strip --strip-debug '{}' ';'
echo "==> Stripping symbols from binaries..."
-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 '{}' ';'
-exec /usr/bin/strip '{}' ';' 2>&1
# tar it up
echo "==> Compressing package..."
echo "==> Compressing package..." >&2
cd $startdir/pkg
tar czvf $startdir/$pkgname-$pkgver-$pkgrel.pkg.tar.gz .PKGINFO * >../filelist
cd $startdir
echo "==> Finished";
d=`date`
echo "==> Finished ($d)" >&2
exit 0

View file

@ -2,28 +2,48 @@
toplevel=`pwd`
if [ $# -lt 1 ]; then
echo "usage: $0 <destdir>"
if [ $# -lt 2 ]; then
echo "usage: $0 <destdir> <category> [category] ..."
echo " where <category> is base, opt, etc."
echo " eg: makeworld /packages base opt extra"
exit 1
fi
for port in `find $toplevel -type d -maxdepth 1 -mindepth 1 | sort`; do
cd $port
if [ -f PKGBUILD ]; then
. PKGBUILD
donebuild=0
if [ ! -f $1/$pkgname-$pkgver-$pkgrel.pkg.tar.gz ]; then
makepkg
rm -rf pkg src
mv -v $pkgname-$pkgver-$pkgrel.pkg.tar.gz $1/
donebuild=1
dest=$1
shift
sd=`date +"[%b %d %H:%M]"`
for category in $*; do
for port in `find $toplevel/$category -type d -maxdepth 1 -mindepth 1 | sort`; do
cd $port
if [ -f PKGBUILD ]; then
. PKGBUILD
buildstatus=0
if [ ! -f $dest/$pkgname-$pkgver-$pkgrel.pkg.tar.gz ]; then
makepkg
if [ $? -gt 0 ]; then
buildstatus=2
else
rm -rf pkg src
# some packages (mozilla) have been split into multiple packages
mv -v $pkgname-*.pkg.tar.gz $dest/
buildstatus=1
fi
fi
d=`date +"[%b %d %H:%M]"`
echo -n "$d " >>$toplevel/build.log
case $buildstatus in
0) echo "$pkgname already built -- skipping" >>$toplevel/build.log ;;
1) echo "$pkgname was built successfully" >>$toplevel/build.log ;;
2) echo "$pkgname build failed" >>$toplevel/build.log ;;
esac
fi
d=`date +"[%b %d %H:%M]"`
echo -n "$d " >>$toplevel/build.log
if [ $donebuild = 1 ]; then
echo "$pkgname was built successfully" >>$toplevel/build.log
else
echo "$pkgname already built -- skipping" >>$toplevel/build.log
fi
fi
done
done
ed=`date +"[%b %d %H:%M]"`
echo "makeworld complete." >>$toplevel/build.log
echo " started: $sd" >>$toplevel/build.log
echo " finished: $ed" >>$toplevel/build.log

View file

@ -47,6 +47,11 @@ files owned by the package.
.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"
@ -58,6 +63,13 @@ 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 removed from the system, the database is first
checked to see if the file should be renamed to a .save extension
(indicated by a '\fB*\fP' prefix in the pacman database). The \fB--nosave\fP
will turn off all file backups.
.TP
.B "\-r, \-\-root <path>"
Specify alternative installation root (default is "/"). This
should \fInot\fP be used as a way to install software into

170
pacman.c
View file

@ -1,4 +1,4 @@
/**
/*
* pacman
*
* Copyright (c) 2002 by Judd Vinet <jvinet@zeroflux.org>
@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "pacman.h"
#include <stdio.h>
#include <stdarg.h>
@ -191,11 +192,12 @@ int pacman_add(char* pkgfile)
char* expath = NULL;
char* newpath = NULL;
fileset_t files = NULL;
unsigned int filecount = 0;
unsigned int filecount = 0, nb = 0;
struct stat buf;
/* Populate the file list */
filecount = load_pkg(pkgfile, &files, 0);
if(filecount == 0) {
return(1);
}
@ -244,16 +246,18 @@ int pacman_add(char* pkgfile)
strcpy(expath, pmo_root);
strcat(expath, "/");
strcat(expath, th_get_pathname(tar));
/* see if this file should be backed up */
nb = needbackup(expath, files, filecount);
vprint(" %s\n", expath);
if(!stat(expath, &buf)) {
/* if the file ends in .conf, back it up */
if(!strcmp((char*)(expath+strlen(expath)-5), ".conf")) {
newpath = (char*)realloc(newpath, strlen(expath)+6);
strcpy(newpath, expath);
strcat(newpath, ".save");
rename(expath, newpath);
printf("%s renamed to %s\n", expath, newpath);
}
if(!pmo_nosave && nb && !stat(expath, &buf)) {
/* backup this file */
newpath = (char*)realloc(newpath, strlen(expath)+6);
strcpy(newpath, expath);
strcat(newpath, ".save");
rename(expath, newpath);
printf("%s renamed to %s\n", expath, newpath);
}
if(tar_extract_file(tar, expath)) {
errmsg = strerror(errno);
@ -284,9 +288,10 @@ int pacman_remove(char* pkgfile)
int i;
char line[255];
fileset_t files = NULL;
unsigned int filecount = 0;
unsigned int filecount = 0, nb = 0;
struct stat buf;
char* newpath = NULL;
char* file = NULL;
if(pkgfile == NULL) {
return(0);
@ -322,27 +327,36 @@ int pacman_remove(char* pkgfile)
}
/* iterate through the list backwards, unlinking files */
for(i = filecount-1; i >= 0; i--) {
if(lstat(files[i], &buf)) {
vprint("file %s does not exist\n", files[i]);
file = (char*)realloc(file, strlen(files[i])+strlen(pmo_root)+1);
strcpy(file, pmo_root);
if(files[i][0] == '*') {
nb = 1;
strcat(file, (char*)(files[i]+1));
} else {
nb = 0;
strcat(file, files[i]);
}
if(lstat(file, &buf)) {
vprint("file %s does not exist\n", file);
continue;
}
if(S_ISDIR(buf.st_mode)) {
vprint(" removing directory %s\n", files[i]);
if(rmdir(files[i])) {
vprint(" removing directory %s\n", file);
if(rmdir(file)) {
/* this is okay, other packages are probably using it. */
/* perror("cannot remove directory"); */
}
} else {
/* if the file ends in .conf, back it up */
if(!pmo_nosave && !strcmp((char*)(files[i]+strlen(files[i])-5), ".conf")) {
newpath = (char*)realloc(newpath, strlen(files[i])+6);
strcpy(newpath, files[i]);
if(!pmo_nosave && nb) {
newpath = (char*)realloc(newpath, strlen(file)+6);
strcpy(newpath, file);
strcat(newpath, ".save");
rename(files[i], newpath);
printf("%s renamed to %s\n", files[i], newpath);
rename(file, newpath);
printf("%s renamed to %s\n", file, newpath);
} else {
vprint(" unlinking %s\n", files[i]);
if(unlink(files[i])) {
vprint(" unlinking %s\n", file);
if(unlink(file)) {
perror("cannot remove file");
}
}
@ -388,7 +402,11 @@ int pacman_query(char* pkgfile)
if(pmo_q_list) {
for(i = 0; i < filecount; i++) {
if(strcmp(files[i], ".PKGINFO")) {
printf("%s\n", files[i]);
if(files[i][0] == '*') {
printf("%s\n", (char*)(files[i]+1));
} else {
printf("%s\n", files[i]);
}
}
}
} else {
@ -451,7 +469,11 @@ int pacman_query(char* pkgfile)
strcpy(line, trim(line));
if(strlen(line)) {
if(pmo_q_list) {
printf("%s%s\n", pmo_root, line);
if(line[0] == '*') {
printf("%s%s\n", pmo_root, (char*)(line+1));
} else {
printf("%s%s\n", pmo_root, line);
}
}
} else {
found = 1;
@ -493,6 +515,8 @@ int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output)
TAR* tar;
unsigned int filecount = 0;
fileset_t files = NULL;
fileset_t backup = NULL;
unsigned int bakct = 0;
descfile = (char*)malloc(strlen("/tmp/pacman_XXXXXX")+1);
strcpy(descfile, "/tmp/pacman_XXXXXX");
@ -508,12 +532,19 @@ int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output)
vprint("Found package description file.\n");
mkstemp(descfile);
tar_extract_file(tar, descfile);
parse_descfile(descfile, output);
parse_descfile(descfile, output, &backup, &bakct);
continue;
}
/* build the new pathname relative to pmo_root */
expath = (char*)malloc(strlen(th_get_pathname(tar))+strlen(pmo_root)+2);
strcpy(expath, pmo_root);
if(is_in(th_get_pathname(tar), backup, bakct)) {
expath = (char*)malloc(strlen(th_get_pathname(tar))+strlen(pmo_root)+3);
// prepend the backup symbol
strcpy(expath, "*");
} else {
expath = (char*)malloc(strlen(th_get_pathname(tar))+strlen(pmo_root)+2);
expath[0] = '\0';
}
strcat(expath, pmo_root);
strcat(expath, "/");
strcat(expath, th_get_pathname(tar));
/* add the path to the list */
@ -522,7 +553,7 @@ int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output)
if(TH_ISREG(tar) && tar_skip_regfile(tar)) {
perror("bad package file");
return(0);
return(1);
}
expath = NULL;
}
@ -657,6 +688,10 @@ int db_update(fileset_t files, unsigned int filecount)
for(i = 0; i < filecount; i++) {
str = files[i];
str += strlen(pmo_root);
if(files[i][0] == '*') {
fputc('*', dbfp);
str++;
}
fputs(str, dbfp);
fputc('\n', dbfp);
}
@ -680,6 +715,8 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
int i;
char line[255];
char name[255];
char* dbstr = NULL;
char* filestr = NULL;
struct stat buf;
int conflicts = 0;
@ -697,17 +734,25 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
while(!feof(dbfp)) {
fgets(line, 255, dbfp);
strcpy(line, trim(line));
if(!strlen(line)) {
dbstr = line;
if(dbstr[0] == '*') {
dbstr++;
}
if(!strlen(dbstr)) {
break;
}
if(index(line, '/') == (char*)line && (!pmo_upgrade || strcmp(name,pkgname))) {
if(index(dbstr, '/') == dbstr && (!pmo_upgrade || strcmp(name,pkgname))) {
for(i = 0; i < filecount; i++) {
if(!strcmp(line, files[i])) {
if(rindex(files[i], '/') == files[i]+strlen(files[i])-1) {
filestr = files[i];
if(filestr[0] == '*') {
filestr++;
}
if(!strcmp(dbstr, filestr)) {
if(rindex(files[i], '/') == filestr+strlen(filestr)-1) {
/* this filename has a trailing '/', so it's a directory -- skip it. */
continue;
}
printf("conflict: %s already exists in package \"%s\"\n", line, name);
printf("conflict: %s already exists in package \"%s\"\n", dbstr, name);
conflicts = 1;
}
}
@ -718,8 +763,12 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
/* CHECK 2: checking filesystem conflicts */
/* TODO: run filesystem checks for upgrades */
for(i = 0; i < filecount && !pmo_upgrade; i++) {
if(!stat(files[i], &buf) && !S_ISDIR(buf.st_mode)) {
printf("conflict: %s already exists in filesystem\n", files[i]);
filestr = files[i];
if(filestr[0] == '*') {
filestr++;
}
if(!stat(filestr, &buf) && !S_ISDIR(buf.st_mode)) {
printf("conflict: %s already exists in filesystem\n", filestr);
conflicts = 1;
}
}
@ -733,13 +782,16 @@ int db_find_conflicts(fileset_t files, unsigned int filecount)
* Returns: 0 on success, 1 on error
*
*/
int parse_descfile(char* descfile, unsigned short output)
int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr,
unsigned int* bakct)
{
FILE* fp;
char line[255];
char* ptr = NULL;
char* key = NULL;
int linenum = 0;
fileset_t backup = NULL;
unsigned int count = 0;
if((fp = fopen(descfile, "r")) == NULL) {
perror(descfile);
@ -775,6 +827,10 @@ int parse_descfile(char* descfile, unsigned short output)
strcpy(pkgver, ptr);
} else if(!strcmp(key, "PKGDESC")) {
/* Not used yet */
} else if(!strcmp(key, "BACKUP")) {
backup = (fileset_t)realloc(backup, (++count) * sizeof(char*));
backup[count-1] = (char*)malloc(strlen(ptr)+1);
strcpy(backup[count-1], ptr);
} else {
printf("Syntax error in description file line %d\n", linenum);
}
@ -783,6 +839,12 @@ int parse_descfile(char* descfile, unsigned short output)
}
fclose(fp);
unlink(descfile);
if(count > 0) {
(*bakptr) = backup;
(*bakct) = count;
}
return(0);
}
@ -879,20 +941,20 @@ void usage(int op, char* myname)
printf("usage: %s {-A --add} [options] <file>\n", myname);
printf("options:\n");
printf(" -f, --force force install, overwrite conflicting files\n");
printf(" -n, --nosave do not save .conf files\n");
printf(" -n, --nosave do not save configuration files\n");
printf(" -v, --verbose be verbose\n");
printf(" -r, --root <path> set an alternative installation root\n");
} else if(op == PM_REMOVE) {
printf("usage: %s {-R --remove} [options] <package>\n", myname);
printf("options:\n");
printf(" -n, --nosave do not save .conf files\n");
printf(" -n, --nosave do not save configuration files\n");
printf(" -v, --verbose be verbose\n");
printf(" -r, --root <path> set an alternative installation root\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(" -n, --nosave do not save .conf files\n");
printf(" -n, --nosave do not save configuration files\n");
printf(" -v, --verbose be verbose\n");
printf(" -r, --root <path> set an alternative installation root\n");
} else if(op == PM_QUERY) {
@ -934,6 +996,34 @@ int vprint(char* fmt, ...)
return(0);
}
/* See if a file should be backed up or not
*/
int needbackup(char* file, fileset_t files, unsigned int filect)
{
int i;
for(i = 0; i < filect; i++) {
if(files[i][0] == '*' && !strcmp((char*)(files[i]+1), file)) {
return(1);
}
}
return(0);
}
/* Test for existence of a string in a fileset
*/
int is_in(char* needle, fileset_t haystack, unsigned int hayct)
{
int i;
for(i = 0; i < hayct; i++) {
if(!strcmp(haystack[i], needle)) {
return(1);
}
}
return(0);
}
/* Convert a string to uppercase
*/
char* strtoupper(char* str)

View file

@ -21,7 +21,7 @@
#ifndef PACMAN_H
#define PACMAN_H
#define VERSION "1.0"
#define VERSION "1.1"
#define PKGEXT ".tar.gz"
#define PKGDB "/var/lib/pacman/pacman.db"
@ -50,11 +50,15 @@ 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);
char* 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);
char* parseargs(int op, int argc, char** argv);
int parse_descfile(char* descfile, unsigned short output);
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);