summaryrefslogtreecommitdiff
path: root/lib/libalpm/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r--lib/libalpm/util.c262
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(&reg, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {
+ RET_ERR(PM_ERR_INVALID_REGEX, -1);
+ }
+ result = regexec(&reg, string, 0, 0, 0);
+ regfree(&reg);
+ return(!(result));
+}
+
+#endif
+
/* vim: set ts=2 sw=2 noet: */