some fixes
authorniki <niki>
Mon, 12 Dec 2005 06:45:38 +0000 (06:45 +0000)
committerniki <niki>
Mon, 12 Dec 2005 06:45:38 +0000 (06:45 +0000)
16 files changed:
clean.sh [new file with mode: 0755]
configure.in
contrib/users [changed mode: 0644->0755]
src/Makefile.am
src/collectd.h
src/plugin.c
src/processes.c [new file with mode: 0644]
src/quota_fs.c
src/quota_fs.h
src/quota_mnt.c
src/quota_mnt.h
src/users.h
src/utils_debug.c
src/utils_debug.h
src/utils_mount.c
src/utils_mount.h

diff --git a/clean.sh b/clean.sh
new file mode 100755 (executable)
index 0000000..5733f2e
--- /dev/null
+++ b/clean.sh
@@ -0,0 +1,46 @@
+#! /bin/sh
+
+set -x
+
+true \
+&& rm -f aclocal.m4 \
+&& rm -f -r autom4te.cache \
+&& rm -f collectd-*.tar.bz2 \
+&& rm -f collectd-*.tar.gz \
+&& rm -f compile \
+&& rm -f config.guess \
+&& rm -f config.log \
+&& rm -f config.status \
+&& rm -f config.sub \
+&& rm -f configure \
+&& rm -f depcomp \
+&& rm -f install-sh \
+&& rm -f -r libltdl \
+&& rm -f libtool \
+&& rm -f ltmain.sh \
+&& rm -f Makefile \
+&& rm -f Makefile.in \
+&& rm -f missing \
+&& rm -f -r src/.deps \
+&& rm -f -r src/.libs \
+&& rm -f src/*.o \
+&& rm -f src/*.la \
+&& rm -f src/*.lo \
+&& rm -f src/collectd \
+&& rm -f src/collectd.1 \
+&& rm -f src/config.h \
+&& rm -f src/config.h.in \
+&& rm -f src/config.h.in~ \
+&& rm -f src/Makefile \
+&& rm -f src/Makefile.in \
+&& rm -f src/stamp-h1 \
+&& rm -f src/stamp-h1.in \
+&& rm -f -r src/libping/.libs \
+&& rm -f src/libping/*.o \
+&& rm -f src/libping/*.la \
+&& rm -f src/libping/*.lo \
+&& rm -f src/libping/config.h \
+&& rm -f src/libping/config.h.in \
+&& rm -f src/libping/Makefile \
+&& rm -f src/libping/Makefile.in \
+&& rm -f src/libping/stamp-h2
index 33d0383..5f7453a 100644 (file)
@@ -1,7 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(collectd, 3.5.alpha1-quota)
 AC_CONFIG_SRCDIR(src/collectd.c)
-AC_CONFIG_HEADERS(src/config.h src/libping/config.h)
+AC_CONFIG_HEADERS(src/config.h)
 AM_INIT_AUTOMAKE(dist-bzip2)
 AC_LANG(C)
 
@@ -30,6 +30,7 @@ AC_CONFIG_SUBDIRS(libltdl)
 # Checks for header files.
 #
 AC_HEADER_SYS_WAIT
+AC_HEADER_DIRENT
 AC_CHECK_HEADERS(fcntl.h)
 AC_CHECK_HEADERS(signal.h)
 AC_CHECK_HEADERS(sys/socket.h)
@@ -54,19 +55,24 @@ AC_CHECK_HEADERS(utmp.h)
 AC_CHECK_HEADERS(utmpx.h)
 
 # For quota module
-AC_CHECK_HEADERS(grp.h pwd.h)
+AC_CHECK_HEADERS(grp.h pwd.h sys/ucred.h)
 AC_CHECK_HEADERS(ctype.h)
 AC_CHECK_HEADERS(limits.h)
 AC_CHECK_HEADERS(sys/quota.h)
 AC_CHECK_HEADERS(xfs/xqm.h)
 
 # For mount interface
+AC_CHECK_HEADERS(fs_info.h)
+AC_CHECK_HEADERS(fshelp.h)
 AC_CHECK_HEADERS(paths.h)
 AC_CHECK_HEADERS(mntent.h)
+AC_CHECK_HEADERS(mnttab.h)
+AC_CHECK_HEADERS(sys/fstyp.h)
 AC_CHECK_HEADERS(sys/fs_types.h)
 AC_CHECK_HEADERS(sys/mntent.h)
 AC_CHECK_HEADERS(sys/mnttab.h)
 AC_CHECK_HEADERS(sys/mount.h)
+AC_CHECK_HEADERS(sys/statfs.h)
 AC_CHECK_HEADERS(sys/vfs.h)
 AC_CHECK_HEADERS(sys/vfstab.h)
 
old mode 100644 (file)
new mode 100755 (executable)
index cab7265..fe1076b 100644 (file)
@@ -1,5 +1,5 @@
 if BUILD_MODULE_PING
-SUBDIRS = libping
+SUBDIRS = libping .
 endif
 
 sbin_PROGRAMS = collectd
index a66647a..1614483 100644 (file)
@@ -2,12 +2,9 @@
 #define COLLECTD_H
 
 #if HAVE_CONFIG_H
-# include "config.h"
+# include <config.h>
 #endif
 
-#if HAVE_STDARG_H
-# include <stdarg.h>
-#endif
 #include <stdio.h>
 #if HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #  include <time.h>
 # endif
 #endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
+#if HAVE_STDARG_H
+# include <stdarg.h>
+#endif
 #if HAVE_CTYPE_H
 # include <ctype.h>
 #endif
index 1a3ab34..20735ba 100644 (file)
@@ -1,7 +1,6 @@
 #include "collectd.h"
 
 #include <ltdl.h>
-#include <dirent.h>
 
 #include "plugin.h"
 #include "multicast.h"
diff --git a/src/processes.c b/src/processes.c
new file mode 100644 (file)
index 0000000..94e86dd
--- /dev/null
@@ -0,0 +1,129 @@
+#include "processes.h"
+
+/*
+ * Originally written by Lyonel Vincent
+ */
+
+#if COLLECT_PROCESSES
+#define MODULE_NAME "processes"
+
+#include "common.h"
+#include "plugin.h"
+
+static char *ps_file = "processes.rrd";
+
+static char *ds_def[] =
+{
+       "DS:running:GAUGE:25:0:65535",
+       "DS:sleeping:GAUGE:25:0:65535",
+       "DS:zombies:GAUGE:25:0:65535",
+       "DS:stopped:GAUGE:25:0:65535",
+       "DS:paging:GAUGE:25:0:65535",
+       "DS:blocked:GAUGE:25:0:65535",
+       NULL
+};
+static int ds_num = 6;
+
+extern time_t curtime;
+
+void ps_init (void)
+{
+}
+
+void ps_write (char *host, char *inst, char *val)
+{
+       rrd_update_file (host, ps_file, val, ds_def, ds_num);
+}
+
+#define BUFSIZE 256
+void ps_submit (unsigned int running,
+               unsigned int sleeping,
+               unsigned int zombies,
+               unsigned int stopped,
+               unsigned int paging,
+               unsigned int blocked)
+{
+       char buf[BUFSIZE];
+
+       if (snprintf (buf, BUFSIZE, "%u:%u:%u:%u:%u:%u:%u",
+                               (unsigned int) curtime,
+                               running, sleeping, zombies, stopped, paging,
+                               blocked) >= BUFSIZE)
+               return;
+
+       plugin_submit (MODULE_NAME, "-", buf);
+}
+
+void ps_read (void)
+{
+#ifdef KERNEL_LINUX
+       unsigned int running, sleeping, zombies, stopped, paging, blocked;
+
+       char buf[BUFSIZE];
+       char filename[20]; /* need 17 bytes */
+       char *fields[256];
+
+       struct dirent *ent;
+       DIR *proc;
+       FILE *fh;
+
+       running = sleeping = zombies = stopped = paging = blocked = 0;
+
+       if ((proc = opendir ("/proc")) == NULL)
+       {
+               syslog (LOG_ERR, "Cannot open `/proc': %s", strerror (errno));
+               return;
+       }
+
+       int strsplit (char *string, char **fields, size_t size);
+
+       while ((ent = readdir (proc)) != NULL)
+       {
+               if (!isdigit (ent->d_name[0]))
+                       continue;
+
+               if (snprintf (filename, 20, "/proc/%s/stat", ent->d_name) >= 20)
+                       continue;
+
+               if ((fh = fopen (filename, "r")) == NULL)
+               {
+                       syslog (LOG_ERR, "Cannot open `%s': %s", filename, strerror (errno));
+                       continue;
+               }
+
+               if (fgets (buf, BUFSIZE, fh) == NULL)
+               {
+                       fclose (fh);
+                       continue;
+               }
+
+               fclose (fh);
+
+               if (strsplit (buf, fields, 256) < 3)
+                       continue;
+
+               switch (fields[2][0])
+               {
+                       case 'R': running++;  break;
+                       case 'S': sleeping++; break;
+                       case 'D': blocked++;  break;
+                       case 'Z': zombies++;  break;
+                       case 'T': stopped++;  break;
+                       case 'W': paging++;   break;
+               }
+       }
+
+       closedir(proc);
+
+       ps_submit (running, sleeping, zombies, stopped, paging, blocked);
+#endif /* defined(KERNEL_LINUX) */
+}
+#undef BUFSIZE
+
+void module_register (void)
+{
+       plugin_register (MODULE_NAME, ps_init, ps_read, ps_write);
+}
+
+#undef MODULE_NAME
+#endif /* COLLECT_PROCESSES */
index 57044e8..2e58e8c 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "common.h"
 #include "utils_debug.h"
+#include "utils_mount.h"
 #include "quota_mnt.h"
 #include "quota_fs.h"
 
@@ -32,6 +33,9 @@
 #if HAVE_GRP_H
 # include <grp.h>
 #endif
+#if HAVE_SYS_UCRED_H
+# include <sys/ucred.h>
+#endif
 #if HAVE_SYS_QUOTA_H
 # include <sys/quota.h>
 #endif
@@ -366,9 +370,6 @@ quota_fs_issupported(const char *fsname)
        {
                return EXIT_SUCCESS;
        } else {
-#if 0
-               DBG("%s filesystem not supported", fsname);
-#endif
                return EXIT_FAILURE;
        }
 } /* int quota_fs_issupported(const char *fsname) */
@@ -423,7 +424,7 @@ quota_fs_getquota(quota_t **quota, quota_mnt_t *mnt)
        quota_t *q = NULL, *qlast = NULL;
 
        while(m != NULL) {
-               switch(quota_mnt_type(m->m->type)) {
+               switch(cu_mount_type(m->m->type)) {
                  case QMT_EXT2:
                  case QMT_EXT3: 
                        qlast = getquota_ext3(&q, m);
index 3404dfe..9236339 100644 (file)
@@ -50,6 +50,7 @@ struct _quota_t {
 int quota_fs_issupported(const char *fsname);
 int quota_fs_isnfs(const char *fsname);
 
+void quota_fs_printquota_dbg(quota_t *quota);
 /*
   DESCRIPTION
        The quota_fs_printquota_dbg() function prints
@@ -58,8 +59,8 @@ int quota_fs_isnfs(const char *fsname);
        If debugging is switched off in quota_debug.h
        then this function does nothing.
 */
-void quota_fs_printquota_dbg(quota_t *quota);
 
+quota_t *quota_fs_getquota(quota_t **quota, quota_mnt_t *m);
 /*
   DESCRIPTION
        The quota_fs_getquota() function goes through the mount
@@ -78,15 +79,14 @@ void quota_fs_printquota_dbg(quota_t *quota);
   NOTES
        In case of an error, *quota is not modified.
 */
-quota_t *quota_fs_getquota(quota_t **quota, quota_mnt_t *m);
 
+void quota_fs_freequota(quota_t *quota);
 /*
   DESCRIPTION
        The quota_fs_freequota() function goes through all entries
        and frees all allocated memory of all data and structures
        not NULL.
 */
-void quota_fs_freequota(quota_t *quota);
 
 #endif /* !COLLECTD_QUOTA_FS_H */
 
index 1917a59..53e1f99 100644 (file)
 
 #include "common.h"
 #include "utils_debug.h"
+#include "utils_mount.h"
 #include "quota_fs.h"
 #include "quota_mnt.h"
 
-
-/* if sthg is changed here also change it in configure.in!!! */
-#if HAVE_MNTENT_H   /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
-# include <mntent.h>
-#endif
-#if HAVE_MNTTAB_H   /* SVR2, SVR3. */
-# include <mnttab.h>
-#endif
-#if HAVE_PATHS_H
-# include <paths.h>
-#endif
-#if HAVE_SYS_FS_TYPES_H   /* Ultrix. */
-# include <sys/fs_types.h>
-#endif
-#if HAVE_SYS_MNTENT_H
-# include <sys/mntent.h>
-#endif
-#if HAVE_SYS_MNTTAB_H   /* SVR4. */
-# include <sys/mnttab.h>
-#endif
-#if HAVE_SYS_MOUNT_H   /* 4.4BSD, Ultrix. */
-# include <sys/mount.h>
-#endif
-#if HAVE_SYS_VFSTAB_H
-# include <sys/vfstab.h>
-#endif
 #if HAVE_SYS_QUOTA_H
 # include <sys/quota.h>
 #endif
-#if HAVE_SYS_VFS_H
-# include <sys/vfs.h>
-#endif
-/* END if sthg is changed here also change it in configure.in!!! */
-#if HAVE_XFS_XQM_H
-# include <xfs/xqm.h>
-#define xfs_mem_dqinfo  fs_quota_stat
-#define Q_XFS_GETQSTAT  Q_XGETQSTAT
-#define XFS_SUPER_MAGIC_STR "XFSB"
-#define XFS_SUPER_MAGIC2_STR "BSFX"
-#endif
 
 
 
@@ -208,6 +172,22 @@ quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list)
 #endif
 
 
+
+static int
+is_relevant(cu_mount_t *m)
+{
+       if(cu_mount_checkoption(m->options, "noquota", 1) != NULL) {
+               return EXIT_FAILURE;
+       }
+       if(quota_fs_issupported(m->type) == EXIT_FAILURE) {
+               return EXIT_FAILURE;
+       }
+
+       return EXIT_SUCCESS;
+} /* static int is_relevant(cu_mount_t *m) */
+
+
+
 quota_mnt_t *
 quota_mnt_getlist(quota_mnt_t **list)
 {
@@ -215,16 +195,22 @@ quota_mnt_getlist(quota_mnt_t **list)
        quota_mnt_t *last = NULL;
 
        (void)cu_mount_getlist(&fulllist);
-       fl = fulllist;
-       while(fl != NULL) {
-
-               fl = fl->next;
-       } /* while(fl != NULL) */
+       for(fl=fulllist; fl!=NULL; fl=fl->next) {
+               if(is_relevant(fl) != EXIT_SUCCESS) {
+                       DBG("not relevant: %s on %s type %s (%s)",
+                               fl->device, fl->dir, fl->type, fl->options);
+                       continue;
+               }
+               DBG("relevant: %s on %s type %s (%s)",
+                       fl->device, fl->dir, fl->type, fl->options);
+       } /* for(fl=fulllist; fl!=NULL; fl=fl->next) */
        cu_mount_freelist(fulllist);
 
        return(last);
 } /* quota_mnt_t *quota_mnt_getlist(quota_mnt_t **list) */
 
+
+
 void
 quota_mnt_freelist(quota_mnt_t *list)
 {
@@ -245,14 +231,16 @@ quota_mnt_freelist(quota_mnt_t *list)
                sfree(l->usrjquota);
                sfree(l->grpjquota);
                sfree(l->jqfmt);
-               sfree(l);
                p = NULL;
                if(l != list) {
+                       sfree(l);
                        l = list;
                } else {
+                       sfree(l);
                        l = NULL;
                }
        } /* while(l != NULL) */
 } /* void quota_mnt_freelist(quota_mnt_t *list) */
 
 
+
index e5893b9..2bfa2bb 100644 (file)
@@ -51,21 +51,17 @@ struct _quota_mnt_t {
        quota_mnt_t *next;
 };
 
-int quota_mnt_type(const char *type);
-
-char *quota_mnt_getmountopt(char *line, char *keyword);
-char *quota_mnt_checkmountopt(char *line, char *keyword, int full);
-
+quota_mnt_t *quota_mnt_getlist(quota_mnt_t **list);
 /*
   DESCRIPTION
        The quota_mnt_getlist() function creates a list
-       of all mountpoints.
+       of all quota-relevant mountpoints.
 
        If *list is NULL, a new list is created and *list is
        set to point to the first entry.
 
-       If *list is set, the list is appended and *list is
-       not changed.
+       If *list is not NULL, the list of mountpoints is appended
+       and *list is not changed.
 
   RETURN VALUE
        The quota_mnt_getlist() function returns a pointer to
@@ -74,8 +70,13 @@ char *quota_mnt_checkmountopt(char *line, char *keyword, int full);
   NOTES
        In case of an error, *list is not modified.
 */
-quota_mnt_t *quota_mnt_getlist(quota_mnt_t **list);
+
 void quota_mnt_freelist(quota_mnt_t *list);
+/*
+  DESCRIPTION
+       The quota_mnt_freelist() function free()s all memory
+       allocated by *list and *list itself as well.
+*/
 
 #endif /* !COLLECTD_QUOTA_MNT_H */
 
index 03306cf..1295901 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef USERS_H
 #define USERS_H 1
 
-#include "config.h"
+#include <config.h>
 
 #if !defined(HAVE_UTMPX_H) || !defined(HAVE_GETUTXENT)
 #undef HAVE_UTMPX_H
index ae984f8..3f432e1 100644 (file)
@@ -177,17 +177,17 @@ cu_debug(const char *file, int line, const char *func, const char *format, ...)
 {
 }
 int
-cu_debug_startfile(const char *file, int line, const char *func, char *format, ...)
+cu_debug_startfile(const char *file, int line, const char *func, const char *format, ...)
 {
        return EXIT_SUCCESS;
 }
 int
-cu_debug_stopfile(const char *file, int line, const char *func, char *format, ...)
+cu_debug_stopfile(const char *file, int line, const char *func, const char *format, ...)
 {
        return EXIT_SUCCESS;
 }
 int
-cu_debug_resetfile(const char *file, int line, const char *func, char *filename)
+cu_debug_resetfile(const char *file, int line, const char *func, const char *filename)
 {
        return EXIT_SUCCESS;
 }
index d5dcebd..247b141 100644 (file)
@@ -44,7 +44,7 @@ int cu_debug_stopfile(const char *file, int line, const char *func,
        const char *format, ...);
 
 int cu_debug_resetfile(const char *file, int line, const char *func,
-       char *filename);
+       const char *filename);
 
 #endif /* !COLLECTD_UTILS_DEBUG_H */
 
index 74bc02f..ecfd0ec 100644 (file)
@@ -26,8 +26,6 @@
 #include "common.h"
 #if HAVE_XFS_XQM_H
 # include <xfs/xqm.h>
-#define xfs_mem_dqinfo  fs_quota_stat
-#define Q_XFS_GETQSTAT  Q_XGETQSTAT
 #define XFS_SUPER_MAGIC_STR "XFSB"
 #define XFS_SUPER_MAGIC2_STR "BSFX"
 #endif
@@ -36,7 +34,9 @@
 
 
 
-/* *** *** ***   local functions   *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
+/* *** *** *** *** *** ***   private functions   *** *** *** *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
 
 
 
@@ -47,8 +47,6 @@
 #define UUID   1
 #define VOL    2
 
-#define AUTOFS_DIR_MAX 64       /* Maximum number of autofs directories */
-
 static struct uuidCache_s {
        struct uuidCache_s *next;
        char uuid[16];
@@ -317,26 +315,6 @@ get_device_name(const char *item)
        return rc;
 }
 
-#if HAVE_LISTMNTENT
-static void
-cu_mount_listmntent(struct tabmntent *mntlist, cu_mount_t **list)
-{
-       struct *p;
-       struct mntent *mnt;
-
-       for(p = mntlist; p; p = p->next) {
-               mnt = p->ment;
-               *list = smalloc(sizeof(cu_mount_t));
-               list->device = strdup(mnt->mnt_fsname);
-               list->name = strdup(mnt->mnt_dir);
-               list->type = strdup(mnt->mnt_type);
-               list->next = NULL;
-               list = &(ist->next);
-       }
-       freemntlist(mntlist);
-}
-#endif /* HAVE_LISTMNTENT */
-
 
 
 #if HAVE_GETVFSENT
@@ -348,87 +326,79 @@ cu_mount_getvfsmnt(FILE *mntf, cu_mount_t **list)
 }
 #endif /* HAVE_GETVFSENT */
 
-char *
-cu_mount_checkmountopt(char *line, char *keyword, int full)
-{
-       char *line2, *l2;
-       int l = strlen(keyword);
-       char *p1, *p2;
-
-       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++;
-       }
-
-       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_checkmountopt(char *line, char *keyword, int full) */
 
-char *
-cu_mount_getmountopt(char *line, char *keyword)
+#if HAVE_LISTMNTENT
+static cu_mount_t *
+cu_mount_listmntent(struct tabmntent *mntlist, cu_mount_t **list)
 {
-       char *r;
+       cu_mount_t *last = *list;
+       struct tabmntent *p;
+       struct mntent *mnt;
 
-       r = cu_mount_checkmountopt(line, keyword, 0);
-       if(r != NULL) {
-               char *p;
-               r += strlen(keyword);
-               p = strchr(r, ',');
-               if(p == NULL) {
-                       if(strlen(r) == 0) {
-                               return NULL;
+       for(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) {
+                               DBG("can't get devicename for fs (%s) %s (%s)"
+                                       ": ignored", mnt->mnt_type,
+                                       mnt->mnt_dir, mnt->mnt_fsname);
+                               continue;
                        }
-                       return sstrdup(r);
                } else {
-                       char *m;
-                       if((p-r) == 1) {
-                               return NULL;
+                       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;
                        }
-                       m = (char *)smalloc(p-r+1);
-                       sstrncpy(m, r, p-r+1);
-                       return m;
+                       last->next = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
+                       last = last->next;
                }
-       }
-       return r;
-} /* char *cu_mount_getmountopt(char *line, char *keyword) */
+               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);
+} /* static cu_mount_t *cu_mount_listmntent(struct tabmntent *mntlist,
+       cu_mount_t **list) */
+#endif /* HAVE_LISTMNTENT */
+
+
 
 #if HAVE_GETMNTENT
 static cu_mount_t *
 cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
 {
        cu_mount_t *last = *list;
-       struct mntent *mnt;
+#if HAVE_GETMNTENT1
+       struct mntent *mnt = NULL;
+#endif
+#if HAVE_GETMNTENT2
+       struct mntent real_mnt;
+       struct mntent *mnt = &real_mnt;
+#endif
 
 #if HAVE_GETMNTENT1
        while((mnt = getmntent(mntf)) != NULL) {
-#endif /* HAVE_GETMNTENT1 */
+#endif
+#if HAVE_GETMNTENT2
+       while(getmntent(mntf, &real_mnt) == 0) {
+#endif
                char *loop = NULL, *device = NULL;
 
-#if 1
+#if 0
                DBG("------------------ BEGIN");
                DBG("mnt->mnt_fsname %s", mnt->mnt_fsname);
                DBG("mnt->mnt_dir    %s", mnt->mnt_dir);
@@ -438,7 +408,7 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
                DBG("mnt->mnt_passno %d", mnt->mnt_passno);
 #endif
 
-               loop = cu_mount_getmountopt(mnt->mnt_opts, "loop=");
+               loop = cu_mount_getoptionvalue(mnt->mnt_opts, "loop=");
                if(loop == NULL) {   /* no loop= mount */
                        device = get_device_name(mnt->mnt_fsname);
                        if(device == NULL) {
@@ -451,14 +421,17 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
                        device = loop;
                }
 
-#if 1
-               DBG("device          %s", device);
+#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;
                }
@@ -468,7 +441,12 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
                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
 
        return last;
 } /* static cu_mount_t *cu_mount_getmntent(FILE *mntf, cu_mount_t **list) */
@@ -476,15 +454,48 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
 
 
 
+/* *** *** *** ******************************************** *** *** *** */
+/* *** *** *** *** *** ***   public functions   *** *** *** *** *** *** */
+/* *** *** *** ******************************************** *** *** *** */
+
+
+
 cu_mount_t *
 cu_mount_getlist(cu_mount_t **list)
 {
        cu_mount_t *last = NULL;
 
-       /* yes, i know that the indentation is wrong.
-          but show me a better way to do this... */
-       /* see lib/mountlist.c of coreutils for all
-          gory details! */
+       /* 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;
@@ -503,32 +514,36 @@ cu_mount_getlist(cu_mount_t **list)
        if((mntf = setmntent(MNTTABNAME, "r")) == NULL) {
                DBG("opening %s failed: %s", MNTTABNAME, strerror(errno));
 #endif
-#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
+#if HAVE_LISTMNTENT
        {
-       FILE *mntf = NULL;
-       if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) {
-               DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno));
+       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_LISTMNTENT
+#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... */
        {
-       struct tabmntent *mntlist;
-
-       if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) {
-               DBG("calling listmntent() failed: %s", strerror(errno));
+       FILE *mntf = NULL;
+       if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) {
+               DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno));
 #endif
-               /* give up */
-               DBG("failed get local mountpoints");
-               return(NULL);
 
-#if HAVE_LISTMNTENT
-       } else { last = cu_mount_listmntent(mntlist, list); }
-       freemntlist(mntlist);
+       /* give up */
+       DBG("failed get local mountpoints");
+       return(NULL);
+
+#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
+       } else { last = cu_mount_getmntent(mntf, list); }
+       (void)endmntent(mntf);
        }
 #endif
 #if HAVE_GETVFSENT && defined(VFSTAB)
@@ -536,9 +551,9 @@ cu_mount_getlist(cu_mount_t **list)
        (void)fclose(mntf);
        }
 #endif
-#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
-       } else { last = cu_mount_getmntent(mntf, list); }
-       (void)endmntent(mntf);
+#if HAVE_LISTMNTENT
+       } else { last = cu_mount_listmntent(mntlist, list); }
+       freemntlist(mntlist);
        }
 #endif
 #if HAVE_GETMNTENT && defined(MNTTABNAME)
@@ -559,6 +574,8 @@ cu_mount_getlist(cu_mount_t **list)
        return(last);
 } /* cu_mount_t *cu_mount_getlist(cu_mount_t **list) */
 
+
+
 void
 cu_mount_freelist(cu_mount_t *list)
 {
@@ -577,16 +594,91 @@ cu_mount_freelist(cu_mount_t *list)
                sfree(l->device);
                sfree(l->type);
                sfree(l->options);
-               sfree(l);
                p = NULL;
                if(l != list) {
+                       sfree(l);
                        l = list;
                } else {
-                       l = NULL;
+                       sfree(l);
+                       l = NULL; /* done by sfree already */
                }
        } /* while(l != NULL) */
 } /* void cu_mount_freelist(cu_mount_t *list) */
 
+
+
+char *
+cu_mount_checkoption(char *line, char *keyword, int full)
+{
+       char *line2, *l2;
+       int l = strlen(keyword);
+       char *p1, *p2;
+
+       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++;
+       }
+
+       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, 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) {
+                       if(strlen(r) == 0) {
+                               return NULL;
+                       }
+                       return sstrdup(r);
+               } else {
+                       char *m;
+                       if((p-r) == 1) {
+                               return NULL;
+                       }
+                       m = (char *)smalloc(p-r+1);
+                       sstrncpy(m, r, p-r+1);
+                       return m;
+               }
+       }
+       return r;
+} /* char *cu_mount_getoptionvalue(char *line, char *keyword) */
+
+
+
 int
 cu_mount_type(const char *type)
 {
index 3f357b8..822f786 100644 (file)
  *   Niki W. Waibel <niki.waibel@gmx.net>
 **/
 
+/* See below for instructions how to use the public functions. */
+
 #if !COLLECTD_UTILS_MOUNT_H
 #define COLLECTD_UTILS_MOUNT_H 1
 
+#include "common.h"
+
+#if HAVE_FS_INFO_H
+# include <fs_info.h>
+#endif
+#if HAVE_FSHELP_H
+# include <fshelp.h>
+#endif
+#if HAVE_PATHS_H
+# include <paths.h>
+#endif
 #if HAVE_MNTENT_H
 # include <mntent.h>
 #endif
 #if HAVE_MNTTAB_H
 # include <mnttab.h>
 #endif
-#if HAVE_PATHS_H
-# include <paths.h>
+#if HAVE_SYS_FSTYP_H
+# include <sys/fstyp.h>
 #endif
 #if HAVE_SYS_FS_TYPES_H
 # include <sys/fs_types.h>
 #if HAVE_SYS_MOUNT_H
 # include <sys/mount.h>
 #endif
-#if HAVE_SYS_VFSTAB_H
-# include <sys/vfstab.h>
+#if HAVE_SYS_STATFS_H
+# include <sys/statfs.h>
 #endif
 #if HAVE_SYS_VFS_H
 # include <sys/vfs.h>
 #endif
-
-#include "common.h"
+#if HAVE_SYS_VFSTAB_H
+# include <sys/vfstab.h>
+#endif
 
 /* Collectd Utils Mount Type */
 #define CUMT_UNKNOWN (0)
 #define CUMT_VXFS    (5)
 #define CUMT_ZFS     (6)
 
-/* Collectd Utils Mount Options */
-#define CUMO_NONE     (0)
-#define CUMO_USRQUOTA (1)
-#define CUMO_GRPQUOTA (2)
-
 typedef struct _cu_mount_t cu_mount_t;
 struct _cu_mount_t {
        char *dir;         /* "/sys" or "/" */
        char *spec_device; /* "LABEL=/" or "none" or "proc" or "/dev/hda1" */
-       char *device;      /* "none" or "proc" "/dev/hda1" */
+       char *device;      /* "none" or "proc" or "/dev/hda1" */
        char *type;        /* "sysfs" or "ext3" */
        char *options;     /* "rw,noatime,commit=600,quota,grpquota" */
        cu_mount_t *next;
 };
 
-int cu_mount_type(const char *type);
-
-char *cu_mount_getmountopt(char *line, char *keyword);
-char *cu_mount_checkmountopt(char *line, char *keyword, int full);
-
+cu_mount_t *cu_mount_getlist(cu_mount_t **list);
 /*
   DESCRIPTION
        The cu_mount_getlist() function creates a list
@@ -91,18 +96,95 @@ char *cu_mount_checkmountopt(char *line, char *keyword, int full);
        If *list is NULL, a new list is created and *list is
        set to point to the first entry.
 
-       If *list is set, the list is appended and *list is
-       not changed.
+       If *list is not NULL, the list of mountpoints is appended
+       and *list is not changed.
 
   RETURN VALUE
        The cu_mount_getlist() function returns a pointer to
-       the last entry of the list, or NULL if an error occured.
+       the last entry of the list, or NULL if an error has
+       occured.
 
   NOTES
        In case of an error, *list is not modified.
 */
-cu_mount_t *cu_mount_getlist(cu_mount_t **list);
+
 void cu_mount_freelist(cu_mount_t *list);
+/*
+  DESCRIPTION
+       The cu_mount_freelist() function free()s all memory
+       allocated by *list and *list itself as well.
+*/
+
+char *cu_mount_checkoption(char *line, char *keyword, int full);
+/*
+  DESCRIPTION
+       The cu_mount_checkoption() function is a replacement of
+       char *hasmntopt(const struct mntent *mnt, const char *opt).
+       In fact hasmntopt() just looks for the first occurence of the
+       characters at opt in mnt->mnt_opts. cu_mount_checkoption()
+       checks for the *option* keyword in line, starting at the
+       first character of line or after a ','.
+
+       If full is not 0 then also the end of keyword has to match
+       either the end of line or a ',' after keyword.
+
+  RETURN VALUE
+       The cu_mount_checkoption() function returns a pointer into
+       string line if a match of keyword is found. If no match is
+       found cu_mount_checkoption() returns NULL.
+
+  NOTES
+       Do *not* try to free() the pointer which is returned! It is
+       just part of the string line.
+
+       full should be set to 0 when matching options like: rw, quota,
+       noatime. Set full to 1 when matching options like: loop=,
+       gid=, commit=.
+
+  EXAMPLES
+       If line is "rw,usrquota,grpquota", keyword is "quota", NULL
+       will be returned (independend of full).
+
+       If line is "rw,usrquota,grpquota", keyword is "usrquota",
+       a pointer to "usrquota,grpquota" is returned (independend
+       of full).
+
+       If line is "rw,loop=/dev/loop1,quota", keyword is "loop="
+       and full is 0, then a pointer to "loop=/dev/loop1,quota"
+       is returned. If full is not 0 then NULL is returned. But
+       maybe you might want to try cu_mount_getoptionvalue()...
+*/
+
+char *cu_mount_getoptionvalue(char *line, char *keyword);
+/*
+  DESCRIPTION
+       The cu_mount_getoptionvalue() function can be used to grab
+       a VALUE out of a mount option (line) like:
+               loop=VALUE
+       whereas "loop=" is the keyword.
+
+  RETURN VALUE
+       If the cu_mount_getoptionvalue() function can find the option
+       keyword in line, then memory is allocated for the value of
+       that option and a pointer to that value is returned.
+
+       If the option keyword is not found, cu_mount_getoptionvalue()
+       returns NULL;
+
+  NOTES
+       Internally it calls cu_mount_checkoption(), then it
+       allocates memory for VALUE and returns a pointer to that
+       string. So *do not forget* to free() the memory returned
+       after use!!!
+*/
+
+int cu_mount_type(const char *type);
+/*
+  DESCRIPTION
+
+  RETURN VALUE
+*/
+
 
 #endif /* !COLLECTD_UTILS_MOUNT_H */