diff options
Diffstat (limited to 'pacman.c')
-rw-r--r-- | pacman.c | 1202 |
1 files changed, 0 insertions, 1202 deletions
diff --git a/pacman.c b/pacman.c deleted file mode 100644 index 74fa36dc..00000000 --- a/pacman.c +++ /dev/null @@ -1,1202 +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. - */ - -#include "pacman.h" -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> -#include <limits.h> -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <libtar.h> -#include <zlib.h> - -/* 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; -} - -static tartype_t gztype = { - (openfunc_t) gzopen_frontend, - (closefunc_t)gzclose, - (readfunc_t) gzread, - (writefunc_t)gzwrite -}; - -/* - * GLOBALS - * - */ -FILE* dbfp = NULL; -char* dbpath = NULL; -char* pkgname = NULL; -char* pkgver = NULL; -char oldpkgver[65]; - -char* pmo_root = NULL; -unsigned short pmo_verbose = 0; -unsigned short pmo_force = 0; -unsigned short pmo_upgrade = 0; -unsigned short pmo_nosave = 0; -unsigned short pmo_nofunc = 0; -unsigned short pmo_haveinst = 0; -unsigned short pmo_q_isfile = 0; -unsigned short pmo_q_info = 0; -unsigned short pmo_q_list = 0; -char* pmo_q_owns = NULL; - -/* list of installed packages */ -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; - -int main(int argc, char* argv[]) -{ - pm_opfunc_t op_func; - int i, ret = 0; - - /* default root */ - pmo_root = (char*)malloc(2); - strcpy(pmo_root, "/"); - - /* db location */ - dbpath = (char*)malloc(strlen(PKGDIR)+strlen(PKGDB)+1); - sprintf(dbpath, "%s/%s", PKGDIR, PKGDB); - - if(argc < 2) { - usage(PM_MAIN, (char*)basename(argv[0])); - return(0); - } - - /* determine the requested operation and pass off to */ - /* the handler function */ - if(!strcmp(argv[1], "-A") || !strcmp(argv[1], "--add")) { - op_func = pacman_add; - ret = parseargs(PM_ADD, argc, argv); - } else if(!strcmp(argv[1], "-R") || !strcmp(argv[1], "--remove")) { - op_func = pacman_remove; - ret = parseargs(PM_REMOVE, argc, argv); - } else if(!strcmp(argv[1], "-Q") || !strcmp(argv[1], "--query")) { - op_func = pacman_query; - ret = parseargs(PM_QUERY, argc, argv); - } else if(!strcmp(argv[1], "-U") || !strcmp(argv[1], "--upgrade")) { - op_func = pacman_upgrade; - ret = parseargs(PM_UPGRADE, argc, argv); - } else if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { - usage(PM_MAIN, (char*)basename(argv[0])); - return(1); - } else if(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { - version(); - return(1); - } else { - fprintf(stderr, "error: invalid operation\n\n"); - usage(PM_MAIN, (char*)basename(argv[0])); - return(1); - } - - if(ret || (pm_targct < 1 && op_func != pacman_query)) { - return(1); - } - vprint("Installation Root: %s\n", pmo_root); - if(pm_targct) { - vprint("Targets:\n"); - for(i = 0; i < pm_targct; i++) { - vprint(" %s\n", pm_targets[i]); - } - } - - /* check for db existence */ - if(pmo_root != NULL && strcmp(pmo_root, "/")) { - /* trim the trailing '/' if there is one */ - if((int)rindex(pmo_root, '/') == ((int)pmo_root)+strlen(pmo_root)-1) { - pmo_root[strlen(pmo_root)-1] = '\0'; - } - free(dbpath); - dbpath = (char*)malloc(strlen(pmo_root)+strlen(PKGDIR)+strlen(PKGDB)+1); - sprintf(dbpath, "%s%s/%s", pmo_root, PKGDIR, PKGDB); - } - vprint("Using package DB: %s\n", dbpath); - - ret = db_open(dbpath); - if(ret == 1) { - fprintf(stderr, "error: Could not open package database file!\n"); - fprintf(stderr, " Check to see that %s exists.\n", dbpath); - fprintf(stderr, " If not, you can create it by \"touch\"-ing it.\n"); - return(1); - } - if(ret == 2) { - fprintf(stderr, "error: Database is corrupt! You may need to use the backup database.\n"); - return(1); - } - - /* start the requested operation */ - if(!pmo_nofunc) { - for(i = 0; i < pm_targct; i++) { - pmo_haveinst = 0; - if(op_func(pm_targets[i])) { - ret = 1; - /* - if(op_func == pacman_add) { - printf("Failed to add %s\n", pkgname != NULL ? pkgname : pm_targets[i]); - } else if(op_func == pacman_remove) { - printf("Failed to remove %s\n", pkgname != NULL ? pkgname : pm_targets[i]); - } else if(op_func == pacman_upgrade) { - printf("Failed to upgrade %s\n", pkgname != NULL ? pkgname : pm_targets[i]); - } - */ - } - } - 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); - return(ret); -} - -int pacman_add(char* pkgfile) -{ - int i, ret = 0, errors = 0; - TAR* tar = NULL; - char* errmsg = NULL; - char* expath = NULL; - char pm_install[PATH_MAX+1]; - char cmdline[PATH_MAX+1]; - /*char* newpath = NULL;*/ - fileset_t files = NULL; - unsigned int filecount = 0, nb = 0; - struct stat buf; - - /* Populate the file list */ - filecount = load_pkg(pkgfile, &files, 0); - - if(filecount == 0) { - return(1); - } - - /* Now check for conflicts in the db */ - vprint("Looking for DB conflicts...\n"); - if((i = db_find_conflicts(files, filecount)) == 1) { - if(pmo_force) { - fprintf(stderr, "\nInstalling package anyway...\n"); - fprintf(stderr, " You might have duplicate entries in your package\n"); - fprintf(stderr, " database now. You may want to edit it and remove\n"); - fprintf(stderr, " one of the copies.\n\n"); - } else { - fprintf(stderr, "Aborting...\n"); - fprintf(stderr, " (use -f to override)\n\n"); - return(1); - } - } else if(i == 2) { - return(1); - } else { - vprint("No DB conflicts found\n"); - } - - /* see if this is an upgrade. if so, remove the old package first */ - if(pmo_upgrade) { - vprint("Removing old package first...\n"); - /* save the old nosave option and disable it for the package remove */ - i = pmo_nosave; - pmo_nosave = 0; - ret = pacman_remove(pkgname); - /* restore nosave */ - pmo_nosave = i; - if(ret == 1) { - fprintf(stderr, "\nUpgrade aborted.\n"); - return(1); - } else if(ret == 2) { - fprintf(stderr, "%s is not installed. skipping...\n", pkgname); - return(0); - } - if(db_update(NULL, 0)) { - fprintf(stderr, "\nError updating database. Upgrade aborted.\n"); - return(1); - } - } - - /* open the .tar.gz package */ - if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { - perror("could not open package"); - return(1); - } - vprint("Extracting files...\n"); - for(i = 0; !th_read(tar); i++) { - if(!strcmp(th_get_pathname(tar), ".PKGINFO")) { - tar_skip_regfile(tar); - 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); - 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(!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); - fprintf(stderr, "%s renamed to %s\n", expath, newpath);*/ - - /* keep the old file and write the new one to a .pacnew extension */ - fprintf(stderr, "%s already exists, extracting to %s.pacnew\n", expath, expath); - expath = (char*)realloc(expath, strlen(expath)+strlen(".pacnew")+1); - strcat(expath, ".pacnew"); - } - if(tar_extract_file(tar, expath)) { - errmsg = strerror(errno); - fprintf(stderr, "could not extract %s: %s\n", th_get_pathname(tar), errmsg); - errors = 1; - } - free(expath); - } - tar_close(tar); - vprint("Done.\n"); - if(errors) { - fprintf(stderr, "There were errors. No database update was performed.\n"); - return(1); - } else { - vprint("Updating database...\n"); - if(db_update(files, filecount)) { - fprintf(stderr, "error: Could not update database! The database may not\n"); - fprintf(stderr, " be in a sane state!\n"); - return(1); - } - vprint("Done.\n"); - } - - /* run the post-install script if it exists */ - snprintf(pm_install, PATH_MAX, "%s%s/scripts/%s", pmo_root, PKGDIR, pkgname); - if(!stat(pm_install, &buf)) { - strcpy(oldpkgver, ""); - for(i = 0; i < pm_pkgcount; i++) { - if(!strcmp(pm_packages[i]->name, pkgname)) { - strcpy(oldpkgver, pm_packages[i]->version); - } - } - vprint("Executing post-install script...\n"); - snprintf(cmdline, PATH_MAX, "cd %s && /bin/sh %s post_%s %s %s", pmo_root, pm_install, - (pmo_upgrade ? "upgrade" : "install"), pkgver, (pmo_upgrade ? oldpkgver : "")); - system(cmdline); - } - - return(0); -} - -int pacman_remove(char* pkgfile) -{ - int found = 0, done = 0; - int i; - char line[PATH_MAX+1]; - char pm_install[PATH_MAX+1]; - fileset_t files = NULL; - unsigned int filecount = 0, nb = 0; - struct stat buf; - char* newpath = NULL; - char* file = NULL; - - if(pkgfile == NULL) { - return(0); - } - - /* find the package's filelist in the db */ - rewind(dbfp); - while(!found && !feof(dbfp)) { - fgets(line, 255, dbfp); - strcpy(line, trim(line)); - if(!strcmp(line, pkgfile)) { - /* read the version */ - fgets(oldpkgver, 63, dbfp); - found = 1; - } - } - if(!found) { - if(pmo_upgrade) { - /* special handling */ - return(2); - } else { - fprintf(stderr, "Cannot remove %s: Package was not found.\n", pkgfile); - return(1); - } - } - - if(!pmo_upgrade) { - /* run the pre-remove script if it exists */ - snprintf(pm_install, PATH_MAX, "%s%s/scripts/%s", pmo_root, PKGDIR, pkgfile); - if(!stat(pm_install, &buf)) { - vprint("Executing pre-remove script...\n"); - snprintf(line, PATH_MAX, "cd %s && /bin/sh %s pre_remove %s", pmo_root, - pm_install, oldpkgver); - - system(line); - } - } - - while(!done) { - fgets(line, PATH_MAX, dbfp); - strcpy(line, trim(line)); - if(strlen(line)) { - /* add the path to the list */ - files = (fileset_t)realloc(files, (++filecount) * sizeof(char*)); - files[filecount-1] = (char*)malloc(strlen(line)+1); - strcpy(files[filecount-1], line); - } else { - done = 1; - } - } - /* iterate through the list backwards, unlinking files */ - for(i = filecount-1; i >= 0; 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", file); - if(rmdir(file)) { - /* this is okay, other packages are probably using it. */ - /* perror("cannot remove directory"); */ - } - } else { - /* if the file is flagged, back it up to .pacsave */ - if(nb) { - if(!pmo_upgrade && !pmo_nosave) { - newpath = (char*)realloc(newpath, strlen(file)+strlen(".pacsave")+1); - strcpy(newpath, file); - strcat(newpath, ".pacsave"); - rename(file, newpath); - fprintf(stderr, "%s renamed to %s\n", file, newpath); - } else if(!pmo_upgrade && pmo_nosave) { - vprint(" unlinking %s\n", file); - if(unlink(file)) { - perror("cannot remove file"); - } - } else { - /* skip */ - } - } else { - vprint(" unlinking %s\n", file); - if(unlink(file)) { - perror("cannot remove file"); - } - } - } - } - - /* now splice this name out of the packages list */ - found = 0; - for(i = 0; i < pm_pkgcount-1; i++) { - if(found) { - pm_packages[i] = pm_packages[i+1]; - } else { - if(!strcmp(pm_packages[i]->name, pkgfile)) { - found = 1; - if(i < pm_pkgcount-1) { - pm_packages[i] = pm_packages[i+1]; - } - } - } - } - /* drop the last item */ - pm_packages = (pkginfo_t**)realloc(pm_packages, (--pm_pkgcount)*sizeof(pkginfo_t*)); - - /* the db will be commited back up in main() */ - return(0); -} - -int pacman_query(char* pkgfile) -{ - char *str = NULL; - char name[256]; - char ver[64]; - char line[PATH_MAX+1]; - int found = 0; - int done = 0; - int i; - unsigned int filecount = 0; - fileset_t files = NULL; - - /* output info for a .tar.gz package */ - if(pmo_q_isfile) { - filecount = load_pkg(pkgfile, &files, pmo_q_info); - if(pmo_q_list) { - for(i = 0; i < filecount; i++) { - if(strcmp(files[i], ".PKGINFO")) { - if(files[i][0] == '*') { - printf("%s\n", (char*)(files[i]+1)); - } else { - printf("%s\n", files[i]); - } - } - } - } else { - printf("%s %s\n", pkgname, pkgver); - } - - return(0); - } - - /* determine the owner of a file */ - if(pmo_q_owns != NULL) { - rewind(dbfp); - while(!found && !feof(dbfp)) { - fgets(name, 255, dbfp); - strcpy(name, trim(name)); - fgets(ver, 63, dbfp); - strcpy(ver, trim(ver)); - strcpy(line, " "); - while(strlen(line) && !feof(dbfp)) { - fgets(line, PATH_MAX, dbfp); - strcpy(line, trim(line)); - str = line; - if(line[0] == '*') { - str++; - } - str += strlen(pmo_root); - if(!strcmp(str, pmo_q_owns)) { - printf("%s %s\n", name, ver); - return(0); - } - } - } - fprintf(stderr, "No package owns this file.\n"); - return(2); - } - - /* find packages in the db */ - rewind(dbfp); - while(!done) { - found = 0; - while(!found && !feof(dbfp)) { - fgets(name, 255, dbfp); - strcpy(name, trim(name)); - if(pkgfile == NULL || (pkgfile != NULL && !strcmp(name, pkgfile))) { - /* read the version */ - fgets(ver, 63, dbfp); - strcpy(ver, trim(ver)); - found = 1; - if(pkgfile != NULL) { - done = 1; - } - } - } - if(feof(dbfp)) { - if(pkgfile != NULL && !found) { - fprintf(stderr, "Package \"%s\" was not found in database.\n", pkgfile); - return(2); - } - break; - } - found = 0; - while(!found) { - fgets(line, PATH_MAX, dbfp); - strcpy(line, trim(line)); - if(strlen(line)) { - if(pmo_q_list) { - if(line[0] == '*') { - printf("%s%s\n", pmo_root, (char*)(line+1)); - } else { - printf("%s%s\n", pmo_root, line); - } - } - } else { - found = 1; - } - } - if(!pmo_q_list) { - printf("%s %s\n", name, ver); - } - if(feof(dbfp)) { - done = 1; - } - } - - return(0); -} - -int pacman_upgrade(char* pkgfile) -{ - /* this is basically just a remove,add process. pacman_add() will */ - /* handle it */ - pmo_upgrade = 1; - return pacman_add(pkgfile); -} - -/* - * Populate the package file list - * pkgfile: filename of package - * listptr: this will be set to the new fileset_t - * - * Returns: the number of filenames read in the package, or 0 on error - * - */ -int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output) -{ - char* expath; - char* descfile; - int i; - 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"); - - if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { - perror("could not open package"); - return(0); - } - vprint("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("Found package description file.\n"); - mkstemp(descfile); - tar_extract_file(tar, descfile); - parse_descfile(descfile, output, &backup, &bakct); - continue; - } - /* build the new pathname relative to 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 */ - files = (fileset_t)realloc(files, (++filecount) * sizeof(char*)); - files[filecount-1] = expath; - - if(TH_ISREG(tar) && tar_skip_regfile(tar)) { - perror("bad package file"); - return(1); - } - expath = NULL; - } - tar_close(tar); - - free(descfile); - - if(pkgname == NULL || pkgver == NULL) { - fprintf(stderr, "Error: Missing .PKGINFO file in %s\n", pkgfile); - return(0); - } - - (*listptr) = files; - return(filecount); -} - -/* Open the database file - * path: the full pathname of the file - */ -int db_open(char* path) -{ - char line[PATH_MAX+1]; - int i; - 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"); - if(dbfp == NULL) { - return(1); - } - while(!feof(dbfp)) { - info = (pkginfo_t*)malloc(sizeof(pkginfo_t)); - fgets(line, sizeof(info->name)-1, dbfp); - if(feof(dbfp)) { - break; - } - strcpy(info->name, trim(line)); - fgets(line, sizeof(info->version)-1, dbfp); - strcpy(info->version, trim(line)); - /* add to the collective */ - pm_packages = (pkginfo_t**)realloc(pm_packages, (++pm_pkgcount) * sizeof(pkginfo_t*)); - pm_packages[pm_pkgcount-1] = info; - for(;;) { - fgets(line, PATH_MAX, dbfp); - if(feof(dbfp)) { - return(2); - } - if(strlen(trim(line)) == 0) { - break; - } - } - } - - return(0); -} - -/* Copy the old database file to a backup and build the - * new copy in its place. - * files: list of files in the new package, can be null - * filecount: number of entries in files - * - * Returns: 0 on success - * - */ -int db_update(fileset_t files, unsigned int filecount) -{ - FILE* olddb = NULL; - char* newpath = NULL; - char* str = NULL; - char name[256]; - char ver[64]; - char line[PATH_MAX+1]; - int i = 0, found = 0, done = 0; - - /* build the backup pathname */ - newpath = (char*)malloc(strlen(dbpath)+5); - strcpy(newpath, dbpath); - strcat(newpath, ".bak"); - - /* rename the existing db */ - fclose(dbfp); - rename(dbpath, newpath); - - olddb = fopen(newpath, "r"); - free(newpath); - dbfp = fopen(dbpath, "w"); - if(olddb == NULL || dbfp == NULL) { - return(1); - } - - rewind(olddb); - while(!feof(olddb)) { - if(!fgets(name, 255, olddb)) { - break; - } - strcpy(name, trim(name)); - fgets(ver, 63, olddb); - found = 0; - for(i = 0; i < pm_pkgcount && !found; i++) { - if(!strcmp(pm_packages[i]->name, name)) { - /* it's there... copy the entries over */ - found = 1; - fputs(name, dbfp); - fputc('\n', dbfp); - fputs(ver, dbfp); - for(done = 0; !done;) { - fgets(line, PATH_MAX, olddb); - if(found) { - fputs(line, dbfp); - } - if(strlen(trim(line)) == 0 || feof(olddb)) { - done = 1; - } - } - } - } - if(!found) { - /* skip through filelist for this package */ - for(done = 0; !done;) { - fgets(line, PATH_MAX, olddb); - if(strlen(trim(line)) == 0 || feof(olddb)) { - done = 1; - } - } - } - } - fclose(olddb); - - /* write the current info */ - if(files != NULL) { - fputs(pkgname, dbfp); - fputc('\n', dbfp); - fputs(pkgver, dbfp); - fputc('\n', dbfp); - 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); - } - fputs("\n", dbfp); - } - fclose(dbfp); - db_open(dbpath); - - return(0); -} - -/* Check the database for conflicts - * files: list of files in the new package - * filecount: number of entries in files - * - * Returns: 0 if no conflicts were found, 1 otherwise - * - */ -int db_find_conflicts(fileset_t files, unsigned int filecount) -{ - int i; - char line[PATH_MAX+1]; - char name[256]; - char* dbstr = NULL; - char* filestr = NULL; - struct stat buf; - int conflicts = 0; - - /* CHECK 1: checking db conflicts */ - rewind(dbfp); - while(!feof(dbfp)) { - fgets(name, 255, dbfp); - strcpy(name, trim(name)); - if(!pmo_upgrade && !strcmp(name, pkgname)) { - fprintf(stderr, "error: This package is already installed.\n"); - fprintf(stderr, " Maybe you should be using --upgrade.\n"); - return(2); - } - fgets(line, 64, dbfp); - while(!feof(dbfp)) { - fgets(line, PATH_MAX, dbfp); - strcpy(line, trim(line)); - dbstr = line; - if(dbstr[0] == '*') { - dbstr++; - } - if(!strlen(dbstr)) { - break; - } - 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++) { - 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; - } - fprintf(stderr, "conflict: %s already exists in package \"%s\"\n", dbstr, name); - conflicts = 1; - } - } - } - } - } - - /* CHECK 2: checking filesystem conflicts */ - /* TODO: run filesystem checks for upgrades */ - for(i = 0; i < filecount && !pmo_upgrade; i++) { - filestr = files[i]; - if(filestr[0] == '*') { - filestr++; - } - if(!stat(filestr, &buf) && !S_ISDIR(buf.st_mode)) { - fprintf(stderr, "conflict: %s already exists in filesystem\n", filestr); - conflicts = 1; - } - } - - return(conflicts); -} - -/* Parses the package description file for the current package - * descfile: the full pathname of the description file - * - * Returns: 0 on success, 1 on error - * - */ -int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr, - unsigned int* bakct) -{ - FILE* fp = NULL; - FILE* inst = NULL; - char line[PATH_MAX+1]; - 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); - return(1); - } - - while(!feof(fp)) { - fgets(line, PATH_MAX, fp); - if(output) { - printf("%s", line); - } - linenum++; - strcpy(line, trim(line)); - if(index(line, '#') == (char*)line) { - 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 { - key = trim(key); - key = strtoupper(key); - ptr = trim(ptr); - if(!strcmp(key, "PKGNAME")) { - pkgname = (char*)malloc(strlen(ptr)+1); - strcpy(pkgname, ptr); - } else if(!strcmp(key, "PKGVER")) { - pkgver = (char*)malloc(strlen(ptr)+1); - 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 { - fprintf(stderr, "Syntax error in description file line %d\n", linenum); - } - } - line[0] = '\0'; - } - fclose(fp); - unlink(descfile); - - if(inst != NULL) { - fputs("exit 0\n", inst); - fclose(inst); - } - - if(count > 0) { - (*bakptr) = backup; - (*bakct) = count; - } - - 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 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")) { - pmo_nofunc = 1; - usage(op, (char*)basename(argv[0])); - return(1); - } else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) { - pmo_verbose = 1; - } else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force")) { - pmo_force = 1; - } else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--root")) { - i++; - if(i >= argc) { - fprintf(stderr, "error: missing argument for %s\n", argv[i-1]); - return(1); - } - free(pmo_root); - pmo_root = (char*)malloc(PATH_MAX); - if(realpath(argv[i], pmo_root) == NULL) { - perror("bad root path"); - return(1); - } - } else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--nosave")) { - pmo_nosave = 1; - } else if(!strcmp(argv[i], "-o") || !strcmp(argv[i], "--owns")) { - /* PM_QUERY only */ - i++; - if(i >= argc) { - fprintf(stderr, "error: missing argument for %s\n", argv[i-1]); - return(1); - } - if(strlen(argv[i]) > PATH_MAX) { - fprintf(stderr, "error: argument %d is too long.\n", i); - return(1); - } - free(pmo_q_owns); - pmo_q_owns = (char*)malloc(PATH_MAX); - if(realpath(argv[i], pmo_q_owns) == NULL) { - perror("bad path specified for --owns"); - pmo_nofunc = 1; - return(1); - } - /* trim off the leading slash */ - pmo_q_owns++; - } else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) { - /* PM_QUERY only */ - pmo_q_list = 1; - } else if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--file")) { - /* PM_QUERY only */ - pmo_q_isfile = 1; - } else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--info")) { - /* PM_QUERY only */ - pmo_q_info = 1; - } else { - /* 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 && pm_targct < 1) { - fprintf(stderr, "error: no package specified\n\n"); - usage(op, (char*)basename(argv[0])); - return(1); - } - if(op == PM_QUERY && pmo_q_isfile && pm_targct < 1) { - fprintf(stderr, "error: no package file specified\n\n"); - return(1); - } - 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); - } 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(" -n, --nosave overwrite configuration files as well\n"); - printf(" -v, --verbose be verbose\n"); - printf(" -r, --root <path> set an alternate 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 configuration files as .pacsave\n"); - printf(" -v, --verbose be verbose\n"); - printf(" -r, --root <path> set an alternate 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 upgrade configuration files as well (old one is deleted)\n"); - printf(" -v, --verbose be verbose\n"); - printf(" -r, --root <path> set an alternate installation root\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 the package info file (only used with -p)\n"); - printf(" -p, --file if used, then [package] will be the path\n"); - printf(" to a .tar.gz package file to query\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", VERSION); - 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); -} - -/* 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) -{ - char* ptr = str; - - while(*ptr) { - (*ptr) = toupper(*ptr); - ptr++; - } - return str; -} - -/* Trim whitespace and newlines from a string - */ -char* trim(char* str) -{ - char* start = str; - char* end = str + strlen(str); - int mid = 0; - char ch; - - while(mid < 2) { - if(!mid) { - ch = *start; - if(ch == 10 || ch == 13 || ch == 9 || ch == 32) { - start++; - } else { - mid = 1; - } - } else { - end--; - ch = *end; - if(ch == 10 || ch == 13 || ch == 9 || ch == 32) { - *end = '\0'; - } else { - mid = 2; - } - } - } - return(start); -} - -/* vim: set ts=2 noet: */ |