Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib/mountpoint.c @ 8590:b9faf4db2a9f HEAD
Updated copyright notices to include year 2009.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 06 Jan 2009 09:25:38 -0500 |
parents | 56c0494d8c49 |
children | 00cd9aacd03c |
line wrap: on
line source
/* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "mountpoint.h" #include <sys/stat.h> #ifdef HAVE_SYS_VMOUNT_H # include <stdio.h> # include <sys/vmount.h> /* AIX */ #elif defined(HAVE_STATVFS_MNTFROMNAME) # include <sys/statvfs.h> /* NetBSD 3.0+, FreeBSD 5.0+ */ # define STATVFS_STR "statvfs" #elif defined(HAVE_STATFS_MNTFROMNAME) # include <sys/param.h> /* Older BSDs */ # include <sys/mount.h> # define statvfs statfs # define STATVFS_STR "statfs" #elif defined(HAVE_MNTENT_H) # include <stdio.h> # include <mntent.h> /* Linux */ #elif defined(HAVE_SYS_MNTTAB_H) # include <stdio.h> # include <sys/mnttab.h> /* Solaris */ # include <sys/mntent.h> #else # define MOUNTPOINT_UNKNOWN #endif #ifdef HAVE_SYS_MNTTAB_H # define MTAB_PATH MNTTAB /* Solaris */ #else # define MTAB_PATH "/etc/mtab" /* Linux */ #endif /* AIX doesn't have these defined */ #ifndef MNTTYPE_SWAP # define MNTTYPE_SWAP "swap" #endif #ifndef MNTTYPE_IGNORE # define MNTTYPE_IGNORE "ignore" #endif #ifndef MNTTYPE_JFS # define MNTTYPE_JFS "jfs" #endif #ifndef MNTTYPE_NFS # define MNTTYPE_NFS "nfs" #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 (HAVE_STATFS_MNTFROMNAME) || defined(HAVE_STATVFS_MNTFROMNAME) /* BSDs */ struct statvfs buf; memset(point_r, 0, sizeof(*point_r)); if (statvfs(path, &buf) < 0) { if (errno == ENOENT) return 0; i_error(STATVFS_STR"(%s) failed: %m", path); return -1; } point_r->device_path = p_strdup(pool, buf.f_mntfromname); point_r->mount_path = p_strdup(pool, buf.f_mntonname); #ifdef __osf__ /* Tru64 */ point_r->type = p_strdup(pool, getvfsbynumber(buf.f_type)); #else point_r->type = p_strdup(pool, buf.f_fstypename); #endif point_r->block_size = buf.f_bsize; return 1; #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 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) { if (errno == ENOENT) return 0; i_error("stat(%s) failed: %m", path); return -1; } block_size = st.st_blksize; #ifdef HAVE_SYS_VMOUNT_H { char static_mtab[STATIC_MTAB_SIZE], *mtab = static_mtab; int i, count; const struct vmount *vmt; 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); } if (count < 0) { i_error("mntctl(MCTL_QUERY) failed: %m"); return -1; } 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; 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; 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; 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); } } #elif defined(HAVE_SYS_MNTTAB_H) /* Solaris */ f = fopen(MTAB_PATH, "r"); if (f == NULL) { i_error("fopen(%s) failed: %m", MTAB_PATH); return -1; } while ((getextmntent(f, &ent.ext, sizeof(ent.ext))) == 0) { if (hasmntopt(&ent.ent, MNTOPT_IGNORE) != NULL) continue; /* 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 }