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