1 /*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)ufs_vnops.c 8.10 (Berkeley) 4/1/94
39 * $FreeBSD: src/sys/ufs/ufs/ufs_vnops.c,v 1.41.2.6 1999/09/05 08:24:10 peter Exp $
40 */
41
42 #include "opt_quota.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/namei.h>
47 #include <sys/resourcevar.h>
48 #include <sys/kernel.h>
49 #include <sys/fcntl.h>
50 #include <sys/stat.h>
51 #include <sys/buf.h>
52 #include <sys/proc.h>
53 #include <sys/conf.h>
54 #include <sys/mount.h>
55 #include <sys/unistd.h>
56 #include <sys/vnode.h>
57 #include <sys/malloc.h>
58 #include <sys/dirent.h>
59 #include <sys/lockf.h>
60
61 #include <vm/vm.h>
62
63 #include <miscfs/specfs/specdev.h>
64 #include <miscfs/fifofs/fifo.h>
65
66 #include <ufs/ufs/quota.h>
67 #include <ufs/ufs/inode.h>
68 #include <ufs/ufs/dir.h>
69 #include <ufs/ufs/ufsmount.h>
70 #include <ufs/ufs/ufs_extern.h>
71
72 static int ufs_chmod __P((struct vnode *, int, struct ucred *, struct proc *));
73 static int ufs_chown
74 __P((struct vnode *, uid_t, gid_t, struct ucred *, struct proc *));
75
76 #ifdef EXT2FS
77 #include <gnu/ext2fs/ext2_extern.h>
78 #include <gnu/ext2fs/ext2_fs.h>
79 #include <gnu/ext2fs/ext2_fs_sb.h>
80 #endif /* EXT2FS */
81
82 union _qcvt {
83 quad_t qcvt;
84 long val[2];
85 };
86 #define SETHIGH(q, h) { \
87 union _qcvt tmp; \
88 tmp.qcvt = (q); \
89 tmp.val[_QUAD_HIGHWORD] = (h); \
90 (q) = tmp.qcvt; \
91 }
92 #define SETLOW(q, l) { \
93 union _qcvt tmp; \
94 tmp.qcvt = (q); \
95 tmp.val[_QUAD_LOWWORD] = (l); \
96 (q) = tmp.qcvt; \
97 }
98
99 /*
100 * Create a regular file
101 */
102 int
103 ufs_create(ap)
104 struct vop_create_args /* {
105 struct vnode *a_dvp;
106 struct vnode **a_vpp;
107 struct componentname *a_cnp;
108 struct vattr *a_vap;
109 } */ *ap;
110 {
111 int error;
112
113 error =
114 ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
115 ap->a_dvp, ap->a_vpp, ap->a_cnp);
116 if (error)
117 return (error);
118 return (0);
119 }
120
121 /*
122 * Mknod vnode call
123 */
124 /* ARGSUSED */
125 int
126 ufs_mknod(ap)
127 struct vop_mknod_args /* {
128 struct vnode *a_dvp;
129 struct vnode **a_vpp;
130 struct componentname *a_cnp;
131 struct vattr *a_vap;
132 } */ *ap;
133 {
134 struct vattr *vap = ap->a_vap;
135 struct vnode **vpp = ap->a_vpp;
136 struct inode *ip;
137 int error;
138
139 error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
140 ap->a_dvp, vpp, ap->a_cnp);
141 if (error)
142 return (error);
143 ip = VTOI(*vpp);
144 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
145 if (vap->va_rdev != VNOVAL) {
146 /*
147 * Want to be able to use this to make badblock
148 * inodes, so don't truncate the dev number.
149 */
150 ip->i_rdev = vap->va_rdev;
151 }
152 /*
153 * Remove inode so that it will be reloaded by VFS_VGET and
154 * checked to see if it is an alias of an existing entry in
155 * the inode cache.
156 */
157 vput(*vpp);
158 (*vpp)->v_type = VNON;
159 vgone(*vpp);
160 *vpp = 0;
161 return (0);
162 }
163
164 /*
165 * Open called.
166 *
167 * Nothing to do.
168 */
169 /* ARGSUSED */
170 int
171 ufs_open(ap)
172 struct vop_open_args /* {
173 struct vnode *a_vp;
174 int a_mode;
175 struct ucred *a_cred;
176 struct proc *a_p;
177 } */ *ap;
178 {
179
180 /*
181 * Files marked append-only must be opened for appending.
182 */
183 if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
184 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
185 return (EPERM);
186 return (0);
187 }
188
189 /*
190 * Close called.
191 *
192 * Update the times on the inode.
193 */
194 /* ARGSUSED */
195 int
196 ufs_close(ap)
197 struct vop_close_args /* {
198 struct vnode *a_vp;
199 int a_fflag;
200 struct ucred *a_cred;
201 struct proc *a_p;
202 } */ *ap;
203 {
204 register struct vnode *vp = ap->a_vp;
205 register struct inode *ip = VTOI(vp);
206
207 if (vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
208 ITIMES(ip, &time, &time);
209 return (0);
210 }
211
212 int
213 ufs_access(ap)
214 struct vop_access_args /* {
215 struct vnode *a_vp;
216 int a_mode;
217 struct ucred *a_cred;
218 struct proc *a_p;
219 } */ *ap;
220 {
221 struct vnode *vp = ap->a_vp;
222 struct inode *ip = VTOI(vp);
223 struct ucred *cred = ap->a_cred;
224 mode_t mask, mode = ap->a_mode;
225 register gid_t *gp;
226 int i;
227 #ifdef QUOTA
228 int error;
229 #endif
230
231 /*
232 * Disallow write attempts on read-only file systems;
233 * unless the file is a socket, fifo, or a block or
234 * character device resident on the file system.
235 */
236 if (mode & VWRITE) {
237 switch (vp->v_type) {
238 case VDIR:
239 case VLNK:
240 case VREG:
241 if (vp->v_mount->mnt_flag & MNT_RDONLY)
242 return (EROFS);
243 #ifdef QUOTA
244 if (error = getinoquota(ip))
245 return (error);
246 #endif
247 break;
248 }
249 }
250
251 /* If immutable bit set, nobody gets to write it. */
252 if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
253 return (EPERM);
254
255 /* Otherwise, user id 0 always gets access. */
256 if (cred->cr_uid == 0)
257 return (0);
258
259 mask = 0;
260
261 /* Otherwise, check the owner. */
262 if (cred->cr_uid == ip->i_uid) {
263 if (mode & VEXEC)
264 mask |= S_IXUSR;
265 if (mode & VREAD)
266 mask |= S_IRUSR;
267 if (mode & VWRITE)
268 mask |= S_IWUSR;
269 return ((ip->i_mode & mask) == mask ? 0 : EACCES);
270 }
271
272 /* Otherwise, check the groups. */
273 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
274 if (ip->i_gid == *gp) {
275 if (mode & VEXEC)
276 mask |= S_IXGRP;
277 if (mode & VREAD)
278 mask |= S_IRGRP;
279 if (mode & VWRITE)
280 mask |= S_IWGRP;
281 return ((ip->i_mode & mask) == mask ? 0 : EACCES);
282 }
283
284 /* Otherwise, check everyone else. */
285 if (mode & VEXEC)
286 mask |= S_IXOTH;
287 if (mode & VREAD)
288 mask |= S_IROTH;
289 if (mode & VWRITE)
290 mask |= S_IWOTH;
291 return ((ip->i_mode & mask) == mask ? 0 : EACCES);
292 }
293
294 /* ARGSUSED */
295 int
296 ufs_getattr(ap)
297 struct vop_getattr_args /* {
298 struct vnode *a_vp;
299 struct vattr *a_vap;
300 struct ucred *a_cred;
301 struct proc *a_p;
302 } */ *ap;
303 {
304 register struct vnode *vp = ap->a_vp;
305 register struct inode *ip = VTOI(vp);
306 register struct vattr *vap = ap->a_vap;
307
308 ITIMES(ip, &time, &time);
309 /*
310 * Copy from inode table
311 */
312 vap->va_fsid = ip->i_dev;
313 vap->va_fileid = ip->i_number;
314 vap->va_mode = ip->i_mode & ~IFMT;
315 vap->va_nlink = ip->i_nlink;
316 vap->va_uid = ip->i_uid;
317 vap->va_gid = ip->i_gid;
318 vap->va_rdev = (dev_t)ip->i_rdev;
319 vap->va_size = ip->i_din.di_size;
320 vap->va_atime = ip->i_atime;
321 vap->va_mtime = ip->i_mtime;
322 vap->va_ctime = ip->i_ctime;
323 vap->va_flags = ip->i_flags;
324 vap->va_gen = ip->i_gen;
325 /* this doesn't belong here */
326 if (vp->v_type == VBLK)
327 vap->va_blocksize = BLKDEV_IOSIZE;
328 else if (vp->v_type == VCHR)
329 vap->va_blocksize = MAXBSIZE;
330 else
331 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
332 vap->va_bytes = dbtob(ip->i_blocks);
333 vap->va_type = vp->v_type;
334 vap->va_filerev = ip->i_modrev;
335 return (0);
336 }
337
338 /*
339 * Set attribute vnode op. called from several syscalls
340 */
341 int
342 ufs_setattr(ap)
343 struct vop_setattr_args /* {
344 struct vnode *a_vp;
345 struct vattr *a_vap;
346 struct ucred *a_cred;
347 struct proc *a_p;
348 } */ *ap;
349 {
350 struct vattr *vap = ap->a_vap;
351 struct vnode *vp = ap->a_vp;
352 struct inode *ip = VTOI(vp);
353 struct ucred *cred = ap->a_cred;
354 struct proc *p = ap->a_p;
355 struct timeval atimeval, mtimeval;
356 int error;
357
358 /*
359 * Check for unsettable attributes.
360 */
361 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
362 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
363 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
364 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
365 return (EINVAL);
366 }
367 if (vap->va_flags != VNOVAL) {
368 if (vp->v_mount->mnt_flag & MNT_RDONLY)
369 return (EROFS);
370 if (cred->cr_uid != ip->i_uid &&
371 (error = suser(cred, &p->p_acflag)))
372 return (error);
373 if (cred->cr_uid == 0) {
374 if ((ip->i_flags
375 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) &&
376 securelevel > 0)
377 return (EPERM);
378 ip->i_flags = vap->va_flags;
379 } else {
380 if (ip->i_flags
381 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND))
382 return (EPERM);
383 ip->i_flags &= SF_SETTABLE;
384 ip->i_flags |= (vap->va_flags & UF_SETTABLE);
385 }
386 ip->i_flag |= IN_CHANGE;
387 if (vap->va_flags & (IMMUTABLE | APPEND))
388 return (0);
389 }
390 if (ip->i_flags & (IMMUTABLE | APPEND))
391 return (EPERM);
392 /*
393 * Go through the fields and update iff not VNOVAL.
394 */
395 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
396 if (vp->v_mount->mnt_flag & MNT_RDONLY)
397 return (EROFS);
398 error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
399 if (error)
400 return (error);
401 }
402 if (vap->va_size != VNOVAL) {
403 /*
404 * Disallow write attempts on read-only file systems;
405 * unless the file is a socket, fifo, or a block or
406 * character device resident on the file system.
407 */
408 switch (vp->v_type) {
409 case VDIR:
410 return (EISDIR);
411 case VLNK:
412 case VREG:
413 if (vp->v_mount->mnt_flag & MNT_RDONLY)
414 return (EROFS);
415 break;
416 }
417 error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p);
418 if (error)
419 return (error);
420 }
421 ip = VTOI(vp);
422 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
423 if (vp->v_mount->mnt_flag & MNT_RDONLY)
424 return (EROFS);
425 if (cred->cr_uid != ip->i_uid &&
426 (error = suser(cred, &p->p_acflag)) &&
427 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
428 (error = VOP_ACCESS(vp, VWRITE, cred, p))))
429 return (error);
430 if (vap->va_atime.tv_sec != VNOVAL)
431 ip->i_flag |= IN_ACCESS;
432 if (vap->va_mtime.tv_sec != VNOVAL)
433 ip->i_flag |= IN_CHANGE | IN_UPDATE;
434 atimeval.tv_sec = vap->va_atime.tv_sec;
435 atimeval.tv_usec = vap->va_atime.tv_nsec / 1000;
436 mtimeval.tv_sec = vap->va_mtime.tv_sec;
437 mtimeval.tv_usec = vap->va_mtime.tv_nsec / 1000;
438 error = VOP_UPDATE(vp, &atimeval, &mtimeval, 1);
439 if (error)
440 return (error);
441 }
442 error = 0;
443 if (vap->va_mode != (mode_t)VNOVAL) {
444 if (vp->v_mount->mnt_flag & MNT_RDONLY)
445 return (EROFS);
446 error = ufs_chmod(vp, (int)vap->va_mode, cred, p);
447 }
448 return (error);
449 }
450
451 /*
452 * Change the mode on a file.
453 * Inode must be locked before calling.
454 */
455 static int
456 ufs_chmod(vp, mode, cred, p)
457 register struct vnode *vp;
458 register int mode;
459 register struct ucred *cred;
460 struct proc *p;
461 {
462 register struct inode *ip = VTOI(vp);
463 int error;
464
465 if (cred->cr_uid != ip->i_uid) {
466 error = suser(cred, &p->p_acflag);
467 if (error)
468 return (error);
469 }
470 if (cred->cr_uid) {
471 if (vp->v_type != VDIR && (mode & S_ISTXT))
472 return (EFTYPE);
473 if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
474 return (EPERM);
475 }
476 ip->i_mode &= ~ALLPERMS;
477 ip->i_mode |= (mode & ALLPERMS);
478 ip->i_flag |= IN_CHANGE;
479 return (0);
480 }
481
482 /*
483 * Perform chown operation on inode ip;
484 * inode must be locked prior to call.
485 */
486 static int
487 ufs_chown(vp, uid, gid, cred, p)
488 register struct vnode *vp;
489 uid_t uid;
490 gid_t gid;
491 struct ucred *cred;
492 struct proc *p;
493 {
494 register struct inode *ip = VTOI(vp);
495 uid_t ouid;
496 gid_t ogid;
497 int error = 0;
498 #ifdef QUOTA
499 register int i;
500 long change;
501 #endif
502
503 if (uid == (uid_t)VNOVAL)
504 uid = ip->i_uid;
505 if (gid == (gid_t)VNOVAL)
506 gid = ip->i_gid;
507 /*
508 * If we don't own the file, are trying to change the owner
509 * of the file, or are not a member of the target group,
510 * the caller must be superuser or the call fails.
511 */
512 if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
513 (gid != ip->i_gid && !groupmember((gid_t)gid, cred))) &&
514 (error = suser(cred, &p->p_acflag)))
515 return (error);
516 ogid = ip->i_gid;
517 ouid = ip->i_uid;
518 #ifdef QUOTA
519 if (error = getinoquota(ip))
520 return (error);
521 if (ouid == uid) {
522 dqrele(vp, ip->i_dquot[USRQUOTA]);
523 ip->i_dquot[USRQUOTA] = NODQUOT;
524 }
525 if (ogid == gid) {
526 dqrele(vp, ip->i_dquot[GRPQUOTA]);
527 ip->i_dquot[GRPQUOTA] = NODQUOT;
528 }
529 change = ip->i_blocks;
530 (void) chkdq(ip, -change, cred, CHOWN);
531 (void) chkiq(ip, -1, cred, CHOWN);
532 for (i = 0; i < MAXQUOTAS; i++) {
533 dqrele(vp, ip->i_dquot[i]);
534 ip->i_dquot[i] = NODQUOT;
535 }
536 #endif
537 ip->i_gid = gid;
538 ip->i_uid = uid;
539 #ifdef QUOTA
540 if ((error = getinoquota(ip)) == 0) {
541 if (ouid == uid) {
542 dqrele(vp, ip->i_dquot[USRQUOTA]);
543 ip->i_dquot[USRQUOTA] = NODQUOT;
544 }
545 if (ogid == gid) {
546 dqrele(vp, ip->i_dquot[GRPQUOTA]);
547 ip->i_dquot[GRPQUOTA] = NODQUOT;
548 }
549 if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
550 if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
551 goto good;
552 else
553 (void) chkdq(ip, -change, cred, CHOWN|FORCE);
554 }
555 for (i = 0; i < MAXQUOTAS; i++) {
556 dqrele(vp, ip->i_dquot[i]);
557 ip->i_dquot[i] = NODQUOT;
558 }
559 }
560 ip->i_gid = ogid;
561 ip->i_uid = ouid;
562 if (getinoquota(ip) == 0) {
563 if (ouid == uid) {
564 dqrele(vp, ip->i_dquot[USRQUOTA]);
565 ip->i_dquot[USRQUOTA] = NODQUOT;
566 }
567 if (ogid == gid) {
568 dqrele(vp, ip->i_dquot[GRPQUOTA]);
569 ip->i_dquot[GRPQUOTA] = NODQUOT;
570 }
571 (void) chkdq(ip, change, cred, FORCE|CHOWN);
572 (void) chkiq(ip, 1, cred, FORCE|CHOWN);
573 (void) getinoquota(ip);
574 }
575 return (error);
576 good:
577 if (getinoquota(ip))
578 panic("chown: lost quota");
579 #endif /* QUOTA */
580 if (ouid != uid || ogid != gid)
581 ip->i_flag |= IN_CHANGE;
582 if (ouid != uid && cred->cr_uid != 0)
583 ip->i_mode &= ~ISUID;
584 if (ogid != gid && cred->cr_uid != 0)
585 ip->i_mode &= ~ISGID;
586 return (0);
587 }
588
589 /* ARGSUSED */
590 int
591 ufs_ioctl(ap)
592 struct vop_ioctl_args /* {
593 struct vnode *a_vp;
594 int a_command;
595 caddr_t a_data;
596 int a_fflag;
597 struct ucred *a_cred;
598 struct proc *a_p;
599 } */ *ap;
600 {
601
602 return (ENOTTY);
603 }
604
605 /* ARGSUSED */
606 int
607 ufs_select(ap)
608 struct vop_select_args /* {
609 struct vnode *a_vp;
610 int a_which;
611 int a_fflags;
612 struct ucred *a_cred;
613 struct proc *a_p;
614 } */ *ap;
615 {
616
617 /*
618 * We should really check to see if I/O is possible.
619 */
620 return (1);
621 }
622
623 /*
624 * Mmap a file
625 *
626 * NB Currently unsupported.
627 */
628 /* ARGSUSED */
629 int
630 ufs_mmap(ap)
631 struct vop_mmap_args /* {
632 struct vnode *a_vp;
633 int a_fflags;
634 struct ucred *a_cred;
635 struct proc *a_p;
636 } */ *ap;
637 {
638
639 return (EINVAL);
640 }
641
642 /*
643 * Seek on a file
644 *
645 * Nothing to do, so just return.
646 */
647 /* ARGSUSED */
648 int
649 ufs_seek(ap)
650 struct vop_seek_args /* {
651 struct vnode *a_vp;
652 off_t a_oldoff;
653 off_t a_newoff;
654 struct ucred *a_cred;
655 } */ *ap;
656 {
657
658 return (0);
659 }
660
661 int
662 ufs_remove(ap)
663 struct vop_remove_args /* {
664 struct vnode *a_dvp;
665 struct vnode *a_vp;
666 struct componentname *a_cnp;
667 } */ *ap;
668 {
669 struct inode *ip;
670 struct vnode *vp = ap->a_vp;
671 struct vnode *dvp = ap->a_dvp;
672 int error;
673
674 ip = VTOI(vp);
675 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
676 (VTOI(dvp)->i_flags & APPEND)) {
677 error = EPERM;
678 goto out;
679 }
680 #ifdef EXT2FS
681 if (IS_EXT2_VNODE(dvp)) {
682 error = ext2_dirremove(dvp, ap->a_cnp);
683 } else {
684 error = ufs_dirremove(dvp, ap->a_cnp);
685 }
686 #else
687 error = ufs_dirremove(dvp, ap->a_cnp);
688 #endif /* EXT2FS */
689 if (error == 0) {
690 ip->i_nlink--;
691 ip->i_flag |= IN_CHANGE;
692 }
693 out:
694 if (dvp == vp)
695 vrele(vp);
696 else
697 vput(vp);
698 vput(dvp);
699 return (error);
700 }
701
702 /*
703 * link vnode call
704 */
705 int
706 ufs_link(ap)
707 struct vop_link_args /* {
708 struct vnode *a_tdvp;
709 struct vnode *a_vp;
710 struct componentname *a_cnp;
711 } */ *ap;
712 {
713 struct vnode *vp = ap->a_vp;
714 struct vnode *tdvp = ap->a_tdvp;
715 struct componentname *cnp = ap->a_cnp;
716 struct inode *ip;
717 struct timeval tv;
718 int error;
719
720 #ifdef DIAGNOSTIC
721 if ((cnp->cn_flags & HASBUF) == 0)
722 panic("ufs_link: no name");
723 #endif
724 if (vp->v_mount != tdvp->v_mount) {
725 VOP_ABORTOP(tdvp, cnp);
726 error = EXDEV;
727 goto out2;
728 }
729 if (vp != tdvp && (error = VOP_LOCK(vp))) {
730 VOP_ABORTOP(tdvp, cnp);
731 goto out2;
732 }
733 ip = VTOI(vp);
734 if ((nlink_t)ip->i_nlink >= LINK_MAX) {
735 VOP_ABORTOP(tdvp, cnp);
736 error = EMLINK;
737 goto out1;
738 }
739 if (ip->i_flags & (IMMUTABLE | APPEND)) {
740 VOP_ABORTOP(tdvp, cnp);
741 error = EPERM;
742 goto out1;
743 }
744 ip->i_nlink++;
745 ip->i_flag |= IN_CHANGE;
746 tv = time;
747 error = VOP_UPDATE(vp, &tv, &tv, 1);
748 if (!error) {
749 #ifdef EXT2FS
750 if (IS_EXT2_VNODE(tdvp)) {
751 error = ext2_direnter(ip, tdvp, cnp);
752 } else {
753 error = ufs_direnter(ip, tdvp, cnp);
754 }
755 #else
756 error = ufs_direnter(ip, tdvp, cnp);
757 #endif /* EXT2FS */
758 }
759
760 if (error) {
761 ip->i_nlink--;
762 ip->i_flag |= IN_CHANGE;
763 }
764 FREE(cnp->cn_pnbuf, M_NAMEI);
765 out1:
766 if (vp != tdvp)
767 VOP_UNLOCK(vp);
768 out2:
769 vput(tdvp);
770 return (error);
771 }
772
773
774 /*
775 * Rename system call.
776 * rename("foo", "bar");
777 * is essentially
778 * unlink("bar");
779 * link("foo", "bar");
780 * unlink("foo");
781 * but ``atomically''. Can't do full commit without saving state in the
782 * inode on disk which isn't feasible at this time. Best we can do is
783 * always guarantee the target exists.
784 *
785 * Basic algorithm is:
786 *
787 * 1) Bump link count on source while we're linking it to the
788 * target. This also ensure the inode won't be deleted out
789 * from underneath us while we work (it may be truncated by
790 * a concurrent `trunc' or `open' for creation).
791 * 2) Link source to destination. If destination already exists,
792 * delete it first.
793 * 3) Unlink source reference to inode if still around. If a
794 * directory was moved and the parent of the destination
795 * is different from the source, patch the ".." entry in the
796 * directory.
797 */
798 int
799 ufs_rename(ap)
800 struct vop_rename_args /* {
801 struct vnode *a_fdvp;
802 struct vnode *a_fvp;
803 struct componentname *a_fcnp;
804 struct vnode *a_tdvp;
805 struct vnode *a_tvp;
806 struct componentname *a_tcnp;
807 } */ *ap;
808 {
809 struct vnode *tvp = ap->a_tvp;
810 register struct vnode *tdvp = ap->a_tdvp;
811 struct vnode *fvp = ap->a_fvp;
812 struct vnode *fdvp = ap->a_fdvp;
813 struct componentname *tcnp = ap->a_tcnp;
814 struct componentname *fcnp = ap->a_fcnp;
815 struct inode *ip, *xp, *dp;
816 struct dirtemplate dirbuf;
817 struct timeval tv;
818 int doingdirectory = 0, oldparent = 0, newparent = 0;
819 int error = 0;
820 u_char namlen;
821
822 #ifdef DIAGNOSTIC
823 if ((tcnp->cn_flags & HASBUF) == 0 ||
824 (fcnp->cn_flags & HASBUF) == 0)
825 panic("ufs_rename: no name");
826 #endif
827 /*
828 * Check for cross-device rename.
829 */
830 if ((fvp->v_mount != tdvp->v_mount) ||
831 (tvp && (fvp->v_mount != tvp->v_mount))) {
832 error = EXDEV;
833 abortit:
834 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
835 if (tdvp == tvp)
836 vrele(tdvp);
837 else
838 vput(tdvp);
839 if (tvp)
840 vput(tvp);
841 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
842 vrele(fdvp);
843 vrele(fvp);
844 return (error);
845 }
846
847 if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
848 (VTOI(tdvp)->i_flags & APPEND))) {
849 error = EPERM;
850 goto abortit;
851 }
852
853 /*
854 * Check if just deleting a link name or if we've lost a race.
855 * If another process completes the same rename after we've looked
856 * up the source and have blocked looking up the target, then the
857 * source and target inodes may be identical now although the
858 * names were never linked.
859 */
860 if (fvp == tvp) {
861 if (fvp->v_type == VDIR) {
862 /*
863 * Linked directories are impossible, so we must
864 * have lost the race. Pretend that the rename
865 * completed before the lookup.
866 */
867 #ifdef UFS_RENAME_DEBUG
868 printf("ufs_rename: fvp == tvp for directories\n");
869 #endif
870 error = ENOENT;
871 goto abortit;
872 }
873
874 /* Release destination completely. */
875 VOP_ABORTOP(tdvp, tcnp);
876 vput(tdvp);
877 vput(tvp);
878
879 /*
880 * Delete source. There is another race now that everything
881 * is unlocked, but this doesn't cause any new complications.
882 * Relookup() may find a file that is unrelated to the
883 * original one, or it may fail. Too bad.
884 */
885 vrele(fdvp);
886 vrele(fvp);
887 fcnp->cn_flags &= ~MODMASK;
888 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
889 if ((fcnp->cn_flags & SAVESTART) == 0)
890 panic("ufs_rename: lost from startdir");
891 fcnp->cn_nameiop = DELETE;
892 VREF(fdvp);
893 error = relookup(fdvp, &fvp, fcnp);
894 if (error == 0)
895 vrele(fdvp);
896 if (fvp == NULL) {
897 #ifdef UFS_RENAME_DEBUG
898 printf("ufs_rename: from name disappeared\n");
899 #endif
900 return (ENOENT);
901 }
902 return (VOP_REMOVE(fdvp, fvp, fcnp));
903 }
904 error = VOP_LOCK(fvp);
905 if (error)
906 goto abortit;
907 dp = VTOI(fdvp);
908 ip = VTOI(fvp);
909 if (ip->i_nlink >= LINK_MAX) {
910 VOP_UNLOCK(fvp);
911 error = EMLINK;
912 goto abortit;
913 }
914 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
915 || (dp->i_flags & APPEND)) {
916 VOP_UNLOCK(fvp);
917 error = EPERM;
918 goto abortit;
919 }
920 if ((ip->i_mode & IFMT) == IFDIR) {
921 /*
922 * Avoid ".", "..", and aliases of "." for obvious reasons.
923 */
924 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
925 dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT ||
926 (ip->i_flag & IN_RENAME)) {
927 VOP_UNLOCK(fvp);
928 error = EINVAL;
929 goto abortit;
930 }
931 ip->i_flag |= IN_RENAME;
932 oldparent = dp->i_number;
933 doingdirectory++;
934 }
935 vrele(fdvp);
936
937 /*
938 * When the target exists, both the directory
939 * and target vnodes are returned locked.
940 */
941 dp = VTOI(tdvp);
942 xp = NULL;
943 if (tvp)
944 xp = VTOI(tvp);
945
946 /*
947 * 1) Bump link count while we're moving stuff
948 * around. If we crash somewhere before
949 * completing our work, the link count
950 * may be wrong, but correctable.
951 */
952 ip->i_nlink++;
953 ip->i_flag |= IN_CHANGE;
954 tv = time;
955 error = VOP_UPDATE(fvp, &tv, &tv, 1);
956 if (error) {
957 VOP_UNLOCK(fvp);
958 goto bad;
959 }
960
961 /*
962 * If ".." must be changed (ie the directory gets a new
963 * parent) then the source directory must not be in the
964 * directory heirarchy above the target, as this would
965 * orphan everything below the source directory. Also
966 * the user must have write permission in the source so
967 * as to be able to change "..". We must repeat the call
968 * to namei, as the parent directory is unlocked by the
969 * call to checkpath().
970 */
971 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
972 VOP_UNLOCK(fvp);
973 if (oldparent != dp->i_number)
974 newparent = dp->i_number;
975 if (doingdirectory && newparent) {
976 if (error) /* write access check above */
977 goto bad;
978 if (xp != NULL)
979 vput(tvp);
980 #ifdef EXT2FS
981 if (IS_EXT2_VNODE(tdvp)) {
982 error = ext2_checkpath(ip, dp, tcnp->cn_cred);
983 } else {
984 error = ufs_checkpath(ip, dp, tcnp->cn_cred);
985 }
986 #else
987 error = ufs_checkpath(ip, dp, tcnp->cn_cred);
988 #endif /* EXT2FS */
989 if (error)
990 goto out;
991 if ((tcnp->cn_flags & SAVESTART) == 0)
992 panic("ufs_rename: lost to startdir");
993 VREF(tdvp);
994 error = relookup(tdvp, &tvp, tcnp);
995 if (error)
996 goto out;
997 vrele(tdvp);
998 dp = VTOI(tdvp);
999 xp = NULL;
1000 if (tvp)
1001 xp = VTOI(tvp);
1002 }
1003 /*
1004 * 2) If target doesn't exist, link the target
1005 * to the source and unlink the source.
1006 * Otherwise, rewrite the target directory
1007 * entry to reference the source inode and
1008 * expunge the original entry's existence.
1009 */
1010 if (xp == NULL) {
1011 if (dp->i_dev != ip->i_dev)
1012 panic("rename: EXDEV");
1013 /*
1014 * Account for ".." in new directory.
1015 * When source and destination have the same
1016 * parent we don't fool with the link count.
1017 */
1018 if (doingdirectory && newparent) {
1019 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1020 error = EMLINK;
1021 goto bad;
1022 }
1023 dp->i_nlink++;
1024 dp->i_flag |= IN_CHANGE;
1025 error = VOP_UPDATE(tdvp, &tv, &tv, 1);
1026 if (error)
1027 goto bad;
1028 }
1029 #ifdef EXT2FS
1030 if (IS_EXT2_VNODE(tdvp)) {
1031 error = ext2_direnter(ip, tdvp, tcnp);
1032 } else {
1033 error = ufs_direnter(ip, tdvp, tcnp);
1034 }
1035 #else
1036 error = ufs_direnter(ip, tdvp, tcnp);
1037 #endif /* EXT2FS */
1038 if (error) {
1039 if (doingdirectory && newparent) {
1040 dp->i_nlink--;
1041 dp->i_flag |= IN_CHANGE;
1042 (void)VOP_UPDATE(tdvp, &tv, &tv, 1);
1043 }
1044 goto bad;
1045 }
1046 vput(tdvp);
1047 } else {
1048 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1049 panic("rename: EXDEV");
1050 /*
1051 * Short circuit rename(foo, foo).
1052 */
1053 if (xp->i_number == ip->i_number)
1054 panic("rename: same file");
1055 /*
1056 * If the parent directory is "sticky", then the user must
1057 * own the parent directory, or the destination of the rename,
1058 * otherwise the destination may not be changed (except by
1059 * root). This implements append-only directories.
1060 */
1061 if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
1062 tcnp->cn_cred->cr_uid != dp->i_uid &&
1063 xp->i_uid != tcnp->cn_cred->cr_uid) {
1064 error = EPERM;
1065 goto bad;
1066 }
1067 /*
1068 * Target must be empty if a directory and have no links
1069 * to it. Also, ensure source and target are compatible
1070 * (both directories, or both not directories).
1071 */
1072 if ((xp->i_mode&IFMT) == IFDIR) {
1073 #ifdef EXT2FS
1074 if (! (IS_EXT2_VNODE(ITOV(xp)) ?
1075 ext2_dirempty : ufs_dirempty)
1076 #else
1077 if (! ufs_dirempty
1078 #endif /* EXT2FS */
1079 (xp, dp->i_number, tcnp->cn_cred) ||
1080 xp->i_nlink > 2) {
1081 error = ENOTEMPTY;
1082 goto bad;
1083 }
1084 if (!doingdirectory) {
1085 error = ENOTDIR;
1086 goto bad;
1087 }
1088 cache_purge(tdvp);
1089 } else if (doingdirectory) {
1090 error = EISDIR;
1091 goto bad;
1092 }
1093 #ifdef EXT2FS
1094 if (IS_EXT2_VNODE(ITOV(dp))) {
1095 error = ext2_dirrewrite(dp, ip, tcnp);
1096 } else {
1097 error = ufs_dirrewrite(dp, ip, tcnp);
1098 }
1099 #else
1100 error = ufs_dirrewrite(dp, ip, tcnp);
1101 #endif /* EXT2FS */
1102 if (error)
1103 goto bad;
1104 /*
1105 * If the target directory is in the same
1106 * directory as the source directory,
1107 * decrement the link count on the parent
1108 * of the target directory.
1109 */
1110 if (doingdirectory && !newparent) {
1111 dp->i_nlink--;
1112 dp->i_flag |= IN_CHANGE;
1113 }
1114 vput(tdvp);
1115 /*
1116 * Adjust the link count of the target to
1117 * reflect the dirrewrite above. If this is
1118 * a directory it is empty and there are
1119 * no links to it, so we can squash the inode and
1120 * any space associated with it. We disallowed
1121 * renaming over top of a directory with links to
1122 * it above, as the remaining link would point to
1123 * a directory without "." or ".." entries.
1124 */
1125 xp->i_nlink--;
1126 if (doingdirectory) {
1127 if (--xp->i_nlink != 0)
1128 panic("rename: linked directory");
1129 error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
1130 tcnp->cn_cred, tcnp->cn_proc);
1131 }
1132 xp->i_flag |= IN_CHANGE;
1133 vput(tvp);
1134 xp = NULL;
1135 }
1136
1137 /*
1138 * 3) Unlink the source.
1139 */
1140 fcnp->cn_flags &= ~MODMASK;
1141 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1142 if ((fcnp->cn_flags & SAVESTART) == 0)
1143 panic("ufs_rename: lost from startdir");
1144 VREF(fdvp);
1145 error = relookup(fdvp, &fvp, fcnp);
1146 if (error == 0)
1147 vrele(fdvp);
1148 if (fvp != NULL) {
1149 xp = VTOI(fvp);
1150 dp = VTOI(fdvp);
1151 } else {
1152 /*
1153 * From name has disappeared.
1154 */
1155 if (doingdirectory)
1156 panic("rename: lost dir entry");
1157 vrele(ap->a_fvp);
1158 return (0);
1159 }
1160 /*
1161 * Ensure that the directory entry still exists and has not
1162 * changed while the new name has been entered. If the source is
1163 * a file then the entry may have been unlinked or renamed. In
1164 * either case there is no further work to be done. If the source
1165 * is a directory then it cannot have been rmdir'ed; its link
1166 * count of three would cause a rmdir to fail with ENOTEMPTY.
1167 * The IN_RENAME flag ensures that it cannot be moved by another
1168 * rename.
1169 */
1170 if (xp != ip) {
1171 if (doingdirectory)
1172 panic("rename: lost dir entry");
1173 } else {
1174 /*
1175 * If the source is a directory with a
1176 * new parent, the link count of the old
1177 * parent directory must be decremented
1178 * and ".." set to point to the new parent.
1179 */
1180 if (doingdirectory && newparent) {
1181 dp->i_nlink--;
1182 dp->i_flag |= IN_CHANGE;
1183 error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
1184 sizeof (struct dirtemplate), (off_t)0,
1185 UIO_SYSSPACE, IO_NODELOCKED,
1186 tcnp->cn_cred, (int *)0, (struct proc *)0);
1187 if (error == 0) {
1188 # if (BYTE_ORDER == LITTLE_ENDIAN)
1189 if (fvp->v_mount->mnt_maxsymlinklen <= 0)
1190 namlen = dirbuf.dotdot_type;
1191 else
1192 namlen = dirbuf.dotdot_namlen;
1193 # else
1194 namlen = dirbuf.dotdot_namlen;
1195 # endif
1196 #ifdef EXT2FS
1197 if(IS_EXT2_VNODE(fvp))
1198 namlen = ((struct odirtemplate *)
1199 &dirbuf)->dotdot_namlen;
1200 #endif /* EXT2FS */
1201 if (namlen != 2 ||
1202 dirbuf.dotdot_name[0] != '.' ||
1203 dirbuf.dotdot_name[1] != '.') {
1204 ufs_dirbad(xp, (doff_t)12,
1205 "rename: mangled dir");
1206 } else {
1207 dirbuf.dotdot_ino = newparent;
1208 (void) vn_rdwr(UIO_WRITE, fvp,
1209 (caddr_t)&dirbuf,
1210 sizeof (struct dirtemplate),
1211 (off_t)0, UIO_SYSSPACE,
1212 IO_NODELOCKED|IO_SYNC,
1213 tcnp->cn_cred, (int *)0,
1214 (struct proc *)0);
1215 cache_purge(fdvp);
1216 }
1217 }
1218 }
1219 #ifdef EXT2FS
1220 if (IS_EXT2_VNODE(fdvp)) {
1221 error = ext2_dirremove(fdvp, fcnp);
1222 } else {
1223 error = ufs_dirremove(fdvp, fcnp);
1224 }
1225 #else
1226 error = ufs_dirremove(fdvp, fcnp);
1227 #endif /* EXT2FS */
1228 if (!error) {
1229 xp->i_nlink--;
1230 xp->i_flag |= IN_CHANGE;
1231 }
1232 xp->i_flag &= ~IN_RENAME;
1233 }
1234 if (dp)
1235 vput(fdvp);
1236 if (xp)
1237 vput(fvp);
1238 vrele(ap->a_fvp);
1239 return (error);
1240
1241 bad:
1242 if (xp)
1243 vput(ITOV(xp));
1244 vput(ITOV(dp));
1245 out:
1246 if (VOP_LOCK(fvp) == 0) {
1247 ip->i_nlink--;
1248 ip->i_flag |= IN_CHANGE;
1249 ip->i_flag &= ~IN_RENAME;
1250 vput(fvp);
1251 } else
1252 vrele(fvp);
1253 return (error);
1254 }
1255
1256 /*
1257 * A virgin directory (no blushing please).
1258 */
1259 static struct dirtemplate mastertemplate = {
1260 0, 12, DT_DIR, 1, { '.', 0 },
1261 0, DIRBLKSIZ - 12, DT_DIR, 2, { '.', '.', 0 }
1262 };
1263 static struct odirtemplate omastertemplate = {
1264 0, 12, 1, { '.', 0 },
1265 0, DIRBLKSIZ - 12, 2, { '.', '.', 0 }
1266 };
1267
1268 /*
1269 * Mkdir system call
1270 */
1271 int
1272 ufs_mkdir(ap)
1273 struct vop_mkdir_args /* {
1274 struct vnode *a_dvp;
1275 struct vnode **a_vpp;
1276 struct componentname *a_cnp;
1277 struct vattr *a_vap;
1278 } */ *ap;
1279 {
1280 register struct vnode *dvp = ap->a_dvp;
1281 register struct vattr *vap = ap->a_vap;
1282 register struct componentname *cnp = ap->a_cnp;
1283 register struct inode *ip, *dp;
1284 struct vnode *tvp;
1285 struct dirtemplate dirtemplate, *dtp;
1286 struct timeval tv;
1287 int error, dmode;
1288
1289 #ifdef DIAGNOSTIC
1290 if ((cnp->cn_flags & HASBUF) == 0)
1291 panic("ufs_mkdir: no name");
1292 #endif
1293 dp = VTOI(dvp);
1294 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1295 error = EMLINK;
1296 goto out;
1297 }
1298 dmode = vap->va_mode & 0777;
1299 dmode |= IFDIR;
1300 /*
1301 * Must simulate part of ufs_makeinode here to acquire the inode,
1302 * but not have it entered in the parent directory. The entry is
1303 * made later after writing "." and ".." entries.
1304 */
1305 error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp);
1306 if (error)
1307 goto out;
1308 ip = VTOI(tvp);
1309 ip->i_uid = cnp->cn_cred->cr_uid;
1310 ip->i_gid = dp->i_gid;
1311 #ifdef QUOTA
1312 if ((error = getinoquota(ip)) ||
1313 (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
1314 free(cnp->cn_pnbuf, M_NAMEI);
1315 VOP_VFREE(tvp, ip->i_number, dmode);
1316 vput(tvp);
1317 vput(dvp);
1318 return (error);
1319 }
1320 #endif
1321 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1322 ip->i_mode = dmode;
1323 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
1324 ip->i_nlink = 2;
1325 tv = time;
1326 error = VOP_UPDATE(tvp, &tv, &tv, 1);
1327
1328 /*
1329 * Bump link count in parent directory
1330 * to reflect work done below. Should
1331 * be done before reference is created
1332 * so reparation is possible if we crash.
1333 */
1334 dp->i_nlink++;
1335 dp->i_flag |= IN_CHANGE;
1336 error = VOP_UPDATE(dvp, &tv, &tv, 1);
1337 if (error)
1338 goto bad;
1339
1340 /* Initialize directory with "." and ".." from static template. */
1341 if (dvp->v_mount->mnt_maxsymlinklen > 0
1342 #ifdef EXT2FS
1343 /* omastertemplate is want we want for EXT2 */
1344 && !IS_EXT2_VNODE(dvp)
1345 #endif /* EXT2FS */
1346 )
1347 dtp = &mastertemplate;
1348 else
1349 dtp = (struct dirtemplate *)&omastertemplate;
1350 dirtemplate = *dtp;
1351 dirtemplate.dot_ino = ip->i_number;
1352 dirtemplate.dotdot_ino = dp->i_number;
1353 #ifdef EXT2FS
1354 /* note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE
1355 * so let's just redefine it - for this function only
1356 */
1357 #undef DIRBLKSIZ
1358 #define DIRBLKSIZ (IS_EXT2_VNODE(dvp) ? \
1359 VTOI(dvp)->i_e2fs->s_blocksize : DEV_BSIZE)
1360 if(IS_EXT2_VNODE(dvp))
1361 dirtemplate.dotdot_reclen = DIRBLKSIZ - 12;
1362 #endif /* EXT2FS */
1363 error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
1364 sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
1365 IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0);
1366 if (error) {
1367 dp->i_nlink--;
1368 dp->i_flag |= IN_CHANGE;
1369 goto bad;
1370 }
1371 if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
1372 panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
1373 else {
1374 ip->i_size = DIRBLKSIZ;
1375 ip->i_flag |= IN_CHANGE;
1376 }
1377
1378 /* Directory set up, now install it's entry in the parent directory. */
1379 #ifdef EXT2FS
1380 if (IS_EXT2_VNODE(dvp)) {
1381 error = ext2_direnter(ip, dvp, cnp);
1382 } else {
1383 error = ufs_direnter(ip, dvp, cnp);
1384 }
1385 #else
1386 error = ufs_direnter(ip, dvp, cnp);
1387 #endif /* EXT2FS */
1388 if (error) {
1389 dp->i_nlink--;
1390 dp->i_flag |= IN_CHANGE;
1391 }
1392 bad:
1393 /*
1394 * No need to do an explicit VOP_TRUNCATE here, vrele will do this
1395 * for us because we set the link count to 0.
1396 */
1397 if (error) {
1398 ip->i_nlink = 0;
1399 ip->i_flag |= IN_CHANGE;
1400 vput(tvp);
1401 } else
1402 *ap->a_vpp = tvp;
1403 out:
1404 FREE(cnp->cn_pnbuf, M_NAMEI);
1405 vput(dvp);
1406 return (error);
1407 #ifdef EXT2FS
1408 #undef DIRBLKSIZ
1409 #define DIRBLKSIZ DEV_BSIZE
1410 #endif /* EXT2FS */
1411 }
1412
1413 /*
1414 * Rmdir system call.
1415 */
1416 int
1417 ufs_rmdir(ap)
1418 struct vop_rmdir_args /* {
1419 struct vnode *a_dvp;
1420 struct vnode *a_vp;
1421 struct componentname *a_cnp;
1422 } */ *ap;
1423 {
1424 struct vnode *vp = ap->a_vp;
1425 struct vnode *dvp = ap->a_dvp;
1426 struct componentname *cnp = ap->a_cnp;
1427 struct inode *ip, *dp;
1428 int error;
1429
1430 ip = VTOI(vp);
1431 dp = VTOI(dvp);
1432 /*
1433 * No rmdir "." please.
1434 */
1435 if (dp == ip) {
1436 vrele(dvp);
1437 vput(vp);
1438 return (EINVAL);
1439 }
1440 /*
1441 * Verify the directory is empty (and valid).
1442 * (Rmdir ".." won't be valid since
1443 * ".." will contain a reference to
1444 * the current directory and thus be
1445 * non-empty.)
1446 * Do not allow the removal of mounted on
1447 * directories (this can happen when an NFS
1448 * exported filesystem tries to remove a
1449 * locally mounted on directory).
1450 */
1451 error = 0;
1452 if (ip->i_nlink != 2 ||
1453 #ifdef EXT2FS
1454 !(IS_EXT2_VNODE(ITOV(ip)) ? ext2_dirempty : ufs_dirempty)
1455 (ip, dp->i_number, cnp->cn_cred)) {
1456 #else
1457 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1458 #endif /* EXT2FS */
1459 error = ENOTEMPTY;
1460 goto out;
1461 }
1462 if ((dp->i_flags & APPEND)
1463 || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
1464 error = EPERM;
1465 goto out;
1466 }
1467 if (vp->v_mountedhere != 0) {
1468 error = EINVAL;
1469 goto out;
1470 }
1471 /*
1472 * Delete reference to directory before purging
1473 * inode. If we crash in between, the directory
1474 * will be reattached to lost+found,
1475 */
1476 #ifdef EXT2FS
1477 if (IS_EXT2_VNODE(dvp)) {
1478 error = ext2_dirremove(dvp, cnp);
1479 } else {
1480 error = ufs_dirremove(dvp, cnp);
1481 }
1482 #else
1483 error = ufs_dirremove(dvp, cnp);
1484 #endif /* EXT2FS */
1485 if (error)
1486 goto out;
1487 dp->i_nlink--;
1488 dp->i_flag |= IN_CHANGE;
1489 cache_purge(dvp);
1490 vput(dvp);
1491 dvp = NULL;
1492 /*
1493 * Truncate inode. The only stuff left
1494 * in the directory is "." and "..". The
1495 * "." reference is inconsequential since
1496 * we're quashing it. The ".." reference
1497 * has already been adjusted above. We've
1498 * removed the "." reference and the reference
1499 * in the parent directory, but there may be
1500 * other hard links so decrement by 2 and
1501 * worry about them later.
1502 */
1503 ip->i_nlink -= 2;
1504 error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
1505 cnp->cn_proc);
1506 cache_purge(ITOV(ip));
1507 out:
1508 if (dvp)
1509 vput(dvp);
1510 vput(vp);
1511 return (error);
1512 }
1513
1514 /*
1515 * symlink -- make a symbolic link
1516 */
1517 int
1518 ufs_symlink(ap)
1519 struct vop_symlink_args /* {
1520 struct vnode *a_dvp;
1521 struct vnode **a_vpp;
1522 struct componentname *a_cnp;
1523 struct vattr *a_vap;
1524 char *a_target;
1525 } */ *ap;
1526 {
1527 register struct vnode *vp, **vpp = ap->a_vpp;
1528 register struct inode *ip;
1529 int len, error;
1530
1531 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
1532 vpp, ap->a_cnp);
1533 if (error)
1534 return (error);
1535 vp = *vpp;
1536 len = strlen(ap->a_target);
1537 if (len < vp->v_mount->mnt_maxsymlinklen) {
1538 ip = VTOI(vp);
1539 bcopy(ap->a_target, (char *)ip->i_shortlink, len);
1540 ip->i_size = len;
1541 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1542 } else
1543 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1544 UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0,
1545 (struct proc *)0);
1546 vput(vp);
1547 return (error);
1548 }
1549
1550 /*
1551 * Vnode op for reading directories.
1552 *
1553 * The routine below assumes that the on-disk format of a directory
1554 * is the same as that defined by <sys/dirent.h>. If the on-disk
1555 * format changes, then it will be necessary to do a conversion
1556 * from the on-disk format that read returns to the format defined
1557 * by <sys/dirent.h>.
1558 */
1559 int
1560 ufs_readdir(ap)
1561 struct vop_readdir_args /* {
1562 struct vnode *a_vp;
1563 struct uio *a_uio;
1564 struct ucred *a_cred;
1565 int *a_ncookies;
1566 u_int **cookies;
1567 } */ *ap;
1568 {
1569 register struct uio *uio = ap->a_uio;
1570 off_t off;
1571 int count, lost, error;
1572
1573 if (ap->a_ncookies != NULL)
1574 /*
1575 * Ensure that the block is aligned. The caller can use
1576 * the cookies to determine where in the block to start.
1577 */
1578 uio->uio_offset &= ~(DIRBLKSIZ - 1);
1579 off = uio->uio_offset;
1580 count = uio->uio_resid;
1581 count &= ~(DIRBLKSIZ - 1);
1582 lost = uio->uio_resid - count;
1583 if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
1584 return (EINVAL);
1585 uio->uio_resid = count;
1586 uio->uio_iov->iov_len = count;
1587 # if (BYTE_ORDER == LITTLE_ENDIAN)
1588 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) {
1589 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1590 } else {
1591 struct dirent *dp, *edp;
1592 struct uio auio;
1593 struct iovec aiov;
1594 caddr_t dirbuf;
1595 int readcnt;
1596 u_char tmp;
1597
1598 auio = *uio;
1599 auio.uio_iov = &aiov;
1600 auio.uio_iovcnt = 1;
1601 auio.uio_segflg = UIO_SYSSPACE;
1602 aiov.iov_len = count;
1603 MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK);
1604 aiov.iov_base = dirbuf;
1605 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
1606 if (error == 0) {
1607 readcnt = count - auio.uio_resid;
1608 edp = (struct dirent *)&dirbuf[readcnt];
1609 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1610 tmp = dp->d_namlen;
1611 dp->d_namlen = dp->d_type;
1612 dp->d_type = tmp;
1613 if (dp->d_reclen > 0) {
1614 dp = (struct dirent *)
1615 ((char *)dp + dp->d_reclen);
1616 } else {
1617 error = EIO;
1618 break;
1619 }
1620 }
1621 if (dp >= edp)
1622 error = uiomove(dirbuf, readcnt, uio);
1623 }
1624 FREE(dirbuf, M_TEMP);
1625 }
1626 # else
1627 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1628 # endif
1629 if (!error && ap->a_ncookies != NULL) {
1630 struct dirent* dpStart;
1631 struct dirent* dpEnd;
1632 struct dirent* dp;
1633 int ncookies;
1634 u_int *cookies;
1635 u_int *cookiep;
1636
1637 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1638 panic("ufs_readdir: unexpected uio from NFS server");
1639 dpStart = (struct dirent *)
1640 (uio->uio_iov->iov_base - (uio->uio_offset - off));
1641 dpEnd = (struct dirent *) uio->uio_iov->iov_base;
1642 for (dp = dpStart, ncookies = 0;
1643 dp < dpEnd;
1644 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
1645 ncookies++;
1646 MALLOC(cookies, u_int *, ncookies * sizeof(u_int),
1647 M_TEMP, M_WAITOK);
1648 for (dp = dpStart, cookiep = cookies;
1649 dp < dpEnd;
1650 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
1651 off += dp->d_reclen;
1652 *cookiep++ = (u_int) off;
1653 }
1654 *ap->a_ncookies = ncookies;
1655 *ap->a_cookies = cookies;
1656 }
1657 if (ap->a_eofflag)
1658 *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
1659 uio->uio_resid += lost;
1660 return (error);
1661 }
1662
1663 /*
1664 * Return target name of a symbolic link
1665 */
1666 int
1667 ufs_readlink(ap)
1668 struct vop_readlink_args /* {
1669 struct vnode *a_vp;
1670 struct uio *a_uio;
1671 struct ucred *a_cred;
1672 } */ *ap;
1673 {
1674 register struct vnode *vp = ap->a_vp;
1675 register struct inode *ip = VTOI(vp);
1676 int isize;
1677
1678 isize = ip->i_size;
1679 if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
1680 (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */
1681 uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
1682 return (0);
1683 }
1684 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1685 }
1686
1687 /*
1688 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
1689 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
1690 */
1691 /* ARGSUSED */
1692 int
1693 ufs_abortop(ap)
1694 struct vop_abortop_args /* {
1695 struct vnode *a_dvp;
1696 struct componentname *a_cnp;
1697 } */ *ap;
1698 {
1699 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
1700 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
1701 return (0);
1702 }
1703
1704 /*
1705 * Lock an inode. If its already locked, set the WANT bit and sleep.
1706 */
1707 int
1708 ufs_lock(ap)
1709 struct vop_lock_args /* {
1710 struct vnode *a_vp;
1711 } */ *ap;
1712 {
1713 struct proc *p = curproc;
1714 register struct vnode *vp = ap->a_vp;
1715 register struct inode *ip;
1716
1717 start:
1718 while (vp->v_flag & VXLOCK) {
1719 vp->v_flag |= VXWANT;
1720 (void) tsleep((caddr_t)vp, PINOD, "ufslk1", 0);
1721 }
1722 if (vp->v_tag == VT_NON)
1723 return (ENOENT);
1724 ip = VTOI(vp);
1725 if (ip->i_flag & IN_LOCKED) {
1726 if (p->p_pid == ip->i_lockholder) {
1727 if( (ip->i_flag & IN_RECURSE) == 0)
1728 panic("ufs_lock: recursive lock not expected, pid: %d\n",
1729 ip->i_lockholder);
1730 } else {
1731 ip->i_flag |= IN_WANTED;
1732 #ifdef DIAGNOSTIC
1733 if (p)
1734 ip->i_lockwaiter = p->p_pid;
1735 else
1736 ip->i_lockwaiter = -1;
1737 #endif
1738 (void) tsleep((caddr_t)ip, PINOD, "ufslk2", 0);
1739 goto start;
1740 }
1741 }
1742 #ifdef DIAGNOSTIC
1743 ip->i_lockwaiter = 0;
1744 if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0))
1745 panic("lockholder (%d) != 0", ip->i_lockholder);
1746 if (p && p->p_pid == 0)
1747 printf("locking by process 0\n");
1748 #endif
1749
1750 if ((ip->i_flag & IN_RECURSE) == 0)
1751 ip->i_lockcount = 1;
1752 else
1753 ++ip->i_lockcount;
1754
1755 if (p)
1756 ip->i_lockholder = p->p_pid;
1757 else
1758 ip->i_lockholder = -1;
1759 ip->i_flag |= IN_LOCKED;
1760 return (0);
1761 }
1762
1763 /*
1764 * Unlock an inode. If WANT bit is on, wakeup.
1765 */
1766 int lockcount = 90;
1767 int
1768 ufs_unlock(ap)
1769 struct vop_unlock_args /* {
1770 struct vnode *a_vp;
1771 } */ *ap;
1772 {
1773 register struct inode *ip = VTOI(ap->a_vp);
1774
1775 #ifdef DIAGNOSTIC
1776 struct proc *p = curproc;
1777
1778 if ((ip->i_flag & IN_LOCKED) == 0) {
1779 vprint("ufs_unlock: unlocked inode", ap->a_vp);
1780 panic("ufs_unlock NOT LOCKED");
1781 }
1782 if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 &&
1783 ip->i_lockholder > -1 && lockcount++ < 100)
1784 panic("unlocker (%d) != lock holder (%d)",
1785 p->p_pid, ip->i_lockholder);
1786 #endif
1787 if (--ip->i_lockcount > 0) {
1788 if ((ip->i_flag & IN_RECURSE) == 0)
1789 panic("ufs_unlock: recursive lock prematurely released, pid=%d\n",
1790 ip->i_lockholder);
1791 return (0);
1792 }
1793 ip->i_lockholder = 0;
1794 ip->i_flag &= ~(IN_LOCKED|IN_RECURSE);
1795 if (ip->i_flag & IN_WANTED) {
1796 ip->i_flag &= ~IN_WANTED;
1797 wakeup((caddr_t)ip);
1798 }
1799 return (0);
1800 }
1801
1802 /*
1803 * Check for a locked inode.
1804 */
1805 int
1806 ufs_islocked(ap)
1807 struct vop_islocked_args /* {
1808 struct vnode *a_vp;
1809 } */ *ap;
1810 {
1811
1812 if (VTOI(ap->a_vp)->i_flag & IN_LOCKED)
1813 return (1);
1814 return (0);
1815 }
1816
1817 /*
1818 * Calculate the logical to physical mapping if not done already,
1819 * then call the device strategy routine.
1820 */
1821 int
1822 ufs_strategy(ap)
1823 struct vop_strategy_args /* {
1824 struct buf *a_bp;
1825 } */ *ap;
1826 {
1827 register struct buf *bp = ap->a_bp;
1828 register struct vnode *vp = bp->b_vp;
1829 register struct inode *ip;
1830 int error;
1831
1832 ip = VTOI(vp);
1833 if (vp->v_type == VBLK || vp->v_type == VCHR)
1834 panic("ufs_strategy: spec");
1835 if (bp->b_blkno == bp->b_lblkno) {
1836 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL);
1837 if (error) {
1838 bp->b_error = error;
1839 bp->b_flags |= B_ERROR;
1840 biodone(bp);
1841 return (error);
1842 }
1843 if ((long)bp->b_blkno == -1)
1844 vfs_bio_clrbuf(bp);
1845 }
1846 if ((long)bp->b_blkno == -1) {
1847 biodone(bp);
1848 return (0);
1849 }
1850 vp = ip->i_devvp;
1851 bp->b_dev = vp->v_rdev;
1852 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
1853 return (0);
1854 }
1855
1856 /*
1857 * Print out the contents of an inode.
1858 */
1859 int
1860 ufs_print(ap)
1861 struct vop_print_args /* {
1862 struct vnode *a_vp;
1863 } */ *ap;
1864 {
1865 register struct vnode *vp = ap->a_vp;
1866 register struct inode *ip = VTOI(vp);
1867
1868 printf("tag VT_UFS, ino %ld, on dev %d, %d", ip->i_number,
1869 major(ip->i_dev), minor(ip->i_dev));
1870 if (vp->v_type == VFIFO)
1871 fifo_printinfo(vp);
1872 printf("%s\n", (ip->i_flag & IN_LOCKED) ? " (LOCKED)" : "");
1873 if (ip->i_lockholder == 0)
1874 return (0);
1875 printf("\towner pid %lu", (u_long)ip->i_lockholder);
1876 if (ip->i_lockwaiter)
1877 printf(" waiting pid %lu", (u_long)ip->i_lockwaiter);
1878 printf("\n");
1879 return (0);
1880 }
1881
1882 /*
1883 * Read wrapper for special devices.
1884 */
1885 int
1886 ufsspec_read(ap)
1887 struct vop_read_args /* {
1888 struct vnode *a_vp;
1889 struct uio *a_uio;
1890 int a_ioflag;
1891 struct ucred *a_cred;
1892 } */ *ap;
1893 {
1894
1895 /*
1896 * Set access flag.
1897 */
1898 VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1899 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
1900 }
1901
1902 /*
1903 * Write wrapper for special devices.
1904 */
1905 int
1906 ufsspec_write(ap)
1907 struct vop_write_args /* {
1908 struct vnode *a_vp;
1909 struct uio *a_uio;
1910 int a_ioflag;
1911 struct ucred *a_cred;
1912 } */ *ap;
1913 {
1914
1915 /*
1916 * Set update and change flags.
1917 */
1918 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
1919 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
1920 }
1921
1922 /*
1923 * Close wrapper for special devices.
1924 *
1925 * Update the times on the inode then do device close.
1926 */
1927 int
1928 ufsspec_close(ap)
1929 struct vop_close_args /* {
1930 struct vnode *a_vp;
1931 int a_fflag;
1932 struct ucred *a_cred;
1933 struct proc *a_p;
1934 } */ *ap;
1935 {
1936 register struct inode *ip = VTOI(ap->a_vp);
1937
1938 if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
1939 ITIMES(ip, &time, &time);
1940 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
1941 }
1942
1943 /*
1944 * Read wrapper for fifo's
1945 */
1946 int
1947 ufsfifo_read(ap)
1948 struct vop_read_args /* {
1949 struct vnode *a_vp;
1950 struct uio *a_uio;
1951 int a_ioflag;
1952 struct ucred *a_cred;
1953 } */ *ap;
1954 {
1955 /*
1956 * Set access flag.
1957 */
1958 VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1959 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
1960 }
1961
1962 /*
1963 * Write wrapper for fifo's.
1964 */
1965 int
1966 ufsfifo_write(ap)
1967 struct vop_write_args /* {
1968 struct vnode *a_vp;
1969 struct uio *a_uio;
1970 int a_ioflag;
1971 struct ucred *a_cred;
1972 } */ *ap;
1973 {
1974 /*
1975 * Set update and change flags.
1976 */
1977 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
1978 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
1979 }
1980
1981 /*
1982 * Close wrapper for fifo's.
1983 *
1984 * Update the times on the inode then do device close.
1985 */
1986 int
1987 ufsfifo_close(ap)
1988 struct vop_close_args /* {
1989 struct vnode *a_vp;
1990 int a_fflag;
1991 struct ucred *a_cred;
1992 struct proc *a_p;
1993 } */ *ap;
1994 {
1995 register struct inode *ip = VTOI(ap->a_vp);
1996
1997 if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
1998 ITIMES(ip, &time, &time);
1999 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
2000 }
2001
2002 /*
2003 * Return POSIX pathconf information applicable to ufs filesystems.
2004 */
2005 int
2006 ufs_pathconf(ap)
2007 struct vop_pathconf_args /* {
2008 struct vnode *a_vp;
2009 int a_name;
2010 int *a_retval;
2011 } */ *ap;
2012 {
2013
2014 switch (ap->a_name) {
2015 case _PC_LINK_MAX:
2016 *ap->a_retval = LINK_MAX;
2017 return (0);
2018 case _PC_NAME_MAX:
2019 *ap->a_retval = NAME_MAX;
2020 return (0);
2021 case _PC_PATH_MAX:
2022 *ap->a_retval = PATH_MAX;
2023 return (0);
2024 case _PC_PIPE_BUF:
2025 *ap->a_retval = PIPE_BUF;
2026 return (0);
2027 case _PC_CHOWN_RESTRICTED:
2028 *ap->a_retval = 1;
2029 return (0);
2030 case _PC_NO_TRUNC:
2031 *ap->a_retval = 1;
2032 return (0);
2033 default:
2034 return (EINVAL);
2035 }
2036 /* NOTREACHED */
2037 }
2038
2039 /*
2040 * Advisory record locking support
2041 */
2042 int
2043 ufs_advlock(ap)
2044 struct vop_advlock_args /* {
2045 struct vnode *a_vp;
2046 caddr_t a_id;
2047 int a_op;
2048 struct flock *a_fl;
2049 int a_flags;
2050 } */ *ap;
2051 {
2052 register struct inode *ip = VTOI(ap->a_vp);
2053
2054 return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
2055 }
2056
2057 /*
2058 * Initialize the vnode associated with a new inode, handle aliased
2059 * vnodes.
2060 */
2061 int
2062 ufs_vinit(mntp, specops, fifoops, vpp)
2063 struct mount *mntp;
2064 vop_t **specops;
2065 vop_t **fifoops;
2066 struct vnode **vpp;
2067 {
2068 struct inode *ip;
2069 struct vnode *vp, *nvp;
2070
2071 vp = *vpp;
2072 ip = VTOI(vp);
2073 switch(vp->v_type = IFTOVT(ip->i_mode)) {
2074 case VCHR:
2075 case VBLK:
2076 vp->v_op = specops;
2077 nvp = checkalias(vp, ip->i_rdev, mntp);
2078 if (nvp) {
2079 /*
2080 * Discard unneeded vnode, but save its inode.
2081 */
2082 ufs_ihashrem(ip);
2083 VOP_UNLOCK(vp);
2084 nvp->v_data = vp->v_data;
2085 vp->v_data = NULL;
2086 vp->v_op = spec_vnodeop_p;
2087 vrele(vp);
2088 vgone(vp);
2089 /*
2090 * Reinitialize aliased inode.
2091 */
2092 vp = nvp;
2093 ip->i_vnode = vp;
2094 ufs_ihashins(ip);
2095 }
2096 break;
2097 case VFIFO:
2098 vp->v_op = fifoops;
2099 break;
2100 default:
2101 break;
2102
2103 }
2104 if (ip->i_number == ROOTINO)
2105 vp->v_flag |= VROOT;
2106 /*
2107 * Initialize modrev times
2108 */
2109 SETHIGH(ip->i_modrev, mono_time.tv_sec);
2110 SETLOW(ip->i_modrev, mono_time.tv_usec * 4294);
2111 *vpp = vp;
2112 return (0);
2113 }
2114
2115 /*
2116 * Allocate a new inode.
2117 */
2118 int
2119 ufs_makeinode(mode, dvp, vpp, cnp)
2120 int mode;
2121 struct vnode *dvp;
2122 struct vnode **vpp;
2123 struct componentname *cnp;
2124 {
2125 register struct inode *ip, *pdir;
2126 struct timeval tv;
2127 struct vnode *tvp;
2128 int error;
2129
2130 pdir = VTOI(dvp);
2131 #ifdef DIAGNOSTIC
2132 if ((cnp->cn_flags & HASBUF) == 0)
2133 panic("ufs_makeinode: no name");
2134 #endif
2135 *vpp = NULL;
2136 if ((mode & IFMT) == 0)
2137 mode |= IFREG;
2138
2139 error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
2140 if (error) {
2141 free(cnp->cn_pnbuf, M_NAMEI);
2142 vput(dvp);
2143 return (error);
2144 }
2145 ip = VTOI(tvp);
2146 ip->i_gid = pdir->i_gid;
2147 ip->i_uid = cnp->cn_cred->cr_uid;
2148 #ifdef QUOTA
2149 if ((error = getinoquota(ip)) ||
2150 (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
2151 free(cnp->cn_pnbuf, M_NAMEI);
2152 VOP_VFREE(tvp, ip->i_number, mode);
2153 vput(tvp);
2154 vput(dvp);
2155 return (error);
2156 }
2157 #endif
2158 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2159 ip->i_mode = mode;
2160 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
2161 ip->i_nlink = 1;
2162 if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
2163 suser(cnp->cn_cred, NULL))
2164 ip->i_mode &= ~ISGID;
2165
2166 /*
2167 * Make sure inode goes to disk before directory entry.
2168 */
2169 tv = time;
2170 error = VOP_UPDATE(tvp, &tv, &tv, 1);
2171 if (error)
2172 goto bad;
2173 #ifdef EXT2FS
2174 if (IS_EXT2_VNODE(dvp)) {
2175 error = ext2_direnter(ip, dvp, cnp);
2176 } else {
2177 error = ufs_direnter(ip, dvp, cnp);
2178 }
2179 #else
2180 error = ufs_direnter(ip, dvp, cnp);
2181 #endif /* EXT2FS */
2182 if (error)
2183 goto bad;
2184
2185 if ((cnp->cn_flags & SAVESTART) == 0)
2186 FREE(cnp->cn_pnbuf, M_NAMEI);
2187 vput(dvp);
2188 *vpp = tvp;
2189 return (0);
2190
2191 bad:
2192 /*
2193 * Write error occurred trying to update the inode
2194 * or the directory so must deallocate the inode.
2195 */
2196 free(cnp->cn_pnbuf, M_NAMEI);
2197 vput(dvp);
2198 ip->i_nlink = 0;
2199 ip->i_flag |= IN_CHANGE;
2200 vput(tvp);
2201 return (error);
2202 }
Cache object: 53033de3097fc02ab774852c0f0c3e3f
|