mountpoint.c revision 2978aafcf8c306adc2e012aed00546a63c677784
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "lib.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "mountpoint.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen#include <sys/stat.h>
a1607f6001a9949e1cf9d49eb0aa936dbb4c77ffTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#ifdef HAVE_SYS_VMOUNT_H
00d58fcfe8191d6ce7efa801d289a5c0fe88d1aeTimo Sirainen# include <stdio.h>
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# include <sys/vmount.h> /* AIX */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#elif defined(HAVE_STATVFS_MNTFROMNAME)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen# include <sys/statvfs.h> /* NetBSD 3.0+, FreeBSD 5.0+ */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# define STATVFS_STR "statvfs"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#elif defined(HAVE_STATFS_MNTFROMNAME)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# include <sys/param.h> /* Older BSDs */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# include <sys/mount.h>
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# define statvfs statfs
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen# define STATVFS_STR "statfs"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#elif defined(HAVE_MNTENT_H)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen# include <stdio.h>
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen# include <mntent.h> /* Linux */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#elif defined(HAVE_SYS_MNTTAB_H)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen# include <stdio.h>
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen# include <sys/mnttab.h> /* Solaris */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen# include <sys/mntent.h>
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#else
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# define MOUNTPOINT_UNKNOWN
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#endif
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#ifdef HAVE_SYS_MNTTAB_H
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# define MTAB_PATH MNTTAB /* Solaris */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#else
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# define MTAB_PATH "/etc/mtab" /* Linux */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#endif
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen/* AIX doesn't have these defined */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#ifndef MNTTYPE_SWAP
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen# define MNTTYPE_SWAP "swap"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#endif
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#ifndef MNTTYPE_IGNORE
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen# define MNTTYPE_IGNORE "ignore"
4462bd7b4c7ef3de006f060e155a90e5de7cae21Timo Sirainen#endif
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen#ifndef MNTTYPE_JFS
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen# define MNTTYPE_JFS "jfs"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#endif
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#ifndef MNTTYPE_NFS
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen# define MNTTYPE_NFS "nfs"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#endif
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenint mountpoint_get(const char *path, pool_t pool, struct mountpoint *point_r)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#ifdef MOUNTPOINT_UNKNOWN
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen memset(point_r, 0, sizeof(*point_r));
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen errno = ENOSYS;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return -1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#elif defined (HAVE_STATFS_MNTFROMNAME) || defined(HAVE_STATVFS_MNTFROMNAME)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* BSDs */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct statvfs buf;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen memset(point_r, 0, sizeof(*point_r));
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (statvfs(path, &buf) < 0) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (errno == ENOENT)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return 0;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen i_error(STATVFS_STR"(%s) failed: %m", path);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return -1;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen point_r->device_path = p_strdup(pool, buf.f_mntfromname);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen point_r->mount_path = p_strdup(pool, buf.f_mntonname);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#ifdef __osf__ /* Tru64 */
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen point_r->type = p_strdup(pool, getvfsbynumber(buf.f_type));
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen#else
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen point_r->type = p_strdup(pool, buf.f_fstypename);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#endif
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen point_r->block_size = buf.f_bsize;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return 1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen#else
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen /* Linux, Solaris: /etc/mtab reading */
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen#ifdef HAVE_SYS_MNTTAB_H
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen union {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct mnttab ent;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct extmnttab ext;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen } ent;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#else
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen struct mntent *ent;
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen struct stat st2;
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen#endif
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen struct stat st;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const char *device_path = NULL, *mount_path = NULL, *type = NULL;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen unsigned int block_size;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen FILE *f;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen memset(point_r, 0, sizeof(*point_r));
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (stat(path, &st) < 0) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (errno == ENOENT)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen return 0;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen i_error("stat(%s) failed: %m", path);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen return -1;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen block_size = st.st_blksize;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#ifdef HAVE_SYS_VMOUNT_H
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen{
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen char static_mtab[STATIC_MTAB_SIZE], *mtab = static_mtab;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen int i, count;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen const struct vmount *vmt;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen count = mntctl(MCTL_QUERY, sizeof(static_mtab), mtab);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen while (count == 0) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen unsigned int size = *(unsigned int *)mtab;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen mtab = t_malloc(size);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen count = mntctl(MCTL_QUERY, size, mtab);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (count < 0) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen i_error("mntctl(MCTL_QUERY) failed: %m");
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen return -1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen vmt = (struct vmount *)mtab;
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen for (i = 0; i < count && device_path == NULL; i++) {
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen struct stat vst;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const char *vmt_base = (const char *)vmt;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const char *vmt_base, *vmt_object, *vmt_stub, *vmt_hostname;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen vmt_hostname = vmt_base + vmt->vmt_data[VMT_HOSTNAME].vmt_off;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen vmt_object = vmt_base + vmt->vmt_data[VMT_OBJECT].vmt_off;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen vmt_stub = vmt_base + vmt->vmt_data[VMT_STUB].vmt_off;
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen switch (vmt->vmt_gfstype) {
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen case MNT_NFS:
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen case MNT_NFS3:
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen case MNT_NFS4:
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen case MNT_RFS4:
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen if (stat(vmt_stub, &vst) == 0 &&
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen st.st_dev == vst.st_dev) {
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen device_path = t_strconcat(vmt_hostname, ":",
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen vmt_object, NULL);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mount_path = vmt_stub;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen type = MNTTYPE_NFS;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen break;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen case MNT_J2:
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen case MNT_JFS:
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen if (stat(vmt_stub, &vst) == 0 &&
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen st.st_dev == vst.st_dev) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen device_path = vmt_object;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen mount_path = vmt_stub;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen type = MNTTYPE_JFS;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen break;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
5d49cbcf87354f0ddf3b71bc5f0cefdc02b14f68Timo Sirainen vmt = CONST_PTR_OFFSET(vmt, vmt->vmt_length);
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen }
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen}
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen#elif defined(HAVE_SYS_MNTTAB_H)
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* Solaris */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen f = fopen(MTAB_PATH, "r");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (f == NULL) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen i_error("fopen(%s) failed: %m", MTAB_PATH);
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen return -1;
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen }
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen while ((getextmntent(f, &ent.ext, sizeof(ent.ext))) == 0) {
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen if (hasmntopt(&ent.ent, MNTOPT_IGNORE) != NULL)
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen continue;
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen /* mnt_type contains tmpfs with swap */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen if (strcmp(ent.ent.mnt_special, MNTTYPE_SWAP) == 0)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen continue;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (major(st.st_dev) == ent.ext.mnt_major &&
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen minor(st.st_dev) == ent.ext.mnt_minor) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen device_path = ent.ent.mnt_special;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen mount_path = ent.ent.mnt_mountp;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen type = ent.ent.mnt_fstype;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen break;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen fclose(f);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#else
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen /* Linux */
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen f = setmntent(MTAB_PATH, "r");
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen if (f == NULL) {
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen i_error("setmntent(%s) failed: %m", MTAB_PATH);
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen return -1;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen while ((ent = getmntent(f)) != NULL) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (strcmp(ent->mnt_type, MNTTYPE_SWAP) == 0 ||
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen strcmp(ent->mnt_type, MNTTYPE_IGNORE) == 0)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen continue;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (stat(ent->mnt_dir, &st2) == 0 &&
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen CMP_DEV_T(st.st_dev, st2.st_dev)) {
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen device_path = ent->mnt_fsname;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mount_path = ent->mnt_dir;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen type = ent->mnt_type;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen break;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen endmntent(f);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#endif
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (device_path == NULL)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return 0;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen point_r->device_path = p_strdup(pool, device_path);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen point_r->mount_path = p_strdup(pool, mount_path);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen point_r->type = p_strdup(pool, type);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen point_r->block_size = block_size;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return 1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#endif
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen