From 3c754806154581369c6d14a834c8920abcf8b1f5 Mon Sep 17 00:00:00 2001 From: niki Date: Sat, 3 Dec 2005 15:40:31 +0000 Subject: [PATCH] We are getting somewhere. Quotas are read for the first 1000 uids / gids. It is a stupid for()-loop that has to be changed somehow (Cannot/Shouldn't do that for all uids/gids! But it seems that the quota implementations have no easy way to find out which user/group id's are actually used). --- configure.in | 2 +- src/config.h.in | 3 + src/quota_fs.c | 287 +++++++++++++++++++++++++++------------------ src/quota_fs.h | 44 +++++-- src/quota_mnt.c | 13 ++ src/quota_mnt.h | 11 ++ src/quota_plugin.c | 4 +- 7 files changed, 241 insertions(+), 123 deletions(-) diff --git a/configure.in b/configure.in index 5d6bd7d8..9f68d25b 100644 --- a/configure.in +++ b/configure.in @@ -36,7 +36,7 @@ AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS(netdb.h) AC_CHECK_HEADERS(syslog.h) AC_CHECK_HEADERS(dlfcn.h) -AC_CHECK_HEADERS(grp.h) +AC_CHECK_HEADERS(grp.h pwd.h) AC_CHECK_HEADERS(paths.h) AC_CHECK_HEADERS(mntent.h) AC_CHECK_HEADERS(sys/fs_types.h) diff --git a/src/config.h.in b/src/config.h.in index afb9fa00..b4744989 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -138,6 +138,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_PWD_H + /* Define to 1 if you have the `quotactl' function. */ #undef HAVE_QUOTACTL diff --git a/src/quota_fs.c b/src/quota_fs.c index e151c393..0399d392 100644 --- a/src/quota_fs.c +++ b/src/quota_fs.c @@ -27,17 +27,23 @@ #include "quota_mnt.h" #include "quota_fs.h" +#if HAVE_PWD_H +# include +#endif +#if HAVE_GRP_H +# include +#endif #if HAVE_SYS_QUOTA_H # include #endif +#define MY_BLOCKSIZE 1024 /* *** *** *** prototypes of local functions *** *** *** */ -static int qft(const char *type); static quota_t *getquota_ext3(quota_t **quota, quota_mnt_t *m); static quota_t *getquota_ext3_v1(quota_t **quota, quota_mnt_t *m); static quota_t *getquota_ext3_v2(quota_t **quota, quota_mnt_t *m); @@ -51,19 +57,6 @@ static quota_t *getquota_zfs(quota_t **quota, quota_mnt_t *m); -static int -qft(const char *type) -{ - if(strcmp(type, "ext3") == 0) return QFT_EXT3; - if(strcmp(type, "ext2") == 0) return QFT_EXT2; - if(strcmp(type, "ufs") == 0) return QFT_UFS; - if(strcmp(type, "vxfs") == 0) return QFT_VXFS; - if(strcmp(type, "zfs") == 0) return QFT_ZFS; - return QFT_NONE; -} /* static int qft(const char *type) */ - - - static quota_t * getquota_ext3(quota_t **quota, quota_mnt_t *m) { @@ -74,7 +67,8 @@ getquota_ext3(quota_t **quota, quota_mnt_t *m) if(quotactl(QCMD(Q_GETFMT, USRQUOTA), m->device, 0, (void *)&fmt) == -1) { - DBG("quotactl returned -1: %s", strerror(errno)); + DBG("quotactl (Q_GETFMT, USRQUOTA) returned -1 on" + " %s: %s", m->device, strerror(errno)); return NULL; } if(fmt == 1) { @@ -95,92 +89,164 @@ getquota_ext3(quota_t **quota, quota_mnt_t *m) static quota_t * getquota_ext3_v1(quota_t **quota, quota_mnt_t *m) { + quota_t *q = *quota; + int i; + char buf[100]; +#if HAVE_GETPWUID + struct passwd *passwd; +#endif +#if HAVE_GETGRGID + struct group *group; +#endif #if HAVE_QUOTACTL - struct dqinfo dqi_usr, dqi_grp; + struct dqinfo dqiusr, dqigrp; #endif - quota_t *q; - DBG("quota v1:"); +DBG("start"); + #if HAVE_QUOTACTL - if(quotactl(QCMD(Q_GETINFO, USRQUOTA), m->device, - 0, (void *)&dqi_usr) == -1) - { - DBG("quotactl (Q_GETINFO, USRQUOTA) returned -1 on" - " %s: %s", m->device, strerror(errno)); - *quota = NULL; - return NULL; + if(m->opts & QMO_USRQUOTA) { + if(quotactl(QCMD(Q_GETINFO, USRQUOTA), m->device, + 0, (void *)&dqiusr) == -1) + { + DBG("quotactl (Q_GETINFO, USRQUOTA) returned -1 on" + " %s: %s", m->device, strerror(errno)); + m->opts &= ~QMO_USRQUOTA; + DBG("\tusrquota switched off"); + } } - if(quotactl(QCMD(Q_SYNC, USRQUOTA), m->device, 0, NULL) == -1) - { - DBG("quotactl (Q_SYNC, USRQUOTA) returned -1 on" - " %s: %s", m->device, strerror(errno)); - *quota = NULL; - return NULL; + if(m->opts & QMO_USRQUOTA) { + if(quotactl(QCMD(Q_SYNC, USRQUOTA), m->device, 0, NULL) == -1) + { + DBG("quotactl (Q_SYNC, USRQUOTA) returned -1 on" + " %s: %s", m->device, strerror(errno)); + m->opts &= ~QMO_USRQUOTA; + DBG("\tusrquota switched off"); + } } - if(quotactl(QCMD(Q_GETINFO, GRPQUOTA), m->device, - 0, (void *)&dqi_grp) == -1) - { - DBG("quotactl (Q_GETINFO, GRPQUOTA) returned -1 on" - " %s: %s", m->device, strerror(errno)); - *quota = NULL; - return NULL; + if(m->opts & QMO_GRPQUOTA) { + if(quotactl(QCMD(Q_GETINFO, GRPQUOTA), m->device, + 0, (void *)&dqigrp) == -1) + { + DBG("quotactl (Q_GETINFO, GRPQUOTA) returned -1 on" + " %s: %s", m->device, strerror(errno)); + m->opts &= ~QMO_GRPQUOTA; + DBG("\tgrpquota switched off"); + } } - if(quotactl(QCMD(Q_SYNC, GRPQUOTA), m->device, 0, NULL) == -1) - { - DBG("quotactl (Q_SYNC, GRPQUOTA) returned -1 on" - " %s: %s", m->device, strerror(errno)); - *quota = NULL; - return NULL; + if(m->opts & QMO_GRPQUOTA) { + if(quotactl(QCMD(Q_SYNC, GRPQUOTA), m->device, 0, NULL) == -1) + { + DBG("quotactl (Q_SYNC, GRPQUOTA) returned -1 on" + " %s: %s", m->device, strerror(errno)); + m->opts &= ~QMO_GRPQUOTA; + DBG("\tgrpquota switched off"); + } } #endif /* HAVE_QUOTACTL */ - q = *quota = (quota_t *)smalloc(sizeof(quota_t)); + if(m->opts == QMO_NONE) { + return NULL; + } - q->type = (char *)sstrdup("usrquota"); +#if HAVE_QUOTACTL + if(m->opts & QMO_USRQUOTA) { + for(i=0; i<1000; i++) { + struct dqblk dqb; + if(quotactl(QCMD(Q_GETQUOTA, USRQUOTA), + m->device, i, (void *)&dqb) == -1) + { +#if 0 + DBG("quotactl (Q_GETQUOTA, USRQUOTA)" + " returned -1 on %d %s: %s", + i, m->device, strerror(errno)); +#endif + continue; + } + DBG("quotactl (Q_GETQUOTA, USRQUOTA)" + " returned ok on %d %s", + i, m->device); + if(*quota == NULL) { + *quota = (quota_t *)smalloc(sizeof(quota_t)); + q = *quota; + } else { + q->next = (quota_t *)smalloc(sizeof(quota_t)); + q = q->next; + } + q->type = sstrdup(QFT_USRQUOTA); + (void)snprintf(buf, 100, "%ld", (long)i); #if HAVE_GETPWUID -/* struct group *getpwuid((uid_t)500) */ - q->name = (char *)sstrdup("niki"); + passwd = getpwuid((uid_t)i); + q->name = sstrdup(passwd->pw_name); #else - q->name = (char *)sstrdup("500"); + q->name = sstrdup(buf); #endif - q->id = (char *)sstrdup("500"); - q->dir = (char *)sstrdup(m->dir); - q->blocks = 5; - q->bquota = 100; - q->blimit = 180; - q->bgrace = dqi_usr.dqi_bgrace; - q->btimeleft = -1; - q->inodes = 5; - q->iquota = 100; - q->ilimit = 180; - q->igrace = dqi_usr.dqi_igrace; - q->itimeleft = -1; - q->next = NULL; - - q->next = (quota_t *)smalloc(sizeof(quota_t)); - q = q->next; - q->type = (char *)sstrdup("grpquota"); + q->id = sstrdup(buf); + q->dir = sstrdup(m->dir); + q->blocks = dqb.dqb_curspace; + q->bquota = dqb.dqb_bsoftlimit << 10; + q->blimit = dqb.dqb_bhardlimit << 10; + q->bgrace = dqiusr.dqi_bgrace; + q->btimeleft = dqb.dqb_btime; + q->inodes = dqb.dqb_curinodes; + q->iquota = dqb.dqb_isoftlimit; + q->ilimit = dqb.dqb_ihardlimit; + q->igrace = dqiusr.dqi_igrace; + q->itimeleft = dqb.dqb_itime; + q->next = NULL; + } /* for(i=0; i<1000; i++) */ + } /* if(m->opts & QMO_USRQUOTA) */ + + if(m->opts & QMO_GRPQUOTA) { + for(i=0; i<1000; i++) { + struct dqblk dqb; + if(quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), + m->device, i, (void *)&dqb) == -1) + { +#if 0 + DBG("quotactl (Q_GETQUOTA, GRPQUOTA)" + " returned -1 on %d %s: %s", + i, m->device, strerror(errno)); +#endif + continue; + } + DBG("quotactl (Q_GETQUOTA, GRPQUOTA)" + " returned ok on %d %s", + i, m->device); + if(*quota == NULL) { + *quota = (quota_t *)smalloc(sizeof(quota_t)); + q = *quota; + } else { + q->next = (quota_t *)smalloc(sizeof(quota_t)); + q = q->next; + } + q->type = sstrdup(QFT_GRPQUOTA); + (void)snprintf(buf, 100, "%ld", (long)i); #if HAVE_GETGRGID -/* struct group *getgrgid((gid_t)100) */ - q->name = (char *)sstrdup("users"); + group = getgrgid((gid_t)i); + q->name = sstrdup(group->gr_name); #else - q->name = (char *)sstrdup("100"); + q->name = sstrdup(buf); #endif - q->id = (char *)sstrdup("100"); - q->dir = (char *)sstrdup(m->dir); - q->blocks = 5; - q->bquota = 100; - q->blimit = 180; - q->bgrace = dqi_grp.dqi_bgrace; - q->btimeleft = -1; - q->inodes = 5; - q->iquota = 100; - q->ilimit = 180; - q->igrace = dqi_grp.dqi_igrace; - q->itimeleft = -1; - q->next = NULL; - - return *quota; + q->id = sstrdup(buf); + q->dir = sstrdup(m->dir); + q->blocks = dqb.dqb_curspace; + q->bquota = dqb.dqb_bsoftlimit << 10; + q->blimit = dqb.dqb_bhardlimit << 10; + q->bgrace = dqigrp.dqi_bgrace; + q->btimeleft = dqb.dqb_btime; + q->inodes = dqb.dqb_curinodes; + q->iquota = dqb.dqb_isoftlimit; + q->ilimit = dqb.dqb_ihardlimit; + q->igrace = dqigrp.dqi_igrace; + q->itimeleft = dqb.dqb_itime; + q->next = NULL; + } /* for(i=0; i<1000; i++) */ + } /* if(m->opts & QMO_GRPQUOTA) */ +#endif /* HAVE_QUOTACTL */ + +DBG("end"); + return q; } @@ -188,7 +254,6 @@ getquota_ext3_v1(quota_t **quota, quota_mnt_t *m) static quota_t * getquota_ext3_v2(quota_t **quota, quota_mnt_t *m) { - DBG("quota v2:"); return getquota_ext3_v1(quota, m); } @@ -226,6 +291,7 @@ getquota_zfs(quota_t **quota, quota_mnt_t *m) void quota_fs_printquota_dbg(quota_t *q) { + DBG("start"); while(q != NULL) { DBG("\ttype: %s", q->type); DBG("\tname: %s", q->name); @@ -239,7 +305,13 @@ quota_fs_printquota_dbg(quota_t *q) q->igrace, q->itimeleft); q = q->next; } /* while(q != NULL) */ + DBG("end"); } /* void quota_fs_printquota_dbg(quota_t *quota) */ +#else +void +quota_fs_printquota_dbg(quota_t *q) +{ +} #endif /* QUOTA_PLUGIN_DEBUG */ @@ -289,11 +361,11 @@ quota_fs_freequota(quota_t *quota) if(prev != NULL) { prev->next = NULL; } - free(q->type); - free(q->name); - free(q->id); - free(q->dir); - free(q); + sfree(q->type); + sfree(q->name); + sfree(q->id); + sfree(q->dir); + sfree(q); prev = NULL; if(q != quota) { q = quota; @@ -309,37 +381,30 @@ quota_t * quota_fs_getquota(quota_t **quota, quota_mnt_t *mnt) { quota_mnt_t *m = mnt; - quota_t *q = NULL; + quota_t *q = NULL, *qlast = NULL; - *quota = NULL; while(m != NULL) { - switch(qft(m->type)) { - case QFT_EXT2: - case QFT_EXT3: - q = getquota_ext3(&q, m); + switch(quota_mnt_type(m->type)) { + case QMT_EXT2: + case QMT_EXT3: + qlast = getquota_ext3(&q, m); break; - case QFT_UFS: - q = getquota_ufs(&q, m); + case QMT_UFS: + qlast = getquota_ufs(&q, m); break; - case QFT_VXFS: - q = getquota_vxfs(&q, m); + case QMT_VXFS: + qlast = getquota_vxfs(&q, m); break; - case QFT_ZFS: - q = getquota_zfs(&q, m); + case QMT_ZFS: + qlast = getquota_zfs(&q, m); break; } - if(q != NULL) { /* found some quotas */ + if(qlast != NULL) { /* found some quotas */ if(*quota == NULL) { /* not init yet */ *quota = q; /* init */ - } else { /* we have some quotas already */ - quota_t *t = *quota; - /* goto last entry */ - while(t->next != NULL) { - t = t->next; - } - t->next = q; /* set next pointer */ } - } /* if(q != NULL) */ + q = qlast; + } /* if(qlast != NULL) */ m = m->next; } /* while(m != NULL) */ diff --git a/src/quota_fs.h b/src/quota_fs.h index 5d3eb803..b6ec038a 100644 --- a/src/quota_fs.h +++ b/src/quota_fs.h @@ -29,13 +29,8 @@ #include "quota_mnt.h" /* Quota Filesystem Type */ -#define QFT_NONE (0) -#define QFT_EXT2 (1) -#define QFT_EXT3 (2) -#define QFT_XFS (3) -#define QFT_UFS (4) -#define QFT_VXFS (5) -#define QFT_ZFS (6) +#define QFT_USRQUOTA "usrquota" +#define QFT_GRPQUOTA "grpquota" typedef struct _quota_t quota_t; struct _quota_t { @@ -55,11 +50,42 @@ struct _quota_t { int quota_fs_issupported(const char *fsname); int quota_fs_isnfs(const char *fsname); -#if QUOTA_PLUGIN_DEBUG +/* + DESCRIPTION + The quota_fs_printquota_dbg() function prints + the quota list to the log. + + If debugging is switched off in quota_debug.h + then this function does nothing. +*/ void quota_fs_printquota_dbg(quota_t *quota); -#endif +/* + DESCRIPTION + The quota_fs_getquota() function goes through the mount + list m and gets the quotas for all mountpoints. + + If *quota is NULL, a new list is created and *quota is + set to point to the first entry. + + If *quota is set, the list is appended and *quota is + not changed. + + RETURN VALUE + The quota_fs_getquota() function returns a pointer to + the last entry of the list, or NULL if an error occurs. + + NOTES + In case of an error, quota is not modified. +*/ quota_t *quota_fs_getquota(quota_t **quota, quota_mnt_t *m); + +/* + 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 cfb071ff..db62e512 100644 --- a/src/quota_mnt.c +++ b/src/quota_mnt.c @@ -743,3 +743,16 @@ 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 f8e95406..498e0cae 100644 --- a/src/quota_mnt.h +++ b/src/quota_mnt.h @@ -26,6 +26,15 @@ #include "common.h" +/* Quota Mount Type */ +#define QMT_UNKNOWN (0) +#define QMT_EXT2 (1) +#define QMT_EXT3 (2) +#define QMT_XFS (3) +#define QMT_UFS (4) +#define QMT_VXFS (5) +#define QMT_ZFS (6) + /* Quota Mount Options */ #define QMO_NONE (0) #define QMO_USRQUOTA (1) @@ -42,6 +51,8 @@ struct _quota_mnt_t { quota_mnt_t *next; }; +int quota_mnt_type(const char *type); + quota_mnt_t *quota_mnt_getlist(quota_mnt_t **list); void quota_mnt_freelist(quota_mnt_t *list); diff --git a/src/quota_plugin.c b/src/quota_plugin.c index 2fef085e..57394868 100644 --- a/src/quota_plugin.c +++ b/src/quota_plugin.c @@ -151,10 +151,10 @@ quota_read(void) q->inodes, q->iquota, q->ilimit, q->igrace, q->itimeleft); quota_submit(q); - q = q->next; - if(q != NULL) { + if(q->next != NULL) { DBG("\t-- "); } + q = q->next; } DBG("\t== "); -- 2.30.2