From f4e9deb6d74614ac427b37513359d91588dd1542 Mon Sep 17 00:00:00 2001 From: Allan McRae Date: Tue, 16 Nov 2010 16:15:21 +1000 Subject: 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 Signed-off-by: Dan McGee --- configure.ac | 22 ++++++++- lib/libalpm/diskspace.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/libalpm/diskspace.h | 20 ++++++++ 3 files changed, 160 insertions(+), 1 deletion(-) 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 +# include +#if HAVE_SYS_UCRED_H +#include +#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 . */ +#include "config.h" + +#if defined HAVE_GETMNTENT +#include +#include +#elif defined HAVE_GETMNTINFO_STATFS +#include +#include +#if HAVE_SYS_UCRED_H +#include +#endif +#elif defined HAVE_GETMNTINFO_STATVFS +#include +#include +#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 +#else +#include +#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 */ -- cgit v1.2.3-70-g09d2