AC_CHECK_FUNCS(getfsent getvfsent listmntent)
AC_FUNC_GETMNTENT
AC_CHECK_FUNCS(quotactl)
+AC_CHECK_FUNCS(getgrgid getpwuid)
AC_MSG_CHECKING([for kernel type ($host_os)])
case $host_os in
/* Define to 1 if you have the `getfsent' function. */
#undef HAVE_GETFSENT
+/* Define to 1 if you have the `getgrgid' function. */
+#undef HAVE_GETGRGID
+
/* Define to 1 if you have the `gethostbyname' function. */
#undef HAVE_GETHOSTBYNAME
/* Define to 1 if you have the `getmntent' function. */
#undef HAVE_GETMNTENT
+/* Define to 1 if you have the `getpwuid' function. */
+#undef HAVE_GETPWUID
+
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
# include <sys/quota.h>
#endif
+
+
/* *** *** *** 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);
-static quota_t *getquota_ext2(quota_t **quota, quota_mnt_t *m);
static quota_t *getquota_ufs(quota_t **quota, quota_mnt_t *m);
static quota_t *getquota_vxfs(quota_t **quota, quota_mnt_t *m);
static quota_t *getquota_zfs(quota_t **quota, quota_mnt_t *m);
+
+
/* *** *** *** local functions *** *** *** */
+
+
static int
qft(const char *type)
{
return QFT_NONE;
} /* static int qft(const char *type) */
+
+
static quota_t *
getquota_ext3(quota_t **quota, quota_mnt_t *m)
{
return NULL;
} /* 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)
{
if(quotactl(QCMD(Q_GETINFO, USRQUOTA), m->device,
0, (void *)&dqi_usr) == -1)
{
- DBG("quotactl (Q_GETINFO, USRQUOTA) returned -1: %s",
- strerror(errno));
+ DBG("quotactl (Q_GETINFO, USRQUOTA) returned -1 on"
+ " %s: %s", m->device, strerror(errno));
+ *quota = NULL;
+ return NULL;
+ }
+ 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(quotactl(QCMD(Q_GETINFO, GRPQUOTA), m->device,
0, (void *)&dqi_grp) == -1)
{
- DBG("quotactl (Q_GETINFO, GRPQUOTA) returned -1: %s",
- strerror(errno));
+ DBG("quotactl (Q_GETINFO, GRPQUOTA) returned -1 on"
+ " %s: %s", m->device, strerror(errno));
+ *quota = NULL;
+ return NULL;
+ }
+ 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;
}
q = *quota = (quota_t *)smalloc(sizeof(quota_t));
q->type = (char *)sstrdup("usrquota");
-#if HAVE_GRP_H
-/* struct group *getgrid((gid_t)500) */
+#if HAVE_GETPWUID
+/* struct group *getpwuid((uid_t)500) */
q->name = (char *)sstrdup("niki");
#else
- q->name = (char *)sstrdup("");
+ q->name = (char *)sstrdup("500");
#endif
q->id = (char *)sstrdup("500");
q->dir = (char *)sstrdup(m->dir);
q->bquota = 100;
q->blimit = 180;
q->bgrace = dqi_usr.dqi_bgrace;
- q->btimeleft = 0;
+ q->btimeleft = -1;
q->inodes = 5;
q->iquota = 100;
q->ilimit = 180;
q->igrace = dqi_usr.dqi_igrace;
- q->itimeleft = 0;
+ q->itimeleft = -1;
q->next = NULL;
q->next = (quota_t *)smalloc(sizeof(quota_t));
q = q->next;
q->type = (char *)sstrdup("grpquota");
-#if HAVE_GRP_H
-/* struct group *getgrid((gid_t)500) */
+#if HAVE_GETGRGID
+/* struct group *getgrgid((gid_t)100) */
q->name = (char *)sstrdup("users");
#else
- q->name = (char *)sstrdup("");
+ q->name = (char *)sstrdup("100");
#endif
q->id = (char *)sstrdup("100");
q->dir = (char *)sstrdup(m->dir);
q->bquota = 100;
q->blimit = 180;
q->bgrace = dqi_grp.dqi_bgrace;
- q->btimeleft = 0;
+ q->btimeleft = -1;
q->inodes = 5;
q->iquota = 100;
q->ilimit = 180;
q->igrace = dqi_grp.dqi_igrace;
- q->itimeleft = 0;
+ q->itimeleft = -1;
q->next = NULL;
return *quota;
}
+
+
static quota_t *
getquota_ext3_v2(quota_t **quota, quota_mnt_t *m)
{
return getquota_ext3_v1(quota, m);
}
-static quota_t *
-getquota_ext2(quota_t **quota, quota_mnt_t *m)
-{
- return NULL;
-}
+
static quota_t *
getquota_ufs(quota_t **quota, quota_mnt_t *m)
return NULL;
}
+
+
static quota_t *
getquota_vxfs(quota_t **quota, quota_mnt_t *m)
{
return NULL;
}
+
+
static quota_t *
getquota_zfs(quota_t **quota, quota_mnt_t *m)
{
return NULL;
}
+
+
/* *** *** *** global functions *** *** *** */
+
+
+#if QUOTA_PLUGIN_DEBUG
+void
+quota_fs_printquota_dbg(quota_t *q)
+{
+ while(q != NULL) {
+ DBG("\ttype: %s", q->type);
+ DBG("\tname: %s", q->name);
+ DBG("\tid: %s", q->id);
+ DBG("\tdir: %s", q->dir);
+ DBG("\tblocks: %llu (%lld/%lld) %lld %lld",
+ q->blocks, q->bquota, q->blimit,
+ q->bgrace, q->btimeleft);
+ DBG("\tinodes: %llu (%lld/%lld) %lld %lld",
+ q->inodes, q->iquota, q->ilimit,
+ q->igrace, q->itimeleft);
+ q = q->next;
+ } /* while(q != NULL) */
+} /* void quota_fs_printquota_dbg(quota_t *quota) */
+#endif /* QUOTA_PLUGIN_DEBUG */
+
+
+
int
quota_fs_issupported(const char *fsname)
{
}
} /* int quota_fs_issupported(const char *fsname) */
+
+
int
quota_fs_isnfs(const char *fsname)
{
}
} /* int quota_fs_isnfs(const char *fsname) */
+
+
void
quota_fs_freequota(quota_t *quota)
{
quota_t *q = quota, *prev = NULL;
-DBG("x");
while(q != NULL) {
while(q->next != NULL) {
prev = q;
} /* while(q != NULL) */
} /* void quota_fs_freequota(quota_t *quota) */
+
+
quota_t *
quota_fs_getquota(quota_t **quota, quota_mnt_t *mnt)
{
*quota = NULL;
while(m != NULL) {
switch(qft(m->type)) {
+ case QFT_EXT2:
case QFT_EXT3:
q = getquota_ext3(&q, m);
break;
- case QFT_EXT2:
- q = getquota_ext2(&q, m);
- break;
case QFT_UFS:
q = getquota_ufs(&q, m);
break;
break;
}
if(q != NULL) { /* found some quotas */
- DBG("\ttype: %s", (*quota)->type);
- DBG("\tname: %s", (*quota)->name);
- DBG("\tid: %s", (*quota)->id);
- DBG("\tdir: %s", (*quota)->dir);
- DBG("\tblocks: %llu (%lld/%lld) %llu %llu",
- (*quota)->blocks, (*quota)->bquota, (*quota)->blimit,
- (*quota)->bgrace, (*quota)->btimeleft);
- DBG("\tinodes: %llu (%lld/%lld) %llu %llu",
- (*quota)->inodes, (*quota)->iquota, (*quota)->ilimit,
- (*quota)->igrace, (*quota)->itimeleft);
-
if(*quota == NULL) { /* not init yet */
-DBG("a");
*quota = q; /* init */
} else { /* we have some quotas already */
-DBG("b");
quota_t *t = *quota;
/* goto last entry */
while(t->next != NULL) {
t = t->next;
-DBG("c");
}
t->next = q; /* set next pointer */
}
- }
-DBG("z");
+ } /* if(q != NULL) */
m = m->next;
} /* while(m != NULL) */
#define COLLECTD_QUOTA_FS_H 1
#include "common.h"
+#include "quota_debug.h"
#include "quota_mnt.h"
/* Quota Filesystem Type */
char *dir;
unsigned long long blocks;
long long bquota, blimit;
- unsigned long long bgrace, btimeleft;
+ long long bgrace, btimeleft;
unsigned long long inodes;
long long iquota, ilimit;
- unsigned long long igrace, itimeleft;
+ long long igrace, itimeleft;
quota_t *next;
};
int quota_fs_issupported(const char *fsname);
int quota_fs_isnfs(const char *fsname);
+#if QUOTA_PLUGIN_DEBUG
+void quota_fs_printquota_dbg(quota_t *quota);
+#endif
+
quota_t *quota_fs_getquota(quota_t **quota, quota_mnt_t *m);
void quota_fs_freequota(quota_t *quota);
#include "quota_mntopt.h"
+
+
+/* *** *** *** prototypes *** *** *** */
+
+static char *getmountopt(char *line, char *keyword);
+static char *checkmountopt(char *line, char *keyword, int full);
+
+
+
/* *** *** *** local functions *** *** *** */
+
+
/* stolen from quota-3.13 (quota-tools) */
#define PROC_PARTITIONS "/proc/partitions"
return get_spec_by_x(VOL, s);
}
-const char *
+static char *
get_device_name(const char *item)
{
- const char *rc;
+ char *rc;
if(!strncmp(item, "UUID=", 5)) {
DBG("TODO: check UUID= code!");
ret = 1;
#endif /* XFS_ROOTHACK */
}
- free((char *)dev);
+ sfree((char *)dev);
return ret;
}
#endif /* HAVE_XFS_XQM_H */
}
#endif /* HAVE_GETVFSENT */
+static char *
+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;
+} /* static char *checkmountopt(char *line, char *keyword, int full) */
+
+static char *
+getmountopt(char *line, char *keyword)
+{
+ char *r;
+
+ r = 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;
+} /* static char *getmountopt(char *line, char *keyword) */
#if HAVE_GETMNTENT
static void
struct mntent *mnt;
while((mnt = getmntent(mntf)) != NULL) {
- const char *devname;
+ char *loop = NULL, *device = NULL;
+ char *usrjquota = NULL;
+ char *grpjquota = NULL;
#if 0
DBG("------------------");
DBG("mnt->mnt_freq %d", mnt->mnt_freq);
DBG("mnt->mnt_passno %d", mnt->mnt_passno);
#endif
- if(!(devname = get_device_name(mnt->mnt_fsname))) {
- DBG("can't get devicename for fs (%s) %s (%s): ignored",
+
+ if(quota_fs_issupported(mnt->mnt_type) == EXIT_FAILURE)
+ {
+ DBG("unsupportet fs (%s) %s (%s): ignored",
mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
continue;
}
- if(hasmntopt(mnt, MNTOPT_NOQUOTA) != NULL) {
+
+ if(checkmountopt(mnt->mnt_opts, MNTOPT_NOQUOTA, 1) != NULL) {
DBG("noquota option on fs (%s) %s (%s): ignored",
mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
- free((char *)devname);
continue;
}
+
+ if(checkmountopt(mnt->mnt_opts, "bind", 1) != NULL) {
+ DBG("bind mount on fs (%s) %s (%s): ignored",
+ mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
+ continue;
+ }
+
+ loop = 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;
+ }
+
+ usrjquota = getmountopt(mnt->mnt_opts, "usrjquota=");
+ grpjquota = getmountopt(mnt->mnt_opts, "grpjquota=");
+
#if HAVE_XFS_XQM_H
if(!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
if(hasxfsquota(mnt, USRQUOTA) == 0
DBG("no quota on fs (%s) %s (%s): ignored",
mnt->mnt_type, mnt->mnt_dir,
mnt->mnt_fsname);
- free((char *)devname);
+ sfree(loop);
+ sfree(usrjquota);
+ sfree(grpjquota);
continue;
}
} else {
#endif /* HAVE_XFS_XQM_H */
- if(hasmntopt(mnt, MNTOPT_QUOTA) == NULL
- && hasmntopt(mnt, MNTOPT_USRQUOTA) == NULL
- && hasmntopt(mnt, MNTOPT_GRPQUOTA) == NULL
+ if(checkmountopt(mnt->mnt_opts, MNTOPT_QUOTA, 1)
+ == NULL
+ && checkmountopt(mnt->mnt_opts, MNTOPT_USRQUOTA, 1)
+ == NULL
+ && checkmountopt(mnt->mnt_opts, MNTOPT_GRPQUOTA, 1)
+ == NULL
&& quota_fs_isnfs(mnt->mnt_type) == EXIT_FAILURE)
{
DBG("neither quota/usrquota/grpquota option"
" nor nfs fs (%s) %s (%s): ignored",
mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
- free((char *)devname);
+ sfree(loop);
+ sfree(usrjquota);
+ sfree(grpjquota);
continue;
}
#if HAVE_XFS_XQM_H
}
#endif /* HAVE_XFS_XQM_H */
- if(quota_fs_issupported(mnt->mnt_type) == EXIT_FAILURE)
- {
- DBG("unsupportet fs (%s) %s (%s): ignored",
- mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
- free((char *)devname);
- continue;
- }
#if 0
DBG("------------------ OK");
#endif
*list = (quota_mnt_t *)smalloc(sizeof(quota_mnt_t));
(*list)->dir = sstrdup(mnt->mnt_dir);
- (*list)->device = sstrdup(mnt->mnt_fsname);
+ (*list)->device = device;
+ (*list)->usrjquota = usrjquota;
+ (*list)->grpjquota = grpjquota;
(*list)->type = sstrdup(mnt->mnt_type);
(*list)->opts = QMO_NONE;
/* TODO: this is not sufficient for XFS! */
/* TODO: maybe we should anyway NOT rely on the option in the mountfile...
... maybe the fs should be asked direktly all time! */
- if(hasmntopt(mnt, MNTOPT_QUOTA) != NULL
- || hasmntopt(mnt, MNTOPT_USRQUOTA) != NULL) {
+ if(checkmountopt(mnt->mnt_opts, MNTOPT_QUOTA, 1) != NULL
+ || checkmountopt(mnt->mnt_opts, MNTOPT_USRQUOTA, 1) != NULL) {
(*list)->opts |= QMO_USRQUOTA;
}
- if(hasmntopt(mnt, MNTOPT_GRPQUOTA) != NULL) {
+ if(checkmountopt(mnt->mnt_opts, MNTOPT_GRPQUOTA, 1) != NULL) {
(*list)->opts |= QMO_GRPQUOTA;
}
(*list)->next = NULL;
if(p != NULL) {
p->next = NULL;
}
- free(l->dir);
- free(l->device);
- free(l);
+ sfree(l->dir);
+ sfree(l->device);
+ sfree(l->type);
+ sfree(l->usrjquota);
+ sfree(l->grpjquota);
+ sfree(l);
p = NULL;
if(l != list) {
l = list;
char *dir;
char *device;
char *type;
+ char *usrjquota;
+ char *grpjquota;
int opts;
quota_mnt_t *next;
};
char *name, *n;
r = snprintf(buf, BUFSIZE,
- "%u:%llu:%lld:%lld:%llu:%llu:%llu:%lld:%lld:%llu:%llu",
- (unsigned int)curtime,
+ "%ld:%llu:%lld:%lld:%lld:%lld:%llu:%lld:%lld:%lld:%lld",
+ (signed long)curtime,
q->blocks, q->bquota, q->blimit, q->bgrace, q->btimeleft,
q->inodes, q->iquota, q->ilimit, q->igrace, q->itimeleft);
if(r < 1 || r >= BUFSIZE) {
DBG("failed");
return;
}
- n = name = (char *)smalloc(strlen(q->type) + 1 + strlen(q->dir)
- + 1 + strlen(q->name) + 1 + strlen(q->id));
+ n = name = (char *)smalloc(strlen(q->type) + 1 + strlen(q->name)
+ + 1 + strlen(q->id) + 1 + strlen(q->dir) + 1);
sstrncpy(n, q->type, strlen(q->type)+1);
n += strlen(q->type);
sstrncpy(n, "-", 1+1);
sstrncpy(n, "-", 1+1);
n += 1;
sstrncpy(n, q->dir, strlen(q->dir)+1);
- n += strlen(q->dir);
n = name;
/* translate '/' -> '_' */
while(*n != '\0') {
*n = '_';
}
n++;
- }
+ } /* while(*n != '\0') */
DBG("rrd file: %s-%s", MODULE_NAME, name);
plugin_submit(MODULE_NAME, name, buf);
-}
+ free(name);
+} /* static void quota_submit(quota_t *q) */
#undef BUFSIZE
/* *** *** *** local plugin functions *** *** *** */
while(l != NULL) {
DBG("\tdir: %s", l->dir);
DBG("\tdevice: %s", l->device);
+ DBG("\ttype: %s", l->type);
+ DBG("\tusrjquota: %s", l->usrjquota);
+ DBG("\tgrpjquota: %s", l->grpjquota);
DBG("\topts: %s (0x%04x)",
(l->opts == QMO_NONE) ? "-"
: (l->opts == QMO_USRQUOTA) ? "USRQUOTA"
DBG("\tname: %s", q->name);
DBG("\tid: %s", q->id);
DBG("\tdir: %s", q->dir);
- DBG("\tblocks: %llu (%lld/%lld) %llu %llu",
+ DBG("\tblocks: %llu (%lld/%lld) %lld %lld",
q->blocks, q->bquota, q->blimit,
q->bgrace, q->btimeleft);
- DBG("\tinodes: %llu (%lld/%lld) %llu %llu",
+ DBG("\tinodes: %llu (%lld/%lld) %lld %lld",
q->inodes, q->iquota, q->ilimit,
q->igrace, q->itimeleft);
quota_submit(q);