summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan McRae <allan@archlinux.org>2010-11-16 16:15:21 +1000
committerDan McGee <dan@archlinux.org>2010-12-12 20:29:43 -0600
commitf4e9deb6d74614ac427b37513359d91588dd1542 (patch)
tree3f707d2046a12ee0808a3e0cbd3eed8a1d036767
parentadb10c3ab244cc00eb863d5b036fa7bdd76f8152 (diff)
Add function for listing system mount points
Add a mount_point_list() function that attempts to portably obtain a list of system mount points and a struct to hold needed mount point information. Abort the transaction if we are unable to determine the mount points. Signed-off-by: Allan McRae <allan@archlinux.org> Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--configure.ac22
-rw-r--r--lib/libalpm/diskspace.c119
-rw-r--r--lib/libalpm/diskspace.h20
3 files changed, 160 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index a8987a48..cf023002 100644
--- a/configure.ac
+++ b/configure.ac
@@ -169,7 +169,9 @@ AS_IF([test "x$with_fetch" != "xno"],
AM_CONDITIONAL([HAVE_LIBFETCH], [test "x$ac_cv_lib_fetch_fetchParseURL" = "xyes"])
# Checks for header files.
-AC_CHECK_HEADERS([fcntl.h glob.h libintl.h limits.h locale.h string.h strings.h sys/ioctl.h sys/param.h sys/statvfs.h sys/syslimits.h sys/time.h syslog.h wchar.h])
+AC_CHECK_HEADERS([fcntl.h glob.h libintl.h limits.h locale.h mntent.h string.h strings.h \
+ sys/ioctl.h sys/mount.h sys/param.h sys/statvfs.h sys/syslimits.h \
+ sys/time.h sys/types.h sys/ucred.h syslog.h wchar.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
@@ -183,12 +185,30 @@ AC_STRUCT_DIRENT_D_TYPE
# Checks for library functions.
AC_FUNC_FORK
+AC_FUNC_GETMNTENT
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
AC_FUNC_MKTIME
AC_CHECK_FUNCS([geteuid realpath regcomp strcasecmp \
strndup strrchr strsep swprintf \
wcwidth uname])
+# Checks for getmntinfo and determines whether it uses statfs or statvfs
+AC_CHECK_FUNC(getmntinfo,
+ [AC_MSG_CHECKING(parameter style for getmntinfo)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+# include <sys/param.h>
+# include <sys/mount.h>
+#if HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+extern int getmntinfo (struct statfs **, int);
+ ]], [])],
+ [AC_DEFINE(HAVE_GETMNTINFO_STATFS, [], [getmntinfo uses statfs])
+ AC_MSG_RESULT(statfs)],
+ [AC_DEFINE(HAVE_GETMNTINFO_STATVFS, [], [getmntinfo uses statvfs])
+ AC_MSG_RESULT(statvfs)])
+ ])
+
# Enable large file support if available
AC_SYS_LARGEFILE
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index 31a2760d..a5beb84f 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -17,11 +17,130 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "config.h"
+
+#if defined HAVE_GETMNTENT
+#include <mntent.h>
+#include <sys/statvfs.h>
+#elif defined HAVE_GETMNTINFO_STATFS
+#include <sys/param.h>
+#include <sys/mount.h>
+#if HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+#elif defined HAVE_GETMNTINFO_STATVFS
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#endif
+
/* libalpm */
#include "diskspace.h"
+#include "alpm_list.h"
+#include "util.h"
+#include "log.h"
+
+static alpm_list_t *mount_point_list()
+{
+ alpm_list_t *mount_points = NULL;
+ alpm_mountpoint_t *mp;
+
+#if defined HAVE_GETMNTENT
+ struct mntent *mnt;
+ FILE *fp;
+ struct statvfs fsp;
+
+ fp = setmntent(MOUNTED, "r");
+
+ if (fp == NULL) {
+ return NULL;
+ }
+
+ while((mnt = getmntent (fp))) {
+ if(statvfs(mnt->mnt_dir, &fsp) != 0) {
+ _alpm_log(PM_LOG_WARNING, "could not get filesystem information for %s\n", mnt->mnt_dir);
+ continue;
+ }
+
+ MALLOC(mp, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL));
+ mp->mount_dir = strdup(mnt->mnt_dir);
+
+ MALLOC(mp->fsp, sizeof(struct statvfs), RET_ERR(PM_ERR_MEMORY, NULL));
+ memcpy((void *)(mp->fsp), (void *)(&fsp), sizeof(struct statvfs));
+
+ mp->blocks_needed = 0;
+ mp->max_blocks_needed = 0;
+ mp->used = 0;
+
+ mount_points = alpm_list_add(mount_points, mp);
+ }
+
+ endmntent(fp);
+#elif defined HAVE_GETMNTINFO_STATFS
+ int entries;
+ struct statfs *fsp;
+
+ entries = getmntinfo(&fsp, MNT_NOWAIT);
+
+ if (entries < 0) {
+ return NULL;
+ }
+
+ for(; entries-- > 0; fsp++) {
+ MALLOC(mp, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL));
+ mp->mount_dir = strdup(fsp->f_mntonname);
+
+ MALLOC(mp->fsp, sizeof(struct statfs), RET_ERR(PM_ERR_MEMORY, NULL));
+ memcpy((void *)(mp->fsp), (void *)fsp, sizeof(struct statfs));
+
+ mp->blocks_needed = 0;
+ mp->max_blocks_needed = 0;
+
+ mount_points = alpm_list_add(mount_points, mp);
+ }
+#elif defined HAVE_GETMNTINFO_STATVFS
+ int entries;
+ struct statvfs *fsp;
+
+ entries = getmntinfo(&fsp, MNT_NOWAIT);
+
+ if (entries < 0) {
+ return NULL;
+ }
+
+ for (; entries-- > 0; fsp++) {
+ MALLOC(mp, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL));
+ mp->mount_dir = strdup(fsp->f_mntonname);
+
+ MALLOC(mp->fsp, sizeof(struct statvfs), RET_ERR(PM_ERR_MEMORY, NULL));
+ memcpy((void *)(mp->fsp), (void *)fsp, sizeof(struct statvfs));
+
+ mp->blocks_needed = 0;
+ mp->max_blocks_needed = 0;
+
+ mount_points = alpm_list_add(mount_points, mp);
+ }
+#endif
+
+ return(mount_points);
+}
int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db)
{
+ alpm_list_t *mount_points;
+
+ mount_points = mount_point_list();
+ if(mount_points == NULL) {
+ _alpm_log(PM_LOG_ERROR, _("count not determine filesystem mount points"));
+ return -1;
+ }
+
+ for(i = mount_points; i; i = alpm_list_next(i)) {
+ alpm_mountpoint_t *data = i->data;
+ FREE(data->mount_dir);
+ FREE(data->fsp);
+ }
+ FREELIST(mount_points);
+
return 0;
}
diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h
index 69e39d8e..15ff2f67 100644
--- a/lib/libalpm/diskspace.h
+++ b/lib/libalpm/diskspace.h
@@ -20,8 +20,28 @@
#ifndef _ALPM_DISKSPACE_H
#define _ALPM_DISKSPACE_H
+#if defined HAVE_GETMNTINFO_STATFS
+#include <sys/mount.h>
+#else
+#include <sys/statvfs.h>
+#endif
+
#include "alpm.h"
+typedef struct __alpm_mountpoint_t {
+ /* mount point information */
+ char *mount_dir;
+#if defined HAVE_GETMNTINFO_STATFS
+ struct statfs *fsp;
+#else
+ struct statvfs *fsp;
+#endif
+ /* storage for additional disk usage calculations */
+ long blocks_needed;
+ long max_blocks_needed;
+ int used;
+} alpm_mountpoint_t;
+
int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db);
#endif /* _ALPM_DISKSPACE_H */