summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r--lib/libalpm/util.c670
1 files changed, 336 insertions, 334 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index decb5959..2a429488 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -6,7 +6,7 @@
* 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
* the Free Software Foundation; either version 2 of the License, or
@@ -19,7 +19,7 @@
*
* 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,
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
@@ -27,44 +27,133 @@
#include <stdio.h>
#include <stdlib.h>
-#ifdef __sun__
-#include <alloca.h>
-#endif
#include <string.h>
-#include <unistd.h>
-#include <errno.h>
#include <fcntl.h>
+#include <unistd.h>
#include <ctype.h>
#include <dirent.h>
#include <time.h>
#include <syslog.h>
-#include <sys/wait.h>
-#if defined(__APPLE__) || defined(__OpenBSD__)
-#include <sys/syslimits.h>
-#endif
-#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__sun__)
+#include <errno.h>
+#include <sys/types.h>
#include <sys/stat.h>
-#endif
-#include <libintl.h>
-#ifdef CYGWIN
-#include <limits.h> /* PATH_MAX */
-#endif
-#include <sys/statvfs.h>
-#ifndef __sun__
-#include <mntent.h>
-#endif
+
+/* libarchive */
+#include <archive.h>
+#include <archive_entry.h>
/* libalpm */
#include "util.h"
-#include "alpm_list.h"
#include "log.h"
-#include "trans.h"
-#include "sync.h"
#include "error.h"
#include "package.h"
#include "alpm.h"
+#include "alpm_list.h"
+#include "md5.h"
+
+#ifndef HAVE_STRVERSCMP
+/* GNU's strverscmp() function, taken from glibc 2.3.2 sources
+ */
+
+/* Compare strings while treating digits characters numerically.
+ Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+ Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+*/
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+ fractionnal parts, S_Z: idem but with leading Zeroes only */
+#define S_N 0x0
+#define S_I 0x4
+#define S_F 0x8
+#define S_Z 0xC
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP 2
+#define LEN 3
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+ returning less than, equal to or greater than zero if S1 is less than,
+ equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int strverscmp (s1, s2)
+ const char *s1;
+ const char *s2;
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+ int state;
+ int diff;
+
+ /* Symbol(s) 0 [1-9] others (padding)
+ Transition (10) 0 (01) d (00) x (11) - */
+ static const unsigned int next_state[] =
+ {
+ /* state x d 0 - */
+ /* S_N */ S_N, S_I, S_Z, S_N,
+ /* S_I */ S_N, S_I, S_I, S_I,
+ /* S_F */ S_N, S_F, S_F, S_F,
+ /* S_Z */ S_N, S_F, S_Z, S_Z
+ };
+
+ static const int result_type[] =
+ {
+ /* state x/x x/d x/0 x/- d/x d/d d/0 d/-
+ 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */
+
+ /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP,
+ +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+ /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP,
+ -1, CMP, CMP, CMP
+ };
+
+ if (p1 == p2)
+ return 0;
+
+ c1 = *p1++;
+ c2 = *p2++;
+ /* Hint: '0' is a digit too. */
+ state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
+
+ while ((diff = c1 - c2) == 0 && c1 != '\0')
+ {
+ state = next_state[state];
+ c1 = *p1++;
+ c2 = *p2++;
+ state |= (c1 == '0') + (isdigit (c1) != 0);
+ }
+
+ state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];
+
+ switch (state)
+ {
+ case CMP:
+ return diff;
+
+ case LEN:
+ while (isdigit (*p1++))
+ if (!isdigit (*p2++))
+ return 1;
+
+ return isdigit (*p2) ? -1 : diff;
+
+ default:
+ return state;
+ }
+}
+#endif
-#ifdef __sun__
+#ifndef HAVE_STRSEP
/* 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)
@@ -89,33 +178,6 @@ char* strsep(char** str, const char* delims)
*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' */
@@ -139,7 +201,7 @@ int _alpm_makepath(const char *path)
if(mkdir(full, 0755)) {
FREE(orig);
umask(oldmask);
- _alpm_log(PM_LOG_ERROR, _("failed to make path '%s' : %s"),
+ _alpm_log(PM_LOG_ERROR, _("failed to make path '%s' : %s\n"),
path, strerror(errno));
return(1);
}
@@ -167,30 +229,30 @@ int _alpm_copyfile(const char *src, const char *dest)
return(1);
}
+ /* do the actual file copy */
while((len = fread(buf, 1, 4096, in))) {
fwrite(buf, 1, len, out);
}
-
fclose(in);
- fclose(out);
- return(0);
-}
-/* Convert a string to uppercase
- */
-char *_alpm_strtoupper(char *str)
-{
- char *ptr = str;
-
- while(*ptr) {
- (*ptr) = toupper(*ptr);
- ptr++;
+ /* chmod dest to permissions of src, as long as it is not a symlink */
+ struct stat statbuf;
+ if(!stat(src, &statbuf)) {
+ if(! S_ISLNK(statbuf.st_mode)) {
+ fchmod(fileno(out), statbuf.st_mode);
+ }
+ } else {
+ /* stat was unsuccessful */
+ fclose(out);
+ return(1);
}
- return(str);
+
+ fclose(out);
+ return(0);
}
/* Trim whitespace and newlines from a string
- */
+*/
char *_alpm_strtrim(char *str)
{
char *pch = str;
@@ -212,7 +274,7 @@ char *_alpm_strtrim(char *str)
return(str);
}
- pch = (char *)(str + (strlen(str) - 1));
+ pch = (str + (strlen(str) - 1));
while(isspace((int)*pch)) {
pch--;
}
@@ -221,12 +283,57 @@ char *_alpm_strtrim(char *str)
return(str);
}
-/* Create a lock file
- */
-int _alpm_lckmk(const char *file)
+/* Helper function for _alpm_strreplace */
+static void _strnadd(char **str, const char *append, unsigned int count)
+{
+ if(*str) {
+ *str = realloc(*str, strlen(*str) + count + 1);
+ } else {
+ *str = calloc(count + 1, sizeof(char));
+ }
+
+ strncat(*str, append, count);
+}
+
+/* Replace all occurances of 'needle' with 'replace' in 'str', returning
+ * a new string (must be free'd) */
+char *_alpm_strreplace(const char *str, const char *needle, const char *replace)
+{
+ const char *p, *q;
+ p = q = str;
+
+ char *newstr = NULL;
+ unsigned int needlesz = strlen(needle),
+ replacesz = strlen(replace);
+
+ while (1) {
+ q = strstr(p, needle);
+ if(!q) { /* not found */
+ if(*p) {
+ /* add the rest of 'p' */
+ _strnadd(&newstr, p, strlen(p));
+ }
+ break;
+ } else { /* found match */
+ if(q > p){
+ /* add chars between this occurance and last occurance, if any */
+ _strnadd(&newstr, p, q - p);
+ }
+ _strnadd(&newstr, replace, replacesz);
+ p = q + needlesz;
+ }
+ }
+
+ return newstr;
+}
+
+
+/* Create a lock file */
+int _alpm_lckmk()
{
int fd, count = 0;
char *dir, *ptr;
+ const char *file = alpm_option_get_lockfile();
/* create the dir of the lockfile first */
dir = strdup(file);
@@ -236,7 +343,7 @@ int _alpm_lckmk(const char *file)
}
_alpm_makepath(dir);
- while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) {
+ while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) {
if(++count < 1) {
sleep(1);
} else {
@@ -244,27 +351,28 @@ int _alpm_lckmk(const char *file)
}
}
- free(dir);
+ FREE(dir);
return(fd > 0 ? fd : -1);
}
-/* Remove a lock file
- */
-int _alpm_lckrm(const char *file)
+/* Remove a lock file */
+int _alpm_lckrm()
{
+ const char *file = alpm_option_get_lockfile();
if(unlink(file) == -1 && errno != ENOENT) {
return(-1);
}
return(0);
}
-/* Compression functions
- */
+/* Compression functions */
int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
{
- register struct archive *_archive;
+ int ret = 0;
+ mode_t oldmask;
+ struct archive *_archive;
struct archive_entry *entry;
char expath[PATH_MAX];
@@ -276,31 +384,56 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
archive_read_support_compression_all(_archive);
archive_read_support_format_all(_archive);
- if(archive_read_open_file(_archive, archive, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
- _alpm_log(PM_LOG_ERROR, _("could not open %s: %s\n"), archive, archive_error_string(_archive));
+ if(archive_read_open_filename(_archive, archive,
+ ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
+ _alpm_log(PM_LOG_ERROR, _("could not open %s: %s\n"), archive,
+ archive_error_string(_archive));
RET_ERR(PM_ERR_PKG_OPEN, -1);
}
+ oldmask = umask(0022);
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);
+ const struct stat *st;
+ const char *entryname; /* the name of the file in the archive */
+
+ st = archive_entry_stat(entry);
+ entryname = archive_entry_pathname(entry);
+
+ if(S_ISREG(st->st_mode)) {
+ archive_entry_set_mode(entry, 0644);
+ }
+
+ if (fn && strcmp(fn, entryname)) {
+ if (archive_read_data_skip(_archive) != ARCHIVE_OK) {
+ ret = 1;
+ goto cleanup;
+ }
continue;
}
- snprintf(expath, PATH_MAX, "%s/%s", prefix, archive_entry_pathname(entry));
+ snprintf(expath, PATH_MAX, "%s/%s", prefix, entryname);
archive_entry_set_pathname(entry, expath);
- if(archive_read_extract(_archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) {
- _alpm_log(PM_LOG_ERROR, _("could not extract %s: %s\n"), archive_entry_pathname(entry), archive_error_string(_archive));
- return(1);
+
+ int readret = archive_read_extract(_archive, entry, 0);
+ if(readret == ARCHIVE_WARN) {
+ /* operation succeeded but a non-critical error was encountered */
+ _alpm_log(PM_LOG_DEBUG, "warning extracting %s (%s)\n",
+ entryname, archive_error_string(_archive));
+ } else if(readret != ARCHIVE_OK) {
+ _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"),
+ entryname, archive_error_string(_archive));
+ ret = 1;
+ goto cleanup;
}
if(fn) {
break;
}
}
-
+
+cleanup:
+ umask(oldmask);
archive_read_finish(_archive);
- return(0);
+ return(ret);
}
/* does the same thing as 'rm -rf' */
@@ -312,7 +445,7 @@ int _alpm_rmrf(const char *path)
char name[PATH_MAX];
struct stat st;
- if(lstat(path, &st) == 0) {
+ if(_alpm_lstat(path, &st) == 0) {
if(!S_ISDIR(st.st_mode)) {
if(!unlink(path)) {
return(0);
@@ -345,12 +478,12 @@ int _alpm_rmrf(const char *path)
return(0);
}
-int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *str)
+int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *fmt, va_list args)
{
- _alpm_log(PM_LOG_DEBUG, _("logaction called: %s"), str);
+ int ret = 0;
if(usesyslog) {
- syslog(LOG_WARNING, "%s", str);
+ vsyslog(LOG_WARNING, fmt, args);
}
if(f) {
@@ -361,14 +494,14 @@ int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *str)
tm = localtime(&t);
/* Use ISO-8601 date format */
- fprintf(f, "[%04d-%02d-%02d %02d:%02d] %s\n",
- tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, str);
-
+ fprintf(f, "[%04d-%02d-%02d %02d:%02d] ",
+ tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min);
+ ret = vfprintf(f, fmt, args);
fflush(f);
}
- return(0);
+ return(ret);
}
int _alpm_ldconfig(const char *root)
@@ -389,272 +522,141 @@ int _alpm_ldconfig(const char *root)
return(0);
}
-/* A cheap grep for text files, returns 1 if a substring
- * was found in the text file fn, 0 if it wasn't
- */
-static int grep(const char *fn, const char *needle)
+/* Helper function for comparing strings using the
+ * alpm "compare func" signature */
+int _alpm_str_cmp(const void *s1, const void *s2)
{
- FILE *fp;
-
- if((fp = fopen(fn, "r")) == NULL) {
- return(0);
- }
- while(!feof(fp)) {
- char line[1024];
- fgets(line, 1024, fp);
- if(feof(fp)) {
- continue;
- }
- if(strstr(line, needle)) {
- fclose(fp);
- return(1);
- }
- }
- fclose(fp);
- return(0);
+ return(strcmp(s1, s2));
}
-int _alpm_runscriptlet(const char *root, const char *installfn,
- const char *script, const char *ver,
- const char *oldver, pmtrans_t *trans)
+/** Find a package file in an alpm cachedir.
+ * @param filename name of package file to find
+ * @return malloced path of file, NULL if not found
+ */
+char *_alpm_filecache_find(const char* filename)
{
- char scriptfn[PATH_MAX];
- char cmdline[PATH_MAX];
- char tmpdir[PATH_MAX] = "";
- char *scriptpath;
struct stat buf;
- char cwd[PATH_MAX] = "";
- pid_t pid;
- int retval = 0;
-
- ALPM_LOG_FUNC;
-
- if(stat(installfn, &buf)) {
- /* not found */
- _alpm_log(PM_LOG_DEBUG, "scriptlet '%s' not found", installfn);
- return(0);
- }
+ char path[PATH_MAX];
+ char *retpath;
+ alpm_list_t *i;
- if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) {
- snprintf(tmpdir, PATH_MAX, "%stmp/", root);
- if(stat(tmpdir, &buf)) {
- _alpm_makepath(tmpdir);
+ /* Loop through the cache dirs until we find a matching file */
+ for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) {
+ snprintf(path, PATH_MAX, "%s%s", (char*)alpm_list_getdata(i),
+ filename);
+ if(stat(path, &buf) == 0) {
+ /* TODO maybe check to make sure it is readable? */
+ retpath = strdup(path);
+ _alpm_log(PM_LOG_DEBUG, "found cached pkg: %s\n", retpath);
+ return(retpath);
}
- snprintf(tmpdir, PATH_MAX, "%stmp/alpm_XXXXXX", root);
- if(mkdtemp(tmpdir) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not create temp directory"));
- return(1);
- }
- _alpm_unpack(installfn, tmpdir, ".INSTALL");
- snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir);
- /* chop off the root so we can find the tmpdir in the chroot */
- scriptpath = scriptfn + strlen(root) - 1;
- } else {
- STRNCPY(scriptfn, installfn, PATH_MAX);
- /* chop off the root so we can find the tmpdir in the chroot */
- scriptpath = scriptfn + strlen(root) - 1;
- }
-
- if(!grep(scriptfn, script)) {
- /* script not found in scriptlet file */
- goto cleanup;
- }
-
- /* save the cwd so we can restore it later */
- if(getcwd(cwd, PATH_MAX) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not get current working directory"));
- /* in case of error, cwd content is undefined: so we set it to something */
- cwd[0] = 0;
- }
-
- /* just in case our cwd was removed in the upgrade operation */
- if(chdir(root) != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)"), root, strerror(errno));
- goto cleanup;
- }
-
- _alpm_log(PM_LOG_DEBUG, _("executing %s script..."), script);
-
- if(oldver) {
- snprintf(cmdline, PATH_MAX, "source %s %s %s %s",
- scriptpath, script, ver, oldver);
- } else {
- snprintf(cmdline, PATH_MAX, "source %s %s %s",
- scriptpath, script, ver);
- }
- _alpm_log(PM_LOG_DEBUG, "%s", cmdline);
-
- pid = fork();
- if(pid == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)"), strerror(errno));
- retval = 1;
- goto cleanup;
}
+ /* package wasn't found in any cachedir */
+ return(NULL);
+}
- 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));
- return(1);
- }
- if(chdir("/") != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change directory to / (%s)"), strerror(errno));
- return(1);
- }
- umask(0022);
- _alpm_log(PM_LOG_DEBUG, _("executing \"%s\""), cmdline);
- 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;
- /*TODO clean this code up, remove weird SCRIPTLET_START/DONE,
- * (void*)atol call, etc. */
- /* "START <event desc>" */
- if((strlen(line) > strlen(SCRIPTLET_START))
- && !strncmp(line, SCRIPTLET_START, strlen(SCRIPTLET_START))) {
- EVENT(trans, PM_TRANS_EVT_SCRIPTLET_START,
- _alpm_strtrim(line + strlen(SCRIPTLET_START)), NULL);
- /* "DONE <ret code>" */
- } else if((strlen(line) > strlen(SCRIPTLET_DONE))
- && !strncmp(line, SCRIPTLET_DONE, strlen(SCRIPTLET_DONE))) {
- EVENT(trans, PM_TRANS_EVT_SCRIPTLET_DONE,
- (void*)atol(_alpm_strtrim(line + strlen(SCRIPTLET_DONE))),
- NULL);
- } else {
- _alpm_strtrim(line);
- /* log our script output */
- alpm_logaction(line);
- EVENT(trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL);
+/** Check the alpm cachedirs for existance and find a writable one.
+ * If no valid cache directory can be found, use /tmp.
+ * @return pointer to a writable cache directory.
+ */
+const char *_alpm_filecache_setup(void)
+{
+ struct stat buf;
+ alpm_list_t *i, *tmp;
+ char *cachedir;
+
+ /* Loop through the cache dirs until we find a writeable dir */
+ for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) {
+ cachedir = alpm_list_getdata(i);
+ if(stat(cachedir, &buf) != 0) {
+ /* cache directory does not exist.... try creating it */
+ _alpm_log(PM_LOG_WARNING, _("no %s cache exists, creating...\n"),
+ cachedir);
+ alpm_logaction("warning: no %s cache exists, creating...\n",
+ cachedir);
+ if(_alpm_makepath(cachedir) == 0) {
+ _alpm_log(PM_LOG_DEBUG, "using cachedir: %s\n", cachedir);
+ return(cachedir);
}
- }
- pclose(pp);
- exit(0);
- } else {
- if(waitpid(pid, 0, 0) == -1) {
- _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)"),
- strerror(errno));
- retval = 1;
- goto cleanup;
+ } else if(S_ISDIR(buf.st_mode) && (buf.st_mode & S_IWUSR)) {
+ _alpm_log(PM_LOG_DEBUG, "using cachedir: %s\n", cachedir);
+ return(cachedir);
}
}
-cleanup:
- if(strlen(tmpdir) && _alpm_rmrf(tmpdir)) {
- _alpm_log(PM_LOG_WARNING, _("could not remove tmpdir %s"), tmpdir);
- }
- if(strlen(cwd)) {
- chdir(cwd);
- }
-
- return(retval);
+ /* we didn't find a valid cache directory. use /tmp. */
+ i = alpm_option_get_cachedirs();
+ tmp = alpm_list_add(NULL, strdup("/tmp/"));
+ FREELIST(i);
+ alpm_option_set_cachedirs(tmp);
+ _alpm_log(PM_LOG_DEBUG, "using cachedir: %s", "/tmp/\n");
+ _alpm_log(PM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n"));
+ alpm_logaction("warning: couldn't create package cache, using /tmp instead\n");
+ return(alpm_list_getdata(tmp));
}
-#ifndef __sun__
-static long long get_freespace()
+/** lstat wrapper that treats /path/dirsymlink/ the same as /path/dirsymlink.
+ * Linux lstat follows POSIX semantics and still performs a dereference on
+ * the first, and for uses of lstat in libalpm this is not what we want.
+ * @param path path to file to lstat
+ * @param buf structure to fill with stat information
+ * @return the return code from lstat
+ */
+int _alpm_lstat(const char *path, struct stat *buf)
{
- struct mntent *mnt;
- const char *table = MOUNTED;
- FILE *fp;
- long long ret=0;
-
- if((fp = setmntent(table, "r")) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("cannot read disk space information from %s: %s"),
- table, strerror(errno));
- return(-1);
- }
-
- while ((mnt = getmntent(fp)))
- {
- struct statvfs64 buf;
+ int ret;
+ char *newpath = strdup(path);
+ int len = strlen(newpath);
- statvfs64(mnt->mnt_dir, &buf);
- ret += buf.f_bavail * buf.f_bsize;
+ /* strip the trailing slash if one exists */
+ if(len != 0 && newpath[len - 1] == '/') {
+ newpath[len - 1] = '\0';
}
- endmntent(fp);
+ ret = lstat(newpath, buf);
+ FREE(newpath);
return(ret);
}
-int _alpm_check_freespace(pmtrans_t *trans, alpm_list_t **data)
+/** Get the md5 sum of file.
+ * @param filename name of the file
+ * @return the checksum on success, NULL on error
+ * @addtogroup alpm_misc
+ */
+char SYMEXPORT *alpm_get_md5sum(const char *filename)
{
- alpm_list_t *i;
- long long pkgsize=0, freespace;
+ unsigned char output[16];
+ char *md5sum;
+ int ret, i;
ALPM_LOG_FUNC;
- 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 += alpm_pkg_get_isize(pkg);
- }
- }
- else
- {
- pmpkg_t *pkg = i->data;
- pkgsize += alpm_pkg_get_size(pkg);
- }
- }
- 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);
+ ASSERT(filename != NULL, return(NULL));
+
+ /* allocate 32 chars plus 1 for null */
+ md5sum = calloc(33, sizeof(char));
+ ret = md5_file(filename, output);
+
+ if (ret > 0) {
+ if (ret == 1) {
+ _alpm_log(PM_LOG_ERROR, _("md5: %s can't be opened\n"), filename);
+ } else if (ret == 2) {
+ _alpm_log(PM_LOG_ERROR, _("md5: %s can't be read\n"), filename);
}
- pm_errno = PM_ERR_DISK_FULL;
- return(-1);
- }
- else {
- return(0);
+
+ return(NULL);
}
-}
-#endif
-/* convert a time_t to a string - buffer MUST be large enough for
- * YYYYMMDDHHMMSS - 15 chars */
-void _alpm_time2string(time_t t, char *buffer)
-{
- if(buffer) {
- struct tm *lt;
- lt = localtime(&t);
- sprintf(buffer, "%4d%02d%02d%02d%02d%02d",
- lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
- lt->tm_hour, lt->tm_min, lt->tm_sec);
- buffer[14] = '\0';
+ /* Convert the result to something readable */
+ for (i = 0; i < 16; i++) {
+ /* sprintf is acceptable here because we know our output */
+ sprintf(md5sum +(i * 2), "%02x", output[i]);
}
-}
+ md5sum[32] = '\0';
-/* Helper function for comparing strings using the
- * alpm "compare func" signature */
-int _alpm_str_cmp(const void *s1, const void *s2)
-{
- return(strcmp(s1, s2));
+ _alpm_log(PM_LOG_DEBUG, "md5(%s) = %s\n", filename, md5sum);
+ return(md5sum);
}
-
/* vim: set ts=2 sw=2 noet: */