summaryrefslogtreecommitdiff
path: root/lib/libalpm/diskspace.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/diskspace.c')
-rw-r--r--lib/libalpm/diskspace.c114
1 files changed, 86 insertions, 28 deletions
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index 45908b22..daee2447 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -17,8 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdio.h>
#include <errno.h>
@@ -60,6 +58,17 @@ static int mount_point_cmp(const void *p1, const void *p2)
return -strcmp(mp1->mount_dir, mp2->mount_dir);
}
+static void mount_point_list_free(alpm_list_t *mount_points)
+{
+ alpm_list_t *i;
+
+ for(i = mount_points; i; i = i->next) {
+ alpm_mountpoint_t *data = i->data;
+ FREE(data->mount_dir);
+ }
+ FREELIST(mount_points);
+}
+
static alpm_list_t *mount_point_list(alpm_handle_t *handle)
{
alpm_list_t *mount_points = NULL, *ptr;
@@ -215,6 +224,7 @@ static int calculate_removed_size(alpm_handle_t *handle,
alpm_mountpoint_t *mp;
struct stat st;
char path[PATH_MAX];
+ blkcnt_t remove_size;
const char *filename = file->name;
snprintf(path, PATH_MAX, "%s%s", handle->root, filename);
@@ -234,8 +244,8 @@ static int calculate_removed_size(alpm_handle_t *handle,
}
/* the addition of (divisor - 1) performs ceil() with integer division */
- mp->blocks_needed -=
- (st.st_size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ remove_size = (st.st_size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ mp->blocks_needed -= remove_size;
mp->used |= USED_REMOVE;
}
@@ -256,6 +266,7 @@ static int calculate_installed_size(alpm_handle_t *handle,
const alpm_file_t *file = filelist->files + i;
alpm_mountpoint_t *mp;
char path[PATH_MAX];
+ blkcnt_t install_size;
const char *filename = file->name;
/* libarchive reports these as zero size anyways */
@@ -280,14 +291,80 @@ static int calculate_installed_size(alpm_handle_t *handle,
}
/* the addition of (divisor - 1) performs ceil() with integer division */
- mp->blocks_needed +=
- (file->size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ install_size = (file->size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ mp->blocks_needed += install_size;
mp->used |= USED_INSTALL;
}
return 0;
}
+static int check_mountpoint(alpm_handle_t *handle, alpm_mountpoint_t *mp)
+{
+ /* cushion is roughly min(5% capacity, 20MiB) */
+ fsblkcnt_t fivepc = (mp->fsp.f_blocks / 20) + 1;
+ fsblkcnt_t twentymb = (20 * 1024 * 1024 / mp->fsp.f_bsize) + 1;
+ fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb;
+ blkcnt_t needed = mp->max_blocks_needed + cushion;
+
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "partition %s, needed %jd, cushion %ju, free %ju\n",
+ mp->mount_dir, (intmax_t)mp->max_blocks_needed,
+ (uintmax_t)cushion, (uintmax_t)mp->fsp.f_bfree);
+ if(needed >= 0 && (fsblkcnt_t)needed > mp->fsp.f_bfree) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("Partition %s too full: %jd blocks needed, %jd blocks free\n"),
+ mp->mount_dir, (intmax_t)needed, (uintmax_t)mp->fsp.f_bfree);
+ return 1;
+ }
+ return 0;
+}
+
+int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir,
+ size_t num_files, off_t *file_sizes)
+{
+ alpm_list_t *mount_points;
+ alpm_mountpoint_t *cachedir_mp;
+ size_t j;
+ int error = 0;
+
+ mount_points = mount_point_list(handle);
+ if(mount_points == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n"));
+ return -1;
+ }
+
+ cachedir_mp = match_mount_point(mount_points, cachedir);
+ if(cachedir == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine cachedir mount point %s\n"),
+ cachedir);
+ error = 1;
+ goto finish;
+ }
+
+ /* there's no need to check for a R/O mounted filesystem here, as
+ * _alpm_filecache_setup will never give us a non-writable directory */
+
+ /* round up the size of each file to the nearest block and accumulate */
+ for(j = 0; j < num_files; j++) {
+ cachedir_mp->max_blocks_needed += (file_sizes[j] + cachedir_mp->fsp.f_bsize + 1) /
+ cachedir_mp->fsp.f_bsize;
+ }
+
+ if(check_mountpoint(handle, cachedir_mp)) {
+ error = 1;
+ }
+
+finish:
+ mount_point_list_free(mount_points);
+
+ if(error) {
+ RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1);
+ }
+
+ return 0;
+}
+
int _alpm_check_diskspace(alpm_handle_t *handle)
{
alpm_list_t *mount_points, *i;
@@ -356,32 +433,13 @@ int _alpm_check_diskspace(alpm_handle_t *handle)
_alpm_log(handle, ALPM_LOG_ERROR, _("Partition %s is mounted read only\n"),
data->mount_dir);
error = 1;
- } else if(data->used & USED_INSTALL) {
- /* cushion is roughly min(5% capacity, 20MiB) */
- fsblkcnt_t fivepc = (data->fsp.f_blocks / 20) + 1;
- fsblkcnt_t twentymb = (20 * 1024 * 1024 / data->fsp.f_bsize) + 1;
- fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb;
- blkcnt_t needed = data->max_blocks_needed + cushion;
-
- _alpm_log(handle, ALPM_LOG_DEBUG,
- "partition %s, needed %jd, cushion %ju, free %ju\n",
- data->mount_dir, (intmax_t)data->max_blocks_needed,
- (uintmax_t)cushion, (uintmax_t)data->fsp.f_bfree);
- if(needed >= 0 && (fsblkcnt_t)needed > data->fsp.f_bfree) {
- _alpm_log(handle, ALPM_LOG_ERROR,
- _("Partition %s too full: %jd blocks needed, %jd blocks free\n"),
- data->mount_dir, (intmax_t)needed, (uintmax_t)data->fsp.f_bfree);
- error = 1;
- }
+ } else if(data->used & USED_INSTALL && check_mountpoint(handle, data)) {
+ error = 1;
}
}
finish:
- for(i = mount_points; i; i = i->next) {
- alpm_mountpoint_t *data = i->data;
- FREE(data->mount_dir);
- }
- FREELIST(mount_points);
+ mount_point_list_free(mount_points);
if(error) {
RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1);