1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vfs_vnops.c 7.46 (Berkeley) 10/11/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/kernel.h> 13 #include <sys/file.h> 14 #include <sys/stat.h> 15 #include <sys/buf.h> 16 #include <sys/proc.h> 17 #include <sys/mount.h> 18 #include <sys/namei.h> 19 #include <sys/vnode.h> 20 #include <sys/ioctl.h> 21 #include <sys/tty.h> 22 23 #include <vm/vm.h> 24 25 struct fileops vnops = 26 { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; 27 28 /* 29 * Common code for vnode open operations. 30 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 31 */ 32 vn_open(ndp, fmode, cmode) 33 register struct nameidata *ndp; 34 int fmode, cmode; 35 { 36 register struct vnode *vp; 37 register struct proc *p = ndp->ni_cnd.cn_proc; 38 register struct ucred *cred = p->p_ucred; 39 struct vattr vat; 40 struct vattr *vap = &vat; 41 int error; 42 43 if (fmode & O_CREAT) { 44 ndp->ni_cnd.cn_nameiop = CREATE; 45 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 46 if ((fmode & O_EXCL) == 0) 47 ndp->ni_cnd.cn_flags |= FOLLOW; 48 if (error = namei(ndp)) 49 return (error); 50 if (ndp->ni_vp == NULL) { 51 VATTR_NULL(vap); 52 vap->va_type = VREG; 53 vap->va_mode = cmode; 54 LEASE_CHECK(ndp->ni_dvp, p, cred, LEASE_WRITE); 55 if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 56 &ndp->ni_cnd, vap)) 57 return (error); 58 fmode &= ~O_TRUNC; 59 vp = ndp->ni_vp; 60 } else { 61 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 62 if (ndp->ni_dvp == ndp->ni_vp) 63 vrele(ndp->ni_dvp); 64 else 65 vput(ndp->ni_dvp); 66 ndp->ni_dvp = NULL; 67 vp = ndp->ni_vp; 68 if (fmode & O_EXCL) { 69 error = EEXIST; 70 goto bad; 71 } 72 fmode &= ~O_CREAT; 73 } 74 } else { 75 ndp->ni_cnd.cn_nameiop = LOOKUP; 76 ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF; 77 if (error = namei(ndp)) 78 return (error); 79 vp = ndp->ni_vp; 80 } 81 if (vp->v_type == VSOCK) { 82 error = EOPNOTSUPP; 83 goto bad; 84 } 85 if ((fmode & O_CREAT) == 0) { 86 if (fmode & FREAD) { 87 if (error = VOP_ACCESS(vp, VREAD, cred, p)) 88 goto bad; 89 } 90 if (fmode & (FWRITE | O_TRUNC)) { 91 if (vp->v_type == VDIR) { 92 error = EISDIR; 93 goto bad; 94 } 95 if ((error = vn_writechk(vp)) || 96 (error = VOP_ACCESS(vp, VWRITE, cred, p))) 97 goto bad; 98 } 99 } 100 if (fmode & O_TRUNC) { 101 VATTR_NULL(vap); 102 vap->va_size = 0; 103 LEASE_CHECK(vp, p, cred, LEASE_WRITE); 104 if (error = VOP_SETATTR(vp, vap, cred, p)) 105 goto bad; 106 } 107 if (error = VOP_OPEN(vp, fmode, cred, p)) 108 goto bad; 109 if (fmode & FWRITE) 110 vp->v_writecount++; 111 return (0); 112 bad: 113 vput(vp); 114 return (error); 115 } 116 117 /* 118 * Check for write permissions on the specified vnode. 119 * The read-only status of the file system is checked. 120 * Also, prototype text segments cannot be written. 121 */ 122 vn_writechk(vp) 123 register struct vnode *vp; 124 { 125 126 /* 127 * Disallow write attempts on read-only file systems; 128 * unless the file is a socket or a block or character 129 * device resident on the file system. 130 */ 131 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 132 switch (vp->v_type) { 133 case VREG: case VDIR: case VLNK: 134 return (EROFS); 135 } 136 } 137 /* 138 * If there's shared text associated with 139 * the vnode, try to free it up once. If 140 * we fail, we can't allow writing. 141 */ 142 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 143 return (ETXTBSY); 144 return (0); 145 } 146 147 /* 148 * Vnode close call 149 */ 150 vn_close(vp, flags, cred, p) 151 register struct vnode *vp; 152 int flags; 153 struct ucred *cred; 154 struct proc *p; 155 { 156 int error; 157 158 if (flags & FWRITE) 159 vp->v_writecount--; 160 error = VOP_CLOSE(vp, flags, cred, p); 161 vrele(vp); 162 return (error); 163 } 164 165 /* 166 * Package up an I/O request on a vnode into a uio and do it. 167 */ 168 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) 169 enum uio_rw rw; 170 struct vnode *vp; 171 caddr_t base; 172 int len; 173 off_t offset; 174 enum uio_seg segflg; 175 int ioflg; 176 struct ucred *cred; 177 int *aresid; 178 struct proc *p; 179 { 180 struct uio auio; 181 struct iovec aiov; 182 int error; 183 184 if ((ioflg & IO_NODELOCKED) == 0) 185 VOP_LOCK(vp); 186 auio.uio_iov = &aiov; 187 auio.uio_iovcnt = 1; 188 aiov.iov_base = base; 189 aiov.iov_len = len; 190 auio.uio_resid = len; 191 auio.uio_offset = offset; 192 auio.uio_segflg = segflg; 193 auio.uio_rw = rw; 194 auio.uio_procp = p; 195 if (rw == UIO_READ) { 196 LEASE_CHECK(vp, p, cred, LEASE_READ); 197 error = VOP_READ(vp, &auio, ioflg, cred); 198 } else { 199 LEASE_CHECK(vp, p, cred, LEASE_WRITE); 200 error = VOP_WRITE(vp, &auio, ioflg, cred); 201 } 202 if (aresid) 203 *aresid = auio.uio_resid; 204 else 205 if (auio.uio_resid && error == 0) 206 error = EIO; 207 if ((ioflg & IO_NODELOCKED) == 0) 208 VOP_UNLOCK(vp); 209 return (error); 210 } 211 212 /* 213 * File table vnode read routine. 214 */ 215 vn_read(fp, uio, cred) 216 struct file *fp; 217 struct uio *uio; 218 struct ucred *cred; 219 { 220 register struct vnode *vp = (struct vnode *)fp->f_data; 221 int count, error; 222 223 VOP_LOCK(vp); 224 uio->uio_offset = fp->f_offset; 225 count = uio->uio_resid; 226 LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_READ); 227 error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, 228 cred); 229 fp->f_offset += count - uio->uio_resid; 230 VOP_UNLOCK(vp); 231 return (error); 232 } 233 234 /* 235 * File table vnode write routine. 236 */ 237 vn_write(fp, uio, cred) 238 struct file *fp; 239 struct uio *uio; 240 struct ucred *cred; 241 { 242 register struct vnode *vp = (struct vnode *)fp->f_data; 243 int count, error, ioflag = 0; 244 245 if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) 246 ioflag |= IO_APPEND; 247 if (fp->f_flag & FNONBLOCK) 248 ioflag |= IO_NDELAY; 249 VOP_LOCK(vp); 250 uio->uio_offset = fp->f_offset; 251 count = uio->uio_resid; 252 LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_WRITE); 253 error = VOP_WRITE(vp, uio, ioflag, cred); 254 if (ioflag & IO_APPEND) 255 fp->f_offset = uio->uio_offset; 256 else 257 fp->f_offset += count - uio->uio_resid; 258 VOP_UNLOCK(vp); 259 return (error); 260 } 261 262 /* 263 * File table vnode stat routine. 264 */ 265 vn_stat(vp, sb, p) 266 struct vnode *vp; 267 register struct stat *sb; 268 struct proc *p; 269 { 270 struct vattr vattr; 271 register struct vattr *vap; 272 int error; 273 u_short mode; 274 275 vap = &vattr; 276 error = VOP_GETATTR(vp, vap, p->p_ucred, p); 277 if (error) 278 return (error); 279 /* 280 * Copy from vattr table 281 */ 282 sb->st_dev = vap->va_fsid; 283 sb->st_ino = vap->va_fileid; 284 mode = vap->va_mode; 285 switch (vp->v_type) { 286 case VREG: 287 mode |= S_IFREG; 288 break; 289 case VDIR: 290 mode |= S_IFDIR; 291 break; 292 case VBLK: 293 mode |= S_IFBLK; 294 break; 295 case VCHR: 296 mode |= S_IFCHR; 297 break; 298 case VLNK: 299 mode |= S_IFLNK; 300 break; 301 case VSOCK: 302 mode |= S_IFSOCK; 303 break; 304 case VFIFO: 305 mode |= S_IFIFO; 306 break; 307 default: 308 return (EBADF); 309 }; 310 sb->st_mode = mode; 311 sb->st_nlink = vap->va_nlink; 312 sb->st_uid = vap->va_uid; 313 sb->st_gid = vap->va_gid; 314 sb->st_rdev = vap->va_rdev; 315 sb->st_size = vap->va_size; 316 sb->st_atimespec = vap->va_atime; 317 sb->st_mtimespec= vap->va_mtime; 318 sb->st_ctimespec = vap->va_ctime; 319 sb->st_blksize = vap->va_blocksize; 320 sb->st_flags = vap->va_flags; 321 sb->st_gen = vap->va_gen; 322 sb->st_blocks = vap->va_bytes / S_BLKSIZE; 323 return (0); 324 } 325 326 /* 327 * File table vnode ioctl routine. 328 */ 329 vn_ioctl(fp, com, data, p) 330 struct file *fp; 331 int com; 332 caddr_t data; 333 struct proc *p; 334 { 335 register struct vnode *vp = ((struct vnode *)fp->f_data); 336 struct vattr vattr; 337 int error; 338 339 switch (vp->v_type) { 340 341 case VREG: 342 case VDIR: 343 if (com == FIONREAD) { 344 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 345 return (error); 346 *(int *)data = vattr.va_size - fp->f_offset; 347 return (0); 348 } 349 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 350 return (0); /* XXX */ 351 /* fall into ... */ 352 353 default: 354 return (ENOTTY); 355 356 case VFIFO: 357 case VCHR: 358 case VBLK: 359 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); 360 if (error == 0 && com == TIOCSCTTY) { 361 p->p_session->s_ttyvp = vp; 362 VREF(vp); 363 } 364 return (error); 365 } 366 } 367 368 /* 369 * File table vnode select routine. 370 */ 371 vn_select(fp, which, p) 372 struct file *fp; 373 int which; 374 struct proc *p; 375 { 376 377 return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 378 fp->f_cred, p)); 379 } 380 381 /* 382 * File table vnode close routine. 383 */ 384 vn_closefile(fp, p) 385 struct file *fp; 386 struct proc *p; 387 { 388 389 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, 390 fp->f_cred, p)); 391 } 392