|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1989, 1993
28: * The Regents of the University of California. All rights reserved.
29: * (c) UNIX System Laboratories, Inc.
30: * All or some portions of this file are derived from material licensed
31: * to the University of California by American Telephone and Telegraph
32: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
33: * the permission of UNIX System Laboratories, Inc.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * 4. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: *
63: * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95
64: *
65: * History
66: * 10-20-1997 Umesh Vaishampayan
67: * Fixed the count to be off_t rather than int.
68: */
69:
70: #include <mach_nbc.h>
71: #include <sys/param.h>
72: #include <sys/systm.h>
73: #include <sys/kernel.h>
74: #include <sys/file.h>
75: #include <sys/stat.h>
76: #include <sys/buf.h>
77: #include <sys/proc.h>
78: #include <sys/mount.h>
79: #include <sys/namei.h>
80: #include <sys/vnode.h>
81: #include <sys/ioctl.h>
82: #include <sys/tty.h>
83: #include <kern/mapfs.h>
84:
85: struct fileops vnops =
86: { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile };
87:
88: /*
89: * Common code for vnode open operations.
90: * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
91: */
92: vn_open(ndp, fmode, cmode)
93: register struct nameidata *ndp;
94: int fmode, cmode;
95: {
96: register struct vnode *vp;
97: register struct proc *p = ndp->ni_cnd.cn_proc;
98: register struct ucred *cred = p->p_ucred;
99: struct vattr vat;
100: struct vattr *vap = &vat;
101: int error;
102: #if MACH_NBC
103: int no_mfs = fmode & O_NO_MFS;
104: #endif /* MACH_NBC */
105:
106: if (fmode & O_CREAT) {
107: ndp->ni_cnd.cn_nameiop = CREATE;
108: ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
109: if ((fmode & O_EXCL) == 0)
110: ndp->ni_cnd.cn_flags |= FOLLOW;
111: if (error = namei(ndp))
112: return (error);
113: if (ndp->ni_vp == NULL) {
114: VATTR_NULL(vap);
115: vap->va_type = VREG;
116: vap->va_mode = cmode;
117: if (fmode & O_EXCL)
118: vap->va_vaflags |= VA_EXCLUSIVE;
119: VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
120: if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
121: &ndp->ni_cnd, vap))
122: return (error);
123: fmode &= ~O_TRUNC;
124: vp = ndp->ni_vp;
125: } else {
126: VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
127: if (ndp->ni_dvp == ndp->ni_vp)
128: vrele(ndp->ni_dvp);
129: else
130: vput(ndp->ni_dvp);
131: ndp->ni_dvp = NULL;
132: vp = ndp->ni_vp;
133: if (fmode & O_EXCL) {
134: error = EEXIST;
135: goto bad;
136: }
137: fmode &= ~O_CREAT;
138: }
139: } else {
140: ndp->ni_cnd.cn_nameiop = LOOKUP;
141: ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF;
142: if (error = namei(ndp))
143: return (error);
144: vp = ndp->ni_vp;
145: }
146: if (vp->v_type == VSOCK) {
147: error = EOPNOTSUPP;
148: goto bad;
149: }
150: if ((fmode & O_CREAT) == 0) {
151: if (fmode & FREAD) {
152: if (error = VOP_ACCESS(vp, VREAD, cred, p))
153: goto bad;
154: }
155: if (fmode & (FWRITE | O_TRUNC)) {
156: if (vp->v_type == VDIR) {
157: error = EISDIR;
158: goto bad;
159: }
160: if ((error = vn_writechk(vp)) ||
161: (error = VOP_ACCESS(vp, VWRITE, cred, p)))
162: goto bad;
163: }
164: }
165: if (fmode & O_TRUNC) {
166: VOP_UNLOCK(vp, 0, p); /* XXX */
167: VOP_LEASE(vp, p, cred, LEASE_WRITE);
168: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
169: VATTR_NULL(vap);
170: vap->va_size = 0;
171: if (error = VOP_SETATTR(vp, vap, cred, p))
172: goto bad;
173: }
174: if (error = VOP_OPEN(vp, fmode, cred, p))
175: goto bad;
176: if ((vp->v_type == VREG) && !vp->v_vm_info) // XXX WMG
177: vm_info_init(vp);
178: #if MACH_NBC
179: if ((error == 0) && (no_mfs == 0) && (vp->v_type == VREG)) {
180: /* if the file was never mapped, leave it alone */
181: if (vp->v_vm_info->pager != NULL)
182: map_vnode(vp,p);
183: }
184:
185: /*
186: * if O_NO_MFS is set on open, blow the VM cache.
187: * if someone else is using it in VM then this has no effect.
188: */
189: if ((vp->v_type == VREG) && (no_mfs != 0))
190: (void) vnode_uncache(vp);
191: #endif /* MACH_NBC */
192:
193: if (fmode & FWRITE)
194: vp->v_writecount++;
195: return (0);
196: bad:
197: vput(vp);
198: return (error);
199: }
200:
201: /*
202: * Check for write permissions on the specified vnode.
203: * Prototype text segments cannot be written.
204: */
205: vn_writechk(vp)
206: register struct vnode *vp;
207: {
208:
209: /*
210: * If there's shared text associated with
211: * the vnode, try to free it up once. If
212: * we fail, we can't allow writing.
213: */
214: if ((vp->v_flag & VTEXT) && !vnode_uncache(vp))
215: return (ETXTBSY);
216: return (0);
217: }
218:
219: /*
220: * Vnode close call
221: */
222: vn_close(vp, flags, cred, p)
223: register struct vnode *vp;
224: int flags;
225: struct ucred *cred;
226: struct proc *p;
227: {
228: int error;
229:
230: #if MACH_NBC
231: if ((vp->v_type == VREG) && vp->v_vm_info)
232: unmap_vnode(vp,p);
233: #endif /* MACH_NBC */
234:
235: if (flags & FWRITE)
236: vp->v_writecount--;
237: error = VOP_CLOSE(vp, flags, cred, p);
238: vrele(vp);
239: return (error);
240: }
241:
242: /*
243: * Package up an I/O request on a vnode into a uio and do it.
244: */
245: vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
246: enum uio_rw rw;
247: struct vnode *vp;
248: caddr_t base;
249: int len;
250: off_t offset;
251: enum uio_seg segflg;
252: int ioflg;
253: struct ucred *cred;
254: int *aresid;
255: struct proc *p;
256: {
257: struct uio auio;
258: struct iovec aiov;
259: int error=0;
260:
261: /* The routines that use this under MACH_NBC, call this
262: * routine with IO_NODELOCKED on, which is incorrect.
263: * For ease of code usage in case MACH_NBC is turned off
264: * we will bypass this check and let the callers still use
265: * IO_NODELOCKED flag
266: */
267: /* FIXME XXX */
268: if ((ioflg & IO_NODELOCKED) == 0)
269: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
270: auio.uio_iov = &aiov;
271: auio.uio_iovcnt = 1;
272: aiov.iov_base = base;
273: aiov.iov_len = len;
274: auio.uio_resid = len;
275: auio.uio_offset = offset;
276: auio.uio_segflg = segflg;
277: auio.uio_rw = rw;
278: auio.uio_procp = p;
279: #if MACH_NBC
280: /* if the file was never mapped, leave it alone */
281: if ((vp->v_type == VREG) && (vp->v_vm_info->pager != NULL)) {
282: if (vp->v_vm_info->map_count == 0) {
283: /*
284: * file has a pager but MapFS is not involved yet
285: * get MapFS involved
286: */
287: map_vnode(vp,p); /* vn_close() will loose this map_count */
288: }
289: error = mapfs_io(vp, &auio, rw, ioflg, cred);
290: } else {
291: #endif /* MACH_NBC */
292: if (rw == UIO_READ)
293: error = VOP_READ(vp, &auio, ioflg, cred);
294: else
295: error = VOP_WRITE(vp, &auio, ioflg, cred);
296: #if MACH_NBC
297: }
298: #endif /* MACH_NBC */
299: if (aresid)
300: *aresid = auio.uio_resid;
301: else
302: if (auio.uio_resid && error == 0)
303: error = EIO;
304: if ((ioflg & IO_NODELOCKED) == 0)
305: VOP_UNLOCK(vp, 0, p);
306: return (error);
307: }
308:
309: /*
310: * File table vnode read routine.
311: */
312: vn_read(fp, uio, cred)
313: struct file *fp;
314: struct uio *uio;
315: struct ucred *cred;
316: {
317: struct vnode *vp = (struct vnode *)fp->f_data;
318: struct proc *p = uio->uio_procp;
319: int error;
320: off_t count;
321:
322: VOP_LEASE(vp, p, cred, LEASE_READ);
323: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
324: uio->uio_offset = fp->f_offset;
325: count = uio->uio_resid;
326: #if MACH_NBC
327: if ((vp->v_type == VREG) && (vp->v_vm_info) && (vp->v_vm_info->mapped)) {
328: error = mapfs_io(vp, uio, UIO_READ, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred);
329: } else {
330: #endif /* MACH_NBC */
331: error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred);
332: #if MACH_NBC
333: }
334: #endif /* MACH_NBC */
335:
336: fp->f_offset += count - uio->uio_resid;
337: VOP_UNLOCK(vp, 0, p);
338: return (error);
339: }
340:
341: /*
342: * File table vnode write routine.
343: */
344: vn_write(fp, uio, cred)
345: struct file *fp;
346: struct uio *uio;
347: struct ucred *cred;
348: {
349: struct vnode *vp = (struct vnode *)fp->f_data;
350: struct proc *p = uio->uio_procp;
351: int error, ioflag = IO_UNIT;
352: off_t count;
353:
354: if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
355: ioflag |= IO_APPEND;
356: if (fp->f_flag & FNONBLOCK)
357: ioflag |= IO_NDELAY;
358: if ((fp->f_flag & O_FSYNC) ||
359: (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
360: ioflag |= IO_SYNC;
361: VOP_LEASE(vp, p, cred, LEASE_WRITE);
362: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
363: uio->uio_offset = fp->f_offset;
364: count = uio->uio_resid;
365: #if MACH_NBC
366: if ((vp->v_type == VREG) && (vp->v_vm_info) && (vp->v_vm_info->mapped)) {
367: error = mapfs_io(vp, uio, UIO_WRITE, ioflag, cred);
368: } else {
369: #endif /* MACH_NBC */
370:
371: error = VOP_WRITE(vp, uio, ioflag, cred);
372: #if MACH_NBC
373: }
374: #endif /* MACH_NBC */
375:
376: if (ioflag & IO_APPEND)
377: fp->f_offset = uio->uio_offset;
378: else
379: fp->f_offset += count - uio->uio_resid;
380: VOP_UNLOCK(vp, 0, p);
381: return (error);
382: }
383:
384: /*
385: * File table vnode stat routine.
386: */
387: vn_stat(vp, sb, p)
388: struct vnode *vp;
389: register struct stat *sb;
390: struct proc *p;
391: {
392: struct vattr vattr;
393: register struct vattr *vap;
394: int error;
395: u_short mode;
396:
397: vap = &vattr;
398: error = VOP_GETATTR(vp, vap, p->p_ucred, p);
399: if (error)
400: return (error);
401: /*
402: * Copy from vattr table
403: */
404: sb->st_dev = vap->va_fsid;
405: sb->st_ino = vap->va_fileid;
406: mode = vap->va_mode;
407: switch (vp->v_type) {
408: case VREG:
409: mode |= S_IFREG;
410: break;
411: case VDIR:
412: mode |= S_IFDIR;
413: break;
414: case VBLK:
415: mode |= S_IFBLK;
416: break;
417: case VCHR:
418: mode |= S_IFCHR;
419: break;
420: case VLNK:
421: mode |= S_IFLNK;
422: break;
423: case VSOCK:
424: mode |= S_IFSOCK;
425: break;
426: case VFIFO:
427: mode |= S_IFIFO;
428: break;
429: default:
430: return (EBADF);
431: };
432: sb->st_mode = mode;
433: sb->st_nlink = vap->va_nlink;
434: sb->st_uid = vap->va_uid;
435: sb->st_gid = vap->va_gid;
436: sb->st_rdev = vap->va_rdev;
437: sb->st_size = vap->va_size;
438: sb->st_atimespec = vap->va_atime;
439: sb->st_mtimespec = vap->va_mtime;
440: sb->st_ctimespec = vap->va_ctime;
441: sb->st_blksize = vap->va_blocksize;
442: sb->st_flags = vap->va_flags;
443: /* Do not give the generation number out to unpriviledged users */
444: if (suser(p->p_ucred, &p->p_acflag))
445: sb->st_gen = 0;
446: else
447: sb->st_gen = vap->va_gen;
448: sb->st_blocks = vap->va_bytes / S_BLKSIZE;
449: return (0);
450: }
451:
452: /*
453: * File table vnode ioctl routine.
454: */
455: vn_ioctl(fp, com, data, p)
456: struct file *fp;
457: u_long com;
458: caddr_t data;
459: struct proc *p;
460: {
461: register struct vnode *vp = ((struct vnode *)fp->f_data);
462: struct vattr vattr;
463: int error;
464:
465: switch (vp->v_type) {
466:
467: case VREG:
468: case VDIR:
469: if (com == FIONREAD) {
470: if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
471: return (error);
472: *(int *)data = vattr.va_size - fp->f_offset;
473: return (0);
474: }
475: if (com == FIONBIO || com == FIOASYNC) /* XXX */
476: return (0); /* XXX */
477: /* fall into ... */
478:
479: default:
480: return (ENOTTY);
481:
482: case VFIFO:
483: case VCHR:
484: case VBLK:
485: error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
486: if (error == 0 && com == TIOCSCTTY) {
487: if (p->p_session->s_ttyvp)
488: vrele(p->p_session->s_ttyvp);
489: p->p_session->s_ttyvp = vp;
490: VREF(vp);
491: }
492: return (error);
493: }
494: }
495:
496: /*
497: * File table vnode select routine.
498: */
499: vn_select(fp, which, p)
500: struct file *fp;
501: int which;
502: struct proc *p;
503: {
504:
505: return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
506: fp->f_cred, p));
507: }
508:
509: /*
510: * Check that the vnode is still valid, and if so
511: * acquire requested lock.
512: */
513: int
514: vn_lock(vp, flags, p)
515: struct vnode *vp;
516: int flags;
517: struct proc *p;
518: {
519: int error;
520:
521: do {
522: if ((flags & LK_INTERLOCK) == 0)
523: simple_lock(&vp->v_interlock);
524: if (vp->v_flag & VXLOCK) {
525: vp->v_flag |= VXWANT;
526: simple_unlock(&vp->v_interlock);
527: tsleep((caddr_t)vp, PINOD, "vn_lock", 0);
528: error = ENOENT;
529: } else {
530: error = VOP_LOCK(vp, flags | LK_INTERLOCK, p);
531: if (error == 0)
532: return (error);
533: }
534: flags &= ~LK_INTERLOCK;
535: } while (flags & LK_RETRY);
536: return (error);
537: }
538:
539: /*
540: * File table vnode close routine.
541: */
542: vn_closefile(fp, p)
543: struct file *fp;
544: struct proc *p;
545: {
546:
547: return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
548: fp->f_cred, p));
549: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.