diff options
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r-- | lib/libalpm/util.c | 670 |
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: */ |