From d04baabafa2ebbad92741d1f87e6ff32999f894a Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Tue, 15 Mar 2005 01:51:43 +0000 Subject: Initial revision --- src/pacman/util.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/pacman/util.c (limited to 'src/pacman/util.c') diff --git a/src/pacman/util.c b/src/pacman/util.c new file mode 100644 index 00000000..56c3349b --- /dev/null +++ b/src/pacman/util.c @@ -0,0 +1,297 @@ +/* + * util.c + * + * Copyright (c) 2002-2005 by Judd Vinet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* pacman */ +#include "util.h" + +/* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */ +long 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 (long)gzf; +} + +int unpack(char *archive, const char *prefix, const char *fn) +{ + TAR *tar = NULL; + char expath[PATH_MAX]; + tartype_t gztype = { + (openfunc_t) gzopen_frontend, + (closefunc_t)gzclose, + (readfunc_t) gzread, + (writefunc_t)gzwrite + }; + + /* open the .tar.gz package */ + if(tar_open(&tar, archive, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { + perror(archive); + return(1); + } + while(!th_read(tar)) { + if(fn && strcmp(fn, th_get_pathname(tar))) { + if(TH_ISREG(tar) && tar_skip_regfile(tar)) { + char errorstr[255]; + snprintf(errorstr, 255, "bad tar archive: %s", archive); + perror(errorstr); + tar_close(tar); + return(1); + } + continue; + } + snprintf(expath, PATH_MAX, "%s/%s", prefix, th_get_pathname(tar)); + if(tar_extract_file(tar, expath)) { + fprintf(stderr, "could not extract %s: %s\n", th_get_pathname(tar), strerror(errno)); + } + if(fn) break; + } + tar_close(tar); + + return(0); +} + +/* does the same thing as 'mkdir -p' */ +int makepath(char *path) +{ + char *orig, *str, *ptr; + char full[PATH_MAX] = ""; + mode_t oldmask; + + oldmask = umask(0000); + + orig = strdup(path); + str = orig; + while((ptr = strsep(&str, "/"))) { + if(strlen(ptr)) { + struct stat buf; + + strcat(full, "/"); + strcat(full, ptr); + if(stat(full, &buf)) { + if(mkdir(full, 0755)) { + free(orig); + umask(oldmask); + return(1); + } + } + } + } + free(orig); + umask(oldmask); + return(0); +} + +/* does the same thing as 'rm -rf' */ +int rmrf(char *path) +{ + int errflag = 0; + struct dirent *dp; + DIR *dirp; + char name[PATH_MAX]; + extern int errno; + + if(!unlink(path)) { + return(0); + } else { + if(errno == ENOENT) { + return(0); + } else if(errno == EPERM) { + /* fallthrough */ + } else if(errno == EISDIR) { + /* fallthrough */ + } else if(errno == ENOTDIR) { + return(1); + } else { + /* not a directory */ + return(1); + } + + if((dirp = opendir(path)) == (DIR *)-1) { + return(1); + } + for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { + if(dp->d_ino) { + sprintf(name, "%s/%s", path, dp->d_name); + if(strcmp(dp->d_name, "..") && strcmp(dp->d_name, ".")) { + errflag += rmrf(name); + } + } + } + closedir(dirp); + if(rmdir(path)) { + errflag++; + } + return(errflag); + } + return(0); +} + +/* output a string, but wrap words properly with a specified indentation + */ +void indentprint(char *str, int indent) +{ + char *p = str; + char *cenv = NULL; + int cols = 80; + int cidx = indent; + + cenv = getenv("COLUMNS"); + if(cenv) { + cols = atoi(cenv); + } + + while(*p) { + if(*p == ' ') { + char *next = NULL; + int len; + p++; + if(p == NULL || *p == ' ') continue; + next = strchr(p, ' '); + if(next == NULL) { + next = p + strlen(p); + } + len = next - p; + if(len > (cols-cidx-1)) { + /* newline */ + int i; + fprintf(stdout, "\n"); + for(i = 0; i < indent; i++) { + fprintf(stdout, " "); + } + cidx = indent; + } else { + printf(" "); + cidx++; + } + } + fprintf(stdout, "%c", *p); + p++; + cidx++; + } +} + +/* 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 *strtrim(char *str) +{ + char *pch = str; + while(isspace(*pch)) { + pch++; + } + if(pch != str) { + memmove(str, pch, (strlen(pch) + 1)); + } + + pch = (char *)(str + (strlen(str) - 1)); + while(isspace(*pch)) { + pch--; + } + *++pch = '\0'; + + return str; +} + +/* presents a prompt and gets a Y/N answer + */ +int yesno(char *fmt, ...) +{ + char response[32]; + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + fflush(stdout); + if(fgets(response, 32, stdin)) { + /* trim whitespace and newlines */ + char *pch = response; + while(isspace(*pch)) { + pch++; + } + if(pch != response) { + memmove(response, pch, strlen(pch) + 1); + } + pch = response + strlen(response) - 1; + while(isspace(*pch)) { + pch--; + } + *++pch = 0; + strtrim(response); + + if(!strcasecmp(response, "Y") || !strcasecmp(response, "YES") || !strlen(response)) { + return(1); + } + } + return(0); +} + +/* vim: set ts=2 sw=2 noet: */ -- cgit v1.2.3-24-g4f1b