X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_mount.c;h=3cede018e243067d5f1bcfb71d5f9e76949b074e;hb=f2398e39bc84d49081ca5bdd216584acf70013a0;hp=ecfd0ec6b6515d00ddd5f5570af9badccb1ec585;hpb=76dc4d3055400e59c453ed1ffbfa70c0a28eae15;p=collectd.git diff --git a/src/utils_mount.c b/src/utils_mount.c index ecfd0ec6..3cede018 100644 --- a/src/utils_mount.c +++ b/src/utils_mount.c @@ -1,6 +1,6 @@ /** * collectd - src/utils_mount.c - * Copyright (C) 2005 Niki W. Waibel + * 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- @@ -21,7 +21,9 @@ * Niki W. Waibel **/ - +#if HAVE_CONFIG_H +# include "config.h" +#endif #include "common.h" #if HAVE_XFS_XQM_H @@ -29,17 +31,64 @@ #define XFS_SUPER_MAGIC_STR "XFSB" #define XFS_SUPER_MAGIC2_STR "BSFX" #endif -#include "utils_debug.h" + +#include "plugin.h" #include "utils_mount.h" +#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" @@ -211,7 +260,7 @@ uuidcache_init(void) * (This is useful, if the cdrom on /dev/hdc must not * be accessed.) */ - snprintf(device, sizeof(device), "%s/%s", + ssnprintf(device, sizeof(device), "%s/%s", DEVLABELDIR, ptname); if(!get_label_uuid(device, &label, uuid)) { uuidcache_addentry(sstrdup(device), @@ -285,57 +334,62 @@ get_spec_by_uuid(const char *s) return get_spec_by_x(UUID, uuid); bad_uuid: - DBG("Found an invalid UUID: %s", s); + DEBUG("utils_mount: Found an invalid UUID: %s", s); return NULL; } -static char * -get_spec_by_volume_label(const char *s) +static char *get_spec_by_volume_label(const char *s) { - return get_spec_by_x(VOL, s); + return get_spec_by_x (VOL, s); } -static char * -get_device_name(const char *item) +static char *get_device_name(const char *optstr) { char *rc; - if(!strncmp(item, "UUID=", 5)) { - DBG("TODO: check UUID= code!"); - rc = get_spec_by_uuid(item + 5); - } else if(!strncmp(item, "LABEL=", 6)) { - DBG("TODO: check LABEL= code!"); - rc = get_spec_by_volume_label(item + 6); - } else { - rc = sstrdup(item); + if (optstr == NULL) + { + return (NULL); } - if(!rc) { - DBG("Error checking device name: %s", item); + 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); } - return rc; -} - - -#if HAVE_GETVFSENT -static void -cu_mount_getvfsmnt(FILE *mntf, cu_mount_t **list) -{ - DBG("TODO: getvfsmnt"); - *list = NULL; + if(!rc) + { + DEBUG ("utils_mount: Error checking device name: optstr = %s", optstr); + } + return rc; } -#endif /* HAVE_GETVFSENT */ - - -#if HAVE_LISTMNTENT -static cu_mount_t * -cu_mount_listmntent(struct tabmntent *mntlist, cu_mount_t **list) +/* 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 tabmntent *p; struct mntent *mnt; + struct tabmntent *mntlist; + if(listmntent(&mntlist, COLLECTD_MNTTAB, NULL, NULL) < 0) { +#if COLLECT_DEBUG + char errbuf[1024]; + DEBUG("utils_mount: calling listmntent() failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); +#endif /* COLLECT_DEBUG */ + } + for(p = mntlist; p; p = p->next) { char *loop = NULL, *device = NULL; @@ -344,7 +398,7 @@ cu_mount_listmntent(struct tabmntent *mntlist, cu_mount_t **list) if(loop == NULL) { /* no loop= mount */ device = get_device_name(mnt->mnt_fsname); if(device == NULL) { - DBG("can't get devicename for fs (%s) %s (%s)" + DEBUG("utils_mount: can't get devicename for fs (%s) %s (%s)" ": ignored", mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname); continue; @@ -371,242 +425,282 @@ cu_mount_listmntent(struct tabmntent *mntlist, cu_mount_t **list) } /* for(p = mntlist; p; p = p->next) */ return(last); -} /* static cu_mount_t *cu_mount_listmntent(struct tabmntent *mntlist, - cu_mount_t **list) */ -#endif /* HAVE_LISTMNTENT */ +} /* 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_GETVFSSTAT +# define STRUCT_STATFS struct statvfs +# define CMD_STATFS getvfsstat +# define FLAGS_STATFS ST_NOWAIT +/* #endif HAVE_GETVFSSTAT */ +#elif HAVE_GETFSSTAT +# define STRUCT_STATFS struct statfs +# define CMD_STATFS getfsstat +# define FLAGS_STATFS MNT_NOWAIT +#endif /* HAVE_GETFSSTAT */ + + int bufsize; + STRUCT_STATFS *buf; + + int num; + int i; + + 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 + char errbuf[1024]; + DEBUG ("utils_mount: getv?fsstat failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); +#endif /* COLLECT_DEBUG */ + return (NULL); + } + + if ((buf = (STRUCT_STATFS *) malloc (bufsize * sizeof (STRUCT_STATFS))) + == NULL) + return (NULL); + memset (buf, '\0', bufsize * sizeof (STRUCT_STATFS)); + + /* 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 + char errbuf[1024]; + DEBUG ("utils_mount: getv?fsstat failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); +#endif /* COLLECT_DEBUG */ + free (buf); + return (NULL); + } + + for (i = 0; i < num; i++) + { + if ((new = malloc (sizeof (cu_mount_t))) == NULL) + break; + memset (new, '\0', sizeof (cu_mount_t)); + + /* 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 */ -#if HAVE_GETMNTENT -static cu_mount_t * -cu_mount_getmntent(FILE *mntf, cu_mount_t **list) +/* 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) { - cu_mount_t *last = *list; -#if HAVE_GETMNTENT1 - struct mntent *mnt = NULL; -#endif -#if HAVE_GETMNTENT2 - struct mntent real_mnt; - struct mntent *mnt = &real_mnt; -#endif + struct mnttab mt; + FILE *fp; -#if HAVE_GETMNTENT1 - while((mnt = getmntent(mntf)) != NULL) { -#endif -#if HAVE_GETMNTENT2 - while(getmntent(mntf, &real_mnt) == 0) { -#endif - char *loop = NULL, *device = NULL; + cu_mount_t *first = NULL; + cu_mount_t *last = NULL; + cu_mount_t *new = NULL; -#if 0 - DBG("------------------ BEGIN"); - DBG("mnt->mnt_fsname %s", mnt->mnt_fsname); - DBG("mnt->mnt_dir %s", mnt->mnt_dir); - DBG("mnt->mnt_type %s", mnt->mnt_type); - DBG("mnt->mnt_opts %s", mnt->mnt_opts); - DBG("mnt->mnt_freq %d", mnt->mnt_freq); - DBG("mnt->mnt_passno %d", mnt->mnt_passno); -#endif + DEBUG ("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB); - loop = cu_mount_getoptionvalue(mnt->mnt_opts, "loop="); - if(loop == NULL) { /* no loop= mount */ - device = get_device_name(mnt->mnt_fsname); - if(device == NULL) { - DBG("can't get devicename for fs (%s) %s (%s)" - ": ignored", mnt->mnt_type, - mnt->mnt_dir, mnt->mnt_fsname); - continue; - } - } else { - device = loop; + if ((fp = fopen (COLLECTD_MNTTAB, "r")) == NULL) + { + char errbuf[1024]; + ERROR ("fopen (%s): %s", COLLECTD_MNTTAB, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (NULL); + } + + while (getmntent (fp, &mt) == 0) + { + if ((new = malloc (sizeof (cu_mount_t))) == NULL) + break; + memset (new, '\0', sizeof (cu_mount_t)); + + /* 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; + } + } -#if 0 - DBG("device: %s", device); - DBG("------------------ END"); -#endif - 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; + fclose (fp); + + return (first); +} /* static cu_mount_t *cu_mount_gen_getmntent (void) */ +/* #endif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT */ + +#elif HAVE_SEQ_GETMNTENT +#warn "This version of `getmntent' hat not yet been implemented!" +/* #endif HAVE_SEQ_GETMNTENT */ + +#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) + { + char errbuf[1024]; + ERROR ("setmntent (%s): %s", COLLECTD_MNTTAB, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (NULL); + } + + while ((me = getmntent (fp)) != NULL) + { + if ((new = malloc (sizeof (cu_mount_t))) == NULL) + break; + memset (new, '\0', sizeof (cu_mount_t)); + + /* 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; } - 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; -#if HAVE_GETMNTENT2 - } /* while(getmntent(mntf, &real_mnt) == 0) */ -#endif -#if HAVE_GETMNTENT1 - } /* while((mnt = getmntent(mntf)) != NULL) */ -#endif + else + { + last->next = new; + last = new; + } + } - return last; -} /* static cu_mount_t *cu_mount_getmntent(FILE *mntf, cu_mount_t **list) */ -#endif /* HAVE_GETMNTENT */ + 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 *cu_mount_getlist(cu_mount_t **list) { - cu_mount_t *last = NULL; - - /* see lib/mountlist.c of coreutils for all (ugly) details! */ - -/* - there are two implementations of getmntent(): - * one argument getmntent: - FILE *setmntent(const char *filename, const char *type); - struct mntent *getmntent(FILE *fp); - int endmntent(FILE *fp); - * two argument getmntent: - FILE *fopen(const char *path, const char *mode); - int getmntent(FILE *fp, struct mnttab *mnt); - int fclose(FILE *fp); - and a third (linux/gnu style) version called getmntent_r, which is not used - here (enough trouble with the two versions above). -*/ -#if HAVE_GETMNTENT -# if HAVE_GETMNTENT1 -# define setmntent setmntent -# define endmntent endmntent -# else -# if HAVE_GETMNTENT2 -# define setmntent fopen -# define endmntent fclose -# else -# error HAVE_GETMNTENT defined, but neither HAVE_GETMNTENT1 nor HAVE_GETMNTENT2 -# endif /* HAVE_GETMNTENT2 */ -# endif /* HAVE_GETMNTENT1 */ -#endif /* HAVE_GETMNTENT */ - - /* the indentation is wrong. is there a better way to do this? */ - -#if HAVE_GETMNTENT && defined(_PATH_MOUNTED) - { - FILE *mntf = NULL; - if((mntf = setmntent(_PATH_MOUNTED, "r")) == NULL) { - DBG("opening %s failed: %s", _PATH_MOUNTED, strerror(errno)); -#endif -#if HAVE_GETMNTENT && defined(MNT_MNTTAB) - { - FILE *mntf = NULL; - if((mntf = setmntent(MNT_MNTTAB, "r")) == NULL) { - DBG("opening %s failed: %s", MNT_MNTTAB, strerror(errno)); -#endif -#if HAVE_GETMNTENT && defined(MNTTABNAME) - { - FILE *mntf = NULL; - if((mntf = setmntent(MNTTABNAME, "r")) == NULL) { - DBG("opening %s failed: %s", MNTTABNAME, strerror(errno)); -#endif -#if HAVE_LISTMNTENT - { - struct tabmntent *mntlist; - if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) { - DBG("calling listmntent() failed: %s", strerror(errno)); -#endif -#if HAVE_GETVFSENT && defined(VFSTAB) - /* this is as bad as the next one, read next comment */ - { - FILE *mntf = NULL; - if((mntf = fopen(VFSTAB, "r")) == NULL) { - DBG("opening %s failed: %s", VFSTAB, strerror(errno)); -#endif -#if HAVE_GETMNTENT && defined(_PATH_MNTTAB) - /* _PATH_MNTTAB is usually /etc/fstab and so this should be really - the very last thing to try, because it does not provide a list - of currently mounted filesystems... */ - { - FILE *mntf = NULL; - if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) { - DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno)); -#endif + cu_mount_t *new; + cu_mount_t *first = NULL; + cu_mount_t *last = NULL; - /* give up */ - DBG("failed get local mountpoints"); - return(NULL); + if (list == NULL) + return (NULL); -#if HAVE_GETMNTENT && defined(_PATH_MNTTAB) - } else { last = cu_mount_getmntent(mntf, list); } - (void)endmntent(mntf); - } -#endif -#if HAVE_GETVFSENT && defined(VFSTAB) - } else { last = cu_mount_getvfsmnt(mntf, list); } - (void)fclose(mntf); - } -#endif -#if HAVE_LISTMNTENT - } else { last = cu_mount_listmntent(mntlist, list); } - freemntlist(mntlist); - } -#endif -#if HAVE_GETMNTENT && defined(MNTTABNAME) - } else { last = cu_mount_getmntent(mntf, list); } - (void)endmntent(mntf); + 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 HAVE_GETMNTENT && defined(MNT_MNTTAB) - } else { last = cu_mount_getmntent(mntf, list); } - (void)endmntent(mntf); + + if (first != NULL) + { + last->next = new; } -#endif -#if HAVE_GETMNTENT && defined(_PATH_MOUNTED) - } else { last = cu_mount_getmntent(mntf, list); } - (void)endmntent(mntf); + else + { + first = new; + last = new; + *list = first; } -#endif - return(last); -} /* cu_mount_t *cu_mount_getlist(cu_mount_t **list) */ + 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) +void cu_mount_freelist (cu_mount_t *list) { - cu_mount_t *l = list, *p = NULL; + cu_mount_t *this; + cu_mount_t *next; - while(l != NULL) { - while(l->next != NULL) { - p = l; - l = l->next; - } - if(p != NULL) { - p->next = NULL; - } - sfree(l->dir); - sfree(l->spec_device); - sfree(l->device); - sfree(l->type); - sfree(l->options); - p = NULL; - if(l != list) { - sfree(l); - l = list; - } else { - sfree(l); - l = NULL; /* done by sfree already */ - } - } /* while(l != NULL) */ + for (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, char *keyword, int full) { @@ -647,8 +741,6 @@ cu_mount_checkoption(char *line, char *keyword, int full) return NULL; } /* char *cu_mount_checkoption(char *line, char *keyword, int full) */ - - char * cu_mount_getoptionvalue(char *line, char *keyword) { @@ -660,9 +752,6 @@ cu_mount_getoptionvalue(char *line, char *keyword) r += strlen(keyword); p = strchr(r, ','); if(p == NULL) { - if(strlen(r) == 0) { - return NULL; - } return sstrdup(r); } else { char *m; @@ -677,8 +766,6 @@ cu_mount_getoptionvalue(char *line, char *keyword) return r; } /* char *cu_mount_getoptionvalue(char *line, char *keyword) */ - - int cu_mount_type(const char *type) { @@ -690,5 +777,3 @@ cu_mount_type(const char *type) return CUMT_UNKNOWN; } /* int cu_mount_type(const char *type) */ - -