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