X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_mount.c;h=3cede018e243067d5f1bcfb71d5f9e76949b074e;hb=master;hp=e430cc9c2f789b497f1904ed6008d6ad3f4b1fb7;hpb=7c9d772c992647fcba64a96800c146eb9f1647f8;p=collectd.git diff --git a/src/utils_mount.c b/src/utils_mount.c deleted file mode 100644 index e430cc9c..00000000 --- a/src/utils_mount.c +++ /dev/null @@ -1,763 +0,0 @@ -/** - * collectd - src/utils_mount.c - * Copyright (C) 2005,2006 Niki W. Waibel - * - * This program is free software; you can redistribute it and/ - * or modify it under the terms of the GNU General Public Li- - * cence as published by the Free Software Foundation; either - * version 2 of the Licence, or any later version. - * - * This program is distributed in the hope that it will be use- - * ful, but WITHOUT ANY WARRANTY; without even the implied war- - * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Niki W. Waibel -**/ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#define _GNU_SOURCE - -#include "collectd.h" - -#include "utils_mount.h" - -#if HAVE_XFS_XQM_H -#include -#define XFS_SUPER_MAGIC_STR "XFSB" -#define XFS_SUPER_MAGIC2_STR "BSFX" -#endif - -#include "common.h" /* sstrncpy() et alii */ -#include "plugin.h" /* ERROR() macro */ - -#if HAVE_GETVFSSTAT -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_SYS_STATVFS_H -#include -#endif -/* #endif HAVE_GETVFSSTAT */ - -#elif HAVE_GETFSSTAT -#if HAVE_SYS_PARAM_H -#include -#endif -#if HAVE_SYS_UCRED_H -#include -#endif -#if HAVE_SYS_MOUNT_H -#include -#endif -#endif /* HAVE_GETFSSTAT */ - -#if HAVE_MNTENT_H -#include -#endif -#if HAVE_SYS_MNTTAB_H -#include -#endif - -#if HAVE_PATHS_H -#include -#endif - -#ifdef COLLECTD_MNTTAB -#undef COLLECTD_MNTTAB -#endif - -#if defined(_PATH_MOUNTED) /* glibc */ -#define COLLECTD_MNTTAB _PATH_MOUNTED -#elif defined(MNTTAB) /* Solaris */ -#define COLLECTD_MNTTAB MNTTAB -#elif defined(MNT_MNTTAB) -#define COLLECTD_MNTTAB MNT_MNTTAB -#elif defined(MNTTABNAME) -#define COLLECTD_MNTTAB MNTTABNAME -#elif defined(KMTAB) -#define COLLECTD_MNTTAB KMTAB -#else -#define COLLECTD_MNTTAB "/etc/mnttab" -#endif - -/* *** *** *** ********************************************* *** *** *** */ -/* *** *** *** *** *** *** private functions *** *** *** *** *** *** */ -/* *** *** *** ********************************************* *** *** *** */ - -/* stolen from quota-3.13 (quota-tools) */ - -#define PROC_PARTITIONS "/proc/partitions" -#define DEVLABELDIR "/dev" -#define UUID 1 -#define VOL 2 - -static struct uuidCache_s { - struct uuidCache_s *next; - char uuid[16]; - char *label; - char *device; -} *uuidCache = NULL; - -#define EXT2_SUPER_MAGIC 0xEF53 -struct ext2_super_block { - unsigned char s_dummy1[56]; - unsigned char s_magic[2]; - unsigned char s_dummy2[46]; - unsigned char s_uuid[16]; - char s_volume_name[16]; -}; -#define ext2magic(s) \ - ((unsigned int)s.s_magic[0] + (((unsigned int)s.s_magic[1]) << 8)) - -#if HAVE_XFS_XQM_H -struct xfs_super_block { - unsigned char s_magic[4]; - unsigned char s_dummy[28]; - unsigned char s_uuid[16]; - unsigned char s_dummy2[60]; - char s_fsname[12]; -}; -#endif /* HAVE_XFS_XQM_H */ - -#define REISER_SUPER_MAGIC "ReIsEr2Fs" -struct reiserfs_super_block { - unsigned char s_dummy1[52]; - unsigned char s_magic[10]; - unsigned char s_dummy2[22]; - unsigned char s_uuid[16]; - char s_volume_name[16]; -}; - -/* for now, only ext2 and xfs are supported */ -static int get_label_uuid(const char *device, char **label, char *uuid) { - /* start with ext2 and xfs tests, taken from mount_guess_fstype */ - /* should merge these later */ - int fd, rv = 1; - size_t namesize; - struct ext2_super_block e2sb; -#if HAVE_XFS_XQM_H - struct xfs_super_block xfsb; -#endif - struct reiserfs_super_block reisersb; - - fd = open(device, O_RDONLY); - if (fd == -1) { - return rv; - } - - if (lseek(fd, 1024, SEEK_SET) == 1024 && - read(fd, (char *)&e2sb, sizeof(e2sb)) == sizeof(e2sb) && - ext2magic(e2sb) == EXT2_SUPER_MAGIC) { - memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid)); - namesize = sizeof(e2sb.s_volume_name); - *label = smalloc(namesize + 1); - sstrncpy(*label, e2sb.s_volume_name, namesize); - rv = 0; -#if HAVE_XFS_XQM_H - } else if (lseek(fd, 0, SEEK_SET) == 0 && - read(fd, (char *)&xfsb, sizeof(xfsb)) == sizeof(xfsb) && - (strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC_STR, 4) == 0 || - strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC2_STR, 4) == 0)) { - memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid)); - namesize = sizeof(xfsb.s_fsname); - *label = smalloc(namesize + 1); - sstrncpy(*label, xfsb.s_fsname, namesize); - rv = 0; -#endif /* HAVE_XFS_XQM_H */ - } else if (lseek(fd, 65536, SEEK_SET) == 65536 && - read(fd, (char *)&reisersb, sizeof(reisersb)) == - sizeof(reisersb) && - !strncmp((char *)&reisersb.s_magic, REISER_SUPER_MAGIC, 9)) { - memcpy(uuid, reisersb.s_uuid, sizeof(reisersb.s_uuid)); - namesize = sizeof(reisersb.s_volume_name); - *label = smalloc(namesize + 1); - sstrncpy(*label, reisersb.s_volume_name, namesize); - rv = 0; - } - close(fd); - return rv; -} - -static void uuidcache_addentry(char *device, char *label, char *uuid) { - struct uuidCache_s *last; - - if (!uuidCache) { - last = uuidCache = smalloc(sizeof(*uuidCache)); - } else { - for (last = uuidCache; last->next; last = last->next) - ; - last->next = smalloc(sizeof(*uuidCache)); - last = last->next; - } - last->next = NULL; - last->device = device; - last->label = label; - memcpy(last->uuid, uuid, sizeof(last->uuid)); -} - -static void uuidcache_init(void) { - char line[100]; - char *s; - int ma, mi, sz; - static char ptname[100]; - FILE *procpt; - char uuid[16], *label = NULL; - char device[110]; - int handleOnFirst; - - if (uuidCache) { - return; - } - - procpt = fopen(PROC_PARTITIONS, "r"); - if (procpt == NULL) { - return; - } - - for (int firstPass = 1; firstPass >= 0; firstPass--) { - fseek(procpt, 0, SEEK_SET); - while (fgets(line, sizeof(line), procpt)) { - if (sscanf(line, " %d %d %d %[^\n ]", &ma, &mi, &sz, ptname) != 4) { - continue; - } - - /* skip extended partitions (heuristic: size 1) */ - if (sz == 1) { - continue; - } - - /* look only at md devices on first pass */ - handleOnFirst = !strncmp(ptname, "md", 2); - if (firstPass != handleOnFirst) { - continue; - } - - /* skip entire disk (minor 0, 64, ... on ide; - 0, 16, ... on sd) */ - /* heuristic: partition name ends in a digit */ - - for (s = ptname; *s; s++) - ; - - if (isdigit((int)s[-1])) { - /* - * Note: this is a heuristic only - there is no reason - * why these devices should live in /dev. - * Perhaps this directory should be specifiable by option. - * One might for example have /devlabel with links to /dev - * for the devices that may be accessed in this way. - * (This is useful, if the cdrom on /dev/hdc must not - * be accessed.) - */ - snprintf(device, sizeof(device), "%s/%s", DEVLABELDIR, ptname); - if (!get_label_uuid(device, &label, uuid)) { - uuidcache_addentry(sstrdup(device), label, uuid); - } - } - } - } - fclose(procpt); -} - -static unsigned char fromhex(char c) { - if (isdigit((int)c)) { - return c - '0'; - } else if (islower((int)c)) { - return c - 'a' + 10; - } else { - return c - 'A' + 10; - } -} - -static char *get_spec_by_x(int n, const char *t) { - struct uuidCache_s *uc; - - uuidcache_init(); - uc = uuidCache; - - while (uc) { - switch (n) { - case UUID: - if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) { - return sstrdup(uc->device); - } - break; - case VOL: - if (!strcmp(t, uc->label)) { - return sstrdup(uc->device); - } - break; - } - uc = uc->next; - } - return NULL; -} - -static char *get_spec_by_uuid(const char *s) { - char uuid[16]; - - if (strlen(s) != 36 || s[8] != '-' || s[13] != '-' || s[18] != '-' || - s[23] != '-') { - goto bad_uuid; - } - - for (int i = 0; i < 16; i++) { - if (*s == '-') { - s++; - } - if (!isxdigit((int)s[0]) || !isxdigit((int)s[1])) { - goto bad_uuid; - } - uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1])); - s += 2; - } - return get_spec_by_x(UUID, uuid); - -bad_uuid: - DEBUG("utils_mount: Found an invalid UUID: %s", s); - return NULL; -} - -static char *get_spec_by_volume_label(const char *s) { - return get_spec_by_x(VOL, s); -} - -static char *get_device_name(const char *optstr) { - char *rc; - - if (optstr == NULL) { - return NULL; - } else if (strncmp(optstr, "UUID=", 5) == 0) { - DEBUG("utils_mount: TODO: check UUID= code!"); - rc = get_spec_by_uuid(optstr + 5); - } else if (strncmp(optstr, "LABEL=", 6) == 0) { - DEBUG("utils_mount: TODO: check LABEL= code!"); - rc = get_spec_by_volume_label(optstr + 6); - } else { - rc = sstrdup(optstr); - } - - if (!rc) { - DEBUG("utils_mount: Error checking device name: optstr = %s", optstr); - } - return rc; -} - -/* What weird OS is this..? I can't find any info with google :/ -octo */ -#if HAVE_LISTMNTENT && 0 -static cu_mount_t *cu_mount_listmntent(void) { - cu_mount_t *last = *list; - struct mntent *mnt; - - struct tabmntent *mntlist; - if (listmntent(&mntlist, COLLECTD_MNTTAB, NULL, NULL) < 0) { -#if COLLECT_DEBUG - DEBUG("utils_mount: calling listmntent() failed: %s", STRERRNO); -#endif /* COLLECT_DEBUG */ - } - - for (struct tabmntent *p = mntlist; p; p = p->next) { - char *loop = NULL, *device = NULL; - - mnt = p->ment; - loop = cu_mount_getoptionvalue(mnt->mnt_opts, "loop="); - if (loop == NULL) { /* no loop= mount */ - device = get_device_name(mnt->mnt_fsname); - if (device == NULL) { - DEBUG("utils_mount: can't get devicename for fs (%s) %s (%s)" - ": ignored", - mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname); - continue; - } - } else { - device = loop; - } - if (*list == NULL) { - *list = (cu_mount_t *)smalloc(sizeof(cu_mount_t)); - last = *list; - } else { - while (last->next != NULL) { /* is last really last? */ - last = last->next; - } - last->next = (cu_mount_t *)smalloc(sizeof(cu_mount_t)); - last = last->next; - } - last->dir = sstrdup(mnt->mnt_dir); - last->spec_device = sstrdup(mnt->mnt_fsname); - last->device = device; - last->type = sstrdup(mnt->mnt_type); - last->options = sstrdup(mnt->mnt_opts); - last->next = NULL; - } /* for(p = mntlist; p; p = p->next) */ - - return last; -} /* cu_mount_t *cu_mount_listmntent(void) */ -/* #endif HAVE_LISTMNTENT */ - -/* 4.4BSD and Mac OS X (getfsstat) or NetBSD (getvfsstat) */ -#elif HAVE_GETVFSSTAT || HAVE_GETFSSTAT -static cu_mount_t *cu_mount_getfsstat(void) { -#if HAVE_GETFSSTAT -#define STRUCT_STATFS struct statfs -#define CMD_STATFS getfsstat -#define FLAGS_STATFS MNT_NOWAIT -/* #endif HAVE_GETFSSTAT */ -#elif HAVE_GETVFSSTAT -#define STRUCT_STATFS struct statvfs -#define CMD_STATFS getvfsstat -#define FLAGS_STATFS ST_NOWAIT -#endif /* HAVE_GETVFSSTAT */ - - int bufsize; - STRUCT_STATFS *buf; - - int num; - - cu_mount_t *first = NULL; - cu_mount_t *last = NULL; - cu_mount_t *new = NULL; - - /* Get the number of mounted file systems */ - if ((bufsize = CMD_STATFS(NULL, 0, FLAGS_STATFS)) < 1) { -#if COLLECT_DEBUG - DEBUG("utils_mount: getv?fsstat failed: %s", STRERRNO); -#endif /* COLLECT_DEBUG */ - return NULL; - } - - if ((buf = calloc(bufsize, sizeof(*buf))) == NULL) - return NULL; - - /* The bufsize needs to be passed in bytes. Really. This is not in the - * manpage.. -octo */ - if ((num = CMD_STATFS(buf, bufsize * sizeof(STRUCT_STATFS), FLAGS_STATFS)) < - 1) { -#if COLLECT_DEBUG - DEBUG("utils_mount: getv?fsstat failed: %s", STRERRNO); -#endif /* COLLECT_DEBUG */ - free(buf); - return NULL; - } - - for (int i = 0; i < num; i++) { - if ((new = calloc(1, sizeof(*new))) == NULL) - break; - - /* Copy values from `struct mnttab' */ - new->dir = sstrdup(buf[i].f_mntonname); - new->spec_device = sstrdup(buf[i].f_mntfromname); - new->type = sstrdup(buf[i].f_fstypename); - new->options = NULL; - new->device = get_device_name(new->options); - new->next = NULL; - - /* Append to list */ - if (first == NULL) { - first = new; - last = new; - } else { - last->next = new; - last = new; - } - } - - free(buf); - - return first; -} -/* #endif HAVE_GETVFSSTAT || HAVE_GETFSSTAT */ - -/* Solaris (SunOS 10): int getmntent(FILE *fp, struct mnttab *mp); */ -#elif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT -static cu_mount_t *cu_mount_gen_getmntent(void) { - struct mnttab mt; - FILE *fp; - - cu_mount_t *first = NULL; - cu_mount_t *last = NULL; - cu_mount_t *new = NULL; - - DEBUG("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB); - - if ((fp = fopen(COLLECTD_MNTTAB, "r")) == NULL) { - ERROR("fopen (%s): %s", COLLECTD_MNTTAB, STRERRNO); - return NULL; - } - - while (getmntent(fp, &mt) == 0) { - if ((new = calloc(1, sizeof(*new))) == NULL) - break; - - /* Copy values from `struct mnttab' */ - new->dir = sstrdup(mt.mnt_mountp); - new->spec_device = sstrdup(mt.mnt_special); - new->type = sstrdup(mt.mnt_fstype); - new->options = sstrdup(mt.mnt_mntopts); - new->device = get_device_name(new->options); - new->next = NULL; - - /* Append to list */ - if (first == NULL) { - first = new; - last = new; - } else { - last->next = new; - last = new; - } - } - - fclose(fp); - - return first; -} /* static cu_mount_t *cu_mount_gen_getmntent (void) */ - -#elif HAVE_SEQ_GETMNTENT -#warn "This version of `getmntent' hat not yet been implemented!" -/* #endif HAVE_SEQ_GETMNTENT */ - -#elif HAVE_GETMNTENT_R -static cu_mount_t *cu_mount_getmntent(void) { - FILE *fp; - struct mntent me; - char mntbuf[1024]; - - cu_mount_t *first = NULL; - cu_mount_t *last = NULL; - cu_mount_t *new = NULL; - - DEBUG("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB); - - if ((fp = setmntent(COLLECTD_MNTTAB, "r")) == NULL) { - ERROR("setmntent (%s): %s", COLLECTD_MNTTAB, STRERRNO); - return NULL; - } - - while (getmntent_r(fp, &me, mntbuf, sizeof(mntbuf))) { - if ((new = calloc(1, sizeof(*new))) == NULL) - break; - - /* Copy values from `struct mntent *' */ - new->dir = sstrdup(me.mnt_dir); - new->spec_device = sstrdup(me.mnt_fsname); - new->type = sstrdup(me.mnt_type); - new->options = sstrdup(me.mnt_opts); - new->device = get_device_name(new->options); - new->next = NULL; - - DEBUG("utils_mount: new = {dir = %s, spec_device = %s, type = %s, options " - "= %s, device = %s}", - new->dir, new->spec_device, new->type, new->options, new->device); - - /* Append to list */ - if (first == NULL) { - first = new; - last = new; - } else { - last->next = new; - last = new; - } - } - - endmntent(fp); - - DEBUG("utils_mount: return 0x%p", (void *)first); - - return first; -} /* HAVE_GETMNTENT_R */ - -#elif HAVE_ONE_GETMNTENT -static cu_mount_t *cu_mount_getmntent(void) { - FILE *fp; - struct mntent *me; - - cu_mount_t *first = NULL; - cu_mount_t *last = NULL; - cu_mount_t *new = NULL; - - DEBUG("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB); - - if ((fp = setmntent(COLLECTD_MNTTAB, "r")) == NULL) { - ERROR("setmntent (%s): %s", COLLECTD_MNTTAB, STRERRNO); - return NULL; - } - - while ((me = getmntent(fp)) != NULL) { - if ((new = calloc(1, sizeof(*new))) == NULL) - break; - - /* Copy values from `struct mntent *' */ - new->dir = sstrdup(me->mnt_dir); - new->spec_device = sstrdup(me->mnt_fsname); - new->type = sstrdup(me->mnt_type); - new->options = sstrdup(me->mnt_opts); - new->device = get_device_name(new->options); - new->next = NULL; - - DEBUG("utils_mount: new = {dir = %s, spec_device = %s, type = %s, options " - "= %s, device = %s}", - new->dir, new->spec_device, new->type, new->options, new->device); - - /* Append to list */ - if (first == NULL) { - first = new; - last = new; - } else { - last->next = new; - last = new; - } - } - - endmntent(fp); - - DEBUG("utils_mount: return 0x%p", (void *)first); - - return first; -} -#endif /* HAVE_ONE_GETMNTENT */ - -/* *** *** *** ******************************************** *** *** *** */ -/* *** *** *** *** *** *** public functions *** *** *** *** *** *** */ -/* *** *** *** ******************************************** *** *** *** */ - -cu_mount_t *cu_mount_getlist(cu_mount_t **list) { - cu_mount_t *new; - cu_mount_t *first = NULL; - cu_mount_t *last = NULL; - - if (list == NULL) - return NULL; - - if (*list != NULL) { - first = *list; - last = first; - while (last->next != NULL) - last = last->next; - } - -#if HAVE_LISTMNTENT && 0 - new = cu_mount_listmntent(); -#elif HAVE_GETVFSSTAT || HAVE_GETFSSTAT - new = cu_mount_getfsstat(); -#elif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT - new = cu_mount_gen_getmntent(); -#elif HAVE_SEQ_GETMNTENT -#error "This version of `getmntent' hat not yet been implemented!" -#elif HAVE_ONE_GETMNTENT - new = cu_mount_getmntent(); -#else -#error "Could not determine how to find mountpoints." -#endif - - if (first != NULL) { - last->next = new; - } else { - first = new; - last = new; - *list = first; - } - - while ((last != NULL) && (last->next != NULL)) - last = last->next; - - return last; -} /* cu_mount_t *cu_mount_getlist(cu_mount_t **list) */ - -void cu_mount_freelist(cu_mount_t *list) { - cu_mount_t *next; - - for (cu_mount_t *this = list; this != NULL; this = next) { - next = this->next; - - sfree(this->dir); - sfree(this->spec_device); - sfree(this->device); - sfree(this->type); - sfree(this->options); - sfree(this); - } -} /* void cu_mount_freelist(cu_mount_t *list) */ - -char *cu_mount_checkoption(char *line, const char *keyword, int full) { - char *line2, *l2, *p1, *p2; - size_t l; - - if (line == NULL || keyword == NULL) { - return NULL; - } - - if (full != 0) { - full = 1; - } - - line2 = sstrdup(line); - l2 = line2; - while (*l2 != '\0') { - if (*l2 == ',') { - *l2 = '\0'; - } - l2++; - } - - l = strlen(keyword); - p1 = line - 1; - p2 = strchr(line, ','); - do { - if (strncmp(line2 + (p1 - line) + 1, keyword, l + full) == 0) { - free(line2); - return p1 + 1; - } - p1 = p2; - if (p1 != NULL) { - p2 = strchr(p1 + 1, ','); - } - } while (p1 != NULL); - - free(line2); - return NULL; -} /* char *cu_mount_checkoption(char *line, char *keyword, int full) */ - -char *cu_mount_getoptionvalue(char *line, const char *keyword) { - char *r; - - r = cu_mount_checkoption(line, keyword, 0); - if (r != NULL) { - char *p; - r += strlen(keyword); - p = strchr(r, ','); - if (p == NULL) { - return sstrdup(r); - } else { - char *m; - if ((p - r) == 1) { - return NULL; - } - m = smalloc(p - r + 1); - sstrncpy(m, r, p - r + 1); - return m; - } - } - return r; -} /* char *cu_mount_getoptionvalue(char *line, const char *keyword) */ - -int cu_mount_type(const char *type) { - if (strcmp(type, "ext3") == 0) - return CUMT_EXT3; - if (strcmp(type, "ext2") == 0) - return CUMT_EXT2; - if (strcmp(type, "ufs") == 0) - return CUMT_UFS; - if (strcmp(type, "vxfs") == 0) - return CUMT_VXFS; - if (strcmp(type, "zfs") == 0) - return CUMT_ZFS; - return CUMT_UNKNOWN; -} /* int cu_mount_type(const char *type) */