dovecot-2.1: Added mountpoint_iter_*() for iterating mounted fil...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jan 30 21:03:28 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/8be75a2ea2dd
changeset: 14035:8be75a2ea2dd
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jan 30 20:09:04 2012 +0200
description:
Added mountpoint_iter_*() for iterating mounted filesystems.

diffstat:

 src/lib/mountpoint.c |  317 +++++++++++++++++++++++++++++++++-----------------
 src/lib/mountpoint.h |   10 +-
 2 files changed, 220 insertions(+), 107 deletions(-)

diffs (truncated from 421 to 300 lines):

diff -r cc533cbd77b0 -r 8be75a2ea2dd src/lib/mountpoint.c
--- a/src/lib/mountpoint.c	Sun Jan 29 20:33:34 2012 +0000
+++ b/src/lib/mountpoint.c	Mon Jan 30 20:09:04 2012 +0200
@@ -8,26 +8,31 @@
 #ifdef HAVE_SYS_VMOUNT_H
 #  include <stdio.h>
 #  include <sys/vmount.h> /* AIX */
+#  define MOUNTPOINT_AIX_MNTCTL
 #elif defined(HAVE_STATVFS_MNTFROMNAME)
 #  include <sys/statvfs.h> /* NetBSD 3.0+, FreeBSD 5.0+ */
 #  define STATVFS_STR "statvfs"
+#  define MOUNTPOINT_STATVFS
 #elif defined(HAVE_STATFS_MNTFROMNAME)
 #  include <sys/param.h> /* Older BSDs */
 #  include <sys/mount.h>
 #  define statvfs statfs
 #  define STATVFS_STR "statfs"
+#  define MOUNTPOINT_STATVFS
 #elif defined(HAVE_MNTENT_H)
 #  include <stdio.h>
 #  include <mntent.h> /* Linux */
+#  define MOUNTPOINT_LINUX
 #elif defined(HAVE_SYS_MNTTAB_H)
 #  include <stdio.h>
 #  include <sys/mnttab.h> /* Solaris */
 #  include <sys/mntent.h>
+#  define MOUNTPOINT_SOLARIS
 #else
 #  define MOUNTPOINT_UNKNOWN
 #endif
 
-#ifdef HAVE_SYS_MNTTAB_H
+#ifdef MOUNTPOINT_SOLARIS
 #  define MTAB_PATH MNTTAB /* Solaris */
 #else
 #  define MTAB_PATH "/etc/mtab" /* Linux */
@@ -53,14 +58,11 @@
 #  define MNTTYPE_ROOTFS "rootfs"
 #endif
 
-int mountpoint_get(const char *path, pool_t pool, struct mountpoint *point_r)
+#ifdef MOUNTPOINT_STATVFS
+static int
+mountpoint_get_statvfs(const char *path, pool_t pool,
+                       struct mountpoint *point_r)
 {
-#ifdef MOUNTPOINT_UNKNOWN
-	memset(point_r, 0, sizeof(*point_r));
-	errno = ENOSYS;
-	return -1;
-#elif defined (HAVE_STATFS_MNTFROMNAME) || defined(HAVE_STATVFS_MNTFROMNAME)
-	/* BSDs */
 	struct statvfs buf;
 
 	memset(point_r, 0, sizeof(*point_r));
@@ -81,21 +83,23 @@
 #endif
 	point_r->block_size = buf.f_bsize;
 	return 1;
+}
+#endif
+
+int mountpoint_get(const char *path, pool_t pool, struct mountpoint *point_r)
+{
+#ifdef MOUNTPOINT_UNKNOWN
+	memset(point_r, 0, sizeof(*point_r));
+	errno = ENOSYS;
+	return -1;
+#elif defined (MOUNTPOINT_STATVFS)
+        /* BSDs, Tru64 */
+        return mountpoint_get_statvfs(path, pool, point_r);
 #else
-	/* Linux, Solaris: /etc/mtab reading */
-#ifdef HAVE_SYS_MNTTAB_H
-	union {
-		struct mnttab ent;
-		struct extmnttab ext;
-	} ent;
-#else
-	struct mntent *ent;
-	struct stat st2;
-#endif
+	/* find via mount iteration */
+	struct mountpoint_iter *iter;
+	const struct mountpoint *mnt;
 	struct stat st;
-	const char *device_path = NULL, *mount_path = NULL, *type = NULL;
-	unsigned int block_size;
-	FILE *f;
 
 	memset(point_r, 0, sizeof(*point_r));
 	if (stat(path, &st) < 0) {
@@ -105,72 +109,143 @@
 		i_error("stat(%s) failed: %m", path);
 		return -1;
 	}
-	block_size = st.st_blksize;
 
-#ifdef HAVE_SYS_VMOUNT_H
+	iter = mountpoint_iter_init();
+	while ((mnt = mountpoint_iter_next(iter)) != NULL) {
+		if (minor(st.st_dev) == minor(mnt->dev) &&
+		    major(st.st_dev) == major(mnt->dev))
+			break;
+        }
+        if (mnt != NULL) {
+                point_r->device_path = p_strdup(pool, mnt->device_path);
+                point_r->mount_path = p_strdup(pool, mnt->mount_path);
+                point_r->type = p_strdup(pool, mnt->type);
+                point_r->dev = mnt->dev;
+                point_r->block_size = st.st_blksize;
+        }
+	mountpoint_iter_deinit(&iter);
+        return mnt != NULL ? 1 : 0;
+#endif
+}
+
+struct mountpoint_iter {
+#ifdef MOUNTPOINT_AIX_MNTCTL
+	char *mtab;
+	struct vmount *vmt;
+	int count;
+#elif defined(MOUNTPOINT_SOLARIS) || defined(MOUNTPOINT_LINUX)
+	FILE *f;
+#elif defined(HAVE_GETMNTINFO) /* BSDs */
+	struct statfs *fs;
+	int count;
+#endif
+	struct mountpoint mnt;
+	bool failed;
+};
+
+struct mountpoint_iter *mountpoint_iter_init(void)
 {
-	char static_mtab[STATIC_MTAB_SIZE], *mtab = static_mtab;
-	int i, count;
-	const struct vmount *vmt;
+	struct mountpoint_iter *iter = i_new(struct mountpoint_iter, 1);
+#ifdef MOUNTPOINT_AIX_MNTCTL
+	unsigned int size = STATIC_MTAB_SIZE;
+	char *mtab;
+	int count;
 
-	count = mntctl(MCTL_QUERY, sizeof(static_mtab), mtab);
-	while (count == 0) {
-		unsigned int size = *(unsigned int *)mtab;
-
-		mtab  = t_malloc(size);
-		count = mntctl(MCTL_QUERY, size, mtab);
+	mtab = t_buffer_get(size);
+	while ((count = mntctl(MCTL_QUERY, size, mtab)) == 0) {
+		size = *(unsigned int *)mtab;
+		mtab = t_buffer_get(size);
 	}
 	if (count < 0) {
 		i_error("mntctl(MCTL_QUERY) failed: %m");
-		return -1;
+		iter->failed = TRUE;
+		return iter;
 	}
-	vmt = (struct vmount *)mtab;
-	for (i = 0; i < count && device_path == NULL; i++) {
-		struct stat vst;
-		const char *vmt_base = (const char *)vmt;
-		const char *vmt_object, *vmt_stub, *vmt_hostname;
+	iter->count = count;
+	iter->mtab = i_malloc(size);
+	memcpy(iter->mtab, mtab, size);
+	iter->vmt = (void *)iter->mtab;
+#elif defined(MOUNTPOINT_SOLARIS)
+	iter->f = fopen(MTAB_PATH, "r");
+	if (iter->f == NULL) {
+		i_error("fopen(%s) failed: %m", MTAB_PATH);
+		iter->failed = TRUE;
+		return iter;
+	}
+	resetmnttab(iter->f);
+#elif defined(MOUNTPOINT_LINUX)
+	iter->f = setmntent(MTAB_PATH, "r");
+	if (iter->f == NULL) {
+		i_error("setmntent(%s) failed: %m", MTAB_PATH);
+		iter->failed = TRUE;
+	}
+#elif defined(HAVE_GETMNTINFO) /* BSDs */
+	iter->count = getmntinfo(&iter->fs, MNT_NOWAIT);
+	if (iter->count < 0) {
+		i_error("getmntinfo() failed: %m");
+		iter->failed = TRUE;
+	}
+#else
+	iter->failed = TRUE;
+#endif
+	return iter;
+}
 
-		vmt_hostname = vmt_base + vmt->vmt_data[VMT_HOSTNAME].vmt_off;
-		vmt_object   = vmt_base + vmt->vmt_data[VMT_OBJECT].vmt_off;
-		vmt_stub     = vmt_base + vmt->vmt_data[VMT_STUB].vmt_off;
+const struct mountpoint *mountpoint_iter_next(struct mountpoint_iter *iter)
+{
+#ifdef MOUNTPOINT_AIX_MNTCTL
+	struct vmount *vmt = iter->vmt;
+	char *vmt_base = (char *)vmt;
+	char *vmt_object, *vmt_stub, *vmt_hostname;
+	struct stat vst;
 
-		switch (vmt->vmt_gfstype) {
-		case MNT_NFS:
-		case MNT_NFS3:
-		case MNT_NFS4:
-		case MNT_RFS4:
-			if (stat(vmt_stub, &vst) == 0 &&
-			    st.st_dev == vst.st_dev) {
-				device_path = t_strconcat(vmt_hostname, ":",
-							  vmt_object, NULL);
-				mount_path  = vmt_stub;
-				type        = MNTTYPE_NFS;
-			}
-			break;
+	if (iter->count == 0)
+		return NULL;
+	iter->count--;
 
-		case MNT_J2:
-		case MNT_JFS:
-			if (stat(vmt_stub, &vst) == 0 &&
-			    st.st_dev == vst.st_dev) {
-				device_path = vmt_object;
-				mount_path  = vmt_stub;
-				type        = MNTTYPE_JFS;
-			}
-			break;
-		}
-		vmt = CONST_PTR_OFFSET(vmt, vmt->vmt_length);
+	iter->vmt = PTR_OFFSET(vmt, vmt->vmt_length);
+	vmt_hostname = vmt_base + vmt->vmt_data[VMT_HOSTNAME].vmt_off;
+	vmt_object   = vmt_base + vmt->vmt_data[VMT_OBJECT].vmt_off;
+	vmt_stub     = vmt_base + vmt->vmt_data[VMT_STUB].vmt_off;
+
+	memset(&iter->mnt, 0, sizeof(iter->mnt));
+	switch (vmt->vmt_gfstype) {
+	case MNT_NFS:
+	case MNT_NFS3:
+	case MNT_NFS4:
+	case MNT_RFS4:
+		iter->mnt.device_path =
+			t_strconcat(vmt_hostname, ":", vmt_object, NULL);
+		iter->mnt.mount_path = vmt_stub;
+		iter->mnt.type       = MNTTYPE_NFS;
+		break;
+
+	case MNT_J2:
+	case MNT_JFS:
+		iter->mnt.device_path = vmt_object;
+		iter->mnt.mount_path  = vmt_stub;
+		iter->mnt.type        = MNTTYPE_JFS;
+		break;
+	default:
+		/* unwanted filesystem */
+		return mountpoint_iter_next(iter);
 	}
-}
-#elif defined(HAVE_SYS_MNTTAB_H)
+	if (stat(iter->mnt.mount_path, &vst) == 0) {
+		iter->mnt.dev = vst.st_dev;
+		iter->mnt.block_size = vst.st_blksize;
+	}
+	return &iter->mnt;
+#elif defined (MOUNTPOINT_SOLARIS)
+	union {
+		struct mnttab ent;
+		struct extmnttab ext;
+	} ent;
 
-	/* Solaris */
-	f = fopen(MTAB_PATH, "r");
-	if (f == NULL) {
-		i_error("fopen(%s) failed: %m", MTAB_PATH);
-		return -1;
-	}
-	resetmnttab(f);
-	while ((getextmntent(f, &ent.ext, sizeof(ent.ext))) == 0) {
+	if (iter->f == NULL)
+		return NULL;
+
+	memset(&iter->mnt, 0, sizeof(iter->mnt));
+	while ((getextmntent(iter->f, &ent.ext, sizeof(ent.ext))) == 0) {
 		if (hasmntopt(&ent.ent, MNTOPT_IGNORE) != NULL)
 			continue;
 
@@ -178,45 +253,75 @@
 		if (strcmp(ent.ent.mnt_special, MNTTYPE_SWAP) == 0)
 			continue;
 
-		if (major(st.st_dev) == ent.ext.mnt_major &&
-		    minor(st.st_dev) == ent.ext.mnt_minor) {
-			device_path = ent.ent.mnt_special;
-			mount_path = ent.ent.mnt_mountp;
-			type = ent.ent.mnt_fstype;
-			break;


More information about the dovecot-cvs mailing list