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