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