From: niki Date: Sun, 11 Dec 2005 11:30:40 +0000 (+0000) Subject: Huge changes. Segfaults at the moment, but this is the way we want to go... X-Git-Tag: collectd-3.5.0~1^2~19 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=9cff35bc5208abc167a42ec8e7c541bb0855f4cc;p=collectd.git Huge changes. Segfaults at the moment, but this is the way we want to go... --- diff --git a/build.sh b/build.sh index 852b8eb7..ca41cad0 100755 --- a/build.sh +++ b/build.sh @@ -3,6 +3,7 @@ set -x true \ +&& autoheader --force \ && aclocal --force \ && libtoolize --ltdl --force --copy \ && automake --add-missing --copy \ diff --git a/configure.in b/configure.in index 220f51c9..7556ac3c 100644 --- a/configure.in +++ b/configure.in @@ -24,8 +24,8 @@ AC_PROG_LIBTOOL 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) @@ -71,40 +71,6 @@ AC_CHECK_FUNCS(getgrgid getpwuid) 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 -#endif -#if HAVE_MNTTAB_H -# include -#endif -#if HAVE_PATHS_H -# include -#endif -#if HAVE_SYS_FS_TYPES_H -# include -#endif -#if HAVE_SYS_MNTENT_H -# include -#endif -#if HAVE_SYS_MNTTAB_H -# include -#endif -#if HAVE_SYS_MOUNT_H -# include -#endif -#if HAVE_SYS_VFSTAB_H -# include -#endif -#if HAVE_SYS_QUOTA_H -# include -#endif -#if HAVE_SYS_VFS_H -# include -#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" @@ -112,7 +78,7 @@ if test "x$ac_cv_func_getmntent" = 'xyes'; then [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], @@ -124,7 +90,7 @@ if test "x$ac_cv_func_getmntent" = 'xyes'; then [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);]] ), @@ -191,6 +157,32 @@ then 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" @@ -272,6 +264,46 @@ fi # # 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 @@ -321,7 +353,7 @@ fi 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 @@ -330,7 +362,6 @@ else 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 @@ -338,7 +369,7 @@ else 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"]) @@ -510,15 +541,20 @@ cat < +#endif #include #if HAVE_SYS_TYPES_H # include @@ -103,10 +106,6 @@ #include #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 new file mode 100644 index 00000000..d946cfb4 --- /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 + * Niki W. Waibel +**/ + +#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 new file mode 100644 index 00000000..89cae6a9 --- /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 6a91b3fc..746d711c 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -6,6 +6,12 @@ /* 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 @@ -27,7 +33,10 @@ /* 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 */ @@ -111,6 +120,9 @@ /* 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 @@ -150,6 +162,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_PATHS_H +/* Define to 1 if you have the header file. */ +#undef HAVE_PTH_H + /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H @@ -174,6 +189,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STATGRAB_H +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H diff --git a/src/quota_common.c b/src/quota_common.c deleted file mode 100644 index 7d507426..00000000 --- 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 -**/ - -#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 deleted file mode 100644 index c05b2dc5..00000000 --- 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 -**/ - -#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 deleted file mode 100644 index acaa94ca..00000000 --- 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 -**/ - -#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 deleted file mode 100644 index 6d0d7473..00000000 --- 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 -**/ - -#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 bbacafaf..57044e8d 100644 --- a/src/quota_fs.c +++ b/src/quota_fs.c @@ -22,8 +22,7 @@ **/ #include "common.h" -#include "quota_debug.h" -#include "quota_common.h" +#include "utils_debug.h" #include "quota_mnt.h" #include "quota_fs.h" @@ -64,11 +63,11 @@ getquota_ext3(quota_t **quota, quota_mnt_t *m) 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) { @@ -108,39 +107,39 @@ DBG("start"); #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"); } @@ -159,11 +158,11 @@ DBG("start"); 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; @@ -171,11 +170,11 @@ DBG("start"); 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; @@ -194,18 +193,18 @@ DBG("start"); 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; @@ -222,7 +221,7 @@ DBG("start"); 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; @@ -241,18 +240,18 @@ DBG("start"); 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; @@ -269,7 +268,7 @@ DBG("start"); 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; @@ -424,7 +423,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->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 b689ae84..3404dfe4 100644 --- a/src/quota_fs.h +++ b/src/quota_fs.h @@ -25,7 +25,7 @@ #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 50b0f4ff..1917a59b 100644 --- a/src/quota_mnt.c +++ b/src/quota_mnt.c @@ -22,8 +22,7 @@ **/ #include "common.h" -#include "quota_debug.h" -#include "quota_common.h" +#include "utils_debug.h" #include "quota_fs.h" #include "quota_mnt.h" @@ -68,443 +67,13 @@ #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) @@ -538,7 +107,7 @@ 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; @@ -563,17 +132,17 @@ quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list) 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="); @@ -583,7 +152,7 @@ quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list) 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) { @@ -622,10 +191,10 @@ quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list) 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; @@ -636,89 +205,23 @@ quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list) 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) */ @@ -735,10 +238,10 @@ quota_mnt_freelist(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); @@ -752,16 +255,4 @@ quota_mnt_freelist(quota_mnt_t *list) } /* 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 36484f8f..e5893b9c 100644 --- a/src/quota_mnt.h +++ b/src/quota_mnt.h @@ -25,6 +25,7 @@ #define COLLECTD_QUOTA_MNT_H 1 #include "common.h" +#include "utils_mount.h" /* Quota Mount Type */ #define QMT_UNKNOWN (0) @@ -42,10 +43,7 @@ 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 deleted file mode 100644 index 1160f359..00000000 --- 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 -**/ - -#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 d2d629ab..6dac92c0 100644 --- a/src/quota_plugin.c +++ b/src/quota_plugin.c @@ -23,9 +23,8 @@ #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" @@ -106,7 +105,7 @@ quota_submit(quota_t *q) static void quota_init(void) { - DBG_INIT("quota debug file opened."); + DBG_STARTFILE("quota debug file opened."); } static void @@ -119,10 +118,11 @@ quota_read(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 new file mode 100644 index 00000000..c839ade0 --- /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 +**/ + +#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 new file mode 100644 index 00000000..a7b1971a --- /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 +**/ + +#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 new file mode 100644 index 00000000..74bc02f0 --- /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 +**/ + + + +#include "common.h" +#if HAVE_XFS_XQM_H +# include +#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 new file mode 100644 index 00000000..3f357b8b --- /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 +**/ + +#if !COLLECTD_UTILS_MOUNT_H +#define COLLECTD_UTILS_MOUNT_H 1 + +#if HAVE_MNTENT_H +# include +#endif +#if HAVE_MNTTAB_H +# include +#endif +#if HAVE_PATHS_H +# include +#endif +#if HAVE_SYS_FS_TYPES_H +# include +#endif +#if HAVE_SYS_MNTENT_H +# include +#endif +#if HAVE_SYS_MNTTAB_H +# include +#endif +#if HAVE_SYS_MOUNT_H +# include +#endif +#if HAVE_SYS_VFSTAB_H +# include +#endif +#if HAVE_SYS_VFS_H +# include +#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 */ +