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