diff options
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r-- | lib/libalpm/util.c | 262 |
1 files changed, 221 insertions, 41 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 50b5c5de..c5ad162b 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -1,7 +1,11 @@ /* * util.c - * + * * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> + * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> + * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> + * Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org> + * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.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 @@ -19,9 +23,19 @@ * USA. */ +#if defined(__APPLE__) || defined(__OpenBSD__) +#include <sys/syslimits.h> +#endif +#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__sun__) +#include <sys/stat.h> +#endif + #include "config.h" #include <stdio.h> #include <stdlib.h> +#ifdef __sun__ +#include <alloca.h> +#endif #include <stdarg.h> #include <string.h> #include <unistd.h> @@ -36,12 +50,75 @@ #ifdef CYGWIN #include <limits.h> /* PATH_MAX */ #endif +#include <sys/statvfs.h> +#ifndef __sun__ +#include <mntent.h> +#endif +#include <regex.h> + /* pacman */ #include "log.h" +#include "list.h" +#include "trans.h" +#include "sync.h" #include "util.h" #include "error.h" #include "alpm.h" +#ifdef __sun__ +/* This is a replacement for strsep which is not portable (missing on Solaris). + * Copyright (c) 2001 by François Gouget <fgouget_at_codeweavers.com> */ +char* strsep(char** str, const char* delims) +{ + char* token; + + if (*str==NULL) { + /* No more tokens */ + return NULL; + } + + token=*str; + while (**str!='\0') { + if (strchr(delims,**str)!=NULL) { + **str='\0'; + (*str)++; + return token; + } + (*str)++; + } + /* There is no other token */ + *str=NULL; + return token; +} + +/* Backported from Solaris Express 4/06 + * Copyright (c) 2006 Sun Microsystems, Inc. */ +char * mkdtemp(char *template) +{ + char *t = alloca(strlen(template) + 1); + char *r; + + /* Save template */ + (void) strcpy(t, template); + for (; ; ) { + r = mktemp(template); + + if (*r == '\0') + return (NULL); + + if (mkdir(template, 0700) == 0) + return (r); + + /* Other errors indicate persistent conditions. */ + if (errno != EEXIST) + return (NULL); + + /* Reset template */ + (void) strcpy(template, t); + } +} +#endif + /* does the same thing as 'mkdir -p' */ int _alpm_makepath(char *path) { @@ -122,7 +199,7 @@ char *_alpm_strtrim(char *str) return(str); } - while(isspace(*pch)) { + while(isspace((int)*pch)) { pch++; } if(pch != str) { @@ -135,7 +212,7 @@ char *_alpm_strtrim(char *str) } pch = (char *)(str + (strlen(str) - 1)); - while(isspace(*pch)) { + while(isspace((int)*pch)) { pch--; } *++pch = '\0'; @@ -148,6 +225,15 @@ char *_alpm_strtrim(char *str) int _alpm_lckmk(char *file) { int fd, count = 0; + char *dir, *ptr; + + /* create the dir of the lockfile first */ + dir = strdup(file); + ptr = strrchr(dir, '/'); + if(ptr) { + *ptr = '\0'; + } + _alpm_makepath(dir); while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) { if(++count < 1) { @@ -170,56 +256,43 @@ int _alpm_lckrm(char *file) return(0); } +/* Compression functions + */ + int _alpm_unpack(char *archive, const char *prefix, const char *fn) { register struct archive *_archive; struct archive_entry *entry; char expath[PATH_MAX]; - if((_archive = archive_read_new()) == NULL) { - pm_errno = PM_ERR_LIBARCHIVE_ERROR; - return(1); - } + if ((_archive = archive_read_new ()) == NULL) + RET_ERR(PM_ERR_LIBARCHIVE_ERROR, -1); + archive_read_support_compression_all(_archive); - archive_read_support_format_all(_archive); - /* open the .tar.gz package */ - if(archive_read_open_file(_archive, archive, 10240) != ARCHIVE_OK) { - perror(archive); - return(1); - } - while(!archive_read_next_header(_archive, &entry) == ARCHIVE_OK) { - if(fn && strcmp(fn, archive_entry_pathname(entry))) { - if(archive_read_data_skip(_archive) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("bad archive: %s"), archive); + archive_read_support_format_all (_archive); + + if (archive_read_open_file (_archive, archive, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) + RET_ERR(PM_ERR_PKG_OPEN, -1); + + while (archive_read_next_header (_archive, &entry) == ARCHIVE_OK) { + if (fn && strcmp (fn, archive_entry_pathname (entry))) { + if (archive_read_data_skip (_archive) != ARCHIVE_OK) return(1); - } continue; } - snprintf(expath, PATH_MAX, "%s/%s", prefix, archive_entry_pathname(entry)); - if(archive_read_extract(_archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)"), archive_entry_pathname(entry), archive_error_string(_archive)); - return(1); + snprintf(expath, PATH_MAX, "%s/%s", prefix, archive_entry_pathname (entry)); + archive_entry_set_pathname (entry, expath); + if (archive_read_extract (_archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) { + fprintf(stderr, _("could not extract %s: %s\n"), archive_entry_pathname (entry), archive_error_string (_archive)); + return(1); } - if(fn) break; - } - archive_read_finish(_archive); - return(0); -} - -int _alpm_archive_read_entry_data_into_fd(struct archive *archive, int fd) -{ - register size_t length; - char cache[10240]; - - if(fd == -1) { - return ARCHIVE_RETRY; - } - while((length = archive_read_data(archive, &cache, sizeof(cache))) > 0) { - write(fd, cache, length); + if (fn) + break; } - return ARCHIVE_OK; + archive_read_finish (_archive); + return(0); } /* does the same thing as 'rm -rf' */ @@ -338,7 +411,7 @@ static int grep(const char *fn, const char *needle) return(0); } -int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, char *oldver) +int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, char *oldver, pmtrans_t *trans) { char scriptfn[PATH_MAX]; char cmdline[PATH_MAX]; @@ -410,6 +483,7 @@ int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, cha } if(pid == 0) { + FILE *pp; _alpm_log(PM_LOG_DEBUG, _("chrooting in %s"), root); if(chroot(root) != 0) { _alpm_log(PM_LOG_ERROR, _("could not change the root directory (%s)"), strerror(errno)); @@ -421,7 +495,27 @@ int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, cha } umask(0022); _alpm_log(PM_LOG_DEBUG, _("executing \"%s\""), cmdline); - execl("/bin/sh", "sh", "-c", cmdline, (char *)0); + pp = popen(cmdline, "r"); + if(!pp) { + _alpm_log(PM_LOG_ERROR, _("call to popen failed (%s)"), strerror(errno)); + retval = 1; + goto cleanup; + } + while(!feof(pp)) { + char line[1024]; + if(fgets(line, 1024, pp) == NULL) + break; + /* "START <event desc>" */ + if((strlen(line) > strlen(STARTSTR)) && !strncmp(line, STARTSTR, strlen(STARTSTR))) { + EVENT(trans, PM_TRANS_EVT_SCRIPTLET_START, _alpm_strtrim(line + strlen(STARTSTR)), NULL); + /* "DONE <ret code>" */ + } else if((strlen(line) > strlen(DONESTR)) && !strncmp(line, DONESTR, strlen(DONESTR))) { + EVENT(trans, PM_TRANS_EVT_SCRIPTLET_DONE, (void*)atol(_alpm_strtrim(line + strlen(DONESTR))), NULL); + } else { + EVENT(trans, PM_TRANS_EVT_SCRIPTLET_INFO, _alpm_strtrim(line), NULL); + } + } + pclose(pp); exit(0); } else { if(waitpid(pid, 0, 0) == -1) { @@ -442,4 +536,90 @@ cleanup: return(retval); } +#ifndef __sun__ +static long long get_freespace() +{ + struct mntent *mnt; + char *table = MOUNTED; + FILE *fp; + long long ret=0; + + fp = setmntent (table, "r"); + if(!fp) + return(-1); + while ((mnt = getmntent (fp))) + { + struct statvfs64 buf; + + statvfs64(mnt->mnt_dir, &buf); + ret += buf.f_bavail * buf.f_bsize; + } + return(ret); +} + +int _alpm_check_freespace(pmtrans_t *trans, PMList **data) +{ + PMList *i; + long long pkgsize=0, freespace; + + for(i = trans->packages; i; i = i->next) { + if(trans->type == PM_TRANS_TYPE_SYNC) + { + pmsyncpkg_t *sync = i->data; + if(sync->type != PM_SYNC_TYPE_REPLACE) { + pmpkg_t *pkg = sync->pkg; + pkgsize += pkg->usize; + } + } + else + { + pmpkg_t *pkg = i->data; + pkgsize += pkg->size; + } + } + freespace = get_freespace(); + _alpm_log(PM_LOG_DEBUG, _("check_freespace: total pkg size: %lld, disk space: %lld"), pkgsize, freespace); + if(pkgsize > freespace) { + if(data) { + long long *ptr; + if((ptr = (long long*)malloc(sizeof(long long)))==NULL) { + _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %d bytes"), sizeof(long long)); + pm_errno = PM_ERR_MEMORY; + return(-1); + } + *ptr = pkgsize; + *data = _alpm_list_add(*data, ptr); + if((ptr = (long long*)malloc(sizeof(long long)))==NULL) { + _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %d bytes"), sizeof(long long)); + FREELIST(*data); + pm_errno = PM_ERR_MEMORY; + return(-1); + } + *ptr = freespace; + *data = _alpm_list_add(*data, ptr); + } + pm_errno = PM_ERR_DISK_FULL; + return(-1); + } + else { + return(0); + } +} + +/* match a string against a regular expression */ +int _alpm_reg_match(char *string, char *pattern) +{ + int result; + regex_t reg; + + if(regcomp(®, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) { + RET_ERR(PM_ERR_INVALID_REGEX, -1); + } + result = regexec(®, string, 0, 0, 0); + regfree(®); + return(!(result)); +} + +#endif + /* vim: set ts=2 sw=2 noet: */ |