386BSD 0.1 development
[unix-history] / usr / src / sys.386bsd / ufs / ufs_vnops.c
CommitLineData
b688fc87
WJ
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 */
61ufs_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 */
79ufs_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 */
117ufs_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 */
133ufs_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 */
151ufs_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;
193found:
194 ;
195 }
196 if ((ip->i_mode & mode) != 0)
197 return (0);
198 return (EACCES);
199}
200
201/* ARGSUSED */
202ufs_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 */
251ufs_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 */
314chmod1(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 */
344chown1(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);
433good:
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 */
450ufs_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 */
510ufs_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 */
606ufs_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 */
619ufs_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 */
638ufs_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 */
652ufs_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 */
673ufs_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 */
687ufs_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 */
712ufs_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 */
770ufs_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 */
985unlinkit:
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
1062bad:
1063 if (xp)
1064 vput(ITOV(xp));
1065 vput(ITOV(dp));
1066out:
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 */
1076struct dirtemplate mastertemplate = {
1077 0, 12, 1, ".",
1078 0, DIRBLKSIZ - 12, 2, ".."
1079};
1080
1081/*
1082 * Mkdir system call
1083 */
1084ufs_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 }
1179bad:
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 */
1199ufs_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));
1253out:
1254 if (ndp->ni_dvp)
1255 iput(dp);
1256 iput(ip);
1257 return (error);
1258}
1259
1260/*
1261 * symlink -- make a symbolic link
1262 */
1263ufs_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 */
1285ufs_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 */
1312ufs_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 */
1326ufs_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 */
1338ufs_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 */
1350ufs_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 */
1364ufs_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 */
1376ufs_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 */
1395int checkoverlap = 0;
1396
1397ufs_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 */
1454ufs_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 */
1477ufsspec_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 */
1494ufsspec_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 */
1513ufsspec_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 */
1530ufsfifo_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 */
1547ufsfifo_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 */
1566ufsfifo_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 */
1583maknode(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
1644bad:
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 */
1660ufs_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 */
1747struct 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
1783struct 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
1820struct 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
1857enum vtype iftovt_tab[16] = {
1858 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
1859 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
1860};
1861int vttoif_tab[9] = {
1862 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT,
1863};