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