index : pacman | |
Archlinux32 fork of pacman | gitolite user |
summaryrefslogtreecommitdiff |
author | Allan McRae <allan@archlinux.org> | 2010-11-16 16:30:33 +1000 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2010-12-12 20:29:54 -0600 |
commit | e527699dddca41e3af6c1872e851405a4f5212a0 (patch) | |
tree | 06d8af93ba766f99ab386f9d168289a4f7ca5846 /lib/libalpm/diskspace.c | |
parent | 695656d25279342f80c307035721ced6d37ee08b (diff) |
-rw-r--r-- | lib/libalpm/diskspace.c | 100 |
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 9d153fb4..919d1590 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -33,6 +33,12 @@ #include <sys/statvfs.h> #endif +#include <math.h> + +/* libarchive */ +#include <archive.h> +#include <archive_entry.h> + /* libalpm */ #include "diskspace.h" #include "alpm_list.h" @@ -152,6 +158,100 @@ static alpm_list_t *match_mount_point(const alpm_list_t *mount_points, const cha return NULL; } +static int calculate_removed_size(pmpkg_t *pkg, const alpm_list_t *mount_points) +{ + alpm_list_t *file; + + alpm_list_t *files = alpm_pkg_get_files(pkg); + for(file = files; file; file = file->next) { + alpm_list_t *mp; + alpm_mountpoint_t *data; + struct stat st; + char path[PATH_MAX]; + + /* skip directories to be consistent with libarchive that reports them to be zero size + and to prevent multiple counting across packages */ + if(*((char *)(file->data) + strlen(file->data) - 1) == '/') { + continue; + } + + mp = match_mount_point(mount_points, file->data); + if(mp == NULL) { + _alpm_log(PM_LOG_WARNING, _("could not determine mount point for file %s"), (char *)(file->data)); + continue; + } + + snprintf(path, PATH_MAX, "%s%s", handle->root, (char *)file->data); + _alpm_lstat(path, &st); + + /* skip symlinks to be consistent with libarchive that reports them to be zero size */ + if(S_ISLNK(st.st_mode)) { + continue; + } + + data = mp->data; + data->blocks_needed -= ceil((double)(st.st_size) / + (double)(data->fsp->f_bsize)); + data->used = 1; + } + + return 0; +} + +static int calculate_installed_size(pmpkg_t *pkg, const alpm_list_t *mount_points) +{ + int ret=0; + struct archive *archive; + struct archive_entry *entry; + const char *file; + + if ((archive = archive_read_new()) == NULL) { + pm_errno = PM_ERR_LIBARCHIVE; + ret = -1; + goto cleanup; + } + + archive_read_support_compression_all(archive); + archive_read_support_format_all(archive); + + if(archive_read_open_filename(archive, pkg->origin_data.file, + ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { + pm_errno = PM_ERR_PKG_OPEN; + ret = -1; + goto cleanup; + } + + while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { + alpm_list_t *mp; + alpm_mountpoint_t *data; + + file = archive_entry_pathname(entry); + + /* approximate space requirements for db entries */ + if(strcmp(file, ".PKGINFO") == 0 || + strcmp(file, ".INSTALL") == 0 || + strcmp(file, ".CHANGELOG") == 0) { + file = alpm_option_get_dbpath(); + } + + mp = match_mount_point(mount_points, file); + if(mp == NULL) { + _alpm_log(PM_LOG_WARNING, _("could not determine mount point for file %s"), archive_entry_pathname(entry)); + continue; + } + + data = mp->data; + data->blocks_needed += ceil((double)(archive_entry_size(entry)) / + (double)(data->fsp->f_bsize)); + data->used = 1; + } + + archive_read_finish(archive); + +cleanup: + return ret; +} + int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db) { alpm_list_t *mount_points; |