1 /* 2 * Copyright (c) 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 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 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95 35 * $FreeBSD: src/sys/ufs/ufs/ufs_vfsops.c,v 1.17.2.3 2001/10/14 19:08:16 iedowse Exp $ 36 * $DragonFly: src/sys/vfs/ufs/ufs_vfsops.c,v 1.17 2008/09/17 21:44:25 dillon Exp $ 37 */ 38 39 #include "opt_quota.h" 40 41 #include <sys/param.h> 42 #include <sys/kernel.h> 43 #include <sys/mount.h> 44 #include <sys/proc.h> 45 #include <sys/priv.h> 46 #include <sys/malloc.h> 47 #include <sys/vnode.h> 48 49 #include "quota.h" 50 #include "inode.h" 51 #include "ufsmount.h" 52 #include "ufs_extern.h" 53 54 MALLOC_DEFINE(M_UFSMNT, "UFS mount", "UFS mount structure"); 55 /* 56 * Return the root of a filesystem. 57 */ 58 int 59 ufs_root(struct mount *mp, struct vnode **vpp) 60 { 61 struct vnode *nvp; 62 int error; 63 64 error = VFS_VGET(mp, NULL, (ino_t)ROOTINO, &nvp); 65 if (error) 66 return (error); 67 *vpp = nvp; 68 return (0); 69 } 70 71 /* 72 * Do operations associated with quotas 73 */ 74 int 75 ufs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, 76 struct ucred *cred) 77 { 78 #ifndef QUOTA 79 return (EOPNOTSUPP); 80 #else 81 int cmd, type, error; 82 83 type = cmds & SUBCMDMASK; 84 cmd = cmds >> SUBCMDSHIFT; 85 86 if (uid == -1) { 87 switch(type) { 88 case USRQUOTA: 89 uid = cred->cr_ruid; 90 break; 91 case GRPQUOTA: 92 uid = cred->cr_rgid; 93 break; 94 default: 95 return (EINVAL); 96 } 97 } 98 99 /* 100 * Check permissions. 101 */ 102 switch (cmd) { 103 104 case Q_QUOTAON: 105 error = priv_check_cred(cred, PRIV_UFS_QUOTAON, 0); 106 break; 107 108 case Q_QUOTAOFF: 109 error = priv_check_cred(cred, PRIV_UFS_QUOTAOFF, 0); 110 break; 111 112 case Q_SETQUOTA: 113 error = priv_check_cred(cred, PRIV_VFS_SETQUOTA, 0); 114 break; 115 116 case Q_SETUSE: 117 error = priv_check_cred(cred, PRIV_UFS_SETUSE, 0); 118 break; 119 120 case Q_GETQUOTA: 121 if (uid == cred->cr_ruid) 122 error = 0; 123 else 124 error = priv_check_cred(cred, PRIV_VFS_GETQUOTA, 0); 125 break; 126 127 case Q_SYNC: 128 error = 0; 129 break; 130 131 default: 132 error = EINVAL; 133 break; 134 } 135 136 if (error) 137 return (error); 138 139 140 if ((uint)type >= MAXQUOTAS) 141 return (EINVAL); 142 if (vfs_busy(mp, LK_NOWAIT)) 143 return (0); 144 145 switch (cmd) { 146 147 case Q_QUOTAON: 148 error = ufs_quotaon(cred, mp, type, arg); 149 break; 150 151 case Q_QUOTAOFF: 152 error = ufs_quotaoff(mp, type); 153 break; 154 155 case Q_SETQUOTA: 156 error = ufs_setquota(mp, uid, type, arg); 157 break; 158 159 case Q_SETUSE: 160 error = ufs_setuse(mp, uid, type, arg); 161 break; 162 163 case Q_GETQUOTA: 164 error = ufs_getquota(mp, uid, type, arg); 165 break; 166 167 case Q_SYNC: 168 error = ufs_qsync(mp); 169 break; 170 171 default: 172 error = EINVAL; 173 break; 174 } 175 vfs_unbusy(mp); 176 return (error); 177 #endif 178 } 179 180 /* 181 * Initial UFS filesystems, done only once. 182 */ 183 int 184 ufs_init(struct vfsconf *vfsp) 185 { 186 static int done; 187 188 if (done) 189 return (0); 190 done = 1; 191 #ifdef QUOTA 192 ufs_dqinit(); 193 #endif 194 return (0); 195 } 196 197 /* 198 * This is the generic part of fhtovp called after the underlying 199 * filesystem has validated the file handle. 200 * 201 * Call the VFS_CHECKEXP beforehand to verify access. 202 */ 203 int 204 ufs_fhtovp(struct mount *mp, struct vnode *rootvp, 205 struct ufid *ufhp, struct vnode **vpp) 206 { 207 struct inode *ip; 208 struct vnode *nvp; 209 int error; 210 211 error = VFS_VGET(mp, NULL, ufhp->ufid_ino, &nvp); 212 if (error) { 213 *vpp = NULLVP; 214 return (error); 215 } 216 ip = VTOI(nvp); 217 if (ip->i_mode == 0 || 218 ip->i_gen != ufhp->ufid_gen || 219 (VFSTOUFS(mp)->um_i_effnlink_valid ? ip->i_effnlink : 220 ip->i_nlink) <= 0) { 221 vput(nvp); 222 *vpp = NULLVP; 223 return (ESTALE); 224 } 225 *vpp = nvp; 226 return (0); 227 } 228 229 230 /* 231 * This is the generic part of fhtovp called after the underlying 232 * filesystem has validated the file handle. 233 * 234 * Verify that a host should have access to a filesystem. 235 */ 236 int 237 ufs_check_export(struct mount *mp, struct sockaddr *nam, int *exflagsp, 238 struct ucred **credanonp) 239 { 240 struct netcred *np; 241 struct ufsmount *ump; 242 243 ump = VFSTOUFS(mp); 244 /* 245 * Get the export permission structure for this <mp, client> tuple. 246 */ 247 np = vfs_export_lookup(mp, &ump->um_export, nam); 248 if (np == NULL) 249 return (EACCES); 250 251 *exflagsp = np->netc_exflags; 252 *credanonp = &np->netc_anon; 253 return (0); 254 } 255