/** Open an archive for reading and perform the necessary boilerplate. * This takes care of creating the libarchive 'archive' struct, setting up * compression and format options, opening a file descriptor, setting up the * buffer size, and performing a stat on the path once opened. * On error, no file descriptor is opened, and the archive pointer returned * will be set to NULL. * @param handle the context handle * @param path the path of the archive to open * @param buf space for a stat buffer for the given path * @param archive pointer to place the created archive object * @param error error code to set on failure to open archive * @return -1 on failure, >=0 file descriptor on success */ int _alpm_open_archive(alpm_handle_t *handle, const char *path, struct stat *buf, struct archive **archive, alpm_errno_t error) { int fd; size_t bufsize = ALPM_BUFFER_SIZE; errno = 0; if((*archive = archive_read_new()) == NULL) { RET_ERR(handle, ALPM_ERR_LIBARCHIVE, -1); } _alpm_archive_read_support_filter_all(*archive); archive_read_support_format_all(*archive); _alpm_log(handle, ALPM_LOG_DEBUG, "opening archive %s\n", path); OPEN(fd, path, O_RDONLY | O_CLOEXEC); if(fd < 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; } if(fstat(fd, buf) != 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not stat file %s: %s\n"), path, strerror(errno)); goto error; } #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE if(buf->st_blksize > ALPM_BUFFER_SIZE) { bufsize = buf->st_blksize; } #endif if(archive_read_open_fd(*archive, fd, bufsize) != ARCHIVE_OK) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), path, archive_error_string(*archive)); goto error; } return fd; error: _alpm_archive_read_free(*archive); *archive = NULL; if(fd >= 0) { close(fd); } RET_ERR(handle, error, -1); }
/** * Open a package mtree file for reading. * @param pkg the local package to read the changelog of * @return a archive structure for the package mtree file */ static struct archive *_cache_mtree_open(alpm_pkg_t *pkg) { int r; struct archive *mtree; alpm_db_t *db = alpm_pkg_get_db(pkg); char *mtfile = _alpm_local_db_pkgpath(db, pkg, "mtree"); if(access(mtfile, F_OK) != 0) { /* there is no mtree file for this package */ goto error; } if((mtree = archive_read_new()) == NULL) { pkg->handle->pm_errno = ALPM_ERR_LIBARCHIVE; goto error; } _alpm_archive_read_support_filter_all(mtree); archive_read_support_format_mtree(mtree); if((r = _alpm_archive_read_open_file(mtree, mtfile, ALPM_BUFFER_SIZE))) { _alpm_log(pkg->handle, ALPM_LOG_ERROR, _("error while reading file %s: %s\n"), mtfile, archive_error_string(mtree)); pkg->handle->pm_errno = ALPM_ERR_LIBARCHIVE; _alpm_archive_read_free(mtree); goto error; } free(mtfile); return mtree; error: free(mtfile); return NULL; }