pkgsrc-wip/netatalk/patches/patch-etc_afpd_quota_c
Makoto Fujiwara 685ba70ccc Import netatalk-3.0.4 as wip/netatalk.
Netatalk is a freely-available, kernel level implementation of the AppleTalk
Protocol Suite, originally for BSD-derived systems. A *NIX/*BSD system
running netatalk is capable of serving many macintosh clients simultaneously
as an AppleTalk router, AppleShare file server (AFP), *NIX/*BSD print server,
and for accessing AppleTalk printers via Printer Access Protocol (PAP).
Included are a number of minor printing and debugging utilities.
2013-06-07 00:28:22 +00:00

166 lines
4.5 KiB
Text

$NetBSD: patch-etc_afpd_quota_c,v 1.1 2013/06/07 00:28:23 makoto Exp $
Use the netbsd-6 quota API, not the prerelease stuff from 5.99.x.
Fix some glaring bugs in the code for the 5.99.x quotas (seteuid'ing
to group ids, using uninitialized group quota values, etc.)
--- etc/afpd/quota.c.orig 2013-03-07 16:03:18.000000000 +0900
+++ etc/afpd/quota.c 2013-06-07 07:51:30.000000000 +0900
@@ -36,10 +36,13 @@
static int
getfreespace(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal,
- uid_t uid, const char *classq)
+ id_t id, int idtype)
{
- int retq;
- struct ufs_quota_entry ufsq[QUOTA_NLIMITS];
+ uid_t prevuid;
+ const char *msg;
+ struct quotahandle *qh;
+ struct quotakey qk;
+ struct quotaval qv;
time_t now;
if (time(&now) == -1) {
@@ -48,64 +51,102 @@ getfreespace(const AFPObj *obj, struct v
return -1;
}
+ prevuid = geteuid();
+ if (prevuid == -1) {
+ LOG(log_info, logtype_afpd, "geteuid(): %s",
+ strerror(errno));
+ return -1;
+ }
+
become_root();
- if ((retq = getfsquota(obj, vol, ufsq, uid, classq)) < 0) {
- LOG(log_info, logtype_afpd, "getfsquota(%s, %s): %s",
- vol->v_path, classq, strerror(errno));
- }
-
- unbecome_root();
-
- if (retq < 1)
- return retq;
-
- switch(QL_STATUS(quota_check_limit(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur, 1,
- ufsq[QUOTA_LIMIT_BLOCK].ufsqe_softlimit,
- ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit,
- ufsq[QUOTA_LIMIT_BLOCK].ufsqe_time, now))) {
- case QL_S_DENY_HARD:
- case QL_S_DENY_GRACE:
+ /*
+ * In a tidier world we might keep the quotahandle open for longer...
+ */
+ qh = quota_open(vol->v_path);
+ if (qh == NULL) {
+ if (errno == EOPNOTSUPP || errno == ENXIO) {
+ /* no quotas on this volume */
+ seteuid( prevuid );
+ return 0;
+ }
+
+ LOG(log_info, logtype_afpd, "quota_open(%s): %s", vol->v_path,
+ strerror(errno));
+ seteuid( prevuid );
+ return -1;
+ }
+ qk.qk_idtype = idtype;
+ qk.qk_id = id;
+ qk.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
+ if (quota_get(qh, &qk, &qv) < 0) {
+ if (errno == ENOENT) {
+ /* no quotas for this id */
+ quota_close(qh);
+ seteuid( prevuid );
+ return 0;
+ }
+ msg = strerror(errno);
+ LOG(log_info, logtype_afpd, "quota_get(%s, %s): %s",
+ vol->v_path, quota_idtype_getname(qh, idtype), msg);
+ quota_close(qh);
+ seteuid( prevuid );
+ return -1;
+ }
+
+ quota_close(qh);
+
+ seteuid( prevuid );
+
+ if (qv.qv_usage >= qv.qv_hardlimit ||
+ (qv.qv_usage >= qv.qv_softlimit && now > qv.qv_expiretime)) {
+
*bfree = 0;
- *btotal = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur);
- break;
- default:
- *bfree = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit -
- ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur);
- *btotal = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit);
- break;
+ *btotal = dbtob(qv.qv_usage);
+ }
+ else {
+ *bfree = dbtob(qv.qv_hardlimit - qv.qv_usage);
+ *btotal = dbtob(qv.qv_hardlimit);
+ }
+
}
return 1;
}
int uquota_getvolspace(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal, const u_int32_t bsize)
{
- int uretq, gretq;
+ int uret, gret;
VolSpace ubfree, ubtotal;
VolSpace gbfree, gbtotal;
+ uret = getfreespace(vol, &ubfree, &ubtotal,
+ uuid, QUOTA_IDTYPE_USER);
+ if (uret == 1) {
+ LOG(log_info, logtype_afpd, "quota_get(%s, user): %d %d",
+ vol->v_path, (int)ubfree, (int)ubtotal);
+ }
- uretq = getfreespace(obj, vol, &ubfree, &ubtotal,
- uuid, QUOTADICT_CLASS_USER);
- LOG(log_info, logtype_afpd, "getfsquota(%s): %d %d",
- vol->v_path, (int)ubfree, (int)ubtotal);
if (obj->ngroups >= 1) {
- gretq = getfreespace(vol, &ubfree, &ubtotal,
- obj->groups[0], QUOTADICT_CLASS_GROUP);
+ gret = getfreespace(vol, &gbfree, &gbtotal,
+ groups[0], QUOTA_IDTYPE_GROUP);
+ if (gret == 1) {
+ LOG(log_info, logtype_afpd, "quota_get(%s, group): %d %d",
+ vol->v_path, (int)gbfree, (int)gbtotal);
+ }
} else
- gretq = -1;
- if (uretq < 1 && gretq < 1) { /* no quota for this fs */
+ gret = 0;
+ if (uret < 1 && gret < 1) { /* no quota for this fs */
return AFPERR_PARAM;
}
- if (uretq < 1) {
- /* use group quotas */
+ if (uret < 1) {
+ /* no user quotas, but group quotas; use them */
*bfree = gbfree;
*btotal = gbtotal;
- } else if (gretq < 1) {
- /* use user quotas */
+ } else if (gret < 1) {
+ /* no group quotas, but user quotas; use them */
*bfree = ubfree;
*btotal = ubtotal;
} else {
- /* return smallest remaining space of user and group */
+ /* both; return smallest remaining space of user and group */
if (ubfree < gbfree) {
*bfree = ubfree;
*btotal = ubtotal;