--- quota-fs.c.orig 2006-07-10 22:15:12.000000000 -0400 +++ quota-fs.c 2006-07-11 00:35:00.000000000 -0400 @@ -43,6 +43,7 @@ struct quota_root root; uid_t uid; + gid_t gid; struct fs_quota_mountpoint *mount; }; @@ -63,6 +64,7 @@ root->root.name = i_strdup(name); root->root.v = quota_backend_fs.v; root->uid = geteuid(); + root->gid = getegid(); return &root->root; } @@ -167,7 +169,18 @@ static const char *const * fs_quota_root_get_resources(struct quota_root *root __attr_unused__) { - static const char *resources[] = { QUOTA_NAME_STORAGE, NULL }; + //if (strcmp(storage->name, "maildir") == 0) { + static const char *resources[] = { + QUOTA_NAME_STORAGE, + QUOTA_NAME_MESSAGES, + NULL + }; + /*} else { + static const char *resources[] = { + QUOTA_NAME_STORAGE, + NULL + }; + }*/ return resources; } @@ -182,76 +195,103 @@ struct quotctl ctl; #endif + int value_r_t, limit_r_t, value_r_c=0, limit_r_c=0; + char args[] = {USRQUOTA, GRPQUOTA}; + int what[] = {root->uid, root->gid}; + short i; + int quota_error=0; + *value_r = 0; *limit_r = 0; - if (strcasecmp(name, QUOTA_NAME_STORAGE) != 0 || root->mount == NULL) + if (root->mount == NULL) return 0; + for (i = 0; i < 2; i++) { + #if defined (HAVE_QUOTACTL) && defined(HAVE_SYS_QUOTA_H) - /* Linux */ + /* Linux */ #ifdef HAVE_LINUX_DQBLK_XFS_H - if (strcmp(root->mount->type, "xfs") == 0) { - /* XFS */ - struct fs_disk_quota xdqblk; + if (strcmp(root->mount->type, "xfs") == 0) { + /* XFS */ + struct fs_disk_quota xdqblk; - if (quotactl(QCMD(Q_XGETQUOTA, USRQUOTA), - root->mount->device_path, - root->uid, (caddr_t)&xdqblk) < 0) { - i_error("quotactl(Q_XGETQUOTA, %s) failed: %m", - root->mount->device_path); - quota_set_error(_root->setup->quota, - "Internal quota error"); - return -1; - } + if (quotactl(QCMD(Q_XGETQUOTA, args[i]), + root->mount->device_path, + what[i], (caddr_t)&xdqblk) < 0) { + quota_error = quota_error + 1; + } - /* values always returned in 512 byte blocks */ - *value_r = xdqblk.d_bcount >> 1; - *limit_r = xdqblk.d_blk_softlimit >> 1; - } else + /* values always returned in 512 byte blocks */ + value_r_t = xdqblk.d_bcount >> 1; + limit_r_t = xdqblk.d_blk_softlimit >> 1; + + dqblk.dqb_curinodes = xdqblk.d_icount; + dqblk.dqb_isoftlimit = xdqblk.d_ino_softlimit; + + } else #endif - { - /* ext2, ext3 */ - if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), - root->mount->device_path, - root->uid, (caddr_t)&dqblk) < 0) { - i_error("quotactl(Q_GETQUOTA, %s) failed: %m", - root->mount->device_path); - quota_set_error(_root->setup->quota, - "Internal quota error"); + { + /* ext2, ext3 */ + if (quotactl(QCMD(Q_GETQUOTA, args[i]), + root->mount->device_path, + what[i], (caddr_t)&dqblk) < 0) { + quota_error = quota_error + 1; + } + + value_r_t = dqblk.dqb_curblocks / 1024; + limit_r_t = dqblk.dqb_bsoftlimit; + } + #elif defined(HAVE_QUOTACTL) + /* BSD, AIX */ + if (quotactl(root->mount->mount_path, QCMD(Q_GETQUOTA, args[i]), + what[i], (void *)&dqblk) < 0) { + quota_error = quota_error + 1; + } + value_r_t = (uint64_t)dqblk.dqb_curblocks * 1024 / DEV_BSIZE; + limit_r_t = (uint64_t)dqblk.dqb_bsoftlimit * 1024 / DEV_BSIZE; +#else + /* Solaris */ + if (root->mount->fd == -1) + return 0; + + ctl.op = Q_GETQUOTA; + ctl.uid = root->uid; + ctl.addr = (caddr_t)&dqblk; + if (ioctl(root->mount->fd, Q_QUOTACTL, &ctl) < 0) { + i_error("ioctl(%s, Q_QUOTACTL) failed: %m", root->mount->path); + quota_set_error(_root->setup->quota, "Internal quota error"); return -1; } + value_r_t = (uint64_t)dqblk.dqb_curblocks * 1024 / DEV_BSIZE; + limit_r_t = (uint64_t)dqblk.dqb_bsoftlimit * 1024 / DEV_BSIZE; +#endif - *value_r = dqblk.dqb_curblocks / 1024; - *limit_r = dqblk.dqb_bsoftlimit; + if (strcmp(name, QUOTA_NAME_MESSAGES) == 0) { + value_r_t = (uint64_t)dqblk.dqb_curinodes; + limit_r_t = (uint64_t)dqblk.dqb_isoftlimit; + } + + if ((value_r_c == 0) || // first time in loop + (limit_r_c == 0 && limit_r_t >= 0) || // first quota + (limit_r_c > 0 && limit_r_t > 0 && + (limit_r_t - value_r_t) < (limit_r_c - value_r_c)) || // another quota, closer + (limit_r_c == 0 && limit_r_t == 0 && value_r_t > value_r_c)) { // no quotas, higher usage + limit_r_c = limit_r_t; + value_r_c = value_r_t; + } } -#elif defined(HAVE_QUOTACTL) - /* BSD, AIX */ - if (quotactl(root->mount->mount_path, QCMD(Q_GETQUOTA, USRQUOTA), - root->uid, (void *)&dqblk) < 0) { + + if (quota_error == 2) { i_error("quotactl(Q_GETQUOTA, %s) failed: %m", root->mount->mount_path); quota_set_error(_root->setup->quota, "Internal quota error"); return -1; } - *value_r = (uint64_t)dqblk.dqb_curblocks * 1024 / DEV_BSIZE; - *limit_r = (uint64_t)dqblk.dqb_bsoftlimit * 1024 / DEV_BSIZE; -#else - /* Solaris */ - if (root->mount->fd == -1) - return 0; - ctl.op = Q_GETQUOTA; - ctl.uid = root->uid; - ctl.addr = (caddr_t)&dqblk; - if (ioctl(root->mount->fd, Q_QUOTACTL, &ctl) < 0) { - i_error("ioctl(%s, Q_QUOTACTL) failed: %m", root->mount->path); - quota_set_error(_root->setup->quota, "Internal quota error"); - return -1; - } - *value_r = (uint64_t)dqblk.dqb_curblocks * 1024 / DEV_BSIZE; - *limit_r = (uint64_t)dqblk.dqb_bsoftlimit * 1024 / DEV_BSIZE; -#endif + *limit_r = limit_r_c; + *value_r = value_r_c; + return 1; }