index : pacman | |
Archlinux32 fork of pacman | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | lib/libalpm/util.c | 470 |
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 430da92a..adb1d192 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -53,10 +53,10 @@ /* libalpm */ #include "util.h" #include "log.h" -#include "package.h" #include "alpm.h" #include "alpm_list.h" #include "handle.h" +#include "trans.h" #ifndef HAVE_STRSEP /* This is a replacement for strsep which is not portable (missing on Solaris). @@ -65,14 +65,14 @@ char* strsep(char** str, const char* delims) { char* token; - if (*str==NULL) { + if(*str==NULL) { /* No more tokens */ return NULL; } token=*str; - while (**str!='\0') { - if (strchr(delims,**str)!=NULL) { + while(**str!='\0') { + if(strchr(delims,**str)!=NULL) { **str='\0'; (*str)++; return token; @@ -87,7 +87,7 @@ char* strsep(char** str, const char* delims) int _alpm_makepath(const char *path) { - return(_alpm_makepath_mode(path, 0755)); + return _alpm_makepath_mode(path, 0755); } /* does the same thing as 'mkdir -p' */ @@ -123,7 +123,7 @@ int _alpm_makepath_mode(const char *path, mode_t mode) free(orig); free(incr); umask(oldmask); - return(ret); + return ret; } #define CPBUFSIZE 8 * 1024 @@ -137,12 +137,12 @@ int _alpm_copyfile(const char *src, const char *dest) in = fopen(src, "rb"); if(in == NULL) { - return(1); + return 1; } out = fopen(dest, "wb"); if(out == NULL) { fclose(in); - return(1); + return 1; } CALLOC(buf, (size_t)CPBUFSIZE, (size_t)1, ret = 1; goto cleanup;); @@ -152,9 +152,6 @@ int _alpm_copyfile(const char *src, const char *dest) size_t nwritten = 0; nwritten = fwrite(buf, 1, len, out); if((nwritten != len) || ferror(out)) { - pm_errno = PM_ERR_WRITE; - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - dest, strerror(errno)); ret = -1; goto cleanup; } @@ -175,7 +172,7 @@ cleanup: fclose(in); fclose(out); FREE(buf); - return(ret); + return ret; } /* Trim whitespace and newlines from a string @@ -186,7 +183,7 @@ char *_alpm_strtrim(char *str) if(*str == '\0') { /* string is empty, so we're done. */ - return(str); + return str; } while(isspace((unsigned char)*pch)) { @@ -198,7 +195,7 @@ char *_alpm_strtrim(char *str) /* check if there wasn't anything but whitespace in the string. */ if(*str == '\0') { - return(str); + return str; } pch = (str + (strlen(str) - 1)); @@ -207,7 +204,27 @@ char *_alpm_strtrim(char *str) } *++pch = '\0'; - return(str); + return str; +} + +/** + * Trim trailing newline from a string (if one exists). + * @param str a single line of text + * @return the length of the trimmed string + */ +size_t _alpm_strip_newline(char *str) +{ + size_t len; + if(str == '\0') { + return 0; + } + len = strlen(str); + while(len > 0 && str[len - 1] == '\n') { + len--; + } + str[len] = '\0'; + + return len; } /* Compression functions */ @@ -215,36 +232,39 @@ char *_alpm_strtrim(char *str) /** * @brief Unpack a specific file 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 + * @param handle the context handle + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param filename a file within the archive to unpack * @return 0 on success, 1 on failure */ -int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn) +int _alpm_unpack_single(alpm_handle_t *handle, const char *archive, + const char *prefix, const char *filename) { alpm_list_t *list = NULL; int ret = 0; - if(fn == NULL) { - return(1); + if(filename == NULL) { + return 1; } - list = alpm_list_add(list, (void *)fn); - ret = _alpm_unpack(archive, prefix, list, 1); + list = alpm_list_add(list, (void *)filename); + ret = _alpm_unpack(handle, archive, prefix, list, 1); alpm_list_free(list); - return(ret); + return ret; } /** * @brief Unpack a list of files in an archive. * - * @param archive the archive to unpack - * @param prefix where to extract the files - * @param list a list of files within the archive to unpack or - * NULL for all + * @param handle the context handle + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param list a list of files within the archive to unpack or NULL for all * @param breakfirst break after the first entry found * * @return 0 on success, 1 on failure */ -int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst) +int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, + alpm_list_t *list, int breakfirst) { int ret = 0; mode_t oldmask; @@ -253,33 +273,33 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int char cwd[PATH_MAX]; int restore_cwd = 0; - ALPM_LOG_FUNC; - - if((_archive = archive_read_new()) == NULL) - RET_ERR(PM_ERR_LIBARCHIVE, 1); + if((_archive = archive_read_new()) == NULL) { + RET_ERR(handle, ALPM_ERR_LIBARCHIVE, 1); + } archive_read_support_compression_all(_archive); archive_read_support_format_all(_archive); if(archive_read_open_filename(_archive, archive, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), archive, + _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), archive, archive_error_string(_archive)); - RET_ERR(PM_ERR_PKG_OPEN, 1); + RET_ERR(handle, ALPM_ERR_PKG_OPEN, 1); } oldmask = umask(0022); /* 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\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* just in case our cwd was removed in the upgrade operation */ if(chdir(prefix) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), prefix, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + prefix, strerror(errno)); ret = 1; goto cleanup; } @@ -299,21 +319,21 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int /* If specific files were requested, skip entries that don't match. */ if(list) { - char *prefix = strdup(entryname); - char *p = strstr(prefix,"/"); + char *entry_prefix = strdup(entryname); + char *p = strstr(entry_prefix,"/"); if(p) { *(p+1) = '\0'; } - char *found = alpm_list_find_str(list, prefix); - free(prefix); + char *found = alpm_list_find_str(list, entry_prefix); + free(entry_prefix); if(!found) { - if (archive_read_data_skip(_archive) != ARCHIVE_OK) { + if(archive_read_data_skip(_archive) != ARCHIVE_OK) { ret = 1; goto cleanup; } continue; } else { - _alpm_log(PM_LOG_DEBUG, "extracting: %s\n", entryname); + _alpm_log(handle, ALPM_LOG_DEBUG, "extracting: %s\n", entryname); } } @@ -321,10 +341,10 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int 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_WARNING, _("warning given when extracting %s (%s)\n"), + _alpm_log(handle, ALPM_LOG_WARNING, _("warning given when 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"), + _alpm_log(handle, ALPM_LOG_ERROR, _("could not extract %s (%s)\n"), entryname, archive_error_string(_archive)); ret = 1; goto cleanup; @@ -339,9 +359,10 @@ cleanup: umask(oldmask); archive_read_finish(_archive); if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + cwd, strerror(errno)); } - return(ret); + return ret; } /* does the same thing as 'rm -rf' */ @@ -356,18 +377,18 @@ int _alpm_rmrf(const char *path) if(_alpm_lstat(path, &st) == 0) { if(!S_ISDIR(st.st_mode)) { if(!unlink(path)) { - return(0); + return 0; } else { if(errno == ENOENT) { - return(0); + return 0; } else { - return(1); + return 1; } } } else { dirp = opendir(path); if(!dirp) { - return(1); + return 1; } for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { if(dp->d_ino) { @@ -382,16 +403,58 @@ int _alpm_rmrf(const char *path) errflag++; } } - return(errflag); + return errflag; } - return(0); + return 0; } -int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) +/** + * Determine if there are files in a directory + * @param handle the context handle + * @param path the full absolute directory path + * @param full_count whether to return an exact count of files + * @return a file count if full_count is != 0, else >0 if directory has + * contents, 0 if no contents, and -1 on error + */ +ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, + int full_count) +{ + ssize_t files = 0; + struct dirent *ent; + DIR *dir = opendir(path); + + if(!dir) { + if(errno == ENOTDIR) { + _alpm_log(handle, ALPM_LOG_DEBUG, "%s was not a directory\n", path); + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, "could not read directory %s\n", + path); + } + return -1; + } + while((ent = readdir(dir)) != NULL) { + const char *name = ent->d_name; + + if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + continue; + } + + files++; + + if(!full_count) { + break; + } + } + + closedir(dir); + return files; +} + +int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args) { int ret = 0; - if(usesyslog) { + if(handle->usesyslog) { /* we can't use a va_list more than once, so we need to copy it * so we can use the original when calling vfprintf below. */ va_list args_syslog; @@ -400,7 +463,7 @@ int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) va_end(args_syslog); } - if(f) { + if(handle->logstream) { time_t t; struct tm *tm; @@ -408,17 +471,17 @@ int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) tm = localtime(&t); /* Use ISO-8601 date format */ - fprintf(f, "[%04d-%02d-%02d %02d:%02d] ", + fprintf(handle->logstream, "[%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); + ret = vfprintf(handle->logstream, fmt, args); + fflush(handle->logstream); } - return(ret); + return ret; } -int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) +int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]) { char cwd[PATH_MAX]; pid_t pid; @@ -426,28 +489,28 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) int restore_cwd = 0; int retval = 0; - ALPM_LOG_FUNC; - /* 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\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* 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)\n"), root, strerror(errno)); + if(chdir(handle->root) != 0) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + handle->root, strerror(errno)); goto cleanup; } - _alpm_log(PM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", path, root); + _alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", + path, handle->root); /* Flush open fds before fork() to avoid cloning buffers */ fflush(NULL); if(pipe(pipefd) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -455,7 +518,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) /* fork- parent and child each have seperate code blocks below */ pid = fork(); if(pid == -1) { - _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not fork a new process (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -470,7 +533,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) close(pipefd[1]); /* use fprintf instead of _alpm_log to send output through the parent */ - if(chroot(root) != 0) { + if(chroot(handle->root) != 0) { fprintf(stderr, _("could not change the root directory (%s)\n"), strerror(errno)); exit(1); } @@ -486,27 +549,27 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) } else { /* this code runs for the parent only (wait on the child) */ int status; - FILE *pipe; + FILE *pipe_file; close(pipefd[1]); - pipe = fdopen(pipefd[0], "r"); - if(pipe == NULL) { + pipe_file = fdopen(pipefd[0], "r"); + if(pipe_file == NULL) { close(pipefd[0]); retval = 1; } else { - while(!feof(pipe)) { + while(!feof(pipe_file)) { char line[PATH_MAX]; - if(fgets(line, PATH_MAX, pipe) == NULL) + if(fgets(line, PATH_MAX, pipe_file) == NULL) break; - alpm_logaction("%s", line); - EVENT(handle->trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL); + alpm_logaction(handle, "%s", line); + EVENT(handle->trans, ALPM_TRANS_EVT_SCRIPTLET_INFO, line, NULL); } - fclose(pipe); + fclose(pipe_file); } while(waitpid(pid, &status, 0) == -1) { if(errno != EINTR) { - _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -514,14 +577,14 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) /* report error from above after the child has exited */ if(retval != 0) { - _alpm_log(PM_LOG_ERROR, _("could not open pipe (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not open pipe (%s)\n"), strerror(errno)); goto cleanup; } /* check the return status, make sure it is 0 (success) */ if(WIFEXITED(status)) { - _alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "call to waitpid succeeded\n"); if(WEXITSTATUS(status) != 0) { - _alpm_log(PM_LOG_ERROR, _("command failed to execute correctly\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("command failed to execute correctly\n")); retval = 1; } } @@ -529,42 +592,43 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) cleanup: if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); } - return(retval); + return retval; } -int _alpm_ldconfig(const char *root) +int _alpm_ldconfig(alpm_handle_t *handle) { char line[PATH_MAX]; - _alpm_log(PM_LOG_DEBUG, "running ldconfig\n"); + _alpm_log(handle, ALPM_LOG_DEBUG, "running ldconfig\n"); - snprintf(line, PATH_MAX, "%setc/ld.so.conf", root); + snprintf(line, PATH_MAX, "%setc/ld.so.conf", handle->root); if(access(line, F_OK) == 0) { - snprintf(line, PATH_MAX, "%ssbin/ldconfig", root); + snprintf(line, PATH_MAX, "%ssbin/ldconfig", handle->root); if(access(line, X_OK) == 0) { char *argv[] = { "ldconfig", NULL }; - _alpm_run_chroot(root, "/sbin/ldconfig", argv); + _alpm_run_chroot(handle, "/sbin/ldconfig", argv); } } - return(0); + return 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)); + return strcmp(s1, s2); } /** Find a filename in a registered alpm cachedir. + * @param handle the context handle * @param filename name of file to find * @return malloced path of file, NULL if not found */ -char *_alpm_filecache_find(const char* filename) +char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename) { char path[PATH_MAX]; char *retpath; @@ -572,52 +636,56 @@ char *_alpm_filecache_find(const char* filename) struct stat buf; /* 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), + for(i = alpm_option_get_cachedirs(handle); i; i = alpm_list_next(i)) { + snprintf(path, PATH_MAX, "%s%s", (char *)alpm_list_getdata(i), filename); if(stat(path, &buf) == 0 && S_ISREG(buf.st_mode)) { retpath = strdup(path); - _alpm_log(PM_LOG_DEBUG, "found cached pkg: %s\n", retpath); - return(retpath); + _alpm_log(handle, ALPM_LOG_DEBUG, "found cached pkg: %s\n", retpath); + return retpath; } } /* package wasn't found in any cachedir */ - RET_ERR(PM_ERR_PKG_NOT_FOUND, NULL); + return NULL; } /** Check the alpm cachedirs for existance and find a writable one. * If no valid cache directory can be found, use /tmp. + * @param handle the context handle * @return pointer to a writable cache directory. */ -const char *_alpm_filecache_setup(void) +const char *_alpm_filecache_setup(alpm_handle_t *handle) { 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)) { + for(i = alpm_option_get_cachedirs(handle); 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"), + _alpm_log(handle, ALPM_LOG_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); + _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir); + return cachedir; } } else if(S_ISDIR(buf.st_mode) && (buf.st_mode & S_IWUSR)) { - _alpm_log(PM_LOG_DEBUG, "using cachedir: %s\n", cachedir); - return(cachedir); + _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir); + return cachedir; + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, "skipping cachedir: %s\n", cachedir); } } /* we didn't find a valid cache directory. use /tmp. */ - tmp = alpm_list_add(NULL, strdup("/tmp/")); - 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")); - return(alpm_list_getdata(tmp)); + tmp = alpm_list_add(NULL, "/tmp/"); + alpm_option_set_cachedirs(handle, tmp); + alpm_list_free(tmp); + _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", "/tmp/"); + _alpm_log(handle, ALPM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); + return "/tmp/"; } /** lstat wrapper that treats /path/dirsymlink/ the same as /path/dirsymlink. @@ -630,18 +698,19 @@ const char *_alpm_filecache_setup(void) int _alpm_lstat(const char *path, struct stat *buf) { int ret; - char *newpath = strdup(path); - size_t len = strlen(newpath); + size_t len = strlen(path); /* strip the trailing slash if one exists */ - if(len != 0 && newpath[len - 1] == '/') { - newpath[len - 1] = '\0'; + if(len != 0 && path[len - 1] == '/') { + char *newpath = strdup(path); + newpath[len - 1] = '\0'; + ret = lstat(newpath, buf); + free(newpath); + } else { + ret = lstat(path, buf); } - ret = lstat(newpath, buf); - - FREE(newpath); - return(ret); + return ret; } #ifdef HAVE_LIBSSL @@ -652,11 +721,11 @@ static int md5_file(const char *path, unsigned char output[16]) MD5_CTX ctx; unsigned char *buf; - CALLOC(buf, 8192, sizeof(unsigned char), return(1)); + CALLOC(buf, 8192, sizeof(unsigned char), return 1); if((f = fopen(path, "rb")) == NULL) { free(buf); - return(1); + return 1; } MD5_Init(&ctx); @@ -672,11 +741,11 @@ static int md5_file(const char *path, unsigned char output[16]) if(ferror(f) != 0) { fclose(f); - return(2); + return 2; } fclose(f); - return(0); + return 0; } #endif @@ -691,17 +760,15 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename) char *md5sum; int ret, i; - ALPM_LOG_FUNC; - - ASSERT(filename != NULL, return(NULL)); + ASSERT(filename != NULL, return NULL); /* allocate 32 chars plus 1 for null */ - md5sum = calloc(33, sizeof(char)); + CALLOC(md5sum, 33, sizeof(char), return NULL); /* defined above for OpenSSL, otherwise defined in md5.h */ ret = md5_file(filename, output); - if (ret > 0) { - RET_ERR(PM_ERR_NOT_A_FILE, NULL); + if(ret > 0) { + return NULL; } /* Convert the result to something readable */ @@ -709,10 +776,8 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename) /* sprintf is acceptable here because we know our output */ sprintf(md5sum +(i * 2), "%02x", output[i]); } - md5sum[32] = '\0'; - _alpm_log(PM_LOG_DEBUG, "md5(%s) = %s\n", filename, md5sum); - return(md5sum); + return md5sum; } int _alpm_test_md5sum(const char *filepath, const char *md5sum) @@ -731,7 +796,7 @@ int _alpm_test_md5sum(const char *filepath, const char *md5sum) } FREE(md5sum2); - return(ret); + return ret; } /* Note: does NOT handle sparse files on purpose for speed. */ @@ -753,13 +818,12 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) } /* zero-copy - this is the entire next block of data. */ - b->ret = archive_read_data_block(a, (void*)&b->block, + b->ret = archive_read_data_block(a, (void *)&b->block, &b->block_size, &offset); b->block_offset = b->block; - /* error or end of archive with no data read, cleanup */ - if(b->ret < ARCHIVE_OK || - (b->block_size == 0 && b->ret == ARCHIVE_EOF)) { + /* error, cleanup */ + if(b->ret < ARCHIVE_OK) { goto cleanup; } } @@ -776,20 +840,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) /* allocate our buffer, or ensure our existing one is big enough */ if(!b->line) { /* set the initial buffer to the read block_size */ - CALLOC(b->line, b->block_size + 1, sizeof(char), - RET_ERR(PM_ERR_MEMORY, -1)); + CALLOC(b->line, b->block_size + 1, sizeof(char), b->ret = -ENOMEM; goto cleanup); b->line_size = b->block_size + 1; b->line_offset = b->line; } else { size_t needed = (size_t)((b->line_offset - b->line) + (i - b->block_offset) + 1); if(needed > b->max_line_size) { - RET_ERR(PM_ERR_MEMORY, -1); + b->ret = -ERANGE; + goto cleanup; } if(needed > b->line_size) { /* need to realloc + copy data to fit total length */ char *new; - CALLOC(new, needed, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); + CALLOC(new, needed, sizeof(char), b->ret = -ENOMEM; goto cleanup); memcpy(new, b->line, b->line_size); b->line_size = needed; b->line_offset = new + (b->line_offset - b->line); @@ -804,13 +868,19 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) b->line_offset[len] = '\0'; b->block_offset = ++i; /* this is the main return point; from here you can read b->line */ - return(ARCHIVE_OK); + return ARCHIVE_OK; } else { /* we've looked through the whole block but no newline, copy it */ size_t len = (size_t)(b->block + b->block_size - b->block_offset); memcpy(b->line_offset, b->block_offset, len); b->line_offset += len; b->block_offset = i; + /* there was no new data, return what is left; saved ARCHIVE_EOF will be + * returned on next call */ + if(len == 0) { + b->line_offset[0] = '\0'; + return ARCHIVE_OK; + } } } @@ -819,53 +889,60 @@ cleanup: int ret = b->ret; FREE(b->line); memset(b, 0, sizeof(b)); - return(ret); + return ret; } } -int _alpm_splitname(const char *target, pmpkg_t *pkg) +int _alpm_splitname(const char *target, char **name, char **version, + unsigned long *name_hash) { /* the format of a db entry is as follows: * package-version-rel/ + * package-version-rel/desc (we ignore the filename portion) * package name can contain hyphens, so parse from the back- go back * two hyphens and we have split the version from the name. */ - const char *version, *end; + const char *pkgver, *end; - if(target == NULL || pkg == NULL) { - return(-1); + if(target == NULL) { + return -1; } - end = target + strlen(target); - /* remove any trailing '/' */ - while (*(end - 1) == '/') { - --end; + /* remove anything trailing a '/' */ + end = strchr(target, '/'); + if(!end) { + end = target + strlen(target); } /* do the magic parsing- find the beginning of the version string * by doing two iterations of same loop to lop off two hyphens */ - for(version = end - 1; *version && *version != '-'; version--); - for(version = version - 1; *version && *version != '-'; version--); - if(*version != '-' || version == target) { - return(-1); + for(pkgver = end - 1; *pkgver && *pkgver != '-'; pkgver--); + for(pkgver = pkgver - 1; *pkgver && *pkgver != '-'; pkgver--); + if(*pkgver != '-' || pkgver == target) { + return -1; } /* copy into fields and return */ - if(pkg->version) { - FREE(pkg->version); + if(version) { + if(*version) { + FREE(*version); + } + /* version actually points to the dash, so need to increment 1 and account + * for potential end character */ + STRNDUP(*version, pkgver + 1, end - pkgver - 1, return -1); } - /* version actually points to the dash, so need to increment 1 and account - * for potential end character */ - STRNDUP(pkg->version, version + 1, end - version - 1, - RET_ERR(PM_ERR_MEMORY, -1)); - if(pkg->name) { - FREE(pkg->name); + if(name) { + if(*name) { + FREE(*name); + } + STRNDUP(*name, target, pkgver - target, return -1); + if(name_hash) { + *name_hash = _alpm_hash_sdbm(*name); + } } - STRNDUP(pkg->name, target, version - target, RET_ERR(PM_ERR_MEMORY, -1)); - pkg->name_hash = _alpm_hash_sdbm(pkg->name); - return(0); + return 0; } /** @@ -880,13 +957,13 @@ unsigned long _alpm_hash_sdbm(const char *str) int c; if(!str) { - return(hash); + return hash; } while((c = *str++)) { hash = c + (hash << 6) + (hash << 16) - hash; } - return(hash); + return hash; } long _alpm_parsedate(const char *line) @@ -897,9 +974,60 @@ long _alpm_parsedate(const char *line) setlocale(LC_TIME, "C"); strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm); setlocale(LC_TIME, ""); - return(mktime(&tmp_tm)); + return mktime(&tmp_tm); + } + return atol(line); +} + +/** + * Wrapper around access() which takes a dir and file argument + * separately and generates an appropriate error message. + * If dir is NULL file will be treated as the whole path. + * @param handle an alpm handle + * @param dir directory path ending with and slash + * @param file filename + * @param amode access mode as described in access() + * @return int value returned by access() + */ + +int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode) +{ + size_t len = 0; + int ret = 0; + + if (dir) { + char *check_path; + + len = strlen(dir) + strlen(file) + 1; + CALLOC(check_path, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + snprintf(check_path, len, "%s%s", dir, file); + + ret = access(check_path, amode); + free(check_path); + } else { + dir = ""; + ret = access(file, amode); + } + + if(ret != 0) { + if (amode & R_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not readable: %s\n", + dir, file, strerror(errno)); + } + if (amode & W_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not writable: %s\n", + dir, file, strerror(errno)); + } + if (amode & X_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not executable: %s\n", + dir, file, strerror(errno)); + } + if (amode == F_OK) { + _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" does not exist: %s\n", + dir, file, strerror(errno)); + } } - return(atol(line)); + return ret; } #ifndef HAVE_STRNDUP @@ -908,7 +1036,7 @@ static size_t strnlen(const char *s, size_t max) { register const char *p; for(p = s; *p && max--; ++p); - return(p - s); + return (p - s); } char *strndup(const char *s, size_t n) @@ -916,11 +1044,11 @@ char *strndup(const char *s, size_t n) size_t len = strnlen(s, n); char *new = (char *) malloc(len + 1); - if (new == NULL) + if(new == NULL) return NULL; new[len] = '\0'; - return (char *) memcpy(new, s, len); + return (char *)memcpy(new, s, len); } #endif |