diff options
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r-- | lib/libalpm/util.c | 134 |
1 files changed, 98 insertions, 36 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index e1413a25..55bd46a8 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -43,7 +43,6 @@ /* libalpm */ #include "util.h" #include "log.h" -#include "error.h" #include "package.h" #include "alpm.h" #include "alpm_list.h" @@ -186,57 +185,65 @@ int _alpm_makepath(const char *path) /* does the same thing as 'mkdir -p' */ int _alpm_makepath_mode(const char *path, mode_t mode) { - char *orig, *str, *ptr; - char full[PATH_MAX] = ""; - mode_t oldmask; - - oldmask = umask(0000); + /* A bit of pointer hell here. Descriptions: + * orig - a copy of path so we can safely butcher it with strsep + * str - the current position in the path string (after the delimiter) + * ptr - the original position of str after calling strsep + * incr - incrementally generated path for use in stat/mkdir call + */ + char *orig, *str, *ptr, *incr; + mode_t oldmask = umask(0000); + int ret = 0; orig = strdup(path); + incr = calloc(strlen(orig) + 1, sizeof(char)); str = orig; while((ptr = strsep(&str, "/"))) { if(strlen(ptr)) { struct stat buf; - - strcat(full, "/"); - strcat(full, ptr); - if(stat(full, &buf)) { - if(mkdir(full, mode)) { - FREE(orig); - umask(oldmask); - _alpm_log(PM_LOG_ERROR, _("failed to make path '%s' : %s\n"), - path, strerror(errno)); - return(1); + /* we have another path component- append the newest component to + * existing string and create one more level of dir structure */ + strcat(incr, "/"); + strcat(incr, ptr); + if(stat(incr, &buf)) { + if(mkdir(incr, mode)) { + ret = 1; + break; } } } } - FREE(orig); + free(orig); + free(incr); umask(oldmask); - return(0); + return(ret); } +#define CPBUFSIZE 8 * 1024 + int _alpm_copyfile(const char *src, const char *dest) { FILE *in, *out; size_t len; - char buf[4097]; + char *buf; + int ret = 0; - in = fopen(src, "r"); + in = fopen(src, "rb"); if(in == NULL) { return(1); } - out = fopen(dest, "w"); + out = fopen(dest, "wb"); if(out == NULL) { fclose(in); return(1); } + CALLOC(buf, (size_t)CPBUFSIZE, (size_t)1, ret = 1; goto cleanup;); + /* do the actual file copy */ - while((len = fread(buf, 1, 4096, in))) { + while((len = fread(buf, 1, CPBUFSIZE, in))) { fwrite(buf, 1, len, out); } - fclose(in); /* chmod dest to permissions of src, as long as it is not a symlink */ struct stat statbuf; @@ -246,12 +253,14 @@ int _alpm_copyfile(const char *src, const char *dest) } } else { /* stat was unsuccessful */ - fclose(out); - return(1); + ret = 1; } +cleanup: + fclose(in); fclose(out); - return(0); + FREE(buf); + return(ret); } /* Trim whitespace and newlines from a string @@ -371,6 +380,13 @@ int _alpm_lckrm() /* Compression functions */ +/** + * @brief Unpack a specific file or all files in an archive. + * + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param fn a file within the archive to unpack or NULL for all + */ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) { int ret = 1; @@ -382,7 +398,7 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) ALPM_LOG_FUNC; if((_archive = archive_read_new()) == NULL) - RET_ERR(PM_ERR_LIBARCHIVE_ERROR, -1); + RET_ERR(PM_ERR_LIBARCHIVE, -1); archive_read_support_compression_all(_archive); archive_read_support_format_all(_archive); @@ -408,13 +424,17 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) archive_entry_set_mode(entry, 0755); } + /* If a specific file was requested skip entries that don't match. */ if (fn && strcmp(fn, entryname)) { + _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname); if (archive_read_data_skip(_archive) != ARCHIVE_OK) { ret = 1; goto cleanup; } continue; } + + /* Extract the archive entry. */ ret = 0; snprintf(expath, PATH_MAX, "%s/%s", prefix, entryname); archive_entry_set_pathname(entry, expath); @@ -535,8 +555,8 @@ int _alpm_str_cmp(const void *s1, const void *s2) return(strcmp(s1, s2)); } -/** Find a package file in an alpm cachedir. - * @param filename name of package file to find +/** Find a filename in a registered alpm cachedir. + * @param filename name of file to find * @return malloced path of file, NULL if not found */ char *_alpm_filecache_find(const char* filename) @@ -640,13 +660,7 @@ char SYMEXPORT *alpm_get_md5sum(const char *filename) 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); - } - - return(NULL); + RET_ERR(PM_ERR_NOT_A_FILE, NULL); } /* Convert the result to something readable */ @@ -660,4 +674,52 @@ char SYMEXPORT *alpm_get_md5sum(const char *filename) return(md5sum); } +int _alpm_test_md5sum(const char *filepath, const char *md5sum) +{ + char *md5sum2; + int ret; + + md5sum2 = alpm_get_md5sum(filepath); + + if(md5sum == NULL || md5sum2 == NULL) { + ret = -1; + } else if(strcmp(md5sum, md5sum2) != 0) { + ret = 1; + } else { + ret = 0; + } + + FREE(md5sum2); + return(ret); +} + +char *_alpm_archive_fgets(char *line, size_t size, struct archive *a) +{ + /* for now, just read one char at a time until we get to a + * '\n' char. we can optimize this later with an internal + * buffer. */ + /* leave room for zero terminator */ + char *last = line + size - 1; + char *i; + + for(i = line; i < last; i++) { + int ret = archive_read_data(a, i, 1); + /* special check for first read- if null, return null, + * this indicates EOF */ + if(i == line && (ret <= 0 || *i == '\0')) { + return(NULL); + } + /* check if read value was null or newline */ + if(ret <= 0 || *i == '\0' || *i == '\n') { + last = i + 1; + break; + } + } + + /* always null terminate the buffer */ + *last = '\0'; + + return(line); +} + /* vim: set ts=2 sw=2 noet: */ |