1 /* $NetBSD: compat_50_quota.c,v 1.3 2020/03/09 00:42:36 pgoyette Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: compat_50_quota.c,v 1.3 2020/03/09 00:42:36 pgoyette Exp $"); 33 34 #if defined(_KERNEL_OPT) 35 #include "opt_compat_netbsd.h" 36 #endif 37 38 #include <sys/module.h> 39 #include <sys/namei.h> 40 #include <sys/param.h> 41 #include <sys/quota.h> 42 #include <sys/quotactl.h> 43 #include <sys/systm.h> 44 #include <sys/syscall.h> 45 #include <sys/syscallvar.h> 46 #include <sys/syscallargs.h> 47 #include <sys/vfs_syscalls.h> 48 #include <sys/vnode.h> 49 50 #include <ufs/ufs/quota1.h> 51 52 static const struct syscall_package vfs_syscalls_50_quota_syscalls[] = { 53 { SYS_compat_50_quotactl, 0, (sy_call_t *)compat_50_sys_quotactl }, 54 { 0, 0, NULL } 55 }; 56 57 /* ARGSUSED */ 58 int 59 compat_50_sys_quotactl(struct lwp *l, const struct compat_50_sys_quotactl_args *uap, register_t *retval) 60 { 61 /* { 62 syscallarg(const char *) path; 63 syscallarg(int) cmd; 64 syscallarg(int) uid; 65 syscallarg(void *) arg; 66 } */ 67 struct vnode *vp; 68 struct mount *mp; 69 int q1cmd; 70 int idtype; 71 char *qfile; 72 struct dqblk dqblk; 73 struct quotakey key; 74 struct quotaval blocks, files; 75 struct quotastat qstat; 76 int error; 77 78 error = namei_simple_user(SCARG(uap, path), 79 NSM_FOLLOW_TRYEMULROOT, &vp); 80 if (error != 0) 81 return (error); 82 83 mp = vp->v_mount; 84 q1cmd = SCARG(uap, cmd); 85 idtype = quota_idtype_from_ufs(q1cmd & SUBCMDMASK); 86 87 switch ((q1cmd & ~SUBCMDMASK) >> SUBCMDSHIFT) { 88 case Q_QUOTAON: 89 qfile = PNBUF_GET(); 90 error = copyinstr(SCARG(uap, arg), qfile, PATH_MAX, NULL); 91 if (error != 0) { 92 PNBUF_PUT(qfile); 93 break; 94 } 95 96 error = vfs_quotactl_quotaon(mp, idtype, qfile); 97 98 PNBUF_PUT(qfile); 99 break; 100 101 case Q_QUOTAOFF: 102 error = vfs_quotactl_quotaoff(mp, idtype); 103 break; 104 105 case Q_GETQUOTA: 106 key.qk_idtype = idtype; 107 key.qk_id = SCARG(uap, uid); 108 109 key.qk_objtype = QUOTA_OBJTYPE_BLOCKS; 110 error = vfs_quotactl_get(mp, &key, &blocks); 111 if (error) { 112 break; 113 } 114 115 key.qk_objtype = QUOTA_OBJTYPE_FILES; 116 error = vfs_quotactl_get(mp, &key, &files); 117 if (error) { 118 break; 119 } 120 121 quotavals_to_dqblk(&blocks, &files, &dqblk); 122 error = copyout(&dqblk, SCARG(uap, arg), sizeof(dqblk)); 123 break; 124 125 case Q_SETQUOTA: 126 error = copyin(SCARG(uap, arg), &dqblk, sizeof(dqblk)); 127 if (error) { 128 break; 129 } 130 dqblk_to_quotavals(&dqblk, &blocks, &files); 131 132 key.qk_idtype = idtype; 133 key.qk_id = SCARG(uap, uid); 134 135 key.qk_objtype = QUOTA_OBJTYPE_BLOCKS; 136 error = vfs_quotactl_put(mp, &key, &blocks); 137 if (error) { 138 break; 139 } 140 141 key.qk_objtype = QUOTA_OBJTYPE_FILES; 142 error = vfs_quotactl_put(mp, &key, &files); 143 break; 144 145 case Q_SYNC: 146 /* 147 * not supported but used only to see if quota is supported, 148 * emulate with stat 149 * 150 * XXX should probably be supported 151 */ 152 (void)idtype; /* not used */ 153 154 error = vfs_quotactl_stat(mp, &qstat); 155 break; 156 157 case Q_SETUSE: 158 default: 159 error = EOPNOTSUPP; 160 break; 161 } 162 163 vrele(vp); 164 return error; 165 } 166 167 MODULE(MODULE_CLASS_EXEC, compat_50_quota, "compat_50,ufs"); 168 169 static int 170 compat_50_quota_modcmd(modcmd_t cmd, void *arg) 171 { 172 173 switch (cmd) { 174 case MODULE_CMD_INIT: 175 return syscall_establish(NULL, vfs_syscalls_50_quota_syscalls); 176 case MODULE_CMD_FINI: 177 return syscall_disestablish(NULL, vfs_syscalls_50_quota_syscalls); 178 default: 179 return ENOTTY; 180 } 181 } 182