mountpoint.c revision 310ef47cf7b913dcae4f7e66e931648dd7435ebd
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "lib.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "mountpoint.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen#include <sys/stat.h>
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#ifdef HAVE_SYS_VMOUNT_H
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen# include <stdio.h>
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen# include <sys/vmount.h> /* AIX */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#elif defined(HAVE_STATVFS_MNTFROMNAME)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen# include <sys/statvfs.h> /* NetBSD 3.0+, FreeBSD 5.0+ */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen# define STATVFS_STR "statvfs"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#elif defined(HAVE_STATFS_MNTFROMNAME)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen# include <sys/param.h> /* Older BSDs */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen# include <sys/mount.h>
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen# define statvfs statfs
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen# define STATVFS_STR "statfs"
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen#elif defined(HAVE_MNTENT_H)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen# include <stdio.h>
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen# include <mntent.h> /* Linux */
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen#elif defined(HAVE_SYS_MNTTAB_H)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen# include <stdio.h>
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen# include <sys/mnttab.h> /* Solaris */
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen# include <sys/mntent.h>
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen#else
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen# define MOUNTPOINT_UNKNOWN
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#endif
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#ifdef HAVE_SYS_MNTTAB_H
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen# define MTAB_PATH MNTTAB /* Solaris */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#else
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen# define MTAB_PATH "/etc/mtab" /* Linux */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#endif
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* AIX doesn't have these defined */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#ifndef MNTTYPE_SWAP
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen# define MNTTYPE_SWAP "swap"
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen#endif
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#ifndef MNTTYPE_IGNORE
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen# define MNTTYPE_IGNORE "ignore"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#endif
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#ifndef MNTTYPE_JFS
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen# define MNTTYPE_JFS "jfs"
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen#endif
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#ifndef MNTTYPE_NFS
3b32bc12710240f86465a00fbb2bd1ef030e6c40Timo Sirainen# define MNTTYPE_NFS "nfs"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#endif
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenint mountpoint_get(const char *path, pool_t pool, struct mountpoint *point_r)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen#ifdef MOUNTPOINT_UNKNOWN
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen memset(point_r, 0, sizeof(*point_r));
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen errno = ENOSYS;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#elif defined (HAVE_STATFS_MNTFROMNAME) || defined(HAVE_STATVFS_MNTFROMNAME)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* BSDs */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct statvfs buf;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen memset(point_r, 0, sizeof(*point_r));
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (statvfs(path, &buf) < 0) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (errno == ENOENT)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return 0;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_error(STATVFS_STR"(%s) failed: %m", path);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return -1;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen point_r->device_path = p_strdup(pool, buf.f_mntfromname);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen point_r->mount_path = p_strdup(pool, buf.f_mntonname);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen#ifdef __osf__ /* Tru64 */
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen point_r->type = p_strdup(pool, getvfsbynumber(buf.f_type));
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen#else
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen point_r->type = p_strdup(pool, buf.f_fstypename);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen#endif
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen point_r->block_size = buf.f_bsize;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return 1;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen#else
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* Linux, Solaris: /etc/mtab reading */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#ifdef HAVE_SYS_MNTTAB_H
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen union {
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen struct mnttab ent;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen struct extmnttab ext;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen } ent;
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen#else
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen struct mntent *ent;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen struct stat st2;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#endif
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct stat st;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const char *device_path = NULL, *mount_path = NULL, *type = NULL;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen unsigned int block_size;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen FILE *f;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen memset(point_r, 0, sizeof(*point_r));
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (stat(path, &st) < 0) {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (errno == ENOENT)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return 0;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
9ffdc9d18870acef2e4dde99715d8528ff4b080dTimo Sirainen i_error("stat(%s) failed: %m", path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen block_size = st.st_blksize;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen#ifdef HAVE_SYS_VMOUNT_H
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen{
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen char static_mtab[STATIC_MTAB_SIZE], *mtab = static_mtab;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen int i, count;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const struct vmount *vmt;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen count = mntctl(MCTL_QUERY, sizeof(static_mtab), mtab);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen while (count == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen unsigned int size = *(unsigned int *)mtab;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mtab = t_malloc(size);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen count = mntctl(MCTL_QUERY, size, mtab);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (count < 0) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen i_error("mntctl(MCTL_QUERY) failed: %m");
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen vmt = (struct vmount *)mtab;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen for (i = 0; i < count && device_path == NULL; i++) {
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen struct stat vst;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *vmt_base = (const char *)vmt;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *vmt_object, *vmt_stub, *vmt_hostname;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen vmt_hostname = vmt_base + vmt->vmt_data[VMT_HOSTNAME].vmt_off;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen vmt_object = vmt_base + vmt->vmt_data[VMT_OBJECT].vmt_off;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen vmt_stub = vmt_base + vmt->vmt_data[VMT_STUB].vmt_off;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
306cfd77100131c08b243de10f6d40500f4c27c6Timo Sirainen switch (vmt->vmt_gfstype) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen case MNT_NFS:
09c08fad8e7cc694a6c8d1711e67839acd3a2f04Timo Sirainen case MNT_NFS3:
438f12d7a776da695019114884b48188d94613efTimo Sirainen case MNT_NFS4:
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen case MNT_RFS4:
9ffdc9d18870acef2e4dde99715d8528ff4b080dTimo Sirainen if (stat(vmt_stub, &vst) == 0 &&
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen st.st_dev == vst.st_dev) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen device_path = t_strconcat(vmt_hostname, ":",
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen vmt_object, NULL);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen mount_path = vmt_stub;
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen type = MNTTYPE_NFS;
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen }
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen break;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen case MNT_J2:
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen case MNT_JFS:
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (stat(vmt_stub, &vst) == 0 &&
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen st.st_dev == vst.st_dev) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen device_path = vmt_object;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mount_path = vmt_stub;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen type = MNTTYPE_JFS;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen break;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen vmt = CONST_PTR_OFFSET(vmt, vmt->vmt_length);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen#elif defined(HAVE_SYS_MNTTAB_H)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* Solaris */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen f = fopen(MTAB_PATH, "r");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (f == NULL) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_error("fopen(%s) failed: %m", MTAB_PATH);
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen return -1;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen }
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen while ((getextmntent(f, &ent.ext, sizeof(ent.ext))) == 0) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (hasmntopt(&ent.ent, MNTOPT_IGNORE) != NULL)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen continue;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
/* mnt_type contains tmpfs with swap */
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;
}
}
fclose(f);
#else
/* Linux */
f = setmntent(MTAB_PATH, "r");
if (f == NULL) {
i_error("setmntent(%s) failed: %m", MTAB_PATH);
return -1;
}
while ((ent = getmntent(f)) != NULL) {
if (strcmp(ent->mnt_type, MNTTYPE_SWAP) == 0 ||
strcmp(ent->mnt_type, MNTTYPE_IGNORE) == 0)
continue;
if (stat(ent->mnt_dir, &st2) == 0 &&
CMP_DEV_T(st.st_dev, st2.st_dev)) {
device_path = ent->mnt_fsname;
mount_path = ent->mnt_dir;
type = ent->mnt_type;
break;
}
}
endmntent(f);
#endif
if (device_path == NULL)
return 0;
point_r->device_path = p_strdup(pool, device_path);
point_r->mount_path = p_strdup(pool, mount_path);
point_r->type = p_strdup(pool, type);
point_r->block_size = block_size;
return 1;
#endif
}