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 */ 37 38 #include "opt_quota.h" 39 40 #include <sys/param.h> 41 #include <sys/kernel.h> 42 #include <sys/mount.h> 43 #include <sys/proc.h> 44 #include <sys/priv.h> 45 #include <sys/malloc.h> 46 #include <sys/vnode.h> 47 48 #include "quota.h" 49 #include "inode.h" 50 #include "ufsmount.h" 51 #include "ufs_extern.h" 52 53 MALLOC_DEFINE(M_UFSMNT, "UFS mount", "UFS mount structure"); 54 /* 55 * Return the root of a filesystem. 56 */ 57 int 58 ufs_root(struct mount *mp, struct vnode **vpp) 59 { 60 struct vnode *nvp; 61 int error; 62 63 error = VFS_VGET(mp, NULL, (ino_t)UFS_ROOTINO, &nvp); 64 if (error) 65 return (error); 66 *vpp = nvp; 67 return (0); 68 } 69 70 /* 71 * Do operations associated with quotas 72 */ 73 int 74 ufs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, 75 struct ucred *cred) 76 { 77 #ifndef QUOTA 78 return (EOPNOTSUPP); 79 #else 80 int cmd, type, error; 81 82 type = cmds & SUBCMDMASK; 83 cmd = cmds >> SUBCMDSHIFT; 84 85 if (uid == -1) { 86 switch(type) { 87 case USRQUOTA: 88 uid = cred->cr_ruid; 89 break; 90 case GRPQUOTA: 91 uid = cred->cr_rgid; 92 break; 93 default: 94 return (EINVAL); 95 } 96 } 97 98 /* 99 * Check permissions. 100 */ 101 switch (cmd) { 102 103 case Q_QUOTAON: 104 error = priv_check_cred(cred, PRIV_UFS_QUOTAON, 0); 105 break; 106 107 case Q_QUOTAOFF: 108 error = priv_check_cred(cred, PRIV_UFS_QUOTAOFF, 0); 109 break; 110 111 case Q_SETQUOTA: 112 error = priv_check_cred(cred, PRIV_VFS_SETQUOTA, 0); 113 break; 114 115 case Q_SETUSE: 116 error = priv_check_cred(cred, PRIV_UFS_SETUSE, 0); 117 break; 118 119 case Q_GETQUOTA: 120 if (uid == cred->cr_ruid) 121 error = 0; 122 else 123 error = priv_check_cred(cred, PRIV_VFS_GETQUOTA, 0); 124 break; 125 126 case Q_SYNC: 127 error = 0; 128 break; 129 130 default: 131 error = EINVAL; 132 break; 133 } 134 135 if (error) 136 return (error); 137 138 139 if ((uint)type >= MAXQUOTAS) 140 return (EINVAL); 141 if (vfs_busy(mp, LK_NOWAIT)) 142 return (0); 143 144 switch (cmd) { 145 146 case Q_QUOTAON: 147 error = ufs_quotaon(cred, mp, type, arg); 148 break; 149 150 case Q_QUOTAOFF: 151 error = ufs_quotaoff(mp, type); 152 break; 153 154 case Q_SETQUOTA: 155 error = ufs_setquota(mp, uid, type, arg); 156 break; 157 158 case Q_SETUSE: 159 error = ufs_setuse(mp, uid, type, arg); 160 break; 161 162 case Q_GETQUOTA: 163 error = ufs_getquota(mp, uid, type, arg); 164 break; 165 166 case Q_SYNC: 167 error = ufs_qsync(mp); 168 break; 169 170 default: 171 error = EINVAL; 172 break; 173 } 174 vfs_unbusy(mp); 175 return (error); 176 #endif 177 } 178 179 /* 180 * Initial UFS filesystems, done only once. 181 */ 182 int 183 ufs_init(struct vfsconf *vfsp) 184 { 185 static int done; 186 187 if (done) 188 return (0); 189 done = 1; 190 #ifdef QUOTA 191 ufs_dqinit(); 192 #endif 193 return (0); 194 } 195 196 /* 197 * This is the generic part of fhtovp called after the underlying 198 * filesystem has validated the file handle. 199 * 200 * Call the VFS_CHECKEXP beforehand to verify access. 201 */ 202 int 203 ufs_fhtovp(struct mount *mp, struct vnode *rootvp, 204 struct ufid *ufhp, struct vnode **vpp) 205 { 206 struct inode *ip; 207 struct vnode *nvp; 208 int error; 209 210 error = VFS_VGET(mp, NULL, ufhp->ufid_ino, &nvp); 211 if (error) { 212 *vpp = NULLVP; 213 return (error); 214 } 215 ip = VTOI(nvp); 216 if (ip->i_mode == 0 || 217 ip->i_gen != ufhp->ufid_gen || 218 (VFSTOUFS(mp)->um_i_effnlink_valid ? ip->i_effnlink : 219 ip->i_nlink) <= 0) { 220 vput(nvp); 221 *vpp = NULLVP; 222 return (ESTALE); 223 } 224 *vpp = nvp; 225 return (0); 226 } 227 228 229 /* 230 * This is the generic part of fhtovp called after the underlying 231 * filesystem has validated the file handle. 232 * 233 * Verify that a host should have access to a filesystem. 234 */ 235 int 236 ufs_check_export(struct mount *mp, struct sockaddr *nam, int *exflagsp, 237 struct ucred **credanonp) 238 { 239 struct netcred *np; 240 struct ufsmount *ump; 241 242 ump = VFSTOUFS(mp); 243 /* 244 * Get the export permission structure for this <mp, client> tuple. 245 */ 246 np = vfs_export_lookup(mp, &ump->um_export, nam); 247 if (np == NULL) 248 return (EACCES); 249 250 *exflagsp = np->netc_exflags; 251 *credanonp = &np->netc_anon; 252 return (0); 253 } 254