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