summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--lib/libalpm/diskspace.c24
-rw-r--r--lib/libalpm/diskspace.h1
3 files changed, 25 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 47d60938..1039bba1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -194,6 +194,10 @@ AC_CHECK_FUNCS([geteuid getmntinfo realpath regcomp strcasecmp \
wcwidth uname])
# For the diskspace code
FS_STATS_TYPE
+AC_CHECK_MEMBERS([struct statvfs.f_flag],,,[[#include <sys/statvfs.h>]])
+AC_CHECK_MEMBERS([struct statfs.f_flags],,,[[#include <sys/param.h>
+ #include <sys/mount.h>]])
+
# Enable large file support if available
AC_SYS_LARGEFILE
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index 96f73008..c8c35742 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -19,6 +19,7 @@
#include "config.h"
+#include <errno.h>
#if defined(HAVE_MNTENT_H)
#include <mntent.h>
#endif
@@ -66,7 +67,7 @@ static alpm_list_t *mount_point_list(void)
#if defined HAVE_GETMNTENT
struct mntent *mnt;
FILE *fp;
- FSSTATSTYPE fsp;
+ struct statvfs fsp;
fp = setmntent(MOUNTED, "r");
@@ -75,16 +76,22 @@ static alpm_list_t *mount_point_list(void)
}
while((mnt = getmntent(fp))) {
+ if(!mnt) {
+ _alpm_log(PM_LOG_WARNING, _("could not get filesystem information\n"));
+ continue;
+ }
if(statvfs(mnt->mnt_dir, &fsp) != 0) {
_alpm_log(PM_LOG_WARNING,
- _("could not get filesystem information for %s\n"), mnt->mnt_dir);
+ _("could not get filesystem information for %s: %s\n"),
+ mnt->mnt_dir, strerror(errno));
continue;
}
CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL));
mp->mount_dir = strdup(mnt->mnt_dir);
mp->mount_dir_len = strlen(mp->mount_dir);
- memcpy(&(mp->fsp), &fsp, sizeof(FSSTATSTYPE));
+ memcpy(&(mp->fsp), &fsp, sizeof(struct statvfs));
+ mp->read_only = fsp.f_flag & ST_RDONLY;
mount_points = alpm_list_add(mount_points, mp);
}
@@ -105,6 +112,11 @@ static alpm_list_t *mount_point_list(void)
mp->mount_dir = strdup(fsp->f_mntonname);
mp->mount_dir_len = strlen(mp->mount_dir);
memcpy(&(mp->fsp), fsp, sizeof(FSSTATSTYPE));
+#if defined HAVE_STRUCT_STATVFS_F_FLAG
+ mp->read_only = fsp->f_flag & ST_RDONLY;
+#elif defined HAVE_STRUCT_STATFS_F_FLAGS
+ mp->read_only = fsp->f_flags & MNT_RDONLY;
+#endif
mount_points = alpm_list_add(mount_points, mp);
}
@@ -295,7 +307,11 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local)
for(i = mount_points; i; i = alpm_list_next(i)) {
alpm_mountpoint_t *data = i->data;
- if(data->used == 1) {
+ if(data->used && data->read_only) {
+ _alpm_log(PM_LOG_ERROR, _("Partition %s is mounted read only\n"),
+ data->mount_dir);
+ abort = 1;
+ } else if(data->used) {
/* cushion is roughly min(5% capacity, 20MiB) */
long fivepc = ((long)data->fsp.f_blocks / 20) + 1;
long twentymb = (20 * 1024 * 1024 / (long)data->fsp.f_bsize) + 1;
diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h
index ae99d0c8..7c7dcebd 100644
--- a/lib/libalpm/diskspace.h
+++ b/lib/libalpm/diskspace.h
@@ -37,6 +37,7 @@ typedef struct __alpm_mountpoint_t {
long blocks_needed;
long max_blocks_needed;
int used;
+ int read_only;
FSSTATSTYPE fsp;
} alpm_mountpoint_t;