[pacman-dev] [PATCH] Skip diskspace checking for symlinks and directories in all cases
Dan McGee
dan at archlinux.org
Mon Feb 7 22:35:42 EST 2011
We did this in some but not all cases, assuming the 0 value coming out of
libarchive would not be a problem. However, this does not work for "fake"
filesystems such as rpc_pipefs, which reports a free block and total block
count of zero.
Fix this by not ever counting symlinks or directories, and adding a note
explaining that if we someday do count directories, their size needs to be
attributed to the proper place.
Signed-off-by: Dan McGee <dan at archlinux.org>
---
lib/libalpm/diskspace.c | 85 ++++++++++++++++++++++++-----------------------
lib/libalpm/diskspace.h | 1 +
2 files changed, 44 insertions(+), 42 deletions(-)
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index dfafdac..ae2edf7 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -54,7 +54,8 @@ static int mount_point_cmp(const void *p1, const void *p2)
{
const alpm_mountpoint_t *mp1 = p1;
const alpm_mountpoint_t *mp2 = p2;
- return(strcmp(mp1->mount_dir, mp2->mount_dir));
+ /* the negation will sort all mountpoints before their parent */
+ return(-strcmp(mp1->mount_dir, mp2->mount_dir));
}
static alpm_list_t *mount_point_list(void)
@@ -82,6 +83,7 @@ static alpm_list_t *mount_point_list(void)
MALLOC(mp, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL));
mp->mount_dir = strdup(mnt->mnt_dir);
+ mp->mount_dir_len = strlen(mnt->mnt_dir);
memcpy(&(mp->fsp), &fsp, sizeof(FSSTATSTYPE));
mp->blocks_needed = 0l;
@@ -105,6 +107,7 @@ static alpm_list_t *mount_point_list(void)
for(; entries-- > 0; fsp++) {
MALLOC(mp, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL));
mp->mount_dir = strdup(fsp->f_mntonname);
+ mp->mount_dir_len = strlen(mnt->mnt_dir);
memcpy(&(mp->fsp), fsp, sizeof(FSSTATSTYPE));
mp->blocks_needed = 0l;
@@ -120,22 +123,18 @@ static alpm_list_t *mount_point_list(void)
return(mount_points);
}
-static alpm_list_t *match_mount_point(const alpm_list_t *mount_points,
- const char *file)
+static alpm_mountpoint_t *match_mount_point(const alpm_list_t *mount_points,
+ const char *real_path)
{
- char real_path[PATH_MAX];
- snprintf(real_path, PATH_MAX, "%s%s", handle->root, file);
+ const alpm_list_t *mp;
- alpm_list_t *mp = alpm_list_last(mount_points);
- do {
+ for(mp = mount_points; mp != NULL; mp = mp->next) {
alpm_mountpoint_t *data = mp->data;
- if(strncmp(data->mount_dir, real_path, strlen(data->mount_dir)) == 0) {
- return(mp);
+ if(strncmp(data->mount_dir, real_path, data->mount_dir_len) == 0) {
+ return(data);
}
-
- mp = mp->prev;
- } while (mp != alpm_list_last(mount_points));
+ }
/* should not get here... */
return(NULL);
@@ -148,38 +147,30 @@ static int calculate_removed_size(const alpm_list_t *mount_points,
alpm_list_t *files = alpm_pkg_get_files(pkg);
for(file = files; file; file = file->next) {
- alpm_list_t *mp;
- alpm_mountpoint_t *data;
+ alpm_mountpoint_t *mp;
struct stat st;
char path[PATH_MAX];
const char *filename = file->data;
- /* skip directories to be consistent with libarchive that reports them
- * to be zero size and to prevent multiple counting across packages */
- if(*(filename + strlen(filename) - 1) == '/') {
+ snprintf(path, PATH_MAX, "%s%s", handle->root, filename);
+ _alpm_lstat(path, &st);
+
+ /* skip directories and symlinks to be consistent with libarchive that
+ * reports them to be zero size */
+ if(S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)) {
continue;
}
- mp = match_mount_point(mount_points, filename);
+ mp = match_mount_point(mount_points, path);
if(mp == NULL) {
_alpm_log(PM_LOG_WARNING,
_("could not determine mount point for file %s"), filename);
continue;
}
- snprintf(path, PATH_MAX, "%s%s", handle->root, filename);
- _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;
/* the addition of (divisor - 1) performs ceil() with integer division */
- data->blocks_needed -=
- (st.st_size + data->fsp.f_bsize - 1l) / data->fsp.f_bsize;
+ mp->blocks_needed -=
+ (st.st_size + mp->fsp.f_bsize - 1l) / mp->fsp.f_bsize;
}
return(0);
@@ -191,7 +182,6 @@ static int calculate_installed_size(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;
@@ -210,28 +200,39 @@ static int calculate_installed_size(const alpm_list_t *mount_points,
}
while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
- alpm_list_t *mp;
- alpm_mountpoint_t *data;
+ alpm_mountpoint_t *mp;
+ const char *filename;
+ mode_t mode;
+ char path[PATH_MAX];
- file = archive_entry_pathname(entry);
+ filename = archive_entry_pathname(entry);
+ mode = archive_entry_mode(entry);
+
+ /* libarchive reports these as zero size anyways */
+ /* NOTE: if we do start accounting for directory size, a dir matching a
+ * mountpoint needs to be attributed to the parent, not the mountpoint. */
+ if(S_ISDIR(mode) || S_ISLNK(mode)) {
+ continue;
+ }
/* approximate space requirements for db entries */
- if(file[0] == '.') {
- file = alpm_option_get_dbpath();
+ if(filename[0] == '.') {
+ filename = alpm_option_get_dbpath();
}
- mp = match_mount_point(mount_points, file);
+ snprintf(path, PATH_MAX, "%s%s", handle->root, filename);
+
+ mp = match_mount_point(mount_points, path);
if(mp == NULL) {
_alpm_log(PM_LOG_WARNING,
- _("could not determine mount point for file %s"), file);
+ _("could not determine mount point for file %s"), filename);
continue;
}
- data = mp->data;
/* the addition of (divisor - 1) performs ceil() with integer division */
- data->blocks_needed +=
- (archive_entry_size(entry) + data->fsp.f_bsize - 1l) / data->fsp.f_bsize;
- data->used = 1;
+ mp->blocks_needed +=
+ (archive_entry_size(entry) + mp->fsp.f_bsize - 1l) / mp->fsp.f_bsize;
+ mp->used = 1;
if(archive_read_data_skip(archive)) {
_alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"),
diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h
index 25b9cfb..ae99d0c 100644
--- a/lib/libalpm/diskspace.h
+++ b/lib/libalpm/diskspace.h
@@ -32,6 +32,7 @@
typedef struct __alpm_mountpoint_t {
/* mount point information */
char *mount_dir;
+ size_t mount_dir_len;
/* storage for additional disk usage calculations */
long blocks_needed;
long max_blocks_needed;
--
1.7.4
More information about the pacman-dev
mailing list