xref: /csrg-svn/sys/ufs/lfs/lfs_vnops.c (revision 7535)
1 /*	lfs_vnops.c	4.31	82/07/25	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/file.h"
8 #include "../h/stat.h"
9 #include "../h/inode.h"
10 #include "../h/fs.h"
11 #include "../h/buf.h"
12 #include "../h/proc.h"
13 #include "../h/inline.h"
14 #ifdef EFS
15 #include "../net/in.h"
16 #include "../h/efs.h"
17 #endif
18 #include "../h/quota.h"
19 #include "../h/descrip.h"
20 
21 chdir()
22 {
23 
24 	chdirec(&u.u_cdir);
25 }
26 
27 chroot()
28 {
29 
30 	if (suser())
31 		chdirec(&u.u_rdir);
32 }
33 
34 chdirec(ipp)
35 register struct inode **ipp;
36 {
37 	register struct inode *ip;
38 	struct a {
39 		char	*fname;
40 	};
41 
42 	ip = namei(uchar, 0, 1);
43 	if(ip == NULL)
44 		return;
45 	if((ip->i_mode&IFMT) != IFDIR) {
46 		u.u_error = ENOTDIR;
47 		goto bad;
48 	}
49 	if(access(ip, IEXEC))
50 		goto bad;
51 	iunlock(ip);
52 	if (*ipp)
53 		irele(*ipp);
54 	*ipp = ip;
55 	return;
56 
57 bad:
58 	iput(ip);
59 }
60 
61 /*
62  * Open system call.
63  */
64 open()
65 {
66 	register struct inode *ip;
67 	register struct a {
68 		char	*fname;
69 		int	rwmode;
70 	} *uap;
71 
72 	uap = (struct a *)u.u_ap;
73 	ip = namei(uchar, 0, 1);
74 	if (ip == NULL)
75 		return;
76 	open1(ip, ++uap->rwmode, 0);
77 }
78 
79 /*
80  * Creat system call.
81  */
82 ocreat()
83 {
84 	register struct inode *ip;
85 	register struct a {
86 		char	*fname;
87 		int	fmode;
88 	} *uap;
89 
90 	uap = (struct a *)u.u_ap;
91 	ip = namei(uchar, 1, 1);
92 	if (ip == NULL) {
93 		if (u.u_error)
94 			return;
95 		ip = maknode(uap->fmode&07777&(~ISVTX));
96 		if (ip==NULL)
97 			return;
98 		open1(ip, FWRITE, 2);
99 	} else
100 		open1(ip, FWRITE, 1);
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 open1(ip, mode, trf)
109 	register struct inode *ip;
110 	register mode;
111 {
112 	register struct file *fp;
113 	int i;
114 
115 	if (trf != 2) {
116 		if (mode&FREAD)
117 			(void) access(ip, IREAD);
118 		if (mode&FWRITE) {
119 			(void) access(ip, IWRITE);
120 			if ((ip->i_mode&IFMT) == IFDIR)
121 				u.u_error = EISDIR;
122 		}
123 	}
124 	if (u.u_error) {
125 		iput(ip);
126 		return;
127 	}
128 	if (trf == 1)
129 		itrunc(ip);
130 	iunlock(ip);
131 	if ((fp = falloc()) == NULL)
132 		goto out;
133 	fp->f_flag = mode&(FREAD|FWRITE);
134 	fp->f_type = DTYPE_FILE;
135 	i = u.u_r.r_val1;
136 	fp->f_inode = ip;
137 #ifdef EFS
138 	openi(ip, mode&(FREAD|FWRITE), trf);
139 #else
140 	openi(ip, mode&(FREAD|FWRITE));
141 #endif
142 	if (u.u_error == 0)
143 		return;
144 	u.u_ofile[i] = NULL;
145 	fp->f_count--;
146 out:
147 	irele(ip);
148 }
149 
150 /*
151  * Mknod system call
152  */
153 mknod()
154 {
155 	register struct inode *ip;
156 	register struct a {
157 		char	*fname;
158 		int	fmode;
159 		int	dev;
160 	} *uap;
161 
162 	uap = (struct a *)u.u_ap;
163 	if (suser()) {
164 		ip = namei(uchar, 1, 0);
165 		if (ip != NULL) {
166 			u.u_error = EEXIST;
167 			goto out;
168 		}
169 	}
170 	if (u.u_error)
171 		return;
172 	ip = maknode(uap->fmode);
173 	if (ip == NULL)
174 		return;
175 	if (uap->dev) {
176 		/*
177 		 * Want to be able to use this to make badblock
178 		 * inodes, so don't truncate the dev number.
179 		 */
180 		ip->i_rdev = uap->dev;
181 		ip->i_flag |= IACC|IUPD|ICHG;
182 	}
183 
184 out:
185 	iput(ip);
186 }
187 
188 /*
189  * link system call
190  */
191 link()
192 {
193 	register struct inode *ip, *xp;
194 	register struct a {
195 		char	*target;
196 		char	*linkname;
197 	} *uap;
198 
199 	uap = (struct a *)u.u_ap;
200 	ip = namei(uchar, 0, 1);    /* well, this routine is doomed anyhow */
201 	if (ip == NULL)
202 		return;
203 	if ((ip->i_mode&IFMT)==IFDIR && !suser()) {
204 		iput(ip);
205 		return;
206 	}
207 	ip->i_nlink++;
208 	ip->i_flag |= ICHG;
209 	iupdat(ip, &time, &time, 1);
210 	iunlock(ip);
211 	u.u_dirp = (caddr_t)uap->linkname;
212 	xp = namei(uchar, 1, 0);
213 	if (xp != NULL) {
214 		u.u_error = EEXIST;
215 		iput(xp);
216 		goto out;
217 	}
218 	if (u.u_error)
219 		goto out;
220 	if (u.u_pdir->i_dev != ip->i_dev) {
221 		iput(u.u_pdir);
222 		u.u_error = EXDEV;
223 		goto out;
224 	}
225 	direnter(ip);
226 out:
227 	if (u.u_error) {
228 		ip->i_nlink--;
229 		ip->i_flag |= ICHG;
230 	}
231 out1:
232 	irele(ip);
233 }
234 
235 /*
236  * symlink -- make a symbolic link
237  */
238 symlink()
239 {
240 	register struct a {
241 		char	*target;
242 		char	*linkname;
243 	} *uap;
244 	register struct inode *ip;
245 	register char *tp;
246 	register c, nc;
247 
248 	uap = (struct a *)u.u_ap;
249 	tp = uap->target;
250 	nc = 0;
251 	while (c = fubyte(tp)) {
252 		if (c < 0) {
253 			u.u_error = EFAULT;
254 			return;
255 		}
256 		tp++;
257 		nc++;
258 	}
259 	u.u_dirp = uap->linkname;
260 	ip = namei(uchar, 1, 0);
261 	if (ip) {
262 		iput(ip);
263 		u.u_error = EEXIST;
264 		return;
265 	}
266 	if (u.u_error)
267 		return;
268 	ip = maknode(IFLNK | 0777);
269 	if (ip == NULL)
270 		return;
271 	u.u_base = uap->target;
272 	u.u_count = nc;
273 	u.u_offset = 0;
274 	u.u_segflg = 0;
275 	writei(ip);
276 	iput(ip);
277 }
278 
279 /*
280  * Unlink system call.
281  * Hard to avoid races here, especially
282  * in unlinking directories.
283  */
284 unlink()
285 {
286 	register struct inode *ip, *pp;
287 	struct a {
288 		char	*fname;
289 	};
290 	struct fs *fs;
291 	struct buf *bp;
292 	int lbn, bn, base;
293 	int unlinkingdot = 0;
294 
295 	pp = namei(uchar, 2, 0);
296 	if (pp == NULL)
297 		return;
298 #ifdef EFS
299 	/* divert to extended file system if off machine. */
300 	if (efsinode(pp)) {
301 		dev_t ndev = pp->i_rdev;
302 
303 		iput(pp);	/* avoid recursive hang on inode */
304 		efsunlink(ndev);
305 		if (u.u_error != EEXIST)
306 			return;
307 
308 		/*
309 		 * If a null pathname remainder, then do
310 		 * the unlink locally after restoring state.
311 		 */
312 		u.u_error = 0;
313 		u.u_dirp = (caddr_t)u.u_arg[0];
314 		pp = namei(uchar, 2, 0);
315 	}
316 #endif
317 
318 	/*
319 	 * Check for unlink(".")
320 	 * to avoid hanging on the iget
321 	 */
322 	if (pp->i_number == u.u_dent.d_ino) {
323 		ip = pp;
324 		ip->i_count++;
325 		unlinkingdot++;
326 	} else
327 		ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
328 	if(ip == NULL)
329 		goto out1;
330 	if((ip->i_mode&IFMT)==IFDIR && !suser())
331 		goto out;
332 	/*
333 	 * Don't unlink a mounted file.
334 	 */
335 	if (ip->i_dev != pp->i_dev) {
336 		u.u_error = EBUSY;
337 		goto out;
338 	}
339 	if (ip->i_flag&ITEXT)
340 		xrele(ip);	/* try once to free text */
341 	if (dirremove()) {
342 		ip->i_nlink--;
343 		ip->i_flag |= ICHG;
344 	}
345 out:
346 	if (unlinkingdot)
347 		irele(ip);
348 	else
349 		iput(ip);
350 out1:
351 	iput(pp);
352 }
353 
354 /*
355  * Seek system call
356  */
357 seek()
358 {
359 	register struct file *fp;
360 	register struct a {
361 		int	fdes;
362 		off_t	off;
363 		int	sbase;
364 	} *uap;
365 
366 	uap = (struct a *)u.u_ap;
367 	fp = getf(uap->fdes);
368 	if (fp == NULL)
369 		return;
370 	if (fp->f_type == DTYPE_SOCKET) {
371 		u.u_error = ESPIPE;
372 		return;
373 	}
374 	if (uap->sbase == 1)
375 		uap->off += fp->f_offset;
376 	else if (uap->sbase == 2) {
377 #ifdef EFS
378 		struct inode *ip = fp->f_inode;
379 		uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size;
380 #else
381 		uap->off += fp->f_inode->i_size;
382 #endif
383 	}
384 	fp->f_offset = uap->off;
385 	u.u_r.r_off = uap->off;
386 }
387 
388 /*
389  * Access system call
390  */
391 saccess()
392 {
393 	register svuid, svgid;
394 	register struct inode *ip;
395 	register struct a {
396 		char	*fname;
397 		int	fmode;
398 	} *uap;
399 
400 	uap = (struct a *)u.u_ap;
401 	svuid = u.u_uid;
402 	svgid = u.u_gid;
403 	u.u_uid = u.u_ruid;
404 	u.u_gid = u.u_rgid;
405 	ip = namei(uchar, 0, 1);
406 #ifdef EFS
407 	if (efsinode(ip)) {
408 		dev_t ndev = ip->i_rdev;
409 
410 		iput(ip);
411 		efssaccess(ndev);
412 		if (u.u_error != EEXIST)
413 			return;
414 		u.u_error = 0;
415 		u.u_dirp = (caddr_t)u.u_arg[0];
416 		ip = namei(uchar, 0, 1);
417 	}
418 #endif
419 	if (ip != NULL) {
420 		if (uap->fmode&(IREAD>>6))
421 			(void) access(ip, IREAD);
422 		if (uap->fmode&(IWRITE>>6))
423 			(void) access(ip, IWRITE);
424 		if (uap->fmode&(IEXEC>>6))
425 			(void) access(ip, IEXEC);
426 		iput(ip);
427 	}
428 	u.u_uid = svuid;
429 	u.u_gid = svgid;
430 }
431 
432 /*
433  * the fstat system call.
434  */
435 fstat()
436 {
437 	register struct file *fp;
438 	register struct a {
439 		int	fdes;
440 		struct stat *sb;
441 	} *uap;
442 
443 	uap = (struct a *)u.u_ap;
444 	fp = getf(uap->fdes);
445 	if (fp == NULL)
446 		return;
447 #ifdef EFS
448 	if (efsinode(fp->f_inode)) {
449 		efsfstat(fp->f_inode->i_rdev, fp);
450 		return;
451 	}
452 #endif
453 	if (fp->f_type == DTYPE_SOCKET)
454 		u.u_error = sostat(fp->f_socket, uap->sb);
455 	else
456 		stat1(fp->f_inode, uap->sb);
457 }
458 
459 /*
460  * Stat system call.  This version follows links.
461  */
462 stat()
463 {
464 	register struct inode *ip;
465 	register struct a {
466 		char	*fname;
467 		struct stat *sb;
468 	} *uap;
469 
470 	uap = (struct a *)u.u_ap;
471 	ip = namei(uchar, 0, 1);
472 	if (ip == NULL)
473 		return;
474 #ifdef EFS
475 	if (efsinode(ip)) {
476 		dev_t ndev = ip->i_rdev;
477 
478 		iput(ip);
479 		efsstat(ndev);
480 		if (u.u_error != EEXIST)
481 			return;
482 		u.u_error = 0;
483 		u.u_dirp = (caddr_t)u.u_arg[0];
484 		ip = namei(uchar, 0, 1);
485 	}
486 #endif
487 	stat1(ip, uap->sb);
488 	iput(ip);
489 }
490 
491 /*
492  * Lstat system call.  This version does not follow links.
493  */
494 lstat()
495 {
496 	register struct inode *ip;
497 	register struct a {
498 		char	*fname;
499 		struct stat *sb;
500 	} *uap;
501 
502 	uap = (struct a *)u.u_ap;
503 	ip = namei(uchar, 0, 0);
504 	if (ip == NULL)
505 		return;
506 #ifdef EFS
507 	if (efsinode(ip)) {
508 		dev_t ndev = ip->i_rdev;
509 
510 		iput(ip);
511 		efslstat(ndev);
512 		if (u.u_error != EEXIST)
513 			return;
514 		u.u_error = 0;
515 		u.u_dirp = (caddr_t)u.u_arg[0];
516 		ip = namei(uchar, 0, 0);
517 	}
518 #endif
519 	stat1(ip, uap->sb);
520 	iput(ip);
521 }
522 
523 /*
524  * The basic routine for fstat and stat:
525  * get the inode and pass appropriate parts back.
526  */
527 stat1(ip, ub)
528 	register struct inode *ip;
529 	struct stat *ub;
530 {
531 	struct stat ds;
532 
533 	IUPDAT(ip, &time, &time, 0);
534 	/*
535 	 * Copy from inode table
536 	 */
537 	ds.st_dev = ip->i_dev;
538 	ds.st_ino = ip->i_number;
539 	ds.st_mode = ip->i_mode;
540 	ds.st_nlink = ip->i_nlink;
541 	ds.st_uid = ip->i_uid;
542 	ds.st_gid = ip->i_gid;
543 	ds.st_rdev = (dev_t)ip->i_rdev;
544 	ds.st_size = ip->i_size;
545 	ds.st_atime = ip->i_atime;
546 	ds.st_mtime = ip->i_mtime;
547 	ds.st_ctime = ip->i_ctime;
548 	ds.st_blksize = ip->i_fs->fs_bsize;
549 	if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
550 		u.u_error = EFAULT;
551 }
552 
553 /*
554  * Return target name of a symbolic link
555  */
556 readlink()
557 {
558 	register struct inode *ip;
559 	register struct a {
560 		char	*name;
561 		char	*buf;
562 		int	count;
563 	} *uap;
564 
565 	ip = namei(uchar, 0, 0);
566 	if (ip == NULL)
567 		return;
568 #ifdef EFS
569 	if (efsinode(ip)) {
570 		dev_t ndev = ip->i_rdev;
571 
572 		iput(ip);
573 		efsreadlink(ndev);
574 		if (u.u_error != EEXIST)
575 			return;
576 		u.u_error = 0;
577 		u.u_dirp = (caddr_t)u.u_arg[0];
578 		ip = namei(uchar, 0, 0);
579 		return (0);
580 	}
581 #endif
582 	if ((ip->i_mode&IFMT) != IFLNK) {
583 		u.u_error = ENXIO;
584 		goto out;
585 	}
586 	uap = (struct a *)u.u_ap;
587 	u.u_offset = 0;
588 	u.u_base = uap->buf;
589 	u.u_count = uap->count;
590 	u.u_segflg = 0;
591 	readi(ip);
592 out:
593 	iput(ip);
594 	u.u_r.r_val1 = uap->count - u.u_count;
595 }
596 
597 chmod()
598 {
599 	register struct inode *ip;
600 	register struct a {
601 		char	*fname;
602 		int	fmode;
603 	} *uap;
604 
605 	uap = (struct a *)u.u_ap;
606 	if ((ip = owner(1)) == NULL)
607 		return;
608 #ifdef EFS
609 	if (efsinode(ip)) {
610 		dev_t ndev = ip->i_rdev;
611 
612 		iput(ip);
613 		efschmod(ndev);
614 		if (u.u_error != EEXIST)
615 			return;
616 		u.u_error = 0;
617 		u.u_dirp = (caddr_t)u.u_arg[0];
618 		ip = owner(1);
619 	}
620 #endif
621 	ip->i_mode &= ~07777;
622 	if (u.u_uid) {
623 		uap->fmode &= ~ISVTX;
624 		if (ip->i_gid >= NGRPS ||
625 		    (u.u_grps[ip->i_gid/(sizeof(int)*8)] &
626 		     (1 << ip->i_gid%(sizeof(int)*8))) == 0)
627 			uap->fmode &= ~ISGID;
628 #if	MUSH
629 		if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
630 		    (ip->i_mode & IFMT) != IFCHR)
631 			uap->fmode &= ~u.u_cmask;
632 #endif
633 	}
634 	ip->i_mode |= uap->fmode&07777;
635 	ip->i_flag |= ICHG;
636 	if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
637 		xrele(ip);
638 #ifdef MELB
639 	if ((ip->i_mode & ISUID) && ip->i_uid == 0)
640 		printf("%s: ino %d (%s) setuid root\n"
641 		    , getfs(ip->i_dev)->s_fsmnt
642 		    , ip->i_number
643 		    , u.u_dent.d_name
644 		);
645 #endif
646 	iput(ip);
647 }
648 
649 chown()
650 {
651 	register struct inode *ip;
652 	register struct a {
653 		char	*fname;
654 		int	uid;
655 		int	gid;
656 	} *uap;
657 #if	QUOTA
658 	register long change;
659 #endif
660 
661 	uap = (struct a *)u.u_ap;
662 	if (!suser() || (ip = owner(0)) == NULL)
663 		return;
664 #ifdef EFS
665 	if (efsinode(ip)) {
666 		dev_t ndev = ip->i_rdev;
667 
668 		iput(ip);
669 		efschown(ndev);
670 		if (u.u_error != EEXIST)
671 			return;
672 		u.u_error = 0;
673 		u.u_dirp = (caddr_t)u.u_arg[0];
674 		ip = owner(0);
675 	}
676 #endif
677 #if	QUOTA
678 	/*
679 	 * This doesn't allow for holes in files (which hopefully don't
680 	 * happen often in files that we chown), and is not accurate anyway
681 	 * (eg: it totally ignores 3 level indir blk files - but hopefully
682 	 * noone who can make a file that big will have a quota)
683 	 */
684 	if (ip->i_uid == uap->uid)
685 		change = 0;
686 	else {
687 		register struct fs *fs = ip->i_fs;
688 
689 		if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
690 			register off_t size;
691 
692 			size = blkroundup(fs, ip->i_size) - change;
693 			change += size;
694 			change += fs->fs_bsize;
695 			/* This assumes NIADDR <= 2 */
696 			if (size > NINDIR(fs) * fs->fs_bsize)
697 				change += fs->fs_bsize;
698 		} else
699 			change = fragroundup(fs, ip->i_size);
700 		change /= DEV_BSIZE;
701 	}
702 	chkdq(ip, -change, 1);
703 	chkiq(ip->i_dev, ip, ip->i_uid, 1);
704 	dqrele(ip->i_dquot);
705 #endif
706 	/*
707 	 * keep uid/gid's in sane range - no err, so chown(file, uid, -1)
708 	 * will do something useful
709 	 */
710 	if (uap->uid >= 0 && uap->uid <= 32767)	/* should have a const	*/
711 		ip->i_uid = uap->uid;
712 	if (uap->gid >= 0 && uap->gid <= 32767)	/* same here		*/
713 		ip->i_gid = uap->gid;
714 	ip->i_flag |= ICHG;
715 	if (u.u_ruid != 0)
716 		ip->i_mode &= ~(ISUID|ISGID);
717 #if	QUOTA
718 	ip->i_dquot = inoquota(ip);
719 	chkdq(ip, change, 1);
720 	chkiq(ip->i_dev, NULL, uap->uid, 1);
721 #endif
722 	iput(ip);
723 }
724 
725 /*
726  * Set IUPD and IACC times on file.
727  * Can't set ICHG.
728  */
729 utime()
730 {
731 	register struct a {
732 		char	*fname;
733 		time_t	*tptr;
734 	} *uap;
735 	register struct inode *ip;
736 	time_t tv[2];
737 
738 	uap = (struct a *)u.u_ap;
739 	if ((ip = owner(1)) == NULL)
740 		return;
741 	if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
742 		u.u_error = EFAULT;
743 	} else {
744 #ifdef EFS
745 		if (efsinode(ip)) {
746 			dev_t ndev = ip->i_rdev;
747 
748 			iput(ip);
749 			efsutime(ndev, uap->fname, tv);
750 			if (u.u_error != EEXIST)
751 				return;
752 			u.u_error = 0;
753 			u.u_dirp = (caddr_t)u.u_arg[0];
754 			ip = owner(1);
755 		}
756 #endif
757 		ip->i_flag |= IACC|IUPD|ICHG;
758 		iupdat(ip, &tv[0], &tv[1], 0);
759 	}
760 	iput(ip);
761 }
762 
763 sync()
764 {
765 
766 	update(0);
767 }
768 
769 /*
770  * Make a new file.
771  */
772 struct inode *
773 maknode(mode)
774 	int mode;
775 {
776 	register struct inode *ip;
777 	ino_t ipref;
778 
779 	if ((mode & IFMT) == IFDIR)
780 		ipref = dirpref(u.u_pdir->i_fs);
781 	else
782 		ipref = u.u_pdir->i_number;
783 	ip = ialloc(u.u_pdir, ipref, mode);
784 	if (ip == NULL) {
785 		iput(u.u_pdir);
786 		return(NULL);
787 	}
788 #ifdef	QUOTA
789 	if (ip->i_dquot != NODQUOT)
790 		panic("maknode: dquot");
791 #endif
792 	ip->i_flag |= IACC|IUPD|ICHG;
793 	if ((mode & IFMT) == 0)
794 		mode |= IFREG;
795 	ip->i_mode = mode & ~u.u_cmask;
796 	ip->i_nlink = 1;
797 	ip->i_uid = u.u_uid;
798 	ip->i_gid = u.u_pdir->i_gid;
799 #ifdef	QUOTA
800 	ip->i_dquot = inoquota(ip);
801 #endif
802 
803 	/*
804 	 * Make sure inode goes to disk before directory entry.
805 	 */
806 	iupdat(ip, &time, &time, 1);
807 	direnter(ip);
808 	if (u.u_error) {
809 		/*
810 		 * write error occurred trying to update directory
811 		 * so must deallocate the inode
812 		 */
813 		ip->i_nlink = 0;
814 		ip->i_flag |= ICHG;
815 		iput(ip);
816 		return(NULL);
817 	}
818 	return(ip);
819 }
820