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