summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 909020d)
raw | patch | inline | side by side (parent: 909020d)
author | niki <niki> | |
Sun, 11 Dec 2005 11:30:40 +0000 (11:30 +0000) | ||
committer | niki <niki> | |
Sun, 11 Dec 2005 11:30:40 +0000 (11:30 +0000) |
22 files changed:
diff --git a/build.sh b/build.sh
index 852b8eb79dd27475a640d09dfe24c12518cf07e0..ca41cad0d28dc311373a52b2769ef731bd889582 100755 (executable)
--- a/build.sh
+++ b/build.sh
set -x
true \
+&& autoheader --force \
&& aclocal --force \
&& libtoolize --ltdl --force --copy \
&& automake --add-missing --copy \
diff --git a/configure.in b/configure.in
index 220f51c9b7107fcf24969320aae877b9d9e2d590..7556ac3c0d8cfaaf79a17c5ee6f4981a7dd4db63 100644 (file)
--- a/configure.in
+++ b/configure.in
AC_CONFIG_SUBDIRS(libltdl)
dnl Checks for header files.
-AC_HEADER_STDC
AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(stdarg.h)
AC_CHECK_HEADERS(fcntl.h)
AC_CHECK_HEADERS(signal.h)
AC_CHECK_HEADERS(limits.h)
AC_CHECK_FUNCS(getfsent getvfsent listmntent)
AC_FUNC_GETMNTENT
-def_mnt_includes="\
-/* if sthg is changed here also change it in src/quota_mnt.c!!! */
-#if HAVE_MNTENT_H
-# include <mntent.h>
-#endif
-#if HAVE_MNTTAB_H
-# include <mnttab.h>
-#endif
-#if HAVE_PATHS_H
-# include <paths.h>
-#endif
-#if HAVE_SYS_FS_TYPES_H
-# include <sys/fs_types.h>
-#endif
-#if HAVE_SYS_MNTENT_H
-# include <sys/mntent.h>
-#endif
-#if HAVE_SYS_MNTTAB_H
-# include <sys/mnttab.h>
-#endif
-#if HAVE_SYS_MOUNT_H
-# 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 src/quota_mnt.c!!! */"
-
if test "x$ac_cv_func_getmntent" = 'xyes'; then
saveCFLAGS="$CFLAGS"
CFLAGS="-Wall -Werror $CFLAGS"
[fu_cv_getmntent1],
AC_COMPILE_IFELSE(
AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT
- $def_mnt_includes]],
+#include "$srcdir/src/utils_mount.h"]],
[[(void)getmntent((FILE *)NULL);]]
),
[fu_cv_getmntent1=yes],
[fu_cv_getmntent2],
AC_COMPILE_IFELSE(
AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT
- $def_mnt_includes]],
+#include "$srcdir/src/utils_mount.h"]],
[[(void)getmntent((FILE *)NULL,
(struct mnttab *)NULL);]]
),
fi
AM_CONDITIONAL(BUILD_WITH_RRDTOOL, test "x$with_rrdtool" = "xyes")
+AC_ARG_WITH(pth, AC_HELP_STRING([--with-pth=PFX], [Path to pth (experimental).]),
+[ if test "x$withval" != "xno" -a "x$withval" != "xyes"
+ then
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ with_pth="yes"
+ fi
+], [with_pth="no"])
+if test "x$with_pth" = "xyes"
+then
+ AC_CHECK_LIB(pth, pth_init,, [with_pth="no"], [])
+fi
+if test "x$with_pth" = "xyes"
+then
+ AC_CHECK_HEADERS(pth.h,, [with_pth="no"])
+fi
+if test "x$with_pth" = "xyes"
+then
+ collect_pth=1
+else
+ collect_pth=0
+fi
+AC_DEFINE_UNQUOTED(COLLECT_PTH, [$collect_pth],
+ [Wether or not to use pth (portable threads) library])
+AM_CONDITIONAL(BUILD_WITH_PTH, test "x$with_pth" = "xyes")
+
if test "$ac_system" = "Solaris"
then
with_kstat="yes"
#
# Check for enabled/disabled features
#
+AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],
+ [Enable debugging (disabled by default)]),
+ [], [enable_debug="no"])
+if test "x$enable_debug" = "xno"
+then
+ collect_debug=0
+else
+ if test "x$enable_debug" = "xyes"
+ then
+ collect_debug=1
+ else
+ AC_MSG_NOTICE([Please specify either --enable-debug or --disable-debug; Enabling debugging.])
+ collect_debug=1
+ enable_debug="yes"
+ fi
+fi
+AC_DEFINE_UNQUOTED(COLLECT_DEBUG, [$collect_debug],
+ [Wether or not to enable debugging])
+AM_CONDITIONAL(BUILD_DEBUG, test "x$enable_debug" = "xyes")
+
+AC_ARG_ENABLE(daemon, AC_HELP_STRING([--disable-daemon],
+ [Disable daemon mode (enabled by default)]),
+ [], [enable_daemon="yes"])
+if test "x$enable_daemon" = "xno"
+then
+ collect_daemon=0
+else
+ if test "x$enable_daemon" = "xyes"
+ then
+ collect_daemon=1
+ else
+ AC_MSG_NOTICE([Please specify either --enable-daemon or --disable-daemon; Enabling daemon mode.])
+ collect_daemon=1
+ enable_daemon="yes"
+ fi
+fi
+AC_DEFINE_UNQUOTED(COLLECT_DAEMON, [$collect_daemon],
+ [Wether or not to enable daemon mode])
+AM_CONDITIONAL(BUILD_DAEMON, test "x$enable_daemon" = "xyes")
+
AC_ARG_ENABLE(cpu, AC_HELP_STRING([--disable-cpu], [Disable CPU usage statistics]),, [enable_cpu="yes"])
if test "x$enable_cpu" != "xno"
then
AM_CONDITIONAL(BUILD_MODULE_DISK, test "x$enable_disk" = "xyes")
AC_ARG_ENABLE(quota, AC_HELP_STRING([--enable-quota],
- [Enable quota statistics (experimental, off by default)]),
+ [Enable quota statistics (experimental, disabled by default)]),
[], [enable_quota="no"])
if test "x$enable_quota" = "xno"
then
if test "x$enable_quota" = "xyes"
then
collect_quota=1
- enable_quota="yes"
else
AC_MSG_NOTICE([Please specify either --enable-quota or --disable-quota; Enabling quota statistics.])
collect_quota=1
fi
fi
AC_DEFINE_UNQUOTED(COLLECT_QUOTA, [$collect_quota],
- [Wether or not to collect quotastats])
+ [Wether or not to collect quota statistics])
AM_CONDITIONAL(BUILD_MODULE_QUOTA, test "x$enable_quota" = "xyes")
AC_ARG_ENABLE(hddtemp, AC_HELP_STRING([--disable-hddtemp], [Disable hdd temperature statistics]),, [enable_hddtemp="yes"])
Configuration:
Libraries:
librrd . . . . . . $with_rrdtool
+ libpth . . . . . . $with_pth (experimental)
lm_sensors . . . . $with_lm_sensors
libstatgrab . . . . $with_libstatgrab
libkstat . . . . . $with_kstat
Features:
+ debug . . . . . . . $enable_debug
+ daemon mode . . . . $enable_daemon
+
+ Modules:
cpu . . . . . . . . $enable_cpu
cpufreq . . . . . . $enable_cpufreq
disk . . . . . . . $enable_disk
- quota . . . . . . . $enable_quota
+ quota . . . . . . . $enable_quota (experimental)
hddtemp . . . . . . $enable_hddtemp
load . . . . . . . $enable_load
memory . . . . . . $enable_memory
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b693f90fde7db3eddd0d7f52f3e6345c4f93b31..dc189d4869dd8786a59fb9a479f477edbe43d583 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
sbin_PROGRAMS = collectd
collectd_SOURCES = collectd.c collectd.h \
+ utils_debug.c utils_debug.h \
+ utils_mount.c utils_mount.h \
common.c common.h \
multicast.c multicast.h \
plugin.c plugin.h
#collectd_CFLAGS = -DPLUGINDIR='"$(pkglibdir)"'
collectd_CPPFLAGS = -DLOCALSTATEDIR='"$(localstatedir)"' -DPLUGINDIR='"$(pkglibdir)"'
collectd_LDFLAGS = -export-dynamic
+collectd_CFLAGS = -Werror
collectd_LDADD = $(LIBLTDL) "-dlopen" self
collectd_DEPENDENCIES = $(LIBLTDL)
if BUILD_WITH_RRDTOOL
if BUILD_MODULE_QUOTA
pkglib_LTLIBRARIES += quota.la
quota_la_SOURCES = quota_plugin.c quota_plugin.h
-quota_la_SOURCES += quota_common.c quota_common.h
-quota_la_SOURCES += quota_debug.c quota_debug.h
-quota_la_SOURCES += quota_mnt.c quota_mnt.h quota_mntopt.h
quota_la_SOURCES += quota_fs.c quota_fs.h
+quota_la_SOURCES += quota_mnt.c quota_mnt.h
quota_la_LDFLAGS = -module -avoid-version
quota_la_CFLAGS = -Werror
collectd_LDADD += "-dlopen" quota.la
diff --git a/src/collectd.c b/src/collectd.c
index dabc346e8e8c5e79bfc7b388ad67675a5b0fec31..31f473eeb28b7aa22ce4b86c27b2dcf5d1510a88 100644 (file)
--- a/src/collectd.c
+++ b/src/collectd.c
int main (int argc, char **argv)
{
struct sigaction sigIntAction, sigChldAction;
+#if COLLECTD_DAEMON
pid_t pid;
+#endif
char *plugindir = NULL;
char *basedir = DATADIR;
/*
* fork off child
*/
-#if DEBUG == 0
+#if COLLECTD_DAEMON
if (daemonize)
{
if ((pid = fork ()) == -1)
return (1);
}
} /* if (daemonize) */
-#endif
+#endif /* COLLECTD_DAEMON */
/*
* run the actual loops
diff --git a/src/collectd.h b/src/collectd.h
index 72b2246e0413970272706f65a9abf7396d49510b..a66647a98e187b3206ef7f6243a2e98c1b64ba0e 100644 (file)
--- a/src/collectd.h
+++ b/src/collectd.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 <statgrab.h>
#endif
-#ifndef DEBUG
-#define DEBUG 0
-#endif
-
#ifndef LOCALSTATEDIR
#define LOCALSTATEDIR "/opt/collectd/var"
#endif
diff --git a/src/common.c b/src/common.c
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,306 @@
+/**
+ * collectd - src/common.c
+ * Copyright (C) 2005 Florian octo Forster
+ *
+ * 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
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ * Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+#include "common.h"
+#include "utils_debug.h"
+
+#ifdef HAVE_LIBKSTAT
+extern kstat_ctl_t *kc;
+#endif
+
+#ifdef HAVE_LIBRRD
+static char *rra_def[] =
+{
+ "RRA:AVERAGE:0.2:6:1500",
+ "RRA:AVERAGE:0.1:180:1680",
+ "RRA:AVERAGE:0.1:2160:1520",
+ "RRA:MIN:0.2:6:1500",
+ "RRA:MIN:0.1:180:1680",
+ "RRA:MIN:0.1:2160:1520",
+ "RRA:MAX:0.2:6:1500",
+ "RRA:MAX:0.1:180:1680",
+ "RRA:MAX:0.1:2160:1520",
+ NULL
+};
+static int rra_num = 9;
+#endif /* HAVE_LIBRRD */
+
+void
+sstrncpy(char *d, const char *s, int len)
+{
+ strncpy(d, s, len);
+ d[len - 1] = 0;
+}
+
+char *
+sstrdup(const char *s)
+{
+ char *r = strdup(s);
+ if(r == NULL) {
+ DBG("Not enough memory.");
+ exit(3);
+ }
+ return r;
+}
+
+void *
+smalloc(size_t size)
+{
+ void *r = malloc(size);
+ if(r == NULL) {
+ DBG("Not enough memory.");
+ exit(3);
+ }
+ return r;
+}
+
+int strsplit (char *string, char **fields, size_t size)
+{
+ size_t i;
+ char *ptr;
+
+ i = 0;
+ ptr = string;
+ while ((fields[i] = strtok (ptr, " \t")) != NULL)
+ {
+ ptr = NULL;
+ i++;
+
+ if (i >= size)
+ break;
+ }
+
+ return (i);
+}
+
+#ifdef HAVE_LIBRRD
+int check_create_dir (char *dir)
+{
+ struct stat statbuf;
+
+ if (stat (dir, &statbuf) == -1)
+ {
+ if (errno == ENOENT)
+ {
+ if (mkdir (dir, 0755) == -1)
+ {
+ syslog (LOG_ERR, "mkdir %s: %s", dir, strerror (errno));
+ return (-1);
+ }
+ }
+ else
+ {
+ syslog (LOG_ERR, "stat %s: %s", dir, strerror (errno));
+ return (-1);
+ }
+ }
+ else if (!S_ISDIR (statbuf.st_mode))
+ {
+ syslog (LOG_ERR, "stat %s: Not a directory!", dir);
+ return (-1);
+ }
+
+ return (0);
+}
+
+int rrd_create_file (char *filename, char **ds_def, int ds_num)
+{
+ char **argv;
+ int argc;
+ int i, j;
+ int status = 0;
+
+ argc = ds_num + rra_num + 4;
+
+ if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+ {
+ syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
+ return (-1);
+ }
+
+ argv[0] = "create";
+ argv[1] = filename;
+ argv[2] = "-s";
+ argv[3] = "10";
+
+ j = 4;
+ for (i = 0; i < ds_num; i++)
+ argv[j++] = ds_def[i];
+ for (i = 0; i < rra_num; i++)
+ argv[j++] = rra_def[i];
+ argv[j] = NULL;
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+ if (rrd_create (argc, argv) == -1)
+ {
+ syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
+ status = -1;
+ }
+
+ free (argv);
+
+ return (status);
+}
+#endif /* HAVE_LIBRRD */
+
+int rrd_update_file (char *host, char *file, char *values,
+ char **ds_def, int ds_num)
+{
+#ifdef HAVE_LIBRRD
+ struct stat statbuf;
+ char full_file[1024];
+ char *argv[4] = { "update", full_file, values, NULL };
+
+ /* host == NULL => local mode */
+ if (host != NULL)
+ {
+ if (check_create_dir (host))
+ return (-1);
+
+ if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
+ return (-1);
+ }
+ else
+ {
+ if (snprintf (full_file, 1024, "%s", file) >= 1024)
+ return (-1);
+ }
+
+ if (stat (full_file, &statbuf) == -1)
+ {
+ if (errno == ENOENT)
+ {
+ if (rrd_create_file (full_file, ds_def, ds_num))
+ return (-1);
+ }
+ else
+ {
+ syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
+ return (-1);
+ }
+ }
+ else if (!S_ISREG (statbuf.st_mode))
+ {
+ syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
+ return (-1);
+ }
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+ if (rrd_update (3, argv) == -1)
+ {
+ syslog (LOG_WARNING, "rrd_update failed: %s: %s", full_file, rrd_get_error ());
+ return (-1);
+ }
+#endif /* HAVE_LIBRRD */
+
+ return (0);
+}
+
+#ifdef HAVE_LIBKSTAT
+int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
+{
+ char ident[128];
+
+ if (kc == NULL)
+ return (-1);
+
+ snprintf (ident, 128, "%s,%i,%s", module, instance, name);
+ ident[127] = '\0';
+
+ if (*ksp_ptr == NULL)
+ {
+ if ((*ksp_ptr = kstat_lookup (kc, module, instance, name)) == NULL)
+ {
+ syslog (LOG_ERR, "Cound not find kstat %s", ident);
+ return (-1);
+ }
+
+ if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
+ {
+ syslog (LOG_WARNING, "kstat %s has wrong type", ident);
+ *ksp_ptr = NULL;
+ return (-1);
+ }
+ }
+
+#ifdef assert
+ assert (*ksp_ptr != NULL);
+ assert ((*ksp_ptr)->ks_type == KSTAT_TYPE_NAMED);
+#endif
+
+ if (kstat_read (kc, *ksp_ptr, NULL) == -1)
+ {
+ syslog (LOG_WARNING, "kstat %s could not be read", ident);
+ return (-1);
+ }
+
+ if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
+ {
+ syslog (LOG_WARNING, "kstat %s has wrong type", ident);
+ return (-1);
+ }
+
+ return (0);
+}
+
+long long get_kstat_value (kstat_t *ksp, char *name)
+{
+ kstat_named_t *kn;
+ long long retval = -1LL;
+
+#ifdef assert
+ assert (ksp != NULL);
+ assert (ksp->ks_type == KSTAT_TYPE_NAMED);
+#else
+ if (ksp == NULL)
+ {
+ fprintf (stderr, "ERROR: %s:%i: ksp == NULL\n", __FILE__, __LINE__);
+ return (-1LL);
+ }
+ else if (ksp->ks_type != KSTAT_TYPE_NAMED)
+ {
+ fprintf (stderr, "ERROR: %s:%i: ksp->ks_type != KSTAT_TYPE_NAMED\n", __FILE__, __LINE__);
+ return (-1LL);
+ }
+#endif
+
+ if ((kn = (kstat_named_t *) kstat_data_lookup (ksp, name)) == NULL)
+ return (retval);
+
+ if (kn->data_type == KSTAT_DATA_INT32)
+ retval = (long long) kn->value.i32;
+ else if (kn->data_type == KSTAT_DATA_UINT32)
+ retval = (long long) kn->value.ui32;
+ else if (kn->data_type == KSTAT_DATA_INT64)
+ retval = (long long) kn->value.i64; /* According to ANSI C99 `long long' must hold at least 64 bits */
+ else if (kn->data_type == KSTAT_DATA_UINT64)
+ retval = (long long) kn->value.ui64; /* XXX: Might overflow! */
+ else
+ syslog (LOG_WARNING, "get_kstat_value: Not a numeric value: %s", name);
+
+ return (retval);
+}
+#endif /* HAVE_LIBKSTAT */
diff --git a/src/common.h b/src/common.h
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,26 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "collectd.h"
+
+#define sfree(ptr) \
+ if((ptr) != NULL) { \
+ free(ptr); \
+ } \
+ (ptr) = NULL
+
+void sstrncpy(char *d, const char *s, int len);
+char *sstrdup(const char *s);
+void *smalloc(size_t size);
+
+int strsplit (char *string, char **fields, size_t size);
+
+int rrd_update_file (char *host, char *file, char *values, char **ds_def,
+ int ds_num);
+
+#ifdef HAVE_LIBKSTAT
+int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name);
+long long get_kstat_value (kstat_t *ksp, char *name);
+#endif
+
+#endif /* COMMON_H */
diff --git a/src/config.h.in b/src/config.h.in
index 6a91b3fc236bf9ca715d96e1cedbaed735bf50ef..746d711c3841b0098c84955b220f63dcf63097aa 100644 (file)
--- a/src/config.h.in
+++ b/src/config.h.in
/* Wether or not to collect cpu frequency statistics */
#undef COLLECT_CPUFREQ
+/* Wether or not to enable daemon mode */
+#undef COLLECT_DAEMON
+
+/* Wether or not to enable debugging */
+#undef COLLECT_DEBUG
+
/* Wether or not to collect diskstats */
#undef COLLECT_DISK
/* Wether or not to collect processes statistics */
#undef COLLECT_PROCESSES
-/* Wether or not to collect quotastats */
+/* Wether or not to use pth (portable threads) library */
+#undef COLLECT_PTH
+
+/* Wether or not to collect quota statistics */
#undef COLLECT_QUOTA
/* Wether or not to collect lm_sensors statistics */
/* Define to 1 if you have the `nsl' library (-lnsl). */
#undef HAVE_LIBNSL
+/* Define to 1 if you have the `pth' library (-lpth). */
+#undef HAVE_LIBPTH
+
/* Define to 1 if you have the `resolv' library (-lresolv). */
#undef HAVE_LIBRESOLV
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
+/* Define to 1 if you have the <pth.h> header file. */
+#undef HAVE_PTH_H
+
/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define to 1 if you have the <statgrab.h> header file. */
#undef HAVE_STATGRAB_H
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
diff --git a/src/quota_common.c b/src/quota_common.c
--- a/src/quota_common.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * collectd - src/quota_common.c
- * Copyright (C) 2005 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
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Author:
- * Niki W. Waibel <niki.waibel@gmx.net>
-**/
-
-#include "common.h"
-#include "quota_debug.h"
-#include "quota_common.h"
-
-void
-sstrncpy(char *d, const char *s, int len)
-{
- strncpy(d, s, len);
- d[len - 1] = 0;
-}
-
-char *
-sstrdup(const char *s)
-{
- char *r = strdup(s);
- if(r == NULL) {
- DBG("Not enough memory.");
- exit(3);
- }
- return r;
-}
-
-void *
-smalloc(size_t size)
-{
- void *r = malloc(size);
- if(r == NULL) {
- DBG("Not enough memory.");
- exit(3);
- }
- return r;
-}
-
-void
-sfree(void *ptr)
-{
- if(ptr != NULL) {
- free(ptr);
- }
-}
-
diff --git a/src/quota_common.h b/src/quota_common.h
--- a/src/quota_common.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * collectd - src/quota_common.h
- * Copyright (C) 2005 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
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Author:
- * Niki W. Waibel <niki.waibel@gmx.net>
-**/
-
-#include "common.h"
-
-void sstrncpy(char *d, const char *s, int len);
-char *sstrdup(const char *s);
-void *smalloc(size_t size);
-void sfree(void *ptr);
-
diff --git a/src/quota_debug.c b/src/quota_debug.c
--- a/src/quota_debug.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * collectd - src/quota_plugin.c
- * Copyright (C) 2005 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
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Author:
- * Niki W. Waibel <niki.waibel@gmx.net>
-**/
-
-#include "common.h"
-#include "quota_debug.h"
-
-/* *** *** *** global variables *** *** *** */
-#if QUOTA_PLUGIN_DEBUG
- FILE *QUOTA_DBG_FILE = NULL;
-#endif
-
diff --git a/src/quota_debug.h b/src/quota_debug.h
--- a/src/quota_debug.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * collectd - src/quota_debug.h
- * Copyright (C) 2005 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
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Author:
- * Niki W. Waibel <niki.waibel@gmx.net>
-**/
-
-#if !COLLECTD_QUOTA_DEBUG_H
-#define COLLECTD_QUOTA_DEBUG_H 1
-
-#include "common.h"
-
-#define QUOTA_PLUGIN_DEBUG 1
-#define QUOTA_PLUGIN_DEBUG_FILE "collectd_quota.log"
-
-#if QUOTA_PLUGIN_DEBUG
- extern FILE *QUOTA_DBG_FILE;
- #define DBG(...) \
- { \
- if(QUOTA_DBG_FILE != NULL) { \
- fprintf(QUOTA_DBG_FILE, "%s:%d:%s(): ", \
- __FILE__, __LINE__, __func__); \
- fprintf(QUOTA_DBG_FILE, __VA_ARGS__); \
- fprintf(QUOTA_DBG_FILE, "\n"); \
- fflush(QUOTA_DBG_FILE); \
- } \
- }
- #define DBG_INIT(...) \
- { \
- QUOTA_DBG_FILE = fopen(QUOTA_PLUGIN_DEBUG_FILE, "a"); \
- if(QUOTA_DBG_FILE == NULL) { \
- /* stderr is redirected to /dev/null, so you \
- will not see anything */ \
- fprintf(stderr, "Cannot open quota debug file.\n"); \
- } else { \
- DBG(__VA_ARGS__); \
- } \
- }
-#else /* !QUOTA_PLUGIN_DEBUG */
- #define DBG(...) /**/
- #define DBG_INIT(...) /**/
-#endif /* QUOTA_PLUGIN_DEBUG */
-
-#endif /* !COLLECTD_QUOTA_DEBUG_H */
-
diff --git a/src/quota_fs.c b/src/quota_fs.c
index bbacafaf717531fb57d3b7e4e38f09fa2f39643c..57044e8d88b93483f6947b85137a5c581b043702 100644 (file)
--- a/src/quota_fs.c
+++ b/src/quota_fs.c
**/
#include "common.h"
-#include "quota_debug.h"
-#include "quota_common.h"
+#include "utils_debug.h"
#include "quota_mnt.h"
#include "quota_fs.h"
uint32_t fmt;
#endif
#if HAVE_QUOTACTL
- if(quotactl(QCMD(Q_GETFMT, USRQUOTA), m->device,
+ if(quotactl(QCMD(Q_GETFMT, USRQUOTA), m->m->device,
0, (void *)&fmt) == -1)
{
DBG("quotactl (Q_GETFMT, USRQUOTA) returned -1 on"
- " %s: %s", m->device, strerror(errno));
+ " %s: %s", m->m->device, strerror(errno));
return NULL;
}
if(fmt == 1) {
#if HAVE_QUOTACTL
if(m->opts & QMO_USRQUOTA) {
- if(quotactl(QCMD(Q_GETINFO, USRQUOTA), m->device,
+ if(quotactl(QCMD(Q_GETINFO, USRQUOTA), m->m->device,
0, (void *)&dqiusr) == -1)
{
DBG("quotactl (Q_GETINFO, USRQUOTA) returned -1 on"
- " %s: %s", m->device, strerror(errno));
+ " %s: %s", m->m->device, strerror(errno));
m->opts &= ~QMO_USRQUOTA;
DBG("\tusrquota switched off");
}
}
if(m->opts & QMO_USRQUOTA) {
- if(quotactl(QCMD(Q_SYNC, USRQUOTA), m->device, 0, NULL) == -1)
+ if(quotactl(QCMD(Q_SYNC, USRQUOTA), m->m->device, 0, NULL) == -1)
{
DBG("quotactl (Q_SYNC, USRQUOTA) returned -1 on"
- " %s: %s", m->device, strerror(errno));
+ " %s: %s", m->m->device, strerror(errno));
m->opts &= ~QMO_USRQUOTA;
DBG("\tusrquota switched off");
}
}
if(m->opts & QMO_GRPQUOTA) {
- if(quotactl(QCMD(Q_GETINFO, GRPQUOTA), m->device,
+ if(quotactl(QCMD(Q_GETINFO, GRPQUOTA), m->m->device,
0, (void *)&dqigrp) == -1)
{
DBG("quotactl (Q_GETINFO, GRPQUOTA) returned -1 on"
- " %s: %s", m->device, strerror(errno));
+ " %s: %s", m->m->device, strerror(errno));
m->opts &= ~QMO_GRPQUOTA;
DBG("\tgrpquota switched off");
}
}
if(m->opts & QMO_GRPQUOTA) {
- if(quotactl(QCMD(Q_SYNC, GRPQUOTA), m->device, 0, NULL) == -1)
+ if(quotactl(QCMD(Q_SYNC, GRPQUOTA), m->m->device, 0, NULL) == -1)
{
DBG("quotactl (Q_SYNC, GRPQUOTA) returned -1 on"
- " %s: %s", m->device, strerror(errno));
+ " %s: %s", m->m->device, strerror(errno));
m->opts &= ~QMO_GRPQUOTA;
DBG("\tgrpquota switched off");
}
char *qfname = NULL;
if(m->usrjquota == NULL) {
char *qfn;
- qfname = (char *)smalloc(strlen(m->dir)
+ qfname = (char *)smalloc(strlen(m->m->dir)
+ 1 + strlen("aquota.user") + 1);
qfn = qfname;
- sstrncpy(qfn, m->dir, strlen(m->dir) + 1);
- qfn += strlen(m->dir);
+ sstrncpy(qfn, m->m->dir, strlen(m->m->dir) + 1);
+ qfn += strlen(m->m->dir);
if(qfn[-1] != '/') {
sstrncpy(qfn, "/", 2);
qfn += 1;
sstrncpy(qfn, "aquota.user", strlen("aquota.user") + 1);
} else {
char *qfn;
- qfname = (char *)smalloc(strlen(m->dir)
+ qfname = (char *)smalloc(strlen(m->m->dir)
+ 1 + strlen(m->usrjquota) + 1);
qfn = qfname;
- sstrncpy(qfn, m->dir, strlen(m->dir) + 1);
- qfn += strlen(m->dir);
+ sstrncpy(qfn, m->m->dir, strlen(m->m->dir) + 1);
+ qfn += strlen(m->m->dir);
if(qfn[-1] != '/') {
sstrncpy(qfn, "/", 2);
qfn += 1;
for(i=0; i<0x1000; i++) {
struct dqblk dqb;
if(quotactl(QCMD(Q_GETQUOTA, USRQUOTA),
- m->device, i, (void *)&dqb) == -1)
+ m->m->device, i, (void *)&dqb) == -1)
{
#if 0
DBG("quotactl (Q_GETQUOTA, USRQUOTA)"
" returned -1 on %d %s: %s",
- i, m->device, strerror(errno));
+ i, m->m->device, strerror(errno));
#endif
continue;
}
DBG("quotactl (Q_GETQUOTA, USRQUOTA)"
" returned ok on %d %s",
- i, m->device);
+ i, m->m->device);
if(*quota == NULL) {
*quota = (quota_t *)smalloc(sizeof(quota_t));
q = *quota;
q->name = sstrdup(buf);
#endif
q->id = sstrdup(buf);
- q->dir = sstrdup(m->dir);
+ q->dir = sstrdup(m->m->dir);
q->blocks = dqb.dqb_curspace;
q->bquota = dqb.dqb_bsoftlimit << 10;
q->blimit = dqb.dqb_bhardlimit << 10;
for(i=0; i<0x1000; i++) {
struct dqblk dqb;
if(quotactl(QCMD(Q_GETQUOTA, GRPQUOTA),
- m->device, i, (void *)&dqb) == -1)
+ m->m->device, i, (void *)&dqb) == -1)
{
#if 0
DBG("quotactl (Q_GETQUOTA, GRPQUOTA)"
" returned -1 on %d %s: %s",
- i, m->device, strerror(errno));
+ i, m->m->device, strerror(errno));
#endif
continue;
}
DBG("quotactl (Q_GETQUOTA, GRPQUOTA)"
" returned ok on %d %s",
- i, m->device);
+ i, m->m->device);
if(*quota == NULL) {
*quota = (quota_t *)smalloc(sizeof(quota_t));
q = *quota;
q->name = sstrdup(buf);
#endif
q->id = sstrdup(buf);
- q->dir = sstrdup(m->dir);
+ q->dir = sstrdup(m->m->dir);
q->blocks = dqb.dqb_curspace;
q->bquota = dqb.dqb_bsoftlimit << 10;
q->blimit = dqb.dqb_bhardlimit << 10;
quota_t *q = NULL, *qlast = NULL;
while(m != NULL) {
- switch(quota_mnt_type(m->type)) {
+ switch(quota_mnt_type(m->m->type)) {
case QMT_EXT2:
case QMT_EXT3:
qlast = getquota_ext3(&q, m);
diff --git a/src/quota_fs.h b/src/quota_fs.h
index b689ae842229b914e6503c14bb0713356a45c21c..3404dfe41f730444d90117eabec75b56206466e5 100644 (file)
--- a/src/quota_fs.h
+++ b/src/quota_fs.h
#define COLLECTD_QUOTA_FS_H 1
#include "common.h"
-#include "quota_debug.h"
+#include "utils_debug.h"
#include "quota_mnt.h"
/* Quota Filesystem Type */
diff --git a/src/quota_mnt.c b/src/quota_mnt.c
index 50b0f4ff9429166b7ed8b4b3bdda614403446789..1917a59b22980d460993e6255860723d06758ed3 100644 (file)
--- a/src/quota_mnt.c
+++ b/src/quota_mnt.c
**/
#include "common.h"
-#include "quota_debug.h"
-#include "quota_common.h"
+#include "utils_debug.h"
#include "quota_fs.h"
#include "quota_mnt.h"
#define XFS_SUPER_MAGIC2_STR "BSFX"
#endif
-#include "quota_mntopt.h"
-
/* *** *** *** local functions *** *** *** */
-/* stolen from quota-3.13 (quota-tools) */
-
-#define PROC_PARTITIONS "/proc/partitions"
-#define DEVLABELDIR "/dev"
-#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];
- 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 firstPass;
- int handleOnFirst;
-
- if(uuidCache) {
- return;
- }
-
- procpt = fopen(PROC_PARTITIONS, "r");
- if(procpt == NULL) {
- return;
- }
-
- for(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];
- int i;
-
- if(strlen(s) != 36
- || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') {
- goto bad_uuid;
- }
-
- for(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:
- DBG("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 *item)
-{
- 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(!rc) {
- DBG("Error checking device name: %s", item);
- }
- return rc;
-}
-
-/*
- * Check for various kinds of NFS filesystem
- */
-int
-nfs_fstype(char *type)
-{
- return !strcmp(type, MNTTYPE_NFS) || !strcmp(type, MNTTYPE_NFS4);
-}
-
-#if HAVE_XFS_XQM_H
-/*
- * Check for XFS filesystem with quota accounting enabled
- */
-static int
-hasxfsquota(struct mntent *mnt, int type)
-{
- int ret = 0;
- u_int16_t sbflags;
- struct xfs_mem_dqinfo info;
- const char *dev = get_device_name(mnt->mnt_fsname);
-
- if(!dev) {
- return ret;
- }
-
- memset(&info, 0, sizeof(struct xfs_mem_dqinfo));
- if(!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) {
- sbflags = (info.qs_flags & 0xff00) >> 8;
- if(type == USRQUOTA && (info.qs_flags & XFS_QUOTA_UDQ_ACCT)) {
- ret = 1;
- } else if(type == GRPQUOTA && (info.qs_flags & XFS_QUOTA_GDQ_ACCT)) {
- ret = 1;
- }
- #ifdef XFS_ROOTHACK
- /*
- * Old XFS filesystems (up to XFS 1.2 / Linux 2.5.47) had a
- * hack to allow enabling quota on the root filesystem without
- * having to specify it at mount time.
- */
- else if(strcmp(mnt->mnt_dir, "/")) {
- ret = 0;
- } else if(type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT)) {
- ret = 1;
- } else if(type == GRPQUOTA && (sbflags & XFS_QUOTA_GDQ_ACCT)) {
- ret = 1;
- #endif /* XFS_ROOTHACK */
- }
- sfree((char *)dev);
- return ret;
-}
-#endif /* HAVE_XFS_XQM_H */
-
-
-#if HAVE_LISTMNTENT
-static void
-quota_mnt_listmntent(struct tabmntent *mntlist, quota_mnt_t **list)
-{
- struct *p;
- struct mntent *mnt;
-
- for(p = mntlist; p; p = p->next) {
- mnt = p->ment;
- *list = smalloc(sizeof(quota_mnt_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
-static void
-quota_mnt_getvfsmnt(FILE *mntf, quota_mnt_t **list)
-{
- DBG("TODO: getvfsmnt");
- *list = NULL;
-}
-#endif /* HAVE_GETVFSENT */
-
-char *
-quota_mnt_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 *quota_mnt_checkmountopt(char *line, char *keyword, int full) */
-
-char *
-quota_mnt_getmountopt(char *line, char *keyword)
-{
- char *r;
-
- r = quota_mnt_checkmountopt(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 *quota_mnt_getmountopt(char *line, char *keyword) */
-
+#if 0
#if HAVE_GETMNTENT
static quota_mnt_t *
quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list)
continue;
}
- if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_NOQUOTA, 1) != NULL) {
+ if(quota_mnt_checkmountopt(mnt->mnt_opts, "noquota", 1) != NULL) {
DBG("noquota option on fs (%s) %s (%s): ignored",
mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
continue;
device = loop;
}
- if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_QUOTA, 1) != NULL) {
+ if(quota_mnt_checkmountopt(mnt->mnt_opts, "quota", 1) != NULL) {
opts |= QMO_USRQUOTA;
}
- if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_USRQUOTA, 1) != NULL) {
+ if(quota_mnt_checkmountopt(mnt->mnt_opts, "usrquota", 1) != NULL) {
opts |= QMO_USRQUOTA;
}
usrjquota = quota_mnt_getmountopt(mnt->mnt_opts, "usrjquota=");
if(usrjquota != NULL) {
opts |= QMO_USRQUOTA;
}
- if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_GRPQUOTA, 1) != NULL) {
+ if(quota_mnt_checkmountopt(mnt->mnt_opts, "grpquota", 1) != NULL) {
opts |= QMO_GRPQUOTA;
}
grpjquota = quota_mnt_getmountopt(mnt->mnt_opts, "grpjquota=");
jqfmt = quota_mnt_getmountopt(mnt->mnt_opts, "jqfmt=");
#if HAVE_XFS_XQM_H
- if(!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
+ if(!strcmp(mnt->mnt_type, "xfs")) {
if(hasxfsquota(mnt, USRQUOTA) == 0
&& hasxfsquota(mnt, GRPQUOTA) == 0)
{
last->next = (quota_mnt_t *)smalloc(sizeof(quota_mnt_t));
last = last->next;
}
- last->dir = sstrdup(mnt->mnt_dir);
- last->device = device;
- last->type = sstrdup(mnt->mnt_type);
- last->options = sstrdup(mnt->mnt_opts);
+ last->m->dir = sstrdup(mnt->mnt_dir);
+ last->m->device = device;
+ last->m->type = sstrdup(mnt->mnt_type);
+ last->m->options = sstrdup(mnt->mnt_opts);
last->usrjquota = usrjquota;
last->grpjquota = grpjquota;
last->jqfmt = jqfmt;
return last;
} /* static quota_mnt_t *quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list) */
#endif /* HAVE_GETMNTENT */
-
+#endif
quota_mnt_t *
quota_mnt_getlist(quota_mnt_t **list)
{
+ cu_mount_t *fulllist = NULL, *fl;
quota_mnt_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! */
-#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_GETMNTENT && defined(_PATH_MNTTAB)
- {
- FILE *mntf = NULL;
- if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) {
- DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno));
-#endif
-#if HAVE_GETVFSENT && defined(VFSTAB)
- {
- FILE *mntf = NULL;
- if((mntf = fopen(VFSTAB, "r")) == NULL) {
- DBG("opening %s failed: %s", VFSTAB, strerror(errno));
-#endif
-#if HAVE_LISTMNTENT
- {
- struct tabmntent *mntlist;
+ (void)cu_mount_getlist(&fulllist);
+ fl = fulllist;
+ while(fl != NULL) {
- if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) {
- DBG("calling listmntent() failed: %s", strerror(errno));
-#endif
- /* give up */
- DBG("failed get local mountpoints");
- return(NULL);
+ fl = fl->next;
+ } /* while(fl != NULL) */
+ cu_mount_freelist(fulllist);
-#if HAVE_LISTMNTENT
- } else { last = quota_mnt_listmntent(mntlist, list); }
- freemntlist(mntlist);
- }
-#endif
-#if HAVE_GETVFSENT && defined(VFSTAB)
- } else { last = quota_mnt_getvfsmnt(mntf, list); }
- (void)fclose(mntf);
- }
-#endif
-#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
- } else { last = quota_mnt_getmntent(mntf, list); }
- (void)endmntent(mntf);
- }
-#endif
-#if HAVE_GETMNTENT && defined(MNTTABNAME)
- } else { last = quota_mnt_getmntent(mntf, list); }
- (void)endmntent(mntf);
- }
-#endif
-#if HAVE_GETMNTENT && defined(MNT_MNTTAB)
- } else { last = quota_mnt_getmntent(mntf, list); }
- (void)endmntent(mntf);
- }
-#endif
-#if HAVE_GETMNTENT && defined(_PATH_MOUNTED)
- } else { last = quota_mnt_getmntent(mntf, list); }
- (void)endmntent(mntf);
- }
-#endif
return(last);
} /* quota_mnt_t *quota_mnt_getlist(quota_mnt_t **list) */
if(p != NULL) {
p->next = NULL;
}
- sfree(l->dir);
- sfree(l->device);
- sfree(l->type);
- sfree(l->options);
+ sfree(l->m->dir);
+ sfree(l->m->device);
+ sfree(l->m->type);
+ sfree(l->m->options);
sfree(l->usrjquota);
sfree(l->grpjquota);
sfree(l->jqfmt);
} /* while(l != NULL) */
} /* void quota_mnt_freelist(quota_mnt_t *list) */
-int
-quota_mnt_type(const char *type)
-{
- if(strcmp(type, "ext3") == 0) return QMT_EXT3;
- if(strcmp(type, "ext2") == 0) return QMT_EXT2;
- if(strcmp(type, "ufs") == 0) return QMT_UFS;
- if(strcmp(type, "vxfs") == 0) return QMT_VXFS;
- if(strcmp(type, "zfs") == 0) return QMT_ZFS;
- return QMT_UNKNOWN;
-} /* int quota_mnt_type(const char *type) */
-
-
diff --git a/src/quota_mnt.h b/src/quota_mnt.h
index 36484f8fc3bf732f11c04b69c0dfc6115c6ecdff..e5893b9cd2ef1fa3e1a2845d1ff84c31b0380b64 100644 (file)
--- a/src/quota_mnt.h
+++ b/src/quota_mnt.h
#define COLLECTD_QUOTA_MNT_H 1
#include "common.h"
+#include "utils_mount.h"
/* Quota Mount Type */
#define QMT_UNKNOWN (0)
typedef struct _quota_mnt_t quota_mnt_t;
struct _quota_mnt_t {
- char *dir; /* "/sys" or "/" */
- char *device; /* "none" or "/dev/hda1" */
- char *type; /* "sysfs" or "ext3" */
- char *options; /* "rw,noatime,commit=600,quota,grpquota" */
+ cu_mount_t *m;
char *usrjquota; /* "q.u" */
char *grpjquota; /* "q.g" */
char *jqfmt; /* "TODO" */
diff --git a/src/quota_mntopt.h b/src/quota_mntopt.h
--- a/src/quota_mntopt.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * collectd - src/quota_mntopt.h
- * Copyright (C) 2005 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
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Author:
- * Niki W. Waibel <niki.waibel@gmx.net>
-**/
-
-#if !COLLECTD_QUOTA_MNTOPT_H
-#define COLLECTD_QUOTA_MNTOPT_H 1
-
-#include "common.h"
-
-/* filesystem type */
-#ifndef MNTTYPE_AUTOFS
-#define MNTTYPE_AUTOFS "autofs" /* Automount mountpoint */
-#endif
-#ifndef MNTTYPE_CAPIFS
-#define MNTTYPE_CAPIFS "capifs" /* */
-#endif
-#ifndef MNTTYPE_CRAMFS
-#define MNTTYPE_CRAMFS "cramfs" /* */
-#endif
-#ifndef MNTTYPE_DEVPTS
-#define MNTTYPE_DEVPTS "devpts" /* */
-#endif
-#ifndef MNTTYPE_EXT2
-#define MNTTYPE_EXT2 "ext2" /* 2nd Extended file system */
-#endif
-#ifndef MNTTYPE_EXT3
-#define MNTTYPE_EXT3 "ext3" /* ext2 + journaling */
-#endif
-#ifndef MNTTYPE_FUSE
-#define MNTTYPE_FUSE "fuse" /* */
-#endif
-#ifndef MNTTYPE_HSFS
-#define MNTTYPE_HSFS "hsfs" /* */
-#endif
-#ifndef MNTTYPE_ISO9660
-#define MNTTYPE_ISO9660 "iso9660" /* */
-#endif
-#ifndef MNTTYPE_JFS
-#define MNTTYPE_JFS "jfs" /* JFS file system */
-#endif
-#ifndef MNTTYPE_MINIX
-#define MNTTYPE_MINIX "minix" /* MINIX file system */
-#endif
-#ifndef MNTTYPE_NFS
-#define MNTTYPE_NFS "nfs" /* */
-#endif
-#ifndef MNTTYPE_NFS4
-#define MNTTYPE_NFS4 "nfs4" /* NFSv4 filesystem */
-#endif
-#ifndef MNTTYPE_NTFS
-#define MNTTYPE_NTFS "ntfs" /* */
-#endif
-#ifndef MNTTYPE_PROC
-#define MNTTYPE_PROC "proc" /* */
-#endif
-#ifndef MNTTYPE_RAMFS
-#define MNTTYPE_RAMFS "ramfs" /* */
-#endif
-#ifndef MNTTYPE_ROMFS
-#define MNTTYPE_ROMFS "romfs" /* */
-#endif
-#ifndef MNTTYPE_RELAYFS
-#define MNTTYPE_RELAYFS "relayfs" /* */
-#endif
-#ifndef MNTTYPE_REISER
-#define MNTTYPE_REISER "reiserfs" /* Reiser file system */
-#endif
-#ifndef MNTTYPE_SYSFS
-#define MNTTYPE_SYSFS "sysfs" /* */
-#endif
-#ifndef MNTTYPE_TMPFS
-#define MNTTYPE_TMPFS "tmpfs" /* */
-#endif
-#ifndef MNTTYPE_USBFS
-#define MNTTYPE_USBFS "usbfs" /* */
-#endif
-#ifndef MNTTYPE_UDF
-#define MNTTYPE_UDF "udf" /* OSTA UDF file system */
-#endif
-#ifndef MNTTYPE_UFS
-#define MNTTYPE_UFS "ufs" /* UNIX file system */
-#endif
-#ifndef MNTTYPE_XFS
-#define MNTTYPE_XFS "xfs" /* SGI XFS file system */
-#endif
-#ifndef MNTTYPE_VFAT
-#define MNTTYPE_VFAT "vfat" /* */
-#endif
-#ifndef MNTTYPE_ZFS
-#define MNTTYPE_ZFS "zfs" /* */
-#endif
-
-/* mount options */
-#ifndef MNTOPT_RO
-#define MNTOPT_RO "ro" /* */
-#endif
-#ifndef MNTOPT_RQ
-#define MNTOPT_RQ "rq" /* */
-#endif
-#ifndef MNTOPT_PUBLIC
-#define MNTOPT_PUBLIC "public" /* */
-#endif
-#ifndef MNTOPT_NOQUOTA
-#define MNTOPT_NOQUOTA "noquota" /* don't enforce quota */
-#endif
-#ifndef MNTOPT_QUOTA
-#define MNTOPT_QUOTA "quota" /* enforce user quota */
-#endif
-#ifndef MNTOPT_USRQUOTA
-#define MNTOPT_USRQUOTA "usrquota" /* enforce user quota */
-#endif
-#ifndef MNTOPT_USRJQUOTA
-#define MNTOPT_USRJQUOTA "usrjquota" /* enforce user quota */
-#endif
-#ifndef MNTOPT_GRPQUOTA
-#define MNTOPT_GRPQUOTA "grpquota" /* enforce group quota */
-#endif
-#ifndef MNTOPT_GRPJQUOTA
-#define MNTOPT_GRPJQUOTA "grpjquota" /* enforce group quota */
-#endif
-#ifndef MNTOPT_RSQUASH
-#define MNTOPT_RSQUASH "rsquash" /* root as ordinary user */
-#endif
-#ifndef MNTOPT_BIND
-#define MNTOPT_BIND "bind" /* binded mount */
-#endif
-#ifndef MNTOPT_LOOP
-#define MNTOPT_LOOP "loop" /* loopback mount */
-#endif
-#ifndef MNTOPT_JQFMT
-#define MNTOPT_JQFMT "jqfmt" /* journaled quota format */
-#endif
-
-#endif /* !COLLECTD_QUOTA_MNTOPT_H */
-
diff --git a/src/quota_plugin.c b/src/quota_plugin.c
index d2d629ab8c355b3b65c46a9340f60c7712ad7a8c..6dac92c0ee547822c83fab099d1973890a65442a 100644 (file)
--- a/src/quota_plugin.c
+++ b/src/quota_plugin.c
#include "common.h"
#include "plugin.h"
+#include "utils_debug.h"
-#include "quota_debug.h"
-#include "quota_common.h"
#include "quota_mnt.h"
#include "quota_fs.h"
#include "quota_plugin.h"
static void
quota_init(void)
{
- DBG_INIT("quota debug file opened.");
+ DBG_STARTFILE("quota debug file opened.");
}
static void
l = list;
DBG("local mountpoints:");
while(l != NULL) {
- DBG("\tdir: %s", l->dir);
- DBG("\tdevice: %s", l->device);
- DBG("\ttype: %s", l->type);
- DBG("\toptions: %s", l->options);
+ DBG("\tdir: %s", l->m->dir);
+ DBG("\tspec_device: %s", l->m->spec_device);
+ DBG("\tdevice: %s", l->m->device);
+ DBG("\ttype: %s", l->m->type);
+ DBG("\toptions: %s", l->m->options);
DBG("\tusrjquota: %s", l->usrjquota);
DBG("\tgrpjquota: %s", l->grpjquota);
DBG("\tjqfmt: %s", l->jqfmt);
diff --git a/src/utils_debug.c b/src/utils_debug.c
--- /dev/null
+++ b/src/utils_debug.c
@@ -0,0 +1,196 @@
+/**
+ * collectd - src/utils_debug.c
+ * Copyright (C) 2005 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
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Author:
+ * Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+#include "common.h"
+#include "utils_debug.h"
+
+/* *** *** *** global variables *** *** *** */
+#if COLLECT_DEBUG
+
+#define DEFAULT_FILENAME "collectd.log"
+
+static void cu_vdebug(const char *file, int line, const char *func,
+ const char *format, va_list ap);
+
+/* if preemptive threads are used, these vars need some sort of locking! */
+/* pth is non-preemptive, so no locking is necessary (?) */
+static FILE *cu_debug_file = NULL;
+static char *cu_debug_filename = NULL;
+
+static void
+cu_vdebug(const char *file, int line, const char *func,
+ const char *format, va_list ap)
+{
+ FILE *f;
+ if(cu_debug_file != NULL) {
+ f = cu_debug_file;
+ } else {
+ /* stderr might be redirected to /dev/null. in that case */
+ /* you'll not see anything... */
+ f = stderr;
+ }
+
+ fprintf(f, "%s:%d:%s(): ",
+ file, line, func);
+ vfprintf(f, format, ap);
+ fprintf(f, "\n");
+ fflush(f);
+} /* static void cu_vdebug(const char *file, int line, const char *func,
+ const char *format, va_list ap) */
+
+void
+cu_debug(const char *file, int line, const char *func,
+ const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ cu_vdebug(file, line, func, format, ap);
+ va_end(ap);
+} /* void 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,
+ const char *format, ...)
+{
+ va_list ap;
+
+ if(cu_debug_file != NULL) {
+ DBG("Don't call this function more then once without"
+ " calling cu_debug_stopfile().");
+ return EXIT_FAILURE;
+ }
+
+ if(cu_debug_filename == NULL) {
+ cu_debug_filename = sstrdup(DEFAULT_FILENAME);
+ }
+
+ cu_debug_file = fopen(cu_debug_filename, "a");
+ if(cu_debug_file == NULL) {
+ DBG("Cannot open debug file %s: %s.\n",
+ cu_debug_filename, strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ va_start(ap, format);
+ cu_vdebug(file, line, func, format, ap);
+ va_end(ap);
+
+ return EXIT_SUCCESS;
+} /* int cu_debug_start(const char *file, int line, const char *func,
+ const char *format, ...) */
+
+int
+cu_debug_stopfile(const char *file, int line, const char *func,
+ const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ cu_vdebug(file, line, func, format, ap);
+ va_end(ap);
+
+ if(cu_debug_file == NULL) {
+ DBG("Don't call this function more then once or without"
+ " calling cu_debug_startfile().");
+ return EXIT_FAILURE;
+ }
+
+ if(fclose(cu_debug_file) != 0) {
+ DBG("Cannot close debug file %s: %s.\n",
+ cu_debug_filename, strerror(errno));
+ return EXIT_FAILURE;
+ }
+ cu_debug_file = NULL;
+
+ sfree(cu_debug_filename);
+
+ return EXIT_SUCCESS;
+} /* int cu_debug_stop(const char *file, int line, const char *func,
+ const char *format, ...) */
+
+int
+cu_debug_resetfile(const char *file, int line, const char *func,
+ const char *filename)
+{
+ if(filename == NULL) {
+ DBG("You have to set filename when calling this function!\n");
+ return EXIT_FAILURE;
+ }
+ if(cu_debug_file != NULL) {
+ char *save_filename = NULL;
+
+ /* DBG_STARTFILE was called already */
+ /* reopen file */
+
+ DBG_STOPFILE("Closing %s and reopening %s.",
+ cu_debug_filename, filename);
+ save_filename = smalloc(strlen(cu_debug_filename)+1);
+ sstrncpy(save_filename, cu_debug_filename,
+ strlen(cu_debug_filename)+1);
+ cu_debug_filename = smalloc(strlen(filename)+1);
+ sstrncpy(cu_debug_filename, filename, strlen(filename)+1);
+ DBG_STARTFILE("Reopening %s after closing %s.",
+ filename, save_filename);
+ sfree(save_filename);
+ return EXIT_SUCCESS;
+ }
+
+ /* DBG_STARTFILE was NOT called already */
+ /* setting filename only */
+
+ if(cu_debug_filename != NULL) {
+ sfree(cu_debug_filename);
+ }
+ cu_debug_filename = smalloc(strlen(filename)+1);
+ sstrncpy(cu_debug_filename, filename, strlen(filename)+1);
+
+ return EXIT_SUCCESS;
+} /* int cu_debug_resetfile(const char *file, int line, const char *func,
+ const char *filename) */
+
+#else /* !COLLECT_DEBUG */
+
+void
+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, ...)
+{
+ return EXIT_SUCCESS;
+}
+int
+cu_debug_stopfile(const char *file, int line, const char *func, char *format, ...)
+{
+ return EXIT_SUCCESS;
+}
+int
+cu_debug_setfile(const char *file, int line, const char *func, char *filename)
+{
+ return EXIT_SUCCESS;
+}
+
+#endif /* COLLECT_DEBUG */
+
diff --git a/src/utils_debug.h b/src/utils_debug.h
--- /dev/null
+++ b/src/utils_debug.h
@@ -0,0 +1,50 @@
+/**
+ * collectd - src/utils_debug.h
+ * Copyright (C) 2005 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
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Author:
+ * Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+#if !COLLECTD_UTILS_DEBUG_H
+#define COLLECTD_UTILS_DEBUG_H 1
+
+#define DBG(...) cu_debug(__FILE__, __LINE__, __func__, \
+ __VA_ARGS__)
+
+#define DBG_STARTFILE(...) cu_debug_startfile(__FILE__, __LINE__, \
+ __func__, __VA_ARGS__)
+#define DBG_STOPFILE(...) cu_debug_stopfile(__FILE__, __LINE__, \
+ __func__, __VA_ARGS__)
+
+#define DBG_SETFILE(file) cu_debug_setfile(__FILE__, __LINE__, __func__, \
+ filename)
+
+void 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,
+ const char *format, ...);
+int cu_debug_stopfile(const char *file, int line, const char *func,
+ const char *format, ...);
+
+int cu_debug_setfile(const char *file, int line, const char *func,
+ char *filename);
+
+#endif /* !COLLECTD_UTILS_DEBUG_H */
+
diff --git a/src/utils_mount.c b/src/utils_mount.c
--- /dev/null
+++ b/src/utils_mount.c
@@ -0,0 +1,602 @@
+/**
+ * collectd - src/utils_mount.c
+ * Copyright (C) 2005 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
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Author:
+ * Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+
+
+#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
+#include "utils_debug.h"
+#include "utils_mount.h"
+
+
+
+/* *** *** *** local functions *** *** *** */
+
+
+
+/* stolen from quota-3.13 (quota-tools) */
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR "/dev"
+#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];
+ 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 firstPass;
+ int handleOnFirst;
+
+ if(uuidCache) {
+ return;
+ }
+
+ procpt = fopen(PROC_PARTITIONS, "r");
+ if(procpt == NULL) {
+ return;
+ }
+
+ for(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];
+ int i;
+
+ if(strlen(s) != 36
+ || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') {
+ goto bad_uuid;
+ }
+
+ for(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:
+ DBG("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 *item)
+{
+ 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(!rc) {
+ DBG("Error checking device name: %s", 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
+static void
+cu_mount_getvfsmnt(FILE *mntf, cu_mount_t **list)
+{
+ DBG("TODO: getvfsmnt");
+ *list = NULL;
+}
+#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)
+{
+ char *r;
+
+ 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;
+ }
+ 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_getmountopt(char *line, char *keyword) */
+
+#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
+ while((mnt = getmntent(mntf)) != NULL) {
+#endif /* HAVE_GETMNTENT1 */
+ char *loop = NULL, *device = NULL;
+
+#if 1
+ 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
+
+ loop = cu_mount_getmountopt(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 1
+ DBG("device %s", device);
+ DBG("------------------ END");
+#endif
+ if(*list == NULL) {
+ *list = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
+ last = *list;
+ } else {
+ 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;
+ } /* while((mnt = getmntent(mntf)) != NULL) */
+
+ return last;
+} /* static cu_mount_t *cu_mount_getmntent(FILE *mntf, cu_mount_t **list) */
+#endif /* HAVE_GETMNTENT */
+
+
+
+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! */
+#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_GETMNTENT && defined(_PATH_MNTTAB)
+ {
+ FILE *mntf = NULL;
+ if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) {
+ DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno));
+#endif
+#if HAVE_GETVFSENT && defined(VFSTAB)
+ {
+ FILE *mntf = NULL;
+ if((mntf = fopen(VFSTAB, "r")) == NULL) {
+ DBG("opening %s failed: %s", VFSTAB, strerror(errno));
+#endif
+#if HAVE_LISTMNTENT
+ {
+ struct tabmntent *mntlist;
+
+ if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) {
+ DBG("calling listmntent() failed: %s", strerror(errno));
+#endif
+ /* give up */
+ DBG("failed get local mountpoints");
+ return(NULL);
+
+#if HAVE_LISTMNTENT
+ } else { last = cu_mount_listmntent(mntlist, list); }
+ freemntlist(mntlist);
+ }
+#endif
+#if HAVE_GETVFSENT && defined(VFSTAB)
+ } else { last = cu_mount_getvfsmnt(mntf, list); }
+ (void)fclose(mntf);
+ }
+#endif
+#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
+ } else { last = cu_mount_getmntent(mntf, list); }
+ (void)endmntent(mntf);
+ }
+#endif
+#if HAVE_GETMNTENT && defined(MNTTABNAME)
+ } else { last = cu_mount_getmntent(mntf, list); }
+ (void)endmntent(mntf);
+ }
+#endif
+#if HAVE_GETMNTENT && defined(MNT_MNTTAB)
+ } else { last = cu_mount_getmntent(mntf, list); }
+ (void)endmntent(mntf);
+ }
+#endif
+#if HAVE_GETMNTENT && defined(_PATH_MOUNTED)
+ } else { last = cu_mount_getmntent(mntf, list); }
+ (void)endmntent(mntf);
+ }
+#endif
+ return(last);
+} /* cu_mount_t *cu_mount_getlist(cu_mount_t **list) */
+
+void
+cu_mount_freelist(cu_mount_t *list)
+{
+ cu_mount_t *l = list, *p = NULL;
+
+ 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);
+ sfree(l);
+ p = NULL;
+ if(l != list) {
+ l = list;
+ } else {
+ l = NULL;
+ }
+ } /* while(l != NULL) */
+} /* void cu_mount_freelist(cu_mount_t *list) */
+
+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) */
+
+
+
diff --git a/src/utils_mount.h b/src/utils_mount.h
--- /dev/null
+++ b/src/utils_mount.h
@@ -0,0 +1,108 @@
+/**
+ * collectd - src/utils_mount.h
+ * Copyright (C) 2005 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
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Author:
+ * Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+#if !COLLECTD_UTILS_MOUNT_H
+#define COLLECTD_UTILS_MOUNT_H 1
+
+#if HAVE_MNTENT_H
+# include <mntent.h>
+#endif
+#if HAVE_MNTTAB_H
+# include <mnttab.h>
+#endif
+#if HAVE_PATHS_H
+# include <paths.h>
+#endif
+#if HAVE_SYS_FS_TYPES_H
+# include <sys/fs_types.h>
+#endif
+#if HAVE_SYS_MNTENT_H
+# include <sys/mntent.h>
+#endif
+#if HAVE_SYS_MNTTAB_H
+# include <sys/mnttab.h>
+#endif
+#if HAVE_SYS_MOUNT_H
+# include <sys/mount.h>
+#endif
+#if HAVE_SYS_VFSTAB_H
+# include <sys/vfstab.h>
+#endif
+#if HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+
+#include "common.h"
+
+/* Collectd Utils Mount Type */
+#define CUMT_UNKNOWN (0)
+#define CUMT_EXT2 (1)
+#define CUMT_EXT3 (2)
+#define CUMT_XFS (3)
+#define CUMT_UFS (4)
+#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 *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);
+
+/*
+ DESCRIPTION
+ The cu_mount_getlist() function creates a list
+ of all 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.
+
+ RETURN VALUE
+ The cu_mount_getlist() function returns a pointer to
+ the last entry of the list, or NULL if an error 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);
+
+#endif /* !COLLECTD_UTILS_MOUNT_H */
+