|
|
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.
1.1.1.2 ! root 186: * [internal interface to file i/o for kernel only]
1.1 root 187: */
188: vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
189: enum uio_rw rw;
190: struct vnode *vp;
191: caddr_t base;
192: int len;
193: off_t offset;
194: enum uio_seg segflg;
195: int ioflg;
196: struct ucred *cred;
197: int *aresid;
198: struct proc *p;
199: {
200: struct uio auio;
201: struct iovec aiov;
202: int error;
203:
204: if ((ioflg & IO_NODELOCKED) == 0)
205: VOP_LOCK(vp);
206: auio.uio_iov = &aiov;
207: auio.uio_iovcnt = 1;
208: aiov.iov_base = base;
209: aiov.iov_len = len;
210: auio.uio_resid = len;
211: auio.uio_offset = offset;
212: auio.uio_segflg = segflg;
213: auio.uio_rw = rw;
214: auio.uio_procp = p;
215: if (rw == UIO_READ)
216: error = VOP_READ(vp, &auio, ioflg, cred);
217: else
218: error = VOP_WRITE(vp, &auio, ioflg, cred);
219: if (aresid)
220: *aresid = auio.uio_resid;
221: else
222: if (auio.uio_resid && error == 0)
223: error = EIO;
224: if ((ioflg & IO_NODELOCKED) == 0)
225: VOP_UNLOCK(vp);
226: return (error);
227: }
228:
229: /*
230: * File table vnode read routine.
231: */
232: vn_read(fp, uio, cred)
233: struct file *fp;
234: struct uio *uio;
235: struct ucred *cred;
236: {
237: register struct vnode *vp = (struct vnode *)fp->f_data;
238: int count, error;
239:
240: VOP_LOCK(vp);
241: uio->uio_offset = fp->f_offset;
242: count = uio->uio_resid;
243: error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
244: cred);
245: fp->f_offset += count - uio->uio_resid;
246: VOP_UNLOCK(vp);
247: return (error);
248: }
249:
250: /*
251: * File table vnode write routine.
252: */
253: vn_write(fp, uio, cred)
254: struct file *fp;
255: struct uio *uio;
256: struct ucred *cred;
257: {
258: register struct vnode *vp = (struct vnode *)fp->f_data;
259: int count, error, ioflag = 0;
260:
261: if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
262: ioflag |= IO_APPEND;
263: if (fp->f_flag & FNONBLOCK)
264: ioflag |= IO_NDELAY;
265: VOP_LOCK(vp);
266: uio->uio_offset = fp->f_offset;
267: count = uio->uio_resid;
268: error = VOP_WRITE(vp, uio, ioflag, cred);
269: if (ioflag & IO_APPEND)
270: fp->f_offset = uio->uio_offset;
271: else
272: fp->f_offset += count - uio->uio_resid;
273: VOP_UNLOCK(vp);
274: return (error);
275: }
276:
277: /*
278: * File table vnode stat routine.
279: */
280: vn_stat(vp, sb, p)
281: struct vnode *vp;
282: register struct stat *sb;
283: struct proc *p;
284: {
285: struct vattr vattr;
286: register struct vattr *vap;
287: int error;
288: u_short mode;
289:
290: vap = &vattr;
291: error = VOP_GETATTR(vp, vap, p->p_ucred, p);
292: if (error)
293: return (error);
294: /*
295: * Copy from vattr table
296: */
297: sb->st_dev = vap->va_fsid;
298: sb->st_ino = vap->va_fileid;
299: mode = vap->va_mode;
300: switch (vp->v_type) {
301: case VREG:
302: mode |= S_IFREG;
303: break;
304: case VDIR:
305: mode |= S_IFDIR;
306: break;
307: case VBLK:
308: mode |= S_IFBLK;
309: break;
310: case VCHR:
311: mode |= S_IFCHR;
312: break;
313: case VLNK:
314: mode |= S_IFLNK;
315: break;
316: case VSOCK:
317: mode |= S_IFSOCK;
318: break;
319: case VFIFO:
320: mode |= S_IFIFO;
321: break;
322: default:
323: return (EBADF);
324: };
325: sb->st_mode = mode;
326: sb->st_nlink = vap->va_nlink;
327: sb->st_uid = vap->va_uid;
328: sb->st_gid = vap->va_gid;
329: sb->st_rdev = vap->va_rdev;
330: sb->st_size = vap->va_size;
331: sb->st_atime = vap->va_atime.tv_sec;
332: sb->st_spare1 = 0;
333: sb->st_mtime = vap->va_mtime.tv_sec;
334: sb->st_spare2 = 0;
335: sb->st_ctime = vap->va_ctime.tv_sec;
336: sb->st_spare3 = 0;
337: sb->st_blksize = vap->va_blocksize;
338: sb->st_flags = vap->va_flags;
339: sb->st_gen = vap->va_gen;
340: sb->st_blocks = vap->va_bytes / S_BLKSIZE;
341: return (0);
342: }
343:
344: /*
345: * File table vnode ioctl routine.
346: */
347: vn_ioctl(fp, com, data, p)
348: struct file *fp;
349: int com;
350: caddr_t data;
351: struct proc *p;
352: {
353: register struct vnode *vp = ((struct vnode *)fp->f_data);
354: struct vattr vattr;
355: int error;
356:
357: switch (vp->v_type) {
358:
359: case VREG:
360: case VDIR:
361: if (com == FIONREAD) {
362: if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
363: return (error);
364: *(off_t *)data = vattr.va_size - fp->f_offset;
365: return (0);
366: }
367: if (com == FIONBIO || com == FIOASYNC) /* XXX */
368: return (0); /* XXX */
369: /* fall into ... */
370:
371: default:
372: return (ENOTTY);
373:
374: case VFIFO:
375: case VCHR:
376: case VBLK:
377: error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
378: if (error == 0 && com == TIOCSCTTY) {
379: p->p_session->s_ttyvp = vp;
380: VREF(vp);
381: }
382: return (error);
383: }
384: }
385:
386: /*
387: * File table vnode select routine.
388: */
389: vn_select(fp, which, p)
390: struct file *fp;
391: int which;
392: struct proc *p;
393: {
394:
395: return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
396: fp->f_cred, p));
397: }
398:
399: /*
400: * File table vnode close routine.
401: */
402: vn_closefile(fp, p)
403: struct file *fp;
404: struct proc *p;
405: {
406:
407: return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
408: fp->f_cred, p));
409: }
410:
411: /*
412: * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
413: * - look up fsid in mount list (if not found ret error)
414: * - get vp by calling VFS_FHTOVP() macro
415: * - if lockflag lock it with VOP_LOCK()
416: */
417: vn_fhtovp(fhp, lockflag, vpp)
418: fhandle_t *fhp;
419: int lockflag;
420: struct vnode **vpp;
421: {
422: register struct mount *mp;
423:
424: if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
425: return (ESTALE);
426: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
427: return (ESTALE);
428: if (!lockflag)
429: VOP_UNLOCK(*vpp);
430: return (0);
431: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.