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