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