+/*
+ * Do operations associated with quotas
+ */
+ufs_quotactl(mp, cmds, uid, arg)
+ struct mount *mp;
+ int cmds;
+ uid_t uid;
+ caddr_t arg;
+{
+ register struct nameidata *ndp = &u.u_nd;
+ struct ufsmount *ump = VFSTOUFS(mp);
+ struct proc *p = u.u_procp; /* XXX */
+ int cmd, type, error;
+
+#ifndef QUOTA
+ return (EOPNOTSUPP);
+#else
+ if (uid == -1)
+ uid = p->p_ruid;
+ cmd = cmds >> SUBCMDSHIFT;
+
+ switch (cmd) {
+ case Q_GETQUOTA:
+ case Q_SYNC:
+ if (uid == p->p_ruid)
+ break;
+ /* fall through */
+ default:
+ if (error = suser(ndp->ni_cred, &u.u_acflag))
+ return (error);
+ }
+
+ type = cmd & SUBCMDMASK;
+ if ((u_int)type >= MAXQUOTAS)
+ return (EINVAL);
+
+ switch (cmd) {
+
+ case Q_QUOTAON:
+ return (quotaon(ndp, mp, type, arg));
+
+ case Q_QUOTAOFF:
+ if (vfs_busy(mp))
+ return (0);
+ error = quotaoff(mp, type);
+ vfs_unbusy(mp);
+ return (error);
+
+ case Q_SETQUOTA:
+ return (setquota(mp, uid, type, arg));
+
+ case Q_SETUSE:
+ return (setuse(mp, uid, type, arg));
+
+ case Q_GETQUOTA:
+ return (getquota(mp, uid, type, arg));
+
+ case Q_SYNC:
+ if (vfs_busy(mp))
+ return (0);
+ error = qsync(mp);
+ vfs_unbusy(mp);
+ return (error);
+
+ default:
+ return (EINVAL);
+ }
+ /* NOTREACHED */
+#endif
+}
+