|
|
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: * @(#)ufs_vnops.c 7.64 (Berkeley) 5/16/91
1.1.1.2 ! root 34: *
! 35: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
! 36: * -------------------- ----- ----------------------
! 37: * CURRENT PATCH LEVEL: 2 00026
! 38: * -------------------- ----- ----------------------
! 39: *
! 40: * 27 Nov 92 Bruce Evans Fixed access()
! 41: * 20 Aug 92 David Greenman Fixed incorrect setting of B_AGE after
! 42: * each read to improve cache performance
1.1 root 43: */
44:
45: #include "param.h"
46: #include "systm.h"
47: #include "namei.h"
48: #include "resourcevar.h"
49: #include "kernel.h"
50: #include "file.h"
51: #include "stat.h"
52: #include "buf.h"
53: #include "proc.h"
54: #include "conf.h"
55: #include "mount.h"
56: #include "vnode.h"
57: #include "specdev.h"
58: #include "fifo.h"
59: #include "malloc.h"
60:
61: #include "lockf.h"
62: #include "quota.h"
63: #include "inode.h"
64: #include "dir.h"
65: #include "fs.h"
66:
67: /*
68: * Create a regular file
69: */
70: ufs_create(ndp, vap, p)
71: struct nameidata *ndp;
72: struct vattr *vap;
73: struct proc *p;
74: {
75: struct inode *ip;
76: int error;
77:
78: if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
79: return (error);
80: ndp->ni_vp = ITOV(ip);
81: return (0);
82: }
83:
84: /*
85: * Mknod vnode call
86: */
87: /* ARGSUSED */
88: ufs_mknod(ndp, vap, cred, p)
89: struct nameidata *ndp;
90: struct ucred *cred;
91: struct vattr *vap;
92: struct proc *p;
93: {
94: register struct vnode *vp;
95: struct inode *ip;
96: int error;
97:
98: if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
99: return (error);
100: ip->i_flag |= IACC|IUPD|ICHG;
101: if (vap->va_rdev != VNOVAL) {
102: /*
103: * Want to be able to use this to make badblock
104: * inodes, so don't truncate the dev number.
105: */
106: ip->i_rdev = vap->va_rdev;
107: }
108: /*
109: * Remove inode so that it will be reloaded by iget and
110: * checked to see if it is an alias of an existing entry
111: * in the inode cache.
112: */
113: vp = ITOV(ip);
114: vput(vp);
115: vp->v_type = VNON;
116: vgone(vp);
117: return (0);
118: }
119:
120: /*
121: * Open called.
122: *
123: * Nothing to do.
124: */
125: /* ARGSUSED */
126: ufs_open(vp, mode, cred, p)
127: struct vnode *vp;
128: int mode;
129: struct ucred *cred;
130: struct proc *p;
131: {
132:
133: return (0);
134: }
135:
136: /*
137: * Close called
138: *
139: * Update the times on the inode.
140: */
141: /* ARGSUSED */
142: ufs_close(vp, fflag, cred, p)
143: struct vnode *vp;
144: int fflag;
145: struct ucred *cred;
146: struct proc *p;
147: {
148: register struct inode *ip = VTOI(vp);
149:
150: if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
151: ITIMES(ip, &time, &time);
152: return (0);
153: }
154:
155: /*
156: * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
157: * The mode is shifted to select the owner/group/other fields. The
158: * super user is granted all permissions.
159: */
160: ufs_access(vp, mode, cred, p)
161: struct vnode *vp;
162: register int mode;
163: struct ucred *cred;
164: struct proc *p;
165: {
166: register struct inode *ip = VTOI(vp);
167: register gid_t *gp;
168: int i, error;
169:
170: #ifdef DIAGNOSTIC
171: if (!VOP_ISLOCKED(vp)) {
172: vprint("ufs_access: not locked", vp);
173: panic("ufs_access: not locked");
174: }
175: #endif
176: #ifdef QUOTA
177: if (mode & VWRITE) {
178: switch (vp->v_type) {
179: case VREG: case VDIR: case VLNK:
180: if (error = getinoquota(ip))
181: return (error);
182: }
183: }
184: #endif /* QUOTA */
185: /*
186: * If you're the super-user, you always get access.
187: */
188: if (cred->cr_uid == 0)
189: return (0);
190: /*
191: * Access check is based on only one of owner, group, public.
192: * If not owner, then check group. If not a member of the
193: * group, then check public access.
194: */
195: if (cred->cr_uid != ip->i_uid) {
196: mode >>= 3;
197: gp = cred->cr_groups;
198: for (i = 0; i < cred->cr_ngroups; i++, gp++)
199: if (ip->i_gid == *gp)
200: goto found;
201: mode >>= 3;
202: found:
203: ;
204: }
1.1.1.2 ! root 205: if ((ip->i_mode & mode) == mode)
1.1 root 206: return (0);
207: return (EACCES);
208: }
209:
210: /* ARGSUSED */
211: ufs_getattr(vp, vap, cred, p)
212: struct vnode *vp;
213: register struct vattr *vap;
214: struct ucred *cred;
215: struct proc *p;
216: {
217: register struct inode *ip = VTOI(vp);
218:
219: ITIMES(ip, &time, &time);
220: /*
221: * Copy from inode table
222: */
223: vap->va_fsid = ip->i_dev;
224: vap->va_fileid = ip->i_number;
225: vap->va_mode = ip->i_mode & ~IFMT;
226: vap->va_nlink = ip->i_nlink;
227: vap->va_uid = ip->i_uid;
228: vap->va_gid = ip->i_gid;
229: vap->va_rdev = (dev_t)ip->i_rdev;
230: #ifdef tahoe
231: vap->va_size = ip->i_size;
232: vap->va_size_rsv = 0;
233: #else
234: vap->va_qsize = ip->i_din.di_qsize;
235: #endif
236: vap->va_atime.tv_sec = ip->i_atime;
237: vap->va_atime.tv_usec = 0;
238: vap->va_mtime.tv_sec = ip->i_mtime;
239: vap->va_mtime.tv_usec = 0;
240: vap->va_ctime.tv_sec = ip->i_ctime;
241: vap->va_ctime.tv_usec = 0;
242: vap->va_flags = ip->i_flags;
243: vap->va_gen = ip->i_gen;
244: /* this doesn't belong here */
245: if (vp->v_type == VBLK)
246: vap->va_blocksize = BLKDEV_IOSIZE;
247: else if (vp->v_type == VCHR)
248: vap->va_blocksize = MAXBSIZE;
249: else
250: vap->va_blocksize = ip->i_fs->fs_bsize;
251: vap->va_bytes = dbtob(ip->i_blocks);
252: vap->va_bytes_rsv = 0;
253: vap->va_type = vp->v_type;
254: return (0);
255: }
256:
257: /*
258: * Set attribute vnode op. called from several syscalls
259: */
260: ufs_setattr(vp, vap, cred, p)
261: register struct vnode *vp;
262: register struct vattr *vap;
263: register struct ucred *cred;
264: struct proc *p;
265: {
266: register struct inode *ip = VTOI(vp);
267: int error = 0;
268:
269: /*
270: * Check for unsetable attributes.
271: */
272: if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
273: (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
274: (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
275: ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
276: return (EINVAL);
277: }
278: /*
279: * Go through the fields and update iff not VNOVAL.
280: */
281: if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
282: if (error = chown1(vp, vap->va_uid, vap->va_gid, p))
283: return (error);
284: if (vap->va_size != VNOVAL) {
285: if (vp->v_type == VDIR)
286: return (EISDIR);
287: if (error = itrunc(ip, vap->va_size, 0)) /* XXX IO_SYNC? */
288: return (error);
289: }
290: if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
291: if (cred->cr_uid != ip->i_uid &&
292: (error = suser(cred, &p->p_acflag)))
293: return (error);
294: if (vap->va_atime.tv_sec != VNOVAL)
295: ip->i_flag |= IACC;
296: if (vap->va_mtime.tv_sec != VNOVAL)
297: ip->i_flag |= IUPD;
298: ip->i_flag |= ICHG;
299: if (error = iupdat(ip, &vap->va_atime, &vap->va_mtime, 1))
300: return (error);
301: }
302: if (vap->va_mode != (u_short)VNOVAL)
303: error = chmod1(vp, (int)vap->va_mode, p);
304: if (vap->va_flags != VNOVAL) {
305: if (cred->cr_uid != ip->i_uid &&
306: (error = suser(cred, &p->p_acflag)))
307: return (error);
308: if (cred->cr_uid == 0) {
309: ip->i_flags = vap->va_flags;
310: } else {
311: ip->i_flags &= 0xffff0000;
312: ip->i_flags |= (vap->va_flags & 0xffff);
313: }
314: ip->i_flag |= ICHG;
315: }
316: return (error);
317: }
318:
319: /*
320: * Change the mode on a file.
321: * Inode must be locked before calling.
322: */
323: chmod1(vp, mode, p)
324: register struct vnode *vp;
325: register int mode;
326: struct proc *p;
327: {
328: register struct ucred *cred = p->p_ucred;
329: register struct inode *ip = VTOI(vp);
330: int error;
331:
332: if (cred->cr_uid != ip->i_uid &&
333: (error = suser(cred, &p->p_acflag)))
334: return (error);
335: if (cred->cr_uid) {
336: if (vp->v_type != VDIR && (mode & ISVTX))
337: return (EFTYPE);
338: if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
339: return (EPERM);
340: }
341: ip->i_mode &= ~07777;
342: ip->i_mode |= mode & 07777;
343: ip->i_flag |= ICHG;
344: if ((vp->v_flag & VTEXT) && (ip->i_mode & ISVTX) == 0)
345: (void) vnode_pager_uncache(vp);
346: return (0);
347: }
348:
349: /*
350: * Perform chown operation on inode ip;
351: * inode must be locked prior to call.
352: */
353: chown1(vp, uid, gid, p)
354: register struct vnode *vp;
355: uid_t uid;
356: gid_t gid;
357: struct proc *p;
358: {
359: register struct inode *ip = VTOI(vp);
360: register struct ucred *cred = p->p_ucred;
361: uid_t ouid;
362: gid_t ogid;
363: int error = 0;
364: #ifdef QUOTA
365: register int i;
366: long change;
367: #endif
368:
369: if (uid == (u_short)VNOVAL)
370: uid = ip->i_uid;
371: if (gid == (u_short)VNOVAL)
372: gid = ip->i_gid;
373: /*
374: * If we don't own the file, are trying to change the owner
375: * of the file, or are not a member of the target group,
376: * the caller must be superuser or the call fails.
377: */
378: if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
379: !groupmember((gid_t)gid, cred)) &&
380: (error = suser(cred, &p->p_acflag)))
381: return (error);
382: ouid = ip->i_uid;
383: ogid = ip->i_gid;
384: #ifdef QUOTA
385: if (error = getinoquota(ip))
386: return (error);
387: if (ouid == uid) {
388: dqrele(vp, ip->i_dquot[USRQUOTA]);
389: ip->i_dquot[USRQUOTA] = NODQUOT;
390: }
391: if (ogid == gid) {
392: dqrele(vp, ip->i_dquot[GRPQUOTA]);
393: ip->i_dquot[GRPQUOTA] = NODQUOT;
394: }
395: change = ip->i_blocks;
396: (void) chkdq(ip, -change, cred, CHOWN);
397: (void) chkiq(ip, -1, cred, CHOWN);
398: for (i = 0; i < MAXQUOTAS; i++) {
399: dqrele(vp, ip->i_dquot[i]);
400: ip->i_dquot[i] = NODQUOT;
401: }
402: #endif
403: ip->i_uid = uid;
404: ip->i_gid = gid;
405: #ifdef QUOTA
406: if ((error = getinoquota(ip)) == 0) {
407: if (ouid == uid) {
408: dqrele(vp, ip->i_dquot[USRQUOTA]);
409: ip->i_dquot[USRQUOTA] = NODQUOT;
410: }
411: if (ogid == gid) {
412: dqrele(vp, ip->i_dquot[GRPQUOTA]);
413: ip->i_dquot[GRPQUOTA] = NODQUOT;
414: }
415: if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
416: if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
417: goto good;
418: else
419: (void) chkdq(ip, -change, cred, CHOWN|FORCE);
420: }
421: for (i = 0; i < MAXQUOTAS; i++) {
422: dqrele(vp, ip->i_dquot[i]);
423: ip->i_dquot[i] = NODQUOT;
424: }
425: }
426: ip->i_uid = ouid;
427: ip->i_gid = ogid;
428: if (getinoquota(ip) == 0) {
429: if (ouid == uid) {
430: dqrele(vp, ip->i_dquot[USRQUOTA]);
431: ip->i_dquot[USRQUOTA] = NODQUOT;
432: }
433: if (ogid == gid) {
434: dqrele(vp, ip->i_dquot[GRPQUOTA]);
435: ip->i_dquot[GRPQUOTA] = NODQUOT;
436: }
437: (void) chkdq(ip, change, cred, FORCE|CHOWN);
438: (void) chkiq(ip, 1, cred, FORCE|CHOWN);
439: (void) getinoquota(ip);
440: }
441: return (error);
442: good:
443: if (getinoquota(ip))
444: panic("chown: lost quota");
445: #endif /* QUOTA */
446: if (ouid != uid || ogid != gid)
447: ip->i_flag |= ICHG;
448: if (ouid != uid && cred->cr_uid != 0)
449: ip->i_mode &= ~ISUID;
450: if (ogid != gid && cred->cr_uid != 0)
451: ip->i_mode &= ~ISGID;
452: return (0);
453: }
454:
455: /*
456: * Vnode op for reading.
457: */
458: /* ARGSUSED */
459: ufs_read(vp, uio, ioflag, cred)
460: struct vnode *vp;
461: register struct uio *uio;
462: int ioflag;
463: struct ucred *cred;
464: {
465: register struct inode *ip = VTOI(vp);
466: register struct fs *fs;
467: struct buf *bp;
468: daddr_t lbn, bn, rablock;
469: int size, diff, error = 0;
470: long n, on, type;
471:
472: #ifdef DIAGNOSTIC
473: if (uio->uio_rw != UIO_READ)
474: panic("ufs_read mode");
475: type = ip->i_mode & IFMT;
476: if (type != IFDIR && type != IFREG && type != IFLNK)
477: panic("ufs_read type");
478: #endif
479: if (uio->uio_resid == 0)
480: return (0);
481: if (uio->uio_offset < 0)
482: return (EINVAL);
483: ip->i_flag |= IACC;
484: fs = ip->i_fs;
485: do {
486: lbn = lblkno(fs, uio->uio_offset);
487: on = blkoff(fs, uio->uio_offset);
488: n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
489: diff = ip->i_size - uio->uio_offset;
490: if (diff <= 0)
491: return (0);
492: if (diff < n)
493: n = diff;
494: size = blksize(fs, ip, lbn);
495: rablock = lbn + 1;
496: if (vp->v_lastr + 1 == lbn &&
497: lblktosize(fs, rablock) < ip->i_size)
498: error = breada(ITOV(ip), lbn, size, rablock,
499: blksize(fs, ip, rablock), NOCRED, &bp);
500: else
501: error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
502: vp->v_lastr = lbn;
503: n = MIN(n, size - bp->b_resid);
504: if (error) {
505: brelse(bp);
506: return (error);
507: }
508: error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
1.1.1.2 ! root 509: #if OMIT /* 20 Aug 92*/
1.1 root 510: if (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size)
511: bp->b_flags |= B_AGE;
1.1.1.2 ! root 512: #endif /* OMIT*/
1.1 root 513: brelse(bp);
514: } while (error == 0 && uio->uio_resid > 0 && n != 0);
515: return (error);
516: }
517:
518: /*
519: * Vnode op for writing.
520: */
521: ufs_write(vp, uio, ioflag, cred)
522: register struct vnode *vp;
523: struct uio *uio;
524: int ioflag;
525: struct ucred *cred;
526: {
527: struct proc *p = uio->uio_procp;
528: register struct inode *ip = VTOI(vp);
529: register struct fs *fs;
530: struct buf *bp;
531: daddr_t lbn, bn;
532: u_long osize;
533: int n, on, flags;
534: int size, resid, error = 0;
535:
536: #ifdef DIAGNOSTIC
537: if (uio->uio_rw != UIO_WRITE)
538: panic("ufs_write mode");
539: #endif
540: switch (vp->v_type) {
541: case VREG:
542: if (ioflag & IO_APPEND)
543: uio->uio_offset = ip->i_size;
544: /* fall through */
545: case VLNK:
546: break;
547:
548: case VDIR:
549: if ((ioflag & IO_SYNC) == 0)
550: panic("ufs_write nonsync dir write");
551: break;
552:
553: default:
554: panic("ufs_write type");
555: }
556: if (uio->uio_offset < 0)
557: return (EINVAL);
558: if (uio->uio_resid == 0)
559: return (0);
560: /*
561: * Maybe this should be above the vnode op call, but so long as
562: * file servers have no limits, i don't think it matters
563: */
564: if (vp->v_type == VREG && p &&
565: uio->uio_offset + uio->uio_resid >
566: p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
567: psignal(p, SIGXFSZ);
568: return (EFBIG);
569: }
570: resid = uio->uio_resid;
571: osize = ip->i_size;
572: fs = ip->i_fs;
573: flags = 0;
574: if (ioflag & IO_SYNC)
575: flags = B_SYNC;
576: do {
577: lbn = lblkno(fs, uio->uio_offset);
578: on = blkoff(fs, uio->uio_offset);
579: n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
580: if (n < fs->fs_bsize)
581: flags |= B_CLRBUF;
582: else
583: flags &= ~B_CLRBUF;
584: if (error = balloc(ip, lbn, (int)(on + n), &bp, flags))
585: break;
586: bn = bp->b_blkno;
587: if (uio->uio_offset + n > ip->i_size) {
588: ip->i_size = uio->uio_offset + n;
589: vnode_pager_setsize(vp, ip->i_size);
590: }
591: size = blksize(fs, ip, lbn);
592: (void) vnode_pager_uncache(vp);
593: n = MIN(n, size - bp->b_resid);
594: error = uiomove(bp->b_un.b_addr + on, n, uio);
595: if (ioflag & IO_SYNC)
596: (void) bwrite(bp);
597: else if (n + on == fs->fs_bsize) {
598: bp->b_flags |= B_AGE;
599: bawrite(bp);
600: } else
601: bdwrite(bp);
602: ip->i_flag |= IUPD|ICHG;
603: if (cred->cr_uid != 0)
604: ip->i_mode &= ~(ISUID|ISGID);
605: } while (error == 0 && uio->uio_resid > 0 && n != 0);
606: if (error && (ioflag & IO_UNIT)) {
607: (void) itrunc(ip, osize, ioflag & IO_SYNC);
608: uio->uio_offset -= resid - uio->uio_resid;
609: uio->uio_resid = resid;
610: }
611: if (!error && (ioflag & IO_SYNC))
612: error = iupdat(ip, &time, &time, 1);
613: return (error);
614: }
615:
616: /* ARGSUSED */
617: ufs_ioctl(vp, com, data, fflag, cred, p)
618: struct vnode *vp;
619: int com;
620: caddr_t data;
621: int fflag;
622: struct ucred *cred;
623: struct proc *p;
624: {
625:
626: return (ENOTTY);
627: }
628:
629: /* ARGSUSED */
630: ufs_select(vp, which, fflags, cred, p)
631: struct vnode *vp;
632: int which, fflags;
633: struct ucred *cred;
634: struct proc *p;
635: {
636:
637: /*
638: * We should really check to see if I/O is possible.
639: */
640: return (1);
641: }
642:
643: /*
644: * Mmap a file
645: *
646: * NB Currently unsupported.
647: */
648: /* ARGSUSED */
649: ufs_mmap(vp, fflags, cred, p)
650: struct vnode *vp;
651: int fflags;
652: struct ucred *cred;
653: struct proc *p;
654: {
655:
656: return (EINVAL);
657: }
658:
659: /*
660: * Synch an open file.
661: */
662: /* ARGSUSED */
663: ufs_fsync(vp, fflags, cred, waitfor, p)
664: struct vnode *vp;
665: int fflags;
666: struct ucred *cred;
667: int waitfor;
668: struct proc *p;
669: {
670: struct inode *ip = VTOI(vp);
671:
672: if (fflags & FWRITE)
673: ip->i_flag |= ICHG;
674: vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);
675: return (iupdat(ip, &time, &time, waitfor == MNT_WAIT));
676: }
677:
678: /*
679: * Seek on a file
680: *
681: * Nothing to do, so just return.
682: */
683: /* ARGSUSED */
684: ufs_seek(vp, oldoff, newoff, cred)
685: struct vnode *vp;
686: off_t oldoff, newoff;
687: struct ucred *cred;
688: {
689:
690: return (0);
691: }
692:
693: /*
694: * ufs remove
695: * Hard to avoid races here, especially
696: * in unlinking directories.
697: */
698: ufs_remove(ndp, p)
699: struct nameidata *ndp;
700: struct proc *p;
701: {
702: register struct inode *ip, *dp;
703: int error;
704:
705: ip = VTOI(ndp->ni_vp);
706: dp = VTOI(ndp->ni_dvp);
707: error = dirremove(ndp);
708: if (!error) {
709: ip->i_nlink--;
710: ip->i_flag |= ICHG;
711: }
712: if (dp == ip)
713: vrele(ITOV(ip));
714: else
715: iput(ip);
716: iput(dp);
717: return (error);
718: }
719:
720: /*
721: * link vnode call
722: */
723: ufs_link(vp, ndp, p)
724: register struct vnode *vp;
725: register struct nameidata *ndp;
726: struct proc *p;
727: {
728: register struct inode *ip = VTOI(vp);
729: int error;
730:
731: #ifdef DIANOSTIC
732: if ((ndp->ni_nameiop & HASBUF) == 0)
733: panic("ufs_link: no name");
734: #endif
735: if ((unsigned short)ip->i_nlink >= LINK_MAX) {
736: free(ndp->ni_pnbuf, M_NAMEI);
737: return (EMLINK);
738: }
739: if (ndp->ni_dvp != vp)
740: ILOCK(ip);
741: ip->i_nlink++;
742: ip->i_flag |= ICHG;
743: error = iupdat(ip, &time, &time, 1);
744: if (!error)
745: error = direnter(ip, ndp);
746: if (ndp->ni_dvp != vp)
747: IUNLOCK(ip);
748: FREE(ndp->ni_pnbuf, M_NAMEI);
749: vput(ndp->ni_dvp);
750: if (error) {
751: ip->i_nlink--;
752: ip->i_flag |= ICHG;
753: }
754: return (error);
755: }
756:
757: /*
758: * Rename system call.
759: * rename("foo", "bar");
760: * is essentially
761: * unlink("bar");
762: * link("foo", "bar");
763: * unlink("foo");
764: * but ``atomically''. Can't do full commit without saving state in the
765: * inode on disk which isn't feasible at this time. Best we can do is
766: * always guarantee the target exists.
767: *
768: * Basic algorithm is:
769: *
770: * 1) Bump link count on source while we're linking it to the
771: * target. This also ensure the inode won't be deleted out
772: * from underneath us while we work (it may be truncated by
773: * a concurrent `trunc' or `open' for creation).
774: * 2) Link source to destination. If destination already exists,
775: * delete it first.
776: * 3) Unlink source reference to inode if still around. If a
777: * directory was moved and the parent of the destination
778: * is different from the source, patch the ".." entry in the
779: * directory.
780: */
781: ufs_rename(fndp, tndp, p)
782: register struct nameidata *fndp, *tndp;
783: struct proc *p;
784: {
785: register struct inode *ip, *xp, *dp;
786: struct dirtemplate dirbuf;
787: int doingdirectory = 0, oldparent = 0, newparent = 0;
788: int error = 0;
789:
790: #ifdef DIANOSTIC
791: if ((tndp->ni_nameiop & HASBUF) == 0 ||
792: (fndp->ni_nameiop & HASBUF) == 0)
793: panic("ufs_rename: no name");
794: #endif
795: dp = VTOI(fndp->ni_dvp);
796: ip = VTOI(fndp->ni_vp);
797: /*
798: * Check if just deleting a link name.
799: */
800: if (fndp->ni_vp == tndp->ni_vp) {
801: VOP_ABORTOP(tndp);
802: vput(tndp->ni_dvp);
803: vput(tndp->ni_vp);
804: vrele(fndp->ni_dvp);
805: if ((ip->i_mode&IFMT) == IFDIR) {
806: VOP_ABORTOP(fndp);
807: vrele(fndp->ni_vp);
808: return (EINVAL);
809: }
810: doingdirectory = 0;
811: goto unlinkit;
812: }
813: ILOCK(ip);
814: if ((ip->i_mode&IFMT) == IFDIR) {
815: /*
816: * Avoid ".", "..", and aliases of "." for obvious reasons.
817: */
818: if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
819: dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
820: VOP_ABORTOP(tndp);
821: vput(tndp->ni_dvp);
822: if (tndp->ni_vp)
823: vput(tndp->ni_vp);
824: VOP_ABORTOP(fndp);
825: vrele(fndp->ni_dvp);
826: vput(fndp->ni_vp);
827: return (EINVAL);
828: }
829: ip->i_flag |= IRENAME;
830: oldparent = dp->i_number;
831: doingdirectory++;
832: }
833: vrele(fndp->ni_dvp);
834:
835: /*
836: * 1) Bump link count while we're moving stuff
837: * around. If we crash somewhere before
838: * completing our work, the link count
839: * may be wrong, but correctable.
840: */
841: ip->i_nlink++;
842: ip->i_flag |= ICHG;
843: error = iupdat(ip, &time, &time, 1);
844: IUNLOCK(ip);
845:
846: /*
847: * When the target exists, both the directory
848: * and target vnodes are returned locked.
849: */
850: dp = VTOI(tndp->ni_dvp);
851: xp = NULL;
852: if (tndp->ni_vp)
853: xp = VTOI(tndp->ni_vp);
854: /*
855: * If ".." must be changed (ie the directory gets a new
856: * parent) then the source directory must not be in the
857: * directory heirarchy above the target, as this would
858: * orphan everything below the source directory. Also
859: * the user must have write permission in the source so
860: * as to be able to change "..". We must repeat the call
861: * to namei, as the parent directory is unlocked by the
862: * call to checkpath().
863: */
864: if (oldparent != dp->i_number)
865: newparent = dp->i_number;
866: if (doingdirectory && newparent) {
867: VOP_LOCK(fndp->ni_vp);
868: error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred, p);
869: VOP_UNLOCK(fndp->ni_vp);
870: if (error)
871: goto bad;
872: if (xp != NULL)
873: iput(xp);
874: if (error = checkpath(ip, dp, tndp->ni_cred))
875: goto out;
876: if ((tndp->ni_nameiop & SAVESTART) == 0)
877: panic("ufs_rename: lost to startdir");
878: if (error = lookup(tndp, p))
879: goto out;
880: dp = VTOI(tndp->ni_dvp);
881: xp = NULL;
882: if (tndp->ni_vp)
883: xp = VTOI(tndp->ni_vp);
884: }
885: /*
886: * 2) If target doesn't exist, link the target
887: * to the source and unlink the source.
888: * Otherwise, rewrite the target directory
889: * entry to reference the source inode and
890: * expunge the original entry's existence.
891: */
892: if (xp == NULL) {
893: if (dp->i_dev != ip->i_dev)
894: panic("rename: EXDEV");
895: /*
896: * Account for ".." in new directory.
897: * When source and destination have the same
898: * parent we don't fool with the link count.
899: */
900: if (doingdirectory && newparent) {
901: if ((unsigned short)dp->i_nlink >= LINK_MAX) {
902: error = EMLINK;
903: goto bad;
904: }
905: dp->i_nlink++;
906: dp->i_flag |= ICHG;
907: if (error = iupdat(dp, &time, &time, 1))
908: goto bad;
909: }
910: if (error = direnter(ip, tndp)) {
911: if (doingdirectory && newparent) {
912: dp->i_nlink--;
913: dp->i_flag |= ICHG;
914: (void) iupdat(dp, &time, &time, 1);
915: }
916: goto bad;
917: }
918: iput(dp);
919: } else {
920: if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
921: panic("rename: EXDEV");
922: /*
923: * Short circuit rename(foo, foo).
924: */
925: if (xp->i_number == ip->i_number)
926: panic("rename: same file");
927: /*
928: * If the parent directory is "sticky", then the user must
929: * own the parent directory, or the destination of the rename,
930: * otherwise the destination may not be changed (except by
931: * root). This implements append-only directories.
932: */
933: if ((dp->i_mode & ISVTX) && tndp->ni_cred->cr_uid != 0 &&
934: tndp->ni_cred->cr_uid != dp->i_uid &&
935: xp->i_uid != tndp->ni_cred->cr_uid) {
936: error = EPERM;
937: goto bad;
938: }
939: /*
940: * Target must be empty if a directory and have no links
941: * to it. Also, ensure source and target are compatible
942: * (both directories, or both not directories).
943: */
944: if ((xp->i_mode&IFMT) == IFDIR) {
945: if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
946: xp->i_nlink > 2) {
947: error = ENOTEMPTY;
948: goto bad;
949: }
950: if (!doingdirectory) {
951: error = ENOTDIR;
952: goto bad;
953: }
954: cache_purge(ITOV(dp));
955: } else if (doingdirectory) {
956: error = EISDIR;
957: goto bad;
958: }
959: if (error = dirrewrite(dp, ip, tndp))
960: goto bad;
961: /*
962: * If the target directory is in the same
963: * directory as the source directory,
964: * decrement the link count on the parent
965: * of the target directory.
966: */
967: if (doingdirectory && !newparent) {
968: dp->i_nlink--;
969: dp->i_flag |= ICHG;
970: }
971: vput(ITOV(dp));
972: /*
973: * Adjust the link count of the target to
974: * reflect the dirrewrite above. If this is
975: * a directory it is empty and there are
976: * no links to it, so we can squash the inode and
977: * any space associated with it. We disallowed
978: * renaming over top of a directory with links to
979: * it above, as the remaining link would point to
980: * a directory without "." or ".." entries.
981: */
982: xp->i_nlink--;
983: if (doingdirectory) {
984: if (--xp->i_nlink != 0)
985: panic("rename: linked directory");
986: error = itrunc(xp, (u_long)0, IO_SYNC);
987: }
988: xp->i_flag |= ICHG;
989: iput(xp);
990: xp = NULL;
991: }
992:
993: /*
994: * 3) Unlink the source.
995: */
996: unlinkit:
997: fndp->ni_nameiop &= ~MODMASK;
998: fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
999: if ((fndp->ni_nameiop & SAVESTART) == 0)
1000: panic("ufs_rename: lost from startdir");
1001: (void) lookup(fndp, p);
1002: if (fndp->ni_vp != NULL) {
1003: xp = VTOI(fndp->ni_vp);
1004: dp = VTOI(fndp->ni_dvp);
1005: } else {
1006: /*
1007: * From name has disappeared.
1008: */
1009: if (doingdirectory)
1010: panic("rename: lost dir entry");
1011: vrele(ITOV(ip));
1012: return (0);
1013: }
1014: /*
1015: * Ensure that the directory entry still exists and has not
1016: * changed while the new name has been entered. If the source is
1017: * a file then the entry may have been unlinked or renamed. In
1018: * either case there is no further work to be done. If the source
1019: * is a directory then it cannot have been rmdir'ed; its link
1020: * count of three would cause a rmdir to fail with ENOTEMPTY.
1021: * The IRENAME flag ensures that it cannot be moved by another
1022: * rename.
1023: */
1024: if (xp != ip) {
1025: if (doingdirectory)
1026: panic("rename: lost dir entry");
1027: } else {
1028: /*
1029: * If the source is a directory with a
1030: * new parent, the link count of the old
1031: * parent directory must be decremented
1032: * and ".." set to point to the new parent.
1033: */
1034: if (doingdirectory && newparent) {
1035: dp->i_nlink--;
1036: dp->i_flag |= ICHG;
1037: error = vn_rdwr(UIO_READ, ITOV(xp), (caddr_t)&dirbuf,
1038: sizeof (struct dirtemplate), (off_t)0,
1039: UIO_SYSSPACE, IO_NODELOCKED,
1040: tndp->ni_cred, (int *)0, (struct proc *)0);
1041: if (error == 0) {
1042: if (dirbuf.dotdot_namlen != 2 ||
1043: dirbuf.dotdot_name[0] != '.' ||
1044: dirbuf.dotdot_name[1] != '.') {
1045: dirbad(xp, 12, "rename: mangled dir");
1046: } else {
1047: dirbuf.dotdot_ino = newparent;
1048: (void) vn_rdwr(UIO_WRITE, ITOV(xp),
1049: (caddr_t)&dirbuf,
1050: sizeof (struct dirtemplate),
1051: (off_t)0, UIO_SYSSPACE,
1052: IO_NODELOCKED|IO_SYNC,
1053: tndp->ni_cred, (int *)0,
1054: (struct proc *)0);
1055: cache_purge(ITOV(dp));
1056: }
1057: }
1058: }
1059: error = dirremove(fndp);
1060: if (!error) {
1061: xp->i_nlink--;
1062: xp->i_flag |= ICHG;
1063: }
1064: xp->i_flag &= ~IRENAME;
1065: }
1066: if (dp)
1067: vput(ITOV(dp));
1068: if (xp)
1069: vput(ITOV(xp));
1070: vrele(ITOV(ip));
1071: return (error);
1072:
1073: bad:
1074: if (xp)
1075: vput(ITOV(xp));
1076: vput(ITOV(dp));
1077: out:
1078: ip->i_nlink--;
1079: ip->i_flag |= ICHG;
1080: vrele(ITOV(ip));
1081: return (error);
1082: }
1083:
1084: /*
1085: * A virgin directory (no blushing please).
1086: */
1087: struct dirtemplate mastertemplate = {
1088: 0, 12, 1, ".",
1089: 0, DIRBLKSIZ - 12, 2, ".."
1090: };
1091:
1092: /*
1093: * Mkdir system call
1094: */
1095: ufs_mkdir(ndp, vap, p)
1096: struct nameidata *ndp;
1097: struct vattr *vap;
1098: struct proc *p;
1099: {
1100: register struct inode *ip, *dp;
1101: struct inode *tip;
1102: struct vnode *dvp;
1103: struct dirtemplate dirtemplate;
1104: int error;
1105: int dmode;
1106:
1107: #ifdef DIANOSTIC
1108: if ((ndp->ni_nameiop & HASBUF) == 0)
1109: panic("ufs_mkdir: no name");
1110: #endif
1111: dvp = ndp->ni_dvp;
1112: dp = VTOI(dvp);
1113: if ((unsigned short)dp->i_nlink >= LINK_MAX) {
1114: free(ndp->ni_pnbuf, M_NAMEI);
1115: iput(dp);
1116: return (EMLINK);
1117: }
1118: dmode = vap->va_mode&0777;
1119: dmode |= IFDIR;
1120: /*
1121: * Must simulate part of maknode here to acquire the inode, but
1122: * not have it entered in the parent directory. The entry is made
1123: * later after writing "." and ".." entries.
1124: */
1125: if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
1126: free(ndp->ni_pnbuf, M_NAMEI);
1127: iput(dp);
1128: return (error);
1129: }
1130: ip = tip;
1131: ip->i_uid = ndp->ni_cred->cr_uid;
1132: ip->i_gid = dp->i_gid;
1133: #ifdef QUOTA
1134: if ((error = getinoquota(ip)) ||
1135: (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
1136: free(ndp->ni_pnbuf, M_NAMEI);
1137: ifree(ip, ip->i_number, dmode);
1138: iput(ip);
1139: iput(dp);
1140: return (error);
1141: }
1142: #endif
1143: ip->i_flag |= IACC|IUPD|ICHG;
1144: ip->i_mode = dmode;
1145: ITOV(ip)->v_type = VDIR; /* Rest init'd in iget() */
1146: ip->i_nlink = 2;
1147: error = iupdat(ip, &time, &time, 1);
1148:
1149: /*
1150: * Bump link count in parent directory
1151: * to reflect work done below. Should
1152: * be done before reference is created
1153: * so reparation is possible if we crash.
1154: */
1155: dp->i_nlink++;
1156: dp->i_flag |= ICHG;
1157: if (error = iupdat(dp, &time, &time, 1))
1158: goto bad;
1159:
1160: /*
1161: * Initialize directory with "."
1162: * and ".." from static template.
1163: */
1164: dirtemplate = mastertemplate;
1165: dirtemplate.dot_ino = ip->i_number;
1166: dirtemplate.dotdot_ino = dp->i_number;
1167: error = vn_rdwr(UIO_WRITE, ITOV(ip), (caddr_t)&dirtemplate,
1168: sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
1169: IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0, (struct proc *)0);
1170: if (error) {
1171: dp->i_nlink--;
1172: dp->i_flag |= ICHG;
1173: goto bad;
1174: }
1175: if (DIRBLKSIZ > dp->i_fs->fs_fsize) {
1176: panic("mkdir: blksize"); /* XXX - should grow w/balloc() */
1177: } else {
1178: ip->i_size = DIRBLKSIZ;
1179: ip->i_flag |= ICHG;
1180: }
1181: /*
1182: * Directory all set up, now
1183: * install the entry for it in
1184: * the parent directory.
1185: */
1186: if (error = direnter(ip, ndp)) {
1187: dp->i_nlink--;
1188: dp->i_flag |= ICHG;
1189: }
1190: bad:
1191: /*
1192: * No need to do an explicit itrunc here,
1193: * vrele will do this for us because we set
1194: * the link count to 0.
1195: */
1196: if (error) {
1197: ip->i_nlink = 0;
1198: ip->i_flag |= ICHG;
1199: iput(ip);
1200: } else
1201: ndp->ni_vp = ITOV(ip);
1202: FREE(ndp->ni_pnbuf, M_NAMEI);
1203: iput(dp);
1204: return (error);
1205: }
1206:
1207: /*
1208: * Rmdir system call.
1209: */
1210: ufs_rmdir(ndp, p)
1211: register struct nameidata *ndp;
1212: struct proc *p;
1213: {
1214: register struct inode *ip, *dp;
1215: int error = 0;
1216:
1217: ip = VTOI(ndp->ni_vp);
1218: dp = VTOI(ndp->ni_dvp);
1219: /*
1220: * No rmdir "." please.
1221: */
1222: if (dp == ip) {
1223: vrele(ITOV(dp));
1224: iput(ip);
1225: return (EINVAL);
1226: }
1227: /*
1228: * Verify the directory is empty (and valid).
1229: * (Rmdir ".." won't be valid since
1230: * ".." will contain a reference to
1231: * the current directory and thus be
1232: * non-empty.)
1233: */
1234: if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number, ndp->ni_cred)) {
1235: error = ENOTEMPTY;
1236: goto out;
1237: }
1238: /*
1239: * Delete reference to directory before purging
1240: * inode. If we crash in between, the directory
1241: * will be reattached to lost+found,
1242: */
1243: if (error = dirremove(ndp))
1244: goto out;
1245: dp->i_nlink--;
1246: dp->i_flag |= ICHG;
1247: cache_purge(ITOV(dp));
1248: iput(dp);
1249: ndp->ni_dvp = NULL;
1250: /*
1251: * Truncate inode. The only stuff left
1252: * in the directory is "." and "..". The
1253: * "." reference is inconsequential since
1254: * we're quashing it. The ".." reference
1255: * has already been adjusted above. We've
1256: * removed the "." reference and the reference
1257: * in the parent directory, but there may be
1258: * other hard links so decrement by 2 and
1259: * worry about them later.
1260: */
1261: ip->i_nlink -= 2;
1262: error = itrunc(ip, (u_long)0, IO_SYNC);
1263: cache_purge(ITOV(ip));
1264: out:
1265: if (ndp->ni_dvp)
1266: iput(dp);
1267: iput(ip);
1268: return (error);
1269: }
1270:
1271: /*
1272: * symlink -- make a symbolic link
1273: */
1274: ufs_symlink(ndp, vap, target, p)
1275: struct nameidata *ndp;
1276: struct vattr *vap;
1277: char *target;
1278: struct proc *p;
1279: {
1280: struct inode *ip;
1281: int error;
1282:
1283: error = maknode(IFLNK | vap->va_mode, ndp, &ip);
1284: if (error)
1285: return (error);
1286: error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0,
1287: UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0,
1288: (struct proc *)0);
1289: iput(ip);
1290: return (error);
1291: }
1292:
1293: /*
1294: * Vnode op for read and write
1295: */
1296: ufs_readdir(vp, uio, cred, eofflagp)
1297: struct vnode *vp;
1298: register struct uio *uio;
1299: struct ucred *cred;
1300: int *eofflagp;
1301: {
1302: int count, lost, error;
1303:
1304: count = uio->uio_resid;
1305: count &= ~(DIRBLKSIZ - 1);
1306: lost = uio->uio_resid - count;
1307: if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
1308: return (EINVAL);
1309: uio->uio_resid = count;
1310: uio->uio_iov->iov_len = count;
1311: error = ufs_read(vp, uio, 0, cred);
1312: uio->uio_resid += lost;
1313: if ((VTOI(vp)->i_size - uio->uio_offset) <= 0)
1314: *eofflagp = 1;
1315: else
1316: *eofflagp = 0;
1317: return (error);
1318: }
1319:
1320: /*
1321: * Return target name of a symbolic link
1322: */
1323: ufs_readlink(vp, uiop, cred)
1324: struct vnode *vp;
1325: struct uio *uiop;
1326: struct ucred *cred;
1327: {
1328:
1329: return (ufs_read(vp, uiop, 0, cred));
1330: }
1331:
1332: /*
1333: * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
1334: * done. If a buffer has been saved in anticipation of a CREATE, delete it.
1335: */
1336: /* ARGSUSED */
1337: ufs_abortop(ndp)
1338: struct nameidata *ndp;
1339: {
1340:
1341: if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
1342: FREE(ndp->ni_pnbuf, M_NAMEI);
1343: return (0);
1344: }
1345:
1346: /*
1347: * Lock an inode.
1348: */
1349: ufs_lock(vp)
1350: struct vnode *vp;
1351: {
1352: register struct inode *ip = VTOI(vp);
1353:
1354: ILOCK(ip);
1355: return (0);
1356: }
1357:
1358: /*
1359: * Unlock an inode.
1360: */
1361: ufs_unlock(vp)
1362: struct vnode *vp;
1363: {
1364: register struct inode *ip = VTOI(vp);
1365:
1366: if (!(ip->i_flag & ILOCKED))
1367: panic("ufs_unlock NOT LOCKED");
1368: IUNLOCK(ip);
1369: return (0);
1370: }
1371:
1372: /*
1373: * Check for a locked inode.
1374: */
1375: ufs_islocked(vp)
1376: struct vnode *vp;
1377: {
1378:
1379: if (VTOI(vp)->i_flag & ILOCKED)
1380: return (1);
1381: return (0);
1382: }
1383:
1384: /*
1385: * Get access to bmap
1386: */
1387: ufs_bmap(vp, bn, vpp, bnp)
1388: struct vnode *vp;
1389: daddr_t bn;
1390: struct vnode **vpp;
1391: daddr_t *bnp;
1392: {
1393: struct inode *ip = VTOI(vp);
1394:
1395: if (vpp != NULL)
1396: *vpp = ip->i_devvp;
1397: if (bnp == NULL)
1398: return (0);
1399: return (bmap(ip, bn, bnp));
1400: }
1401:
1402: /*
1403: * Calculate the logical to physical mapping if not done already,
1404: * then call the device strategy routine.
1405: */
1406: int checkoverlap = 0;
1407:
1408: ufs_strategy(bp)
1409: register struct buf *bp;
1410: {
1411: register struct inode *ip = VTOI(bp->b_vp);
1412: struct vnode *vp;
1413: int error;
1414:
1415: if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
1416: panic("ufs_strategy: spec");
1417: if (bp->b_blkno == bp->b_lblkno) {
1418: if (error = bmap(ip, bp->b_lblkno, &bp->b_blkno))
1419: return (error);
1420: if ((long)bp->b_blkno == -1)
1421: clrbuf(bp);
1422: }
1423: if ((long)bp->b_blkno == -1) {
1424: biodone(bp);
1425: return (0);
1426: }
1427: #ifdef DIAGNOSTIC
1428: if (checkoverlap) {
1429: register struct buf *ep;
1430: struct buf *ebp;
1431: daddr_t start, last;
1432:
1433: ebp = &buf[nbuf];
1434: start = bp->b_blkno;
1435: last = start + btodb(bp->b_bcount) - 1;
1436: for (ep = buf; ep < ebp; ep++) {
1437: if (ep == bp || (ep->b_flags & B_INVAL) ||
1438: ep->b_vp == NULLVP)
1439: continue;
1440: if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0))
1441: continue;
1442: if (vp != ip->i_devvp)
1443: continue;
1444: /* look for overlap */
1445: if (ep->b_bcount == 0 || ep->b_blkno > last ||
1446: ep->b_blkno + btodb(ep->b_bcount) <= start)
1447: continue;
1448: vprint("Disk overlap", vp);
1449: printf("\tstart %d, end %d overlap start %d, end %d\n",
1450: start, last, ep->b_blkno,
1451: ep->b_blkno + btodb(ep->b_bcount) - 1);
1452: panic("Disk buffer overlap");
1453: }
1454: }
1455: #endif /* DIAGNOSTIC */
1456: vp = ip->i_devvp;
1457: bp->b_dev = vp->v_rdev;
1458: (*(vp->v_op->vop_strategy))(bp);
1459: return (0);
1460: }
1461:
1462: /*
1463: * Print out the contents of an inode.
1464: */
1465: ufs_print(vp)
1466: struct vnode *vp;
1467: {
1468: register struct inode *ip = VTOI(vp);
1469:
1470: printf("tag VT_UFS, ino %d, on dev %d, %d", ip->i_number,
1471: major(ip->i_dev), minor(ip->i_dev));
1472: #ifdef FIFO
1473: if (vp->v_type == VFIFO)
1474: fifo_printinfo(vp);
1475: #endif /* FIFO */
1476: printf("%s\n", (ip->i_flag & ILOCKED) ? " (LOCKED)" : "");
1477: if (ip->i_spare0 == 0)
1478: return;
1479: printf("\towner pid %d", ip->i_spare0);
1480: if (ip->i_spare1)
1481: printf(" waiting pid %d", ip->i_spare1);
1482: printf("\n");
1483: }
1484:
1485: /*
1486: * Read wrapper for special devices.
1487: */
1488: ufsspec_read(vp, uio, ioflag, cred)
1489: struct vnode *vp;
1490: struct uio *uio;
1491: int ioflag;
1492: struct ucred *cred;
1493: {
1494:
1495: /*
1496: * Set access flag.
1497: */
1498: VTOI(vp)->i_flag |= IACC;
1499: return (spec_read(vp, uio, ioflag, cred));
1500: }
1501:
1502: /*
1503: * Write wrapper for special devices.
1504: */
1505: ufsspec_write(vp, uio, ioflag, cred)
1506: struct vnode *vp;
1507: struct uio *uio;
1508: int ioflag;
1509: struct ucred *cred;
1510: {
1511:
1512: /*
1513: * Set update and change flags.
1514: */
1515: VTOI(vp)->i_flag |= IUPD|ICHG;
1516: return (spec_write(vp, uio, ioflag, cred));
1517: }
1518:
1519: /*
1520: * Close wrapper for special devices.
1521: *
1522: * Update the times on the inode then do device close.
1523: */
1524: ufsspec_close(vp, fflag, cred, p)
1525: struct vnode *vp;
1526: int fflag;
1527: struct ucred *cred;
1528: struct proc *p;
1529: {
1530: register struct inode *ip = VTOI(vp);
1531:
1532: if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
1533: ITIMES(ip, &time, &time);
1534: return (spec_close(vp, fflag, cred, p));
1535: }
1536:
1537: #ifdef FIFO
1538: /*
1539: * Read wrapper for fifo's
1540: */
1541: ufsfifo_read(vp, uio, ioflag, cred)
1542: struct vnode *vp;
1543: struct uio *uio;
1544: int ioflag;
1545: struct ucred *cred;
1546: {
1547:
1548: /*
1549: * Set access flag.
1550: */
1551: VTOI(vp)->i_flag |= IACC;
1552: return (fifo_read(vp, uio, ioflag, cred));
1553: }
1554:
1555: /*
1556: * Write wrapper for fifo's.
1557: */
1558: ufsfifo_write(vp, uio, ioflag, cred)
1559: struct vnode *vp;
1560: struct uio *uio;
1561: int ioflag;
1562: struct ucred *cred;
1563: {
1564:
1565: /*
1566: * Set update and change flags.
1567: */
1568: VTOI(vp)->i_flag |= IUPD|ICHG;
1569: return (fifo_write(vp, uio, ioflag, cred));
1570: }
1571:
1572: /*
1573: * Close wrapper for fifo's.
1574: *
1575: * Update the times on the inode then do device close.
1576: */
1577: ufsfifo_close(vp, fflag, cred, p)
1578: struct vnode *vp;
1579: int fflag;
1580: struct ucred *cred;
1581: struct proc *p;
1582: {
1583: register struct inode *ip = VTOI(vp);
1584:
1585: if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
1586: ITIMES(ip, &time, &time);
1587: return (fifo_close(vp, fflag, cred, p));
1588: }
1589: #endif /* FIFO */
1590:
1591: /*
1592: * Allocate a new inode.
1593: */
1594: maknode(mode, ndp, ipp)
1595: int mode;
1596: register struct nameidata *ndp;
1597: struct inode **ipp;
1598: {
1599: register struct inode *ip;
1600: struct inode *tip;
1601: register struct inode *pdir = VTOI(ndp->ni_dvp);
1602: ino_t ipref;
1603: int error;
1604:
1605: #ifdef DIANOSTIC
1606: if ((ndp->ni_nameiop & HASBUF) == 0)
1607: panic("maknode: no name");
1608: #endif
1609: *ipp = 0;
1610: if ((mode & IFMT) == 0)
1611: mode |= IFREG;
1612: if ((mode & IFMT) == IFDIR)
1613: ipref = dirpref(pdir->i_fs);
1614: else
1615: ipref = pdir->i_number;
1616: if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
1617: free(ndp->ni_pnbuf, M_NAMEI);
1618: iput(pdir);
1619: return (error);
1620: }
1621: ip = tip;
1622: ip->i_uid = ndp->ni_cred->cr_uid;
1623: ip->i_gid = pdir->i_gid;
1624: #ifdef QUOTA
1625: if ((error = getinoquota(ip)) ||
1626: (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
1627: free(ndp->ni_pnbuf, M_NAMEI);
1628: ifree(ip, ip->i_number, mode);
1629: iput(ip);
1630: iput(pdir);
1631: return (error);
1632: }
1633: #endif
1634: ip->i_flag |= IACC|IUPD|ICHG;
1635: ip->i_mode = mode;
1636: ITOV(ip)->v_type = IFTOVT(mode); /* Rest init'd in iget() */
1637: ip->i_nlink = 1;
1638: if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
1639: suser(ndp->ni_cred, NULL))
1640: ip->i_mode &= ~ISGID;
1641:
1642: /*
1643: * Make sure inode goes to disk before directory entry.
1644: */
1645: if (error = iupdat(ip, &time, &time, 1))
1646: goto bad;
1647: if (error = direnter(ip, ndp))
1648: goto bad;
1649: if ((ndp->ni_nameiop & SAVESTART) == 0)
1650: FREE(ndp->ni_pnbuf, M_NAMEI);
1651: iput(pdir);
1652: *ipp = ip;
1653: return (0);
1654:
1655: bad:
1656: /*
1657: * Write error occurred trying to update the inode
1658: * or the directory so must deallocate the inode.
1659: */
1660: free(ndp->ni_pnbuf, M_NAMEI);
1661: iput(pdir);
1662: ip->i_nlink = 0;
1663: ip->i_flag |= ICHG;
1664: iput(ip);
1665: return (error);
1666: }
1667:
1668: /*
1669: * Advisory record locking support
1670: */
1671: ufs_advlock(vp, id, op, fl, flags)
1672: struct vnode *vp;
1673: caddr_t id;
1674: int op;
1675: register struct flock *fl;
1676: int flags;
1677: {
1678: register struct inode *ip = VTOI(vp);
1679: register struct lockf *lock;
1680: off_t start, end;
1681: int error;
1682:
1683: /*
1684: * Avoid the common case of unlocking when inode has no locks.
1685: */
1686: if (ip->i_lockf == (struct lockf *)0) {
1687: if (op != F_SETLK) {
1688: fl->l_type = F_UNLCK;
1689: return (0);
1690: }
1691: }
1692: /*
1693: * Convert the flock structure into a start and end.
1694: */
1695: switch (fl->l_whence) {
1696:
1697: case SEEK_SET:
1698: case SEEK_CUR:
1699: /*
1700: * Caller is responsible for adding any necessary offset
1701: * when SEEK_CUR is used.
1702: */
1703: start = fl->l_start;
1704: break;
1705:
1706: case SEEK_END:
1707: start = ip->i_size + fl->l_start;
1708: break;
1709:
1710: default:
1711: return (EINVAL);
1712: }
1713: if (start < 0)
1714: return (EINVAL);
1715: if (fl->l_len == 0)
1716: end = -1;
1717: else
1718: end = start + fl->l_len - 1;
1719: /*
1720: * Create the lockf structure
1721: */
1722: MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK);
1723: lock->lf_start = start;
1724: lock->lf_end = end;
1725: lock->lf_id = id;
1726: lock->lf_inode = ip;
1727: lock->lf_type = fl->l_type;
1728: lock->lf_next = (struct lockf *)0;
1729: lock->lf_block = (struct lockf *)0;
1730: lock->lf_flags = flags;
1731: /*
1732: * Do the requested operation.
1733: */
1734: switch(op) {
1735: case F_SETLK:
1736: return (lf_setlock(lock));
1737:
1738: case F_UNLCK:
1739: error = lf_clearlock(lock);
1740: FREE(lock, M_LOCKF);
1741: return (error);
1742:
1743: case F_GETLK:
1744: error = lf_getlock(lock, fl);
1745: FREE(lock, M_LOCKF);
1746: return (error);
1747:
1748: default:
1749: free(lock, M_LOCKF);
1750: return (EINVAL);
1751: }
1752: /* NOTREACHED */
1753: }
1754:
1755: /*
1756: * Global vfs data structures for ufs
1757: */
1758: struct vnodeops ufs_vnodeops = {
1759: ufs_lookup, /* lookup */
1760: ufs_create, /* create */
1761: ufs_mknod, /* mknod */
1762: ufs_open, /* open */
1763: ufs_close, /* close */
1764: ufs_access, /* access */
1765: ufs_getattr, /* getattr */
1766: ufs_setattr, /* setattr */
1767: ufs_read, /* read */
1768: ufs_write, /* write */
1769: ufs_ioctl, /* ioctl */
1770: ufs_select, /* select */
1771: ufs_mmap, /* mmap */
1772: ufs_fsync, /* fsync */
1773: ufs_seek, /* seek */
1774: ufs_remove, /* remove */
1775: ufs_link, /* link */
1776: ufs_rename, /* rename */
1777: ufs_mkdir, /* mkdir */
1778: ufs_rmdir, /* rmdir */
1779: ufs_symlink, /* symlink */
1780: ufs_readdir, /* readdir */
1781: ufs_readlink, /* readlink */
1782: ufs_abortop, /* abortop */
1783: ufs_inactive, /* inactive */
1784: ufs_reclaim, /* reclaim */
1785: ufs_lock, /* lock */
1786: ufs_unlock, /* unlock */
1787: ufs_bmap, /* bmap */
1788: ufs_strategy, /* strategy */
1789: ufs_print, /* print */
1790: ufs_islocked, /* islocked */
1791: ufs_advlock, /* advlock */
1792: };
1793:
1794: struct vnodeops spec_inodeops = {
1795: spec_lookup, /* lookup */
1796: spec_create, /* create */
1797: spec_mknod, /* mknod */
1798: spec_open, /* open */
1799: ufsspec_close, /* close */
1800: ufs_access, /* access */
1801: ufs_getattr, /* getattr */
1802: ufs_setattr, /* setattr */
1803: ufsspec_read, /* read */
1804: ufsspec_write, /* write */
1805: spec_ioctl, /* ioctl */
1806: spec_select, /* select */
1807: spec_mmap, /* mmap */
1808: spec_fsync, /* fsync */
1809: spec_seek, /* seek */
1810: spec_remove, /* remove */
1811: spec_link, /* link */
1812: spec_rename, /* rename */
1813: spec_mkdir, /* mkdir */
1814: spec_rmdir, /* rmdir */
1815: spec_symlink, /* symlink */
1816: spec_readdir, /* readdir */
1817: spec_readlink, /* readlink */
1818: spec_abortop, /* abortop */
1819: ufs_inactive, /* inactive */
1820: ufs_reclaim, /* reclaim */
1821: ufs_lock, /* lock */
1822: ufs_unlock, /* unlock */
1823: spec_bmap, /* bmap */
1824: spec_strategy, /* strategy */
1825: ufs_print, /* print */
1826: ufs_islocked, /* islocked */
1827: spec_advlock, /* advlock */
1828: };
1829:
1830: #ifdef FIFO
1831: struct vnodeops fifo_inodeops = {
1832: fifo_lookup, /* lookup */
1833: fifo_create, /* create */
1834: fifo_mknod, /* mknod */
1835: fifo_open, /* open */
1836: ufsfifo_close, /* close */
1837: ufs_access, /* access */
1838: ufs_getattr, /* getattr */
1839: ufs_setattr, /* setattr */
1840: ufsfifo_read, /* read */
1841: ufsfifo_write, /* write */
1842: fifo_ioctl, /* ioctl */
1843: fifo_select, /* select */
1844: fifo_mmap, /* mmap */
1845: fifo_fsync, /* fsync */
1846: fifo_seek, /* seek */
1847: fifo_remove, /* remove */
1848: fifo_link, /* link */
1849: fifo_rename, /* rename */
1850: fifo_mkdir, /* mkdir */
1851: fifo_rmdir, /* rmdir */
1852: fifo_symlink, /* symlink */
1853: fifo_readdir, /* readdir */
1854: fifo_readlink, /* readlink */
1855: fifo_abortop, /* abortop */
1856: ufs_inactive, /* inactive */
1857: ufs_reclaim, /* reclaim */
1858: ufs_lock, /* lock */
1859: ufs_unlock, /* unlock */
1860: fifo_bmap, /* bmap */
1861: fifo_strategy, /* strategy */
1862: ufs_print, /* print */
1863: ufs_islocked, /* islocked */
1864: fifo_advlock, /* advlock */
1865: };
1866: #endif /* FIFO */
1867:
1868: enum vtype iftovt_tab[16] = {
1869: VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
1870: VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
1871: };
1872: int vttoif_tab[9] = {
1873: 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT,
1874: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.