Bumped version to 3.5.2
[collectd.git] / src / utils_mount.c
index 74bc02f..ecfd0ec 100644 (file)
@@ -26,8 +26,6 @@
 #include "common.h"
 #if HAVE_XFS_XQM_H
 # include <xfs/xqm.h>
-#define xfs_mem_dqinfo  fs_quota_stat
-#define Q_XFS_GETQSTAT  Q_XGETQSTAT
 #define XFS_SUPER_MAGIC_STR "XFSB"
 #define XFS_SUPER_MAGIC2_STR "BSFX"
 #endif
@@ -36,7 +34,9 @@
 
 
 
-/* *** *** ***   local functions   *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
+/* *** *** *** *** *** ***   private functions   *** *** *** *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
 
 
 
@@ -47,8 +47,6 @@
 #define UUID   1
 #define VOL    2
 
-#define AUTOFS_DIR_MAX 64       /* Maximum number of autofs directories */
-
 static struct uuidCache_s {
        struct uuidCache_s *next;
        char uuid[16];
@@ -317,26 +315,6 @@ get_device_name(const char *item)
        return rc;
 }
 
-#if HAVE_LISTMNTENT
-static void
-cu_mount_listmntent(struct tabmntent *mntlist, cu_mount_t **list)
-{
-       struct *p;
-       struct mntent *mnt;
-
-       for(p = mntlist; p; p = p->next) {
-               mnt = p->ment;
-               *list = smalloc(sizeof(cu_mount_t));
-               list->device = strdup(mnt->mnt_fsname);
-               list->name = strdup(mnt->mnt_dir);
-               list->type = strdup(mnt->mnt_type);
-               list->next = NULL;
-               list = &(ist->next);
-       }
-       freemntlist(mntlist);
-}
-#endif /* HAVE_LISTMNTENT */
-
 
 
 #if HAVE_GETVFSENT
@@ -348,87 +326,79 @@ cu_mount_getvfsmnt(FILE *mntf, cu_mount_t **list)
 }
 #endif /* HAVE_GETVFSENT */
 
-char *
-cu_mount_checkmountopt(char *line, char *keyword, int full)
-{
-       char *line2, *l2;
-       int l = strlen(keyword);
-       char *p1, *p2;
-
-       if(line == NULL || keyword == NULL) {
-               return NULL;
-       }
-       if(full != 0) {
-               full = 1;
-       }
-
-       line2 = sstrdup(line);
-       l2 = line2;
-       while(*l2 != '\0') {
-               if(*l2 == ',') {
-                       *l2 = '\0';
-               }
-               l2++;
-       }
-
-       p1 = line - 1;
-       p2 = strchr(line, ',');
-       do {
-               if(strncmp(line2+(p1-line)+1, keyword, l+full) == 0) {
-                       free(line2);
-                       return p1+1;
-               }
-               p1 = p2;
-               if(p1 != NULL) {
-                       p2 = strchr(p1+1, ',');
-               }
-       } while(p1 != NULL);
 
-       free(line2);
-       return NULL;
-} /* char *cu_mount_checkmountopt(char *line, char *keyword, int full) */
 
-char *
-cu_mount_getmountopt(char *line, char *keyword)
+#if HAVE_LISTMNTENT
+static cu_mount_t *
+cu_mount_listmntent(struct tabmntent *mntlist, cu_mount_t **list)
 {
-       char *r;
+       cu_mount_t *last = *list;
+       struct tabmntent *p;
+       struct mntent *mnt;
 
-       r = cu_mount_checkmountopt(line, keyword, 0);
-       if(r != NULL) {
-               char *p;
-               r += strlen(keyword);
-               p = strchr(r, ',');
-               if(p == NULL) {
-                       if(strlen(r) == 0) {
-                               return NULL;
+       for(p = mntlist; p; p = p->next) {
+               char *loop = NULL, *device = NULL;
+
+               mnt = p->ment;
+               loop = cu_mount_getoptionvalue(mnt->mnt_opts, "loop=");
+               if(loop == NULL) {   /* no loop= mount */
+                       device = get_device_name(mnt->mnt_fsname);
+                       if(device == NULL) {
+                               DBG("can't get devicename for fs (%s) %s (%s)"
+                                       ": ignored", mnt->mnt_type,
+                                       mnt->mnt_dir, mnt->mnt_fsname);
+                               continue;
                        }
-                       return sstrdup(r);
                } else {
-                       char *m;
-                       if((p-r) == 1) {
-                               return NULL;
+                       device = loop;
+               }
+               if(*list == NULL) {
+                       *list = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
+                       last = *list;
+               } else {
+                       while(last->next != NULL) { /* is last really last? */
+                               last = last->next;
                        }
-                       m = (char *)smalloc(p-r+1);
-                       sstrncpy(m, r, p-r+1);
-                       return m;
+                       last->next = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
+                       last = last->next;
                }
-       }
-       return r;
-} /* char *cu_mount_getmountopt(char *line, char *keyword) */
+               last->dir = sstrdup(mnt->mnt_dir);
+               last->spec_device = sstrdup(mnt->mnt_fsname);
+               last->device = device;
+               last->type = sstrdup(mnt->mnt_type);
+               last->options = sstrdup(mnt->mnt_opts);
+               last->next = NULL;
+       } /* for(p = mntlist; p; p = p->next) */
+
+       return(last);
+} /* static cu_mount_t *cu_mount_listmntent(struct tabmntent *mntlist,
+       cu_mount_t **list) */
+#endif /* HAVE_LISTMNTENT */
+
+
 
 #if HAVE_GETMNTENT
 static cu_mount_t *
 cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
 {
        cu_mount_t *last = *list;
-       struct mntent *mnt;
+#if HAVE_GETMNTENT1
+       struct mntent *mnt = NULL;
+#endif
+#if HAVE_GETMNTENT2
+       struct mntent real_mnt;
+       struct mntent *mnt = &real_mnt;
+#endif
 
 #if HAVE_GETMNTENT1
        while((mnt = getmntent(mntf)) != NULL) {
-#endif /* HAVE_GETMNTENT1 */
+#endif
+#if HAVE_GETMNTENT2
+       while(getmntent(mntf, &real_mnt) == 0) {
+#endif
                char *loop = NULL, *device = NULL;
 
-#if 1
+#if 0
                DBG("------------------ BEGIN");
                DBG("mnt->mnt_fsname %s", mnt->mnt_fsname);
                DBG("mnt->mnt_dir    %s", mnt->mnt_dir);
@@ -438,7 +408,7 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
                DBG("mnt->mnt_passno %d", mnt->mnt_passno);
 #endif
 
-               loop = cu_mount_getmountopt(mnt->mnt_opts, "loop=");
+               loop = cu_mount_getoptionvalue(mnt->mnt_opts, "loop=");
                if(loop == NULL) {   /* no loop= mount */
                        device = get_device_name(mnt->mnt_fsname);
                        if(device == NULL) {
@@ -451,14 +421,17 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
                        device = loop;
                }
 
-#if 1
-               DBG("device          %s", device);
+#if 0
+               DBG("device: %s", device);
                DBG("------------------ END");
 #endif
                if(*list == NULL) {
                        *list = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
                        last = *list;
                } else {
+                       while(last->next != NULL) { /* is last really last? */
+                               last = last->next;
+                       }
                        last->next = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
                        last = last->next;
                }
@@ -468,7 +441,12 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
                last->type = sstrdup(mnt->mnt_type);
                last->options = sstrdup(mnt->mnt_opts);
                last->next = NULL;
+#if HAVE_GETMNTENT2
+       } /* while(getmntent(mntf, &real_mnt) == 0) */
+#endif
+#if HAVE_GETMNTENT1
        } /* while((mnt = getmntent(mntf)) != NULL) */
+#endif
 
        return last;
 } /* static cu_mount_t *cu_mount_getmntent(FILE *mntf, cu_mount_t **list) */
@@ -476,15 +454,48 @@ cu_mount_getmntent(FILE *mntf, cu_mount_t **list)
 
 
 
+/* *** *** *** ******************************************** *** *** *** */
+/* *** *** *** *** *** ***   public functions   *** *** *** *** *** *** */
+/* *** *** *** ******************************************** *** *** *** */
+
+
+
 cu_mount_t *
 cu_mount_getlist(cu_mount_t **list)
 {
        cu_mount_t *last = NULL;
 
-       /* yes, i know that the indentation is wrong.
-          but show me a better way to do this... */
-       /* see lib/mountlist.c of coreutils for all
-          gory details! */
+       /* see lib/mountlist.c of coreutils for all (ugly) details! */
+
+/*
+   there are two implementations of getmntent():
+     * one argument getmntent:
+           FILE *setmntent(const char *filename, const char *type);
+           struct mntent *getmntent(FILE *fp);
+           int endmntent(FILE *fp);
+     * two argument getmntent:
+           FILE *fopen(const char *path, const char *mode);
+           int getmntent(FILE *fp, struct mnttab *mnt);
+           int fclose(FILE *fp);
+   and a third (linux/gnu style) version called getmntent_r, which is not used
+   here (enough trouble with the two versions above).
+*/
+#if HAVE_GETMNTENT
+# if HAVE_GETMNTENT1
+#  define setmntent setmntent
+#  define endmntent endmntent
+# else
+#  if HAVE_GETMNTENT2
+#   define setmntent fopen
+#   define endmntent fclose
+#  else
+#   error HAVE_GETMNTENT defined, but neither HAVE_GETMNTENT1 nor HAVE_GETMNTENT2
+#  endif /* HAVE_GETMNTENT2 */
+# endif /* HAVE_GETMNTENT1 */
+#endif /* HAVE_GETMNTENT */
+
+       /* the indentation is wrong. is there a better way to do this? */
+
 #if HAVE_GETMNTENT && defined(_PATH_MOUNTED)
        {
        FILE *mntf = NULL;
@@ -503,32 +514,36 @@ cu_mount_getlist(cu_mount_t **list)
        if((mntf = setmntent(MNTTABNAME, "r")) == NULL) {
                DBG("opening %s failed: %s", MNTTABNAME, strerror(errno));
 #endif
-#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
+#if HAVE_LISTMNTENT
        {
-       FILE *mntf = NULL;
-       if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) {
-               DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno));
+       struct tabmntent *mntlist;
+       if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) {
+               DBG("calling listmntent() failed: %s", strerror(errno));
 #endif
 #if HAVE_GETVFSENT && defined(VFSTAB)
+       /* this is as bad as the next one, read next comment */
        {
        FILE *mntf = NULL;
        if((mntf = fopen(VFSTAB, "r")) == NULL) {
                DBG("opening %s failed: %s", VFSTAB, strerror(errno));
 #endif
-#if HAVE_LISTMNTENT
+#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
+       /* _PATH_MNTTAB is usually /etc/fstab and so this should be really
+          the very last thing to try, because it does not provide a list
+          of currently mounted filesystems... */
        {
-       struct tabmntent *mntlist;
-
-       if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) {
-               DBG("calling listmntent() failed: %s", strerror(errno));
+       FILE *mntf = NULL;
+       if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) {
+               DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno));
 #endif
-               /* give up */
-               DBG("failed get local mountpoints");
-               return(NULL);
 
-#if HAVE_LISTMNTENT
-       } else { last = cu_mount_listmntent(mntlist, list); }
-       freemntlist(mntlist);
+       /* give up */
+       DBG("failed get local mountpoints");
+       return(NULL);
+
+#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
+       } else { last = cu_mount_getmntent(mntf, list); }
+       (void)endmntent(mntf);
        }
 #endif
 #if HAVE_GETVFSENT && defined(VFSTAB)
@@ -536,9 +551,9 @@ cu_mount_getlist(cu_mount_t **list)
        (void)fclose(mntf);
        }
 #endif
-#if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
-       } else { last = cu_mount_getmntent(mntf, list); }
-       (void)endmntent(mntf);
+#if HAVE_LISTMNTENT
+       } else { last = cu_mount_listmntent(mntlist, list); }
+       freemntlist(mntlist);
        }
 #endif
 #if HAVE_GETMNTENT && defined(MNTTABNAME)
@@ -559,6 +574,8 @@ cu_mount_getlist(cu_mount_t **list)
        return(last);
 } /* cu_mount_t *cu_mount_getlist(cu_mount_t **list) */
 
+
+
 void
 cu_mount_freelist(cu_mount_t *list)
 {
@@ -577,16 +594,91 @@ cu_mount_freelist(cu_mount_t *list)
                sfree(l->device);
                sfree(l->type);
                sfree(l->options);
-               sfree(l);
                p = NULL;
                if(l != list) {
+                       sfree(l);
                        l = list;
                } else {
-                       l = NULL;
+                       sfree(l);
+                       l = NULL; /* done by sfree already */
                }
        } /* while(l != NULL) */
 } /* void cu_mount_freelist(cu_mount_t *list) */
 
+
+
+char *
+cu_mount_checkoption(char *line, char *keyword, int full)
+{
+       char *line2, *l2;
+       int l = strlen(keyword);
+       char *p1, *p2;
+
+       if(line == NULL || keyword == NULL) {
+               return NULL;
+       }
+       if(full != 0) {
+               full = 1;
+       }
+
+       line2 = sstrdup(line);
+       l2 = line2;
+       while(*l2 != '\0') {
+               if(*l2 == ',') {
+                       *l2 = '\0';
+               }
+               l2++;
+       }
+
+       p1 = line - 1;
+       p2 = strchr(line, ',');
+       do {
+               if(strncmp(line2+(p1-line)+1, keyword, l+full) == 0) {
+                       free(line2);
+                       return p1+1;
+               }
+               p1 = p2;
+               if(p1 != NULL) {
+                       p2 = strchr(p1+1, ',');
+               }
+       } while(p1 != NULL);
+
+       free(line2);
+       return NULL;
+} /* char *cu_mount_checkoption(char *line, char *keyword, int full) */
+
+
+
+char *
+cu_mount_getoptionvalue(char *line, char *keyword)
+{
+       char *r;
+
+       r = cu_mount_checkoption(line, keyword, 0);
+       if(r != NULL) {
+               char *p;
+               r += strlen(keyword);
+               p = strchr(r, ',');
+               if(p == NULL) {
+                       if(strlen(r) == 0) {
+                               return NULL;
+                       }
+                       return sstrdup(r);
+               } else {
+                       char *m;
+                       if((p-r) == 1) {
+                               return NULL;
+                       }
+                       m = (char *)smalloc(p-r+1);
+                       sstrncpy(m, r, p-r+1);
+                       return m;
+               }
+       }
+       return r;
+} /* char *cu_mount_getoptionvalue(char *line, char *keyword) */
+
+
+
 int
 cu_mount_type(const char *type)
 {