diff options
author | Dan McGee <dan@archlinux.org> | 2011-10-26 15:51:46 -0500 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2011-11-01 10:27:31 -0500 |
commit | 6df558177fac6bdcbd60de05038d6e6b7f224bd3 (patch) | |
tree | 43c923054e9f8fff09fb29f063a68040c8d3dd6a /lib/libalpm/be_package.c | |
parent | ed3cd7573600bf8be2bda01ad75da8bae2f589fb (diff) | |
download | pacman-6df558177fac6bdcbd60de05038d6e6b7f224bd3.tar.xz |
Convert package and database archive reads to use file descriptors
This gives us a bit more control and over the archive reading process,
and a bit less is done behind the scenes. It also allows us to use
fstat() in preference to stat(), which should avoid some potential race
conditions.
Some reorganization is necessary to move the stat calls after the open()
calls. Error handling and cleanup in general is also improved, as we had
several potential memory and file handle leaks before in some error
paths.
Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'lib/libalpm/be_package.c')
-rw-r--r-- | lib/libalpm/be_package.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 4d9d0e82..90a19722 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -23,6 +23,9 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> /* libarchive */ #include <archive.h> @@ -355,7 +358,7 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle, alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, int full) { - int ret, config = 0; + int ret, fd, config = 0; struct archive *archive; struct archive_entry *entry; alpm_pkg_t *newpkg = NULL; @@ -367,34 +370,41 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL); } - /* attempt to stat the package file, ensure it exists */ - if(stat(pkgfile, &st) == 0) { - newpkg = _alpm_pkg_new(); - if(newpkg == NULL) { - RET_ERR(handle, ALPM_ERR_MEMORY, NULL); - } - newpkg->filename = strdup(pkgfile); - newpkg->size = st.st_size; - } else { - /* couldn't stat the pkgfile, return an error */ - RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, NULL); - } - /* try to create an archive object to read in the package */ if((archive = archive_read_new()) == NULL) { - alpm_pkg_free(newpkg); RET_ERR(handle, ALPM_ERR_LIBARCHIVE, NULL); } archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - if(archive_read_open_filename(archive, pkgfile, + OPEN(fd, pkgfile, O_RDONLY); + if(fd < 0 || archive_read_open_fd(archive, fd, ALPM_BUFFER_SIZE) != ARCHIVE_OK) { - alpm_pkg_free(newpkg); - RET_ERR(handle, ALPM_ERR_PKG_OPEN, NULL); + const char *err = fd < 0 ? strerror(errno) : archive_error_string(archive); + _alpm_log(handle, ALPM_LOG_ERROR, + _("could not open file %s: %s\n"), pkgfile, err); + if(fd < 0 && errno == ENOENT) { + handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND; + } else { + handle->pm_errno = ALPM_ERR_PKG_OPEN; + } + goto error; } + newpkg = _alpm_pkg_new(); + if(newpkg == NULL) { + handle->pm_errno = ALPM_ERR_MEMORY; + goto error; + } + if(fstat(fd, &st) != 0) { + handle->pm_errno = ALPM_ERR_PKG_OPEN; + goto error; + } + STRDUP(newpkg->filename, pkgfile, + handle->pm_errno = ALPM_ERR_MEMORY; goto error); + newpkg->size = st.st_size; + _alpm_log(handle, ALPM_LOG_DEBUG, "starting package load for %s\n", pkgfile); /* If full is false, only read through the archive until we find our needed @@ -476,6 +486,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, } archive_read_finish(archive); + CLOSE(fd); /* internal fields for package struct */ newpkg->origin = PKG_FROM_FILE; @@ -504,6 +515,9 @@ pkg_invalid: error: _alpm_pkg_free(newpkg); archive_read_finish(archive); + if(fd >= 0) { + CLOSE(fd); + } return NULL; } |