xref: /original-bsd/sys/ufs/ufs/ufs_vnops.c (revision acfb0788)
1 /*	ufs_vnops.c	6.14	84/08/29	*/
2 
3 #include "param.h"
4 #include "systm.h"
5 #include "dir.h"
6 #include "user.h"
7 #include "kernel.h"
8 #include "file.h"
9 #include "stat.h"
10 #include "inode.h"
11 #include "fs.h"
12 #include "buf.h"
13 #include "proc.h"
14 #include "quota.h"
15 #include "uio.h"
16 #include "socket.h"
17 #include "socketvar.h"
18 #include "mount.h"
19 
20 extern	struct fileops inodeops;
21 struct	file *getinode();
22 
23 /*
24  * Change current working directory (``.'').
25  */
26 chdir()
27 {
28 
29 	chdirec(&u.u_cdir);
30 }
31 
32 /*
33  * Change notion of root (``/'') directory.
34  */
35 chroot()
36 {
37 
38 	if (suser())
39 		chdirec(&u.u_rdir);
40 }
41 
42 /*
43  * Common routine for chroot and chdir.
44  */
45 chdirec(ipp)
46 	register struct inode **ipp;
47 {
48 	register struct inode *ip;
49 	struct a {
50 		char	*fname;
51 	} *uap = (struct a *)u.u_ap;
52 	register struct nameidata *ndp = &u.u_nd;
53 
54 	ndp->ni_nameiop = LOOKUP | FOLLOW;
55 	ndp->ni_segflg = UIO_USERSPACE;
56 	ndp->ni_dirp = uap->fname;
57 	ip = namei(ndp);
58 	if (ip == NULL)
59 		return;
60 	if ((ip->i_mode&IFMT) != IFDIR) {
61 		u.u_error = ENOTDIR;
62 		goto bad;
63 	}
64 	if (access(ip, IEXEC))
65 		goto bad;
66 	IUNLOCK(ip);
67 	if (*ipp)
68 		irele(*ipp);
69 	*ipp = ip;
70 	return;
71 
72 bad:
73 	iput(ip);
74 }
75 
76 /*
77  * Open system call.
78  */
79 open()
80 {
81 	struct a {
82 		char	*fname;
83 		int	mode;
84 		int	crtmode;
85 	} *uap = (struct a *) u.u_ap;
86 
87 	copen(uap->mode-FOPEN, uap->crtmode, uap->fname);
88 }
89 
90 /*
91  * Creat system call.
92  */
93 creat()
94 {
95 	struct a {
96 		char	*fname;
97 		int	fmode;
98 	} *uap = (struct a *)u.u_ap;
99 
100 	copen(FWRITE|FCREAT|FTRUNC, uap->fmode, uap->fname);
101 }
102 
103 /*
104  * Common code for open and creat.
105  * Check permissions, allocate an open file structure,
106  * and call the device open routine if any.
107  */
108 copen(mode, arg, fname)
109 	register int mode;
110 	int arg;
111 	caddr_t fname;
112 {
113 	register struct inode *ip;
114 	register struct file *fp;
115 	register struct nameidata *ndp = &u.u_nd;
116 	int i;
117 
118 #ifdef notdef
119 	if ((mode&(FREAD|FWRITE)) == 0) {
120 		u.u_error = EINVAL;
121 		return;
122 	}
123 #endif
124 	ndp->ni_segflg = UIO_USERSPACE;
125 	ndp->ni_dirp = fname;
126 	if (mode&FCREAT) {
127 		ndp->ni_nameiop = CREATE | FOLLOW;
128 		ip = namei(ndp);
129 		if (ip == NULL) {
130 			if (u.u_error)
131 				return;
132 			ip = maknode(arg&07777&(~ISVTX), ndp);
133 			if (ip == NULL)
134 				return;
135 			mode &= ~FTRUNC;
136 		} else {
137 			if (mode&FEXCL) {
138 				u.u_error = EEXIST;
139 				iput(ip);
140 				return;
141 			}
142 			mode &= ~FCREAT;
143 		}
144 	} else {
145 		ndp->ni_nameiop = LOOKUP | FOLLOW;
146 		ip = namei(ndp);
147 		if (ip == NULL)
148 			return;
149 	}
150 	if ((ip->i_mode & IFMT) == IFSOCK) {
151 		u.u_error = EOPNOTSUPP;
152 		goto bad;
153 	}
154 	if ((mode&FCREAT) == 0) {
155 		if (mode&FREAD)
156 			if (access(ip, IREAD))
157 				goto bad;
158 		if (mode&(FWRITE|FTRUNC)) {
159 			if (access(ip, IWRITE))
160 				goto bad;
161 			if ((ip->i_mode&IFMT) == IFDIR) {
162 				u.u_error = EISDIR;
163 				goto bad;
164 			}
165 		}
166 	}
167 	fp = falloc();
168 	if (fp == NULL)
169 		goto bad;
170 	if (mode&FTRUNC)
171 		itrunc(ip, (u_long)0);
172 	IUNLOCK(ip);
173 	fp->f_flag = mode&FMASK;
174 	fp->f_type = DTYPE_INODE;
175 	fp->f_ops = &inodeops;
176 	fp->f_data = (caddr_t)ip;
177 	i = u.u_r.r_val1;
178 	if (setjmp(&u.u_qsave)) {
179 		if (u.u_error == 0)
180 			u.u_error = EINTR;
181 		u.u_ofile[i] = NULL;
182 		closef(fp);
183 		return;
184 	}
185 	u.u_error = openi(ip, mode);
186 	if (u.u_error == 0)
187 		return;
188 	u.u_ofile[i] = NULL;
189 	fp->f_count--;
190 	irele(ip);
191 	return;
192 bad:
193 	iput(ip);
194 }
195 
196 /*
197  * Mknod system call
198  */
199 mknod()
200 {
201 	register struct inode *ip;
202 	register struct a {
203 		char	*fname;
204 		int	fmode;
205 		int	dev;
206 	} *uap = (struct a *)u.u_ap;
207 	register struct nameidata *ndp = &u.u_nd;
208 
209 	if (!suser())
210 		return;
211 	ndp->ni_nameiop = CREATE;
212 	ndp->ni_segflg = UIO_USERSPACE;
213 	ndp->ni_dirp = uap->fname;
214 	ip = namei(ndp);
215 	if (ip != NULL) {
216 		u.u_error = EEXIST;
217 		goto out;
218 	}
219 	if (u.u_error)
220 		return;
221 	ip = maknode(uap->fmode, ndp);
222 	if (ip == NULL)
223 		return;
224 	switch (ip->i_mode & IFMT) {
225 
226 	case IFMT:	/* used by badsect to flag bad sectors */
227 	case IFCHR:
228 	case IFBLK:
229 		if (uap->dev) {
230 			/*
231 			 * Want to be able to use this to make badblock
232 			 * inodes, so don't truncate the dev number.
233 			 */
234 			ip->i_rdev = uap->dev;
235 			ip->i_flag |= IACC|IUPD|ICHG;
236 		}
237 	}
238 
239 out:
240 	iput(ip);
241 }
242 
243 /*
244  * link system call
245  */
246 link()
247 {
248 	register struct inode *ip, *xp;
249 	register struct a {
250 		char	*target;
251 		char	*linkname;
252 	} *uap = (struct a *)u.u_ap;
253 	register struct nameidata *ndp = &u.u_nd;
254 
255 	ndp->ni_nameiop = LOOKUP | FOLLOW;
256 	ndp->ni_segflg = UIO_USERSPACE;
257 	ndp->ni_dirp = uap->target;
258 	ip = namei(ndp);	/* well, this routine is doomed anyhow */
259 	if (ip == NULL)
260 		return;
261 	if ((ip->i_mode&IFMT) == IFDIR && !suser()) {
262 		iput(ip);
263 		return;
264 	}
265 	ip->i_nlink++;
266 	ip->i_flag |= ICHG;
267 	iupdat(ip, &time, &time, 1);
268 	IUNLOCK(ip);
269 	ndp->ni_nameiop = CREATE;
270 	ndp->ni_segflg = UIO_USERSPACE;
271 	ndp->ni_dirp = (caddr_t)uap->linkname;
272 	xp = namei(ndp);
273 	if (xp != NULL) {
274 		u.u_error = EEXIST;
275 		iput(xp);
276 		goto out;
277 	}
278 	if (u.u_error)
279 		goto out;
280 	if (ndp->ni_pdir->i_dev != ip->i_dev) {
281 		iput(ndp->ni_pdir);
282 		u.u_error = EXDEV;
283 		goto out;
284 	}
285 	u.u_error = direnter(ip, ndp);
286 out:
287 	if (u.u_error) {
288 		ip->i_nlink--;
289 		ip->i_flag |= ICHG;
290 	}
291 	irele(ip);
292 }
293 
294 /*
295  * symlink -- make a symbolic link
296  */
297 symlink()
298 {
299 	register struct a {
300 		char	*target;
301 		char	*linkname;
302 	} *uap = (struct a *)u.u_ap;
303 	register struct inode *ip;
304 	register char *tp;
305 	register c, nc;
306 	register struct nameidata *ndp = &u.u_nd;
307 
308 	tp = uap->target;
309 	nc = 0;
310 	while (c = fubyte(tp)) {
311 		if (c < 0) {
312 			u.u_error = EFAULT;
313 			return;
314 		}
315 		tp++;
316 		nc++;
317 	}
318 	ndp->ni_nameiop = CREATE;
319 	ndp->ni_segflg = UIO_USERSPACE;
320 	ndp->ni_dirp = uap->linkname;
321 	ip = namei(ndp);
322 	if (ip) {
323 		iput(ip);
324 		u.u_error = EEXIST;
325 		return;
326 	}
327 	if (u.u_error)
328 		return;
329 	ip = maknode(IFLNK | 0777, ndp);
330 	if (ip == NULL)
331 		return;
332 	u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0);
333 	/* handle u.u_error != 0 */
334 	iput(ip);
335 }
336 
337 /*
338  * Unlink system call.
339  * Hard to avoid races here, especially
340  * in unlinking directories.
341  */
342 unlink()
343 {
344 	struct a {
345 		char	*fname;
346 	} *uap = (struct a *)u.u_ap;
347 	register struct inode *ip, *dp;
348 	register struct nameidata *ndp = &u.u_nd;
349 
350 	ndp->ni_nameiop = DELETE | LOCKPARENT;
351 	ndp->ni_segflg = UIO_USERSPACE;
352 	ndp->ni_dirp = uap->fname;
353 	ip = namei(ndp);
354 	if (ip == NULL)
355 		return;
356 	dp = ndp->ni_pdir;
357 	if ((ip->i_mode&IFMT) == IFDIR && !suser())
358 		goto out;
359 	/*
360 	 * Don't unlink a mounted file.
361 	 */
362 	if (ip->i_dev != dp->i_dev) {
363 		u.u_error = EBUSY;
364 		goto out;
365 	}
366 	if (ip->i_flag&ITEXT)
367 		xrele(ip);	/* try once to free text */
368 	if (dirremove(ndp)) {
369 		ip->i_nlink--;
370 		ip->i_flag |= ICHG;
371 	}
372 out:
373 	if (dp == ip)
374 		irele(ip);
375 	else
376 		iput(ip);
377 	iput(dp);
378 }
379 
380 /*
381  * Seek system call
382  */
383 lseek()
384 {
385 	register struct file *fp;
386 	register struct a {
387 		int	fd;
388 		off_t	off;
389 		int	sbase;
390 	} *uap = (struct a *)u.u_ap;
391 
392 	GETF(fp, uap->fd);
393 	if (fp->f_type != DTYPE_INODE) {
394 		u.u_error = ESPIPE;
395 		return;
396 	}
397 	switch (uap->sbase) {
398 
399 	case L_INCR:
400 		fp->f_offset += uap->off;
401 		break;
402 
403 	case L_XTND:
404 		fp->f_offset = uap->off + ((struct inode *)fp->f_data)->i_size;
405 		break;
406 
407 	case L_SET:
408 		fp->f_offset = uap->off;
409 		break;
410 
411 	default:
412 		u.u_error = EINVAL;
413 		return;
414 	}
415 	u.u_r.r_off = fp->f_offset;
416 }
417 
418 /*
419  * Access system call
420  */
421 saccess()
422 {
423 	register svuid, svgid;
424 	register struct inode *ip;
425 	register struct a {
426 		char	*fname;
427 		int	fmode;
428 	} *uap = (struct a *)u.u_ap;
429 	register struct nameidata *ndp = &u.u_nd;
430 
431 	svuid = u.u_uid;
432 	svgid = u.u_gid;
433 	u.u_uid = u.u_ruid;
434 	u.u_gid = u.u_rgid;
435 	ndp->ni_nameiop = LOOKUP | FOLLOW;
436 	ndp->ni_segflg = UIO_USERSPACE;
437 	ndp->ni_dirp = uap->fname;
438 	ip = namei(ndp);
439 	if (ip != NULL) {
440 		if ((uap->fmode&R_OK) && access(ip, IREAD))
441 			goto done;
442 		if ((uap->fmode&W_OK) && access(ip, IWRITE))
443 			goto done;
444 		if ((uap->fmode&X_OK) && access(ip, IEXEC))
445 			goto done;
446 done:
447 		iput(ip);
448 	}
449 	u.u_uid = svuid;
450 	u.u_gid = svgid;
451 }
452 
453 /*
454  * Stat system call.  This version follows links.
455  */
456 stat()
457 {
458 
459 	stat1(FOLLOW);
460 }
461 
462 /*
463  * Lstat system call.  This version does not follow links.
464  */
465 lstat()
466 {
467 
468 	stat1(NOFOLLOW);
469 }
470 
471 stat1(follow)
472 	int follow;
473 {
474 	register struct inode *ip;
475 	register struct a {
476 		char	*fname;
477 		struct stat *ub;
478 	} *uap = (struct a *)u.u_ap;
479 	struct stat sb;
480 	register struct nameidata *ndp = &u.u_nd;
481 
482 	ndp->ni_nameiop = LOOKUP | follow;
483 	ndp->ni_segflg = UIO_USERSPACE;
484 	ndp->ni_dirp = uap->fname;
485 	ip = namei(ndp);
486 	if (ip == NULL)
487 		return;
488 	(void) ino_stat(ip, &sb);
489 	iput(ip);
490 	u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
491 }
492 
493 /*
494  * Return target name of a symbolic link
495  */
496 readlink()
497 {
498 	register struct inode *ip;
499 	register struct a {
500 		char	*name;
501 		char	*buf;
502 		int	count;
503 	} *uap = (struct a *)u.u_ap;
504 	register struct nameidata *ndp = &u.u_nd;
505 	int resid;
506 
507 	ndp->ni_nameiop = LOOKUP;
508 	ndp->ni_segflg = UIO_USERSPACE;
509 	ndp->ni_dirp = uap->name;
510 	ip = namei(ndp);
511 	if (ip == NULL)
512 		return;
513 	if ((ip->i_mode&IFMT) != IFLNK) {
514 		u.u_error = ENXIO;
515 		goto out;
516 	}
517 	u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid);
518 out:
519 	iput(ip);
520 	u.u_r.r_val1 = uap->count - resid;
521 }
522 
523 /*
524  * Change mode of a file given path name.
525  */
526 chmod()
527 {
528 	struct inode *ip;
529 	struct a {
530 		char	*fname;
531 		int	fmode;
532 	} *uap = (struct a *)u.u_ap;
533 
534 	if ((ip = owner(uap->fname, FOLLOW)) == NULL)
535 		return;
536 	chmod1(ip, uap->fmode);
537 	iput(ip);
538 }
539 
540 /*
541  * Change mode of a file given a file descriptor.
542  */
543 fchmod()
544 {
545 	struct a {
546 		int	fd;
547 		int	fmode;
548 	} *uap = (struct a *)u.u_ap;
549 	register struct inode *ip;
550 	register struct file *fp;
551 
552 	fp = getinode(uap->fd);
553 	if (fp == NULL)
554 		return;
555 	ip = (struct inode *)fp->f_data;
556 	if (u.u_uid != ip->i_uid && !suser())
557 		return;
558 	ILOCK(ip);
559 	chmod1(ip, uap->fmode);
560 	IUNLOCK(ip);
561 }
562 
563 /*
564  * Change the mode on a file.
565  * Inode must be locked before calling.
566  */
567 chmod1(ip, mode)
568 	register struct inode *ip;
569 	register int mode;
570 {
571 
572 	ip->i_mode &= ~07777;
573 	if (u.u_uid) {
574 		mode &= ~ISVTX;
575 		if (!groupmember(ip->i_gid))
576 			mode &= ~ISGID;
577 	}
578 	ip->i_mode |= mode&07777;
579 	ip->i_flag |= ICHG;
580 	if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
581 		xrele(ip);
582 }
583 
584 /*
585  * Set ownership given a path name.
586  */
587 chown()
588 {
589 	struct inode *ip;
590 	struct a {
591 		char	*fname;
592 		int	uid;
593 		int	gid;
594 	} *uap = (struct a *)u.u_ap;
595 
596 	if (!suser() || (ip = owner(uap->fname, NOFOLLOW)) == NULL)
597 		return;
598 	u.u_error = chown1(ip, uap->uid, uap->gid);
599 	iput(ip);
600 }
601 
602 /*
603  * Set ownership given a file descriptor.
604  */
605 fchown()
606 {
607 	struct a {
608 		int	fd;
609 		int	uid;
610 		int	gid;
611 	} *uap = (struct a *)u.u_ap;
612 	register struct inode *ip;
613 	register struct file *fp;
614 
615 	fp = getinode(uap->fd);
616 	if (fp == NULL)
617 		return;
618 	ip = (struct inode *)fp->f_data;
619 	if (!suser())
620 		return;
621 	ILOCK(ip);
622 	u.u_error = chown1(ip, uap->uid, uap->gid);
623 	IUNLOCK(ip);
624 }
625 
626 /*
627  * Perform chown operation on inode ip;
628  * inode must be locked prior to call.
629  */
630 chown1(ip, uid, gid)
631 	register struct inode *ip;
632 	int uid, gid;
633 {
634 #ifdef QUOTA
635 	register long change;
636 #endif
637 
638 	if (uid == -1)
639 		uid = ip->i_uid;
640 	if (gid == -1)
641 		gid = ip->i_gid;
642 #ifdef QUOTA
643 	if (ip->i_uid == uid)		/* this just speeds things a little */
644 		change = 0;
645 	else
646 		change = ip->i_blocks;
647 	(void) chkdq(ip, -change, 1);
648 	(void) chkiq(ip->i_dev, ip, ip->i_uid, 1);
649 	dqrele(ip->i_dquot);
650 #endif
651 	ip->i_uid = uid;
652 	ip->i_gid = gid;
653 	ip->i_flag |= ICHG;
654 	if (u.u_ruid != 0)
655 		ip->i_mode &= ~(ISUID|ISGID);
656 #ifdef QUOTA
657 	ip->i_dquot = inoquota(ip);
658 	(void) chkdq(ip, change, 1);
659 	(void) chkiq(ip->i_dev, (struct inode *)NULL, uid, 1);
660 	return (u.u_error);		/* should == 0 ALWAYS !! */
661 #else
662 	return (0);
663 #endif
664 }
665 
666 utimes()
667 {
668 	register struct a {
669 		char	*fname;
670 		struct	timeval *tptr;
671 	} *uap = (struct a *)u.u_ap;
672 	register struct inode *ip;
673 	struct timeval tv[2];
674 
675 	if ((ip = owner(uap->fname, FOLLOW)) == NULL)
676 		return;
677 	u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
678 	if (u.u_error == 0) {
679 		ip->i_flag |= IACC|IUPD|ICHG;
680 		iupdat(ip, &tv[0], &tv[1], 0);
681 	}
682 	iput(ip);
683 }
684 
685 /*
686  * Flush any pending I/O.
687  */
688 sync()
689 {
690 
691 	update();
692 }
693 
694 /*
695  * Truncate a file given its path name.
696  */
697 truncate()
698 {
699 	struct a {
700 		char	*fname;
701 		u_long	length;
702 	} *uap = (struct a *)u.u_ap;
703 	struct inode *ip;
704 	register struct nameidata *ndp = &u.u_nd;
705 
706 	ndp->ni_nameiop = LOOKUP | FOLLOW;
707 	ndp->ni_segflg = UIO_USERSPACE;
708 	ndp->ni_dirp = uap->fname;
709 	ip = namei(ndp);
710 	if (ip == NULL)
711 		return;
712 	if (access(ip, IWRITE))
713 		goto bad;
714 	if ((ip->i_mode&IFMT) == IFDIR) {
715 		u.u_error = EISDIR;
716 		goto bad;
717 	}
718 	itrunc(ip, uap->length);
719 bad:
720 	iput(ip);
721 }
722 
723 /*
724  * Truncate a file given a file descriptor.
725  */
726 ftruncate()
727 {
728 	struct a {
729 		int	fd;
730 		u_long	length;
731 	} *uap = (struct a *)u.u_ap;
732 	struct inode *ip;
733 	struct file *fp;
734 
735 	fp = getinode(uap->fd);
736 	if (fp == NULL)
737 		return;
738 	if ((fp->f_flag&FWRITE) == 0) {
739 		u.u_error = EINVAL;
740 		return;
741 	}
742 	ip = (struct inode *)fp->f_data;
743 	ILOCK(ip);
744 	itrunc(ip, uap->length);
745 	IUNLOCK(ip);
746 }
747 
748 /*
749  * Synch an open file.
750  */
751 fsync()
752 {
753 	struct a {
754 		int	fd;
755 	} *uap = (struct a *)u.u_ap;
756 	struct inode *ip;
757 	struct file *fp;
758 
759 	fp = getinode(uap->fd);
760 	if (fp == NULL)
761 		return;
762 	ip = (struct inode *)fp->f_data;
763 	ILOCK(ip);
764 	syncip(ip);
765 	IUNLOCK(ip);
766 }
767 
768 /*
769  * Rename system call.
770  * 	rename("foo", "bar");
771  * is essentially
772  *	unlink("bar");
773  *	link("foo", "bar");
774  *	unlink("foo");
775  * but ``atomically''.  Can't do full commit without saving state in the
776  * inode on disk which isn't feasible at this time.  Best we can do is
777  * always guarantee the target exists.
778  *
779  * Basic algorithm is:
780  *
781  * 1) Bump link count on source while we're linking it to the
782  *    target.  This also insure the inode won't be deleted out
783  *    from underneath us while we work (it may be truncated by
784  *    a concurrent `trunc' or `open' for creation).
785  * 2) Link source to destination.  If destination already exists,
786  *    delete it first.
787  * 3) Unlink source reference to inode if still around. If a
788  *    directory was moved and the parent of the destination
789  *    is different from the source, patch the ".." entry in the
790  *    directory.
791  *
792  * Source and destination must either both be directories, or both
793  * not be directories.  If target is a directory, it must be empty.
794  */
795 rename()
796 {
797 	struct a {
798 		char	*from;
799 		char	*to;
800 	} *uap = (struct a *)u.u_ap;
801 	register struct inode *ip, *xp, *dp;
802 	struct dirtemplate dirbuf;
803 	int doingdirectory = 0, oldparent = 0, newparent = 0;
804 	register struct nameidata *ndp = &u.u_nd;
805 	int error = 0;
806 
807 	ndp->ni_nameiop = DELETE | LOCKPARENT;
808 	ndp->ni_segflg = UIO_USERSPACE;
809 	ndp->ni_dirp = uap->from;
810 	ip = namei(ndp);
811 	if (ip == NULL)
812 		return;
813 	dp = ndp->ni_pdir;
814 	if ((ip->i_mode&IFMT) == IFDIR) {
815 		register struct direct *d;
816 
817 		d = &ndp->ni_dent;
818 		/*
819 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
820 		 */
821 		if ((d->d_namlen == 1 && d->d_name[0] == '.') ||
822 		    (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) ||
823 		    (dp == ip) || (ip->i_flag & IRENAME)) {
824 			iput(dp);
825 			if (dp == ip)
826 				irele(ip);
827 			else
828 				iput(ip);
829 			u.u_error = EINVAL;
830 			return;
831 		}
832 		ip->i_flag |= IRENAME;
833 		oldparent = dp->i_number;
834 		doingdirectory++;
835 	}
836 	iput(dp);
837 
838 	/*
839 	 * 1) Bump link count while we're moving stuff
840 	 *    around.  If we crash somewhere before
841 	 *    completing our work, the link count
842 	 *    may be wrong, but correctable.
843 	 */
844 	ip->i_nlink++;
845 	ip->i_flag |= ICHG;
846 	iupdat(ip, &time, &time, 1);
847 	IUNLOCK(ip);
848 
849 	/*
850 	 * When the target exists, both the directory
851 	 * and target inodes are returned locked.
852 	 */
853 	ndp->ni_nameiop = CREATE | LOCKPARENT | NOCACHE;
854 	ndp->ni_dirp = (caddr_t)uap->to;
855 	xp = namei(ndp);
856 	if (u.u_error) {
857 		error = u.u_error;
858 		goto out;
859 	}
860 	dp = ndp->ni_pdir;
861 	/*
862 	 * If ".." must be changed (ie the directory gets a new
863 	 * parent) then the source directory must not be in the
864 	 * directory heirarchy above the target, as this would
865 	 * orphan everything below the source directory. Also
866 	 * the user must have write permission in the source so
867 	 * as to be able to change "..". We must repeat the call
868 	 * to namei, as the parent directory is unlocked by the
869 	 * call to checkpath().
870 	 */
871 	if (oldparent != dp->i_number)
872 		newparent = dp->i_number;
873 	if (doingdirectory && newparent) {
874 		if (access(ip, IWRITE))
875 			goto bad;
876 		do {
877 			dp = ndp->ni_pdir;
878 			if (xp != NULL)
879 				iput(xp);
880 			u.u_error = checkpath(ip, dp);
881 			if (u.u_error)
882 				goto out;
883 			xp = namei(ndp);
884 			if (u.u_error) {
885 				error = u.u_error;
886 				goto out;
887 			}
888 		} while (dp != ndp->ni_pdir);
889 	}
890 	/*
891 	 * 2) If target doesn't exist, link the target
892 	 *    to the source and unlink the source.
893 	 *    Otherwise, rewrite the target directory
894 	 *    entry to reference the source inode and
895 	 *    expunge the original entry's existence.
896 	 */
897 	if (xp == NULL) {
898 		if (dp->i_dev != ip->i_dev) {
899 			error = EXDEV;
900 			goto bad;
901 		}
902 		/*
903 		 * Account for ".." in new directory.
904 		 * When source and destination have the same
905 		 * parent we don't fool with the link count.
906 		 */
907 		if (doingdirectory && newparent) {
908 			dp->i_nlink++;
909 			dp->i_flag |= ICHG;
910 			iupdat(dp, &time, &time, 1);
911 		}
912 		error = direnter(ip, ndp);
913 		if (error)
914 			goto out;
915 	} else {
916 		if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) {
917 			error = EXDEV;
918 			goto bad;
919 		}
920 		/*
921 		 * Short circuit rename(foo, foo).
922 		 */
923 		if (xp->i_number == ip->i_number)
924 			goto bad;
925 		/*
926 		 * Target must be empty if a directory
927 		 * and have no links to it.
928 		 * Also, insure source and target are
929 		 * compatible (both directories, or both
930 		 * not directories).
931 		 */
932 		if ((xp->i_mode&IFMT) == IFDIR) {
933 			if (!dirempty(xp, dp->i_number) || xp->i_nlink > 2) {
934 				error = ENOTEMPTY;
935 				goto bad;
936 			}
937 			if (!doingdirectory) {
938 				error = ENOTDIR;
939 				goto bad;
940 			}
941 			cacheinval(dp);
942 		} else if (doingdirectory) {
943 			error = EISDIR;
944 			goto bad;
945 		}
946 		dirrewrite(dp, ip, ndp);
947 		if (u.u_error) {
948 			error = u.u_error;
949 			goto bad1;
950 		}
951 		/*
952 		 * Adjust the link count of the target to
953 		 * reflect the dirrewrite above.  If this is
954 		 * a directory it is empty and there are
955 		 * no links to it, so we can squash the inode and
956 		 * any space associated with it.  We disallowed
957 		 * renaming over top of a directory with links to
958 		 * it above, as the remaining link would point to
959 		 * a directory without "." or ".." entries.
960 		 */
961 		xp->i_nlink--;
962 		if (doingdirectory) {
963 			if (--xp->i_nlink != 0)
964 				panic("rename: linked directory");
965 			itrunc(xp, (u_long)0);
966 		}
967 		xp->i_flag |= ICHG;
968 		iput(xp);
969 		xp = NULL;
970 	}
971 
972 	/*
973 	 * 3) Unlink the source.
974 	 */
975 	ndp->ni_nameiop = DELETE | LOCKPARENT;
976 	ndp->ni_segflg = UIO_USERSPACE;
977 	ndp->ni_dirp = uap->from;
978 	xp = namei(ndp);
979 	dp = ndp->ni_pdir;
980 	/*
981 	 * Insure that the directory entry still exists and has not
982 	 * changed while the new name has been entered. If the source is
983 	 * a file then the entry may have been unlinked or renamed. In
984 	 * either case there is no further work to be done. If the source
985 	 * is a directory then it cannot have been rmdir'ed; its link
986 	 * count of three would cause a rmdir to fail with ENOTEMPTY.
987 	 * The IRENAME flag insures that it cannot be moved by another
988 	 * rename.
989 	 */
990 	if (dp == NULL || xp != ip) {
991 		if (doingdirectory)
992 			panic("rename: lost entry");
993 	} else {
994 		/*
995 		 * If the source is a directory with a
996 		 * new parent, the link count of the old
997 		 * parent directory must be decremented
998 		 * and ".." set to point to the new parent.
999 		 */
1000 		if (doingdirectory && newparent) {
1001 			dp->i_nlink--;
1002 			dp->i_flag |= ICHG;
1003 			error = rdwri(UIO_READ, xp, (caddr_t)&dirbuf,
1004 				sizeof (struct dirtemplate), (off_t)0, 1,
1005 				(int *)0);
1006 			if (error == 0) {
1007 				if (dirbuf.dotdot_namlen != 2 ||
1008 				    dirbuf.dotdot_name[0] != '.' ||
1009 				    dirbuf.dotdot_name[1] != '.') {
1010 					printf("rename: mangled dir\n");
1011 				} else {
1012 					dirbuf.dotdot_ino = newparent;
1013 					(void) rdwri(UIO_WRITE, xp,
1014 					    (caddr_t)&dirbuf,
1015 					    sizeof (struct dirtemplate),
1016 					    (off_t)0, 1, (int *)0);
1017 					cacheinval(dp);
1018 				}
1019 			}
1020 		}
1021 		if (dirremove(ndp)) {
1022 			xp->i_nlink--;
1023 			xp->i_flag |= ICHG;
1024 		}
1025 		xp->i_flag &= ~IRENAME;
1026 		if (error == 0)		/* XXX conservative */
1027 			error = u.u_error;
1028 	}
1029 	if (dp)
1030 		iput(dp);
1031 	if (xp)
1032 		iput(xp);
1033 	irele(ip);
1034 	if (error)
1035 		u.u_error = error;
1036 	return;
1037 
1038 bad:
1039 	iput(dp);
1040 bad1:
1041 	if (xp)
1042 		iput(xp);
1043 out:
1044 	ip->i_nlink--;
1045 	ip->i_flag |= ICHG;
1046 	irele(ip);
1047 	if (error)
1048 		u.u_error = error;
1049 }
1050 
1051 /*
1052  * Make a new file.
1053  */
1054 struct inode *
1055 maknode(mode, ndp)
1056 	int mode;
1057 	register struct nameidata *ndp;
1058 {
1059 	register struct inode *ip;
1060 	register struct inode *pdir = ndp->ni_pdir;
1061 	ino_t ipref;
1062 
1063 	if ((mode & IFMT) == IFDIR)
1064 		ipref = dirpref(pdir->i_fs);
1065 	else
1066 		ipref = pdir->i_number;
1067 	ip = ialloc(pdir, ipref, mode);
1068 	if (ip == NULL) {
1069 		iput(pdir);
1070 		return (NULL);
1071 	}
1072 #ifdef QUOTA
1073 	if (ip->i_dquot != NODQUOT)
1074 		panic("maknode: dquot");
1075 #endif
1076 	ip->i_flag |= IACC|IUPD|ICHG;
1077 	if ((mode & IFMT) == 0)
1078 		mode |= IFREG;
1079 	ip->i_mode = mode & ~u.u_cmask;
1080 	ip->i_nlink = 1;
1081 	ip->i_uid = u.u_uid;
1082 	ip->i_gid = pdir->i_gid;
1083 	if (ip->i_mode & ISGID && !groupmember(ip->i_gid))
1084 		ip->i_mode &= ~ISGID;
1085 #ifdef QUOTA
1086 	ip->i_dquot = inoquota(ip);
1087 #endif
1088 
1089 	/*
1090 	 * Make sure inode goes to disk before directory entry.
1091 	 */
1092 	iupdat(ip, &time, &time, 1);
1093 	u.u_error = direnter(ip, ndp);
1094 	if (u.u_error) {
1095 		/*
1096 		 * Write error occurred trying to update directory
1097 		 * so must deallocate the inode.
1098 		 */
1099 		ip->i_nlink = 0;
1100 		ip->i_flag |= ICHG;
1101 		iput(ip);
1102 		return (NULL);
1103 	}
1104 	return (ip);
1105 }
1106 
1107 /*
1108  * A virgin directory (no blushing please).
1109  */
1110 struct dirtemplate mastertemplate = {
1111 	0, 12, 1, ".",
1112 	0, DIRBLKSIZ - 12, 2, ".."
1113 };
1114 
1115 /*
1116  * Mkdir system call
1117  */
1118 mkdir()
1119 {
1120 	struct a {
1121 		char	*name;
1122 		int	dmode;
1123 	} *uap = (struct a *)u.u_ap;
1124 	register struct inode *ip, *dp;
1125 	struct dirtemplate dirtemplate;
1126 	register struct nameidata *ndp = &u.u_nd;
1127 
1128 	ndp->ni_nameiop = CREATE;
1129 	ndp->ni_segflg = UIO_USERSPACE;
1130 	ndp->ni_dirp = uap->name;
1131 	ip = namei(ndp);
1132 	if (u.u_error)
1133 		return;
1134 	if (ip != NULL) {
1135 		iput(ip);
1136 		u.u_error = EEXIST;
1137 		return;
1138 	}
1139 	dp = ndp->ni_pdir;
1140 	uap->dmode &= 0777;
1141 	uap->dmode |= IFDIR;
1142 	/*
1143 	 * Must simulate part of maknode here
1144 	 * in order to acquire the inode, but
1145 	 * not have it entered in the parent
1146 	 * directory.  The entry is made later
1147 	 * after writing "." and ".." entries out.
1148 	 */
1149 	ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode);
1150 	if (ip == NULL) {
1151 		iput(dp);
1152 		return;
1153 	}
1154 #ifdef QUOTA
1155 	if (ip->i_dquot != NODQUOT)
1156 		panic("mkdir: dquot");
1157 #endif
1158 	ip->i_flag |= IACC|IUPD|ICHG;
1159 	ip->i_mode = uap->dmode & ~u.u_cmask;
1160 	ip->i_nlink = 2;
1161 	ip->i_uid = u.u_uid;
1162 	ip->i_gid = dp->i_gid;
1163 #ifdef QUOTA
1164 	ip->i_dquot = inoquota(ip);
1165 #endif
1166 	iupdat(ip, &time, &time, 1);
1167 
1168 	/*
1169 	 * Bump link count in parent directory
1170 	 * to reflect work done below.  Should
1171 	 * be done before reference is created
1172 	 * so reparation is possible if we crash.
1173 	 */
1174 	dp->i_nlink++;
1175 	dp->i_flag |= ICHG;
1176 	iupdat(dp, &time, &time, 1);
1177 
1178 	/*
1179 	 * Initialize directory with "."
1180 	 * and ".." from static template.
1181 	 */
1182 	dirtemplate = mastertemplate;
1183 	dirtemplate.dot_ino = ip->i_number;
1184 	dirtemplate.dotdot_ino = dp->i_number;
1185 	u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate,
1186 		sizeof (dirtemplate), (off_t)0, 1, (int *)0);
1187 	if (u.u_error) {
1188 		dp->i_nlink--;
1189 		dp->i_flag |= ICHG;
1190 		goto bad;
1191 	}
1192 	/*
1193 	 * Directory all set up, now
1194 	 * install the entry for it in
1195 	 * the parent directory.
1196 	 */
1197 	u.u_error = direnter(ip, ndp);
1198 	dp = NULL;
1199 	if (u.u_error) {
1200 		ndp->ni_nameiop = LOOKUP | NOCACHE;
1201 		ndp->ni_segflg = UIO_USERSPACE;
1202 		ndp->ni_dirp = uap->name;
1203 		dp = namei(ndp);
1204 		if (dp) {
1205 			dp->i_nlink--;
1206 			dp->i_flag |= ICHG;
1207 		}
1208 	}
1209 bad:
1210 	/*
1211 	 * No need to do an explicit itrunc here,
1212 	 * irele will do this for us because we set
1213 	 * the link count to 0.
1214 	 */
1215 	if (u.u_error) {
1216 		ip->i_nlink = 0;
1217 		ip->i_flag |= ICHG;
1218 	}
1219 	if (dp)
1220 		iput(dp);
1221 	iput(ip);
1222 }
1223 
1224 /*
1225  * Rmdir system call.
1226  */
1227 rmdir()
1228 {
1229 	struct a {
1230 		char	*name;
1231 	} *uap = (struct a *)u.u_ap;
1232 	register struct inode *ip, *dp;
1233 	register struct nameidata *ndp = &u.u_nd;
1234 
1235 	ndp->ni_nameiop = DELETE | LOCKPARENT;
1236 	ndp->ni_segflg = UIO_USERSPACE;
1237 	ndp->ni_dirp = uap->name;
1238 	ip = namei(ndp);
1239 	if (ip == NULL)
1240 		return;
1241 	dp = ndp->ni_pdir;
1242 	/*
1243 	 * No rmdir "." please.
1244 	 */
1245 	if (dp == ip) {
1246 		irele(dp);
1247 		iput(ip);
1248 		u.u_error = EINVAL;
1249 		return;
1250 	}
1251 	if ((ip->i_mode&IFMT) != IFDIR) {
1252 		u.u_error = ENOTDIR;
1253 		goto out;
1254 	}
1255 	/*
1256 	 * Don't remove a mounted on directory.
1257 	 */
1258 	if (ip->i_dev != dp->i_dev) {
1259 		u.u_error = EBUSY;
1260 		goto out;
1261 	}
1262 	/*
1263 	 * Verify the directory is empty (and valid).
1264 	 * (Rmdir ".." won't be valid since
1265 	 *  ".." will contain a reference to
1266 	 *  the current directory and thus be
1267 	 *  non-empty.)
1268 	 */
1269 	if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number)) {
1270 		u.u_error = ENOTEMPTY;
1271 		goto out;
1272 	}
1273 	/*
1274 	 * Delete reference to directory before purging
1275 	 * inode.  If we crash in between, the directory
1276 	 * will be reattached to lost+found,
1277 	 */
1278 	if (dirremove(ndp) == 0)
1279 		goto out;
1280 	dp->i_nlink--;
1281 	dp->i_flag |= ICHG;
1282 	cacheinval(dp);
1283 	iput(dp);
1284 	dp = NULL;
1285 	/*
1286 	 * Truncate inode.  The only stuff left
1287 	 * in the directory is "." and "..".  The
1288 	 * "." reference is inconsequential since
1289 	 * we're quashing it.  The ".." reference
1290 	 * has already been adjusted above.  We've
1291 	 * removed the "." reference and the reference
1292 	 * in the parent directory, but there may be
1293 	 * other hard links so decrement by 2 and
1294 	 * worry about them later.
1295 	 */
1296 	ip->i_nlink -= 2;
1297 	itrunc(ip, (u_long)0);
1298 	cacheinval(ip);
1299 out:
1300 	if (dp)
1301 		iput(dp);
1302 	iput(ip);
1303 }
1304 
1305 struct file *
1306 getinode(fdes)
1307 	int fdes;
1308 {
1309 	struct file *fp;
1310 
1311 	if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) {
1312 		u.u_error = EBADF;
1313 		return ((struct file *)0);
1314 	}
1315 	if (fp->f_type != DTYPE_INODE) {
1316 		u.u_error = EINVAL;
1317 		return ((struct file *)0);
1318 	}
1319 	return (fp);
1320 }
1321 
1322 /*
1323  * mode mask for creation of files
1324  */
1325 umask()
1326 {
1327 	register struct a {
1328 		int	mask;
1329 	} *uap = (struct a *)u.u_ap;
1330 
1331 	u.u_r.r_val1 = u.u_cmask;
1332 	u.u_cmask = uap->mask & 07777;
1333 }
1334