summaryrefslogtreecommitdiffstats
path: root/src/pacman/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman/util.c')
-rw-r--r--src/pacman/util.c297
1 files changed, 297 insertions, 0 deletions
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 <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 "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <zlib.h>
+#include <libtar.h>
+
+/* 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: */