From 8cf35f551fd9cf8dc92c9a7c86fd4485f9cec74a Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Sun, 10 Mar 2002 22:34:15 +0000 Subject: Imported from pacman-1.1.tar.gz --- Makefile | 2 +- TODO | 19 +++---- installworld | 25 --------- makepkg | 56 ++++++++++++-------- makeworld | 60 ++++++++++++++------- pacman.8.in | 12 +++++ pacman.c | 170 +++++++++++++++++++++++++++++++++++++++++++++-------------- pacman.h | 10 ++-- 8 files changed, 232 insertions(+), 122 deletions(-) delete mode 100755 installworld diff --git a/Makefile b/Makefile index 58de8a2a..5184a572 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/TODO b/TODO index a08e2597..72b739d7 100644 --- a/TODO +++ b/TODO @@ -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 diff --git a/installworld b/installworld deleted file mode 100755 index fd155622..00000000 --- a/installworld +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -if [ "$1" = "" ]; then - echo "usage: $0 " - 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." diff --git a/makepkg b/makepkg index b9ad4bcb..c286d7fc 100755 --- a/makepkg +++ b/makepkg @@ -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 diff --git a/makeworld b/makeworld index a6c0b470..883e5ad5 100755 --- a/makeworld +++ b/makeworld @@ -2,28 +2,48 @@ toplevel=`pwd` -if [ $# -lt 1 ]; then - echo "usage: $0 " +if [ $# -lt 2 ]; then + echo "usage: $0 [category] ..." + echo " where 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 - 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 +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 - 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 + diff --git a/pacman.8.in b/pacman.8.in index 2db57ced..a7e720ed 100644 --- a/pacman.8.in +++ b/pacman.8.in @@ -47,6 +47,11 @@ files owned by the package. .B "\-i, \-\-info" Output the .PKGINFO file contained in . 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 " Specify alternative installation root (default is "/"). This should \fInot\fP be used as a way to install software into diff --git a/pacman.c b/pacman.c index 60c99726..0a686925 100644 --- a/pacman.c +++ b/pacman.c @@ -1,4 +1,4 @@ -/** +/* * pacman * * Copyright (c) 2002 by Judd Vinet @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ + #include "pacman.h" #include #include @@ -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] \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 set an alternative installation root\n"); } else if(op == PM_REMOVE) { printf("usage: %s {-R --remove} [options] \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 set an alternative installation root\n"); } else if(op == PM_UPGRADE) { printf("usage: %s {-U --upgrade} [options] \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 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) diff --git a/pacman.h b/pacman.h index c9f4fdb0..76914964 100644 --- a/pacman.h +++ b/pacman.h @@ -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); -- cgit v1.2.3-24-g4f1b