xref: /csrg-svn/sys/ufs/ffs/ffs_vnops.c (revision 7505)
1 /*	ffs_vnops.c	4.30	82/07/24	*/
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 	wdir(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 /*
342 	if ((ip->i_flag&ITEXT) && ip->i_nlink==1) {
343  		u.u_error = ETXTBSY;
344 		goto out;
345 	}
346 */
347 	if (u.u_count == 0) {
348 		/*
349 		 * first entry in block, so set d_ino to zero.
350 		 */
351 /*ZZ*/if(u.u_offset&0x1ff)printf("missed dir compact dir %s/%d off %d file %s\n"
352 /*ZZ*/,pp->i_fs->fs_fsmnt,pp->i_number,u.u_offset,u.u_dent.d_name);
353 		u.u_base = (caddr_t)&u.u_dent;
354 		u.u_count = DIRSIZ(&u.u_dent);
355 		u.u_dent.d_ino = 0;
356 		writei(pp);
357 	} else {
358 		/*
359 		 * updating preceeding entry to skip over current entry.
360 		 */
361 		fs = pp->i_fs;
362 		lbn = lblkno(fs, u.u_offset);
363 		base = blkoff(fs, u.u_offset);
364 		bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
365 		bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
366 		if (bp->b_flags & B_ERROR) {
367 			brelse(bp);
368 			goto out;
369 		}
370 		((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
371 		    u.u_dent.d_reclen;
372 /*ZZ*/if(((int)(bp->b_un.b_addr + base)&0x1ff)+u.u_dent.d_reclen>512)
373 /*ZZ*/	panic("unlink: reclen");
374 		bwrite(bp);
375 		pp->i_flag |= IUPD|ICHG;
376 	}
377 	ip->i_nlink--;
378 	ip->i_flag |= ICHG;
379 
380 out:
381 	if (unlinkingdot)
382 		irele(ip);
383 	else
384 		iput(ip);
385 out1:
386 	iput(pp);
387 }
388 
389 /*
390  * Seek system call
391  */
392 seek()
393 {
394 	register struct file *fp;
395 	register struct a {
396 		int	fdes;
397 		off_t	off;
398 		int	sbase;
399 	} *uap;
400 
401 	uap = (struct a *)u.u_ap;
402 	fp = getf(uap->fdes);
403 	if (fp == NULL)
404 		return;
405 	if (fp->f_type == DTYPE_SOCKET) {
406 		u.u_error = ESPIPE;
407 		return;
408 	}
409 	if (uap->sbase == 1)
410 		uap->off += fp->f_offset;
411 	else if (uap->sbase == 2) {
412 #ifdef EFS
413 		struct inode *ip = fp->f_inode;
414 		uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size;
415 #else
416 		uap->off += fp->f_inode->i_size;
417 #endif
418 	}
419 	fp->f_offset = uap->off;
420 	u.u_r.r_off = uap->off;
421 }
422 
423 /*
424  * Access system call
425  */
426 saccess()
427 {
428 	register svuid, svgid;
429 	register struct inode *ip;
430 	register struct a {
431 		char	*fname;
432 		int	fmode;
433 	} *uap;
434 
435 	uap = (struct a *)u.u_ap;
436 	svuid = u.u_uid;
437 	svgid = u.u_gid;
438 	u.u_uid = u.u_ruid;
439 	u.u_gid = u.u_rgid;
440 	ip = namei(uchar, 0, 1);
441 #ifdef EFS
442 	if (efsinode(ip)) {
443 		dev_t ndev = ip->i_rdev;
444 
445 		iput(ip);
446 		efssaccess(ndev);
447 		if (u.u_error != EEXIST)
448 			return;
449 		u.u_error = 0;
450 		u.u_dirp = (caddr_t)u.u_arg[0];
451 		ip = namei(uchar, 0, 1);
452 	}
453 #endif
454 	if (ip != NULL) {
455 		if (uap->fmode&(IREAD>>6))
456 			(void) access(ip, IREAD);
457 		if (uap->fmode&(IWRITE>>6))
458 			(void) access(ip, IWRITE);
459 		if (uap->fmode&(IEXEC>>6))
460 			(void) access(ip, IEXEC);
461 		iput(ip);
462 	}
463 	u.u_uid = svuid;
464 	u.u_gid = svgid;
465 }
466 
467 /*
468  * the fstat system call.
469  */
470 fstat()
471 {
472 	register struct file *fp;
473 	register struct a {
474 		int	fdes;
475 		struct stat *sb;
476 	} *uap;
477 
478 	uap = (struct a *)u.u_ap;
479 	fp = getf(uap->fdes);
480 	if (fp == NULL)
481 		return;
482 #ifdef EFS
483 	if (efsinode(fp->f_inode)) {
484 		efsfstat(fp->f_inode->i_rdev, fp);
485 		return;
486 	}
487 #endif
488 	if (fp->f_type == DTYPE_SOCKET)
489 		u.u_error = sostat(fp->f_socket, uap->sb);
490 	else
491 		stat1(fp->f_inode, uap->sb);
492 }
493 
494 /*
495  * Stat system call.  This version follows links.
496  */
497 stat()
498 {
499 	register struct inode *ip;
500 	register struct a {
501 		char	*fname;
502 		struct stat *sb;
503 	} *uap;
504 
505 	uap = (struct a *)u.u_ap;
506 	ip = namei(uchar, 0, 1);
507 	if (ip == NULL)
508 		return;
509 #ifdef EFS
510 	if (efsinode(ip)) {
511 		dev_t ndev = ip->i_rdev;
512 
513 		iput(ip);
514 		efsstat(ndev);
515 		if (u.u_error != EEXIST)
516 			return;
517 		u.u_error = 0;
518 		u.u_dirp = (caddr_t)u.u_arg[0];
519 		ip = namei(uchar, 0, 1);
520 	}
521 #endif
522 	stat1(ip, uap->sb);
523 	iput(ip);
524 }
525 
526 /*
527  * Lstat system call.  This version does not follow links.
528  */
529 lstat()
530 {
531 	register struct inode *ip;
532 	register struct a {
533 		char	*fname;
534 		struct stat *sb;
535 	} *uap;
536 
537 	uap = (struct a *)u.u_ap;
538 	ip = namei(uchar, 0, 0);
539 	if (ip == NULL)
540 		return;
541 #ifdef EFS
542 	if (efsinode(ip)) {
543 		dev_t ndev = ip->i_rdev;
544 
545 		iput(ip);
546 		efslstat(ndev);
547 		if (u.u_error != EEXIST)
548 			return;
549 		u.u_error = 0;
550 		u.u_dirp = (caddr_t)u.u_arg[0];
551 		ip = namei(uchar, 0, 0);
552 	}
553 #endif
554 	stat1(ip, uap->sb);
555 	iput(ip);
556 }
557 
558 /*
559  * The basic routine for fstat and stat:
560  * get the inode and pass appropriate parts back.
561  */
562 stat1(ip, ub)
563 	register struct inode *ip;
564 	struct stat *ub;
565 {
566 	struct stat ds;
567 
568 	IUPDAT(ip, &time, &time, 0);
569 	/*
570 	 * Copy from inode table
571 	 */
572 	ds.st_dev = ip->i_dev;
573 	ds.st_ino = ip->i_number;
574 	ds.st_mode = ip->i_mode;
575 	ds.st_nlink = ip->i_nlink;
576 	ds.st_uid = ip->i_uid;
577 	ds.st_gid = ip->i_gid;
578 	ds.st_rdev = (dev_t)ip->i_rdev;
579 	ds.st_size = ip->i_size;
580 	ds.st_atime = ip->i_atime;
581 	ds.st_mtime = ip->i_mtime;
582 	ds.st_ctime = ip->i_ctime;
583 	ds.st_blksize = ip->i_fs->fs_bsize;
584 	if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
585 		u.u_error = EFAULT;
586 }
587 
588 /*
589  * Return target name of a symbolic link
590  */
591 readlink()
592 {
593 	register struct inode *ip;
594 	register struct a {
595 		char	*name;
596 		char	*buf;
597 		int	count;
598 	} *uap;
599 
600 	ip = namei(uchar, 0, 0);
601 	if (ip == NULL)
602 		return;
603 #ifdef EFS
604 	if (efsinode(ip)) {
605 		dev_t ndev = ip->i_rdev;
606 
607 		iput(ip);
608 		efsreadlink(ndev);
609 		if (u.u_error != EEXIST)
610 			return;
611 		u.u_error = 0;
612 		u.u_dirp = (caddr_t)u.u_arg[0];
613 		ip = namei(uchar, 0, 0);
614 		return (0);
615 	}
616 #endif
617 	if ((ip->i_mode&IFMT) != IFLNK) {
618 		u.u_error = ENXIO;
619 		goto out;
620 	}
621 	uap = (struct a *)u.u_ap;
622 	u.u_offset = 0;
623 	u.u_base = uap->buf;
624 	u.u_count = uap->count;
625 	u.u_segflg = 0;
626 	readi(ip);
627 out:
628 	iput(ip);
629 	u.u_r.r_val1 = uap->count - u.u_count;
630 }
631 
632 chmod()
633 {
634 	register struct inode *ip;
635 	register struct a {
636 		char	*fname;
637 		int	fmode;
638 	} *uap;
639 
640 	uap = (struct a *)u.u_ap;
641 	if ((ip = owner(1)) == NULL)
642 		return;
643 #ifdef EFS
644 	if (efsinode(ip)) {
645 		dev_t ndev = ip->i_rdev;
646 
647 		iput(ip);
648 		efschmod(ndev);
649 		if (u.u_error != EEXIST)
650 			return;
651 		u.u_error = 0;
652 		u.u_dirp = (caddr_t)u.u_arg[0];
653 		ip = owner(1);
654 	}
655 #endif
656 	ip->i_mode &= ~07777;
657 	if (u.u_uid) {
658 		uap->fmode &= ~ISVTX;
659 		if (ip->i_gid >= NGRPS ||
660 		    (u.u_grps[ip->i_gid/(sizeof(int)*8)] &
661 		     (1 << ip->i_gid%(sizeof(int)*8))) == 0)
662 			uap->fmode &= ~ISGID;
663 #if	MUSH
664 		if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
665 		    (ip->i_mode & IFMT) != IFCHR)
666 			uap->fmode &= ~u.u_cmask;
667 #endif
668 	}
669 	ip->i_mode |= uap->fmode&07777;
670 	ip->i_flag |= ICHG;
671 	if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
672 		xrele(ip);
673 #ifdef MELB
674 	if ((ip->i_mode & ISUID) && ip->i_uid == 0)
675 		printf("%s: ino %d (%s) setuid root\n"
676 		    , getfs(ip->i_dev)->s_fsmnt
677 		    , ip->i_number
678 		    , u.u_dent.d_name
679 		);
680 #endif
681 	iput(ip);
682 }
683 
684 chown()
685 {
686 	register struct inode *ip;
687 	register struct a {
688 		char	*fname;
689 		int	uid;
690 		int	gid;
691 	} *uap;
692 #if	QUOTA
693 	register long change;
694 #endif
695 
696 	uap = (struct a *)u.u_ap;
697 	if (!suser() || (ip = owner(0)) == NULL)
698 		return;
699 #ifdef EFS
700 	if (efsinode(ip)) {
701 		dev_t ndev = ip->i_rdev;
702 
703 		iput(ip);
704 		efschown(ndev);
705 		if (u.u_error != EEXIST)
706 			return;
707 		u.u_error = 0;
708 		u.u_dirp = (caddr_t)u.u_arg[0];
709 		ip = owner(0);
710 	}
711 #endif
712 #if	QUOTA
713 	/*
714 	 * This doesn't allow for holes in files (which hopefully don't
715 	 * happen often in files that we chown), and is not accurate anyway
716 	 * (eg: it totally ignores 3 level indir blk files - but hopefully
717 	 * noone who can make a file that big will have a quota)
718 	 */
719 	if (ip->i_uid == uap->uid)
720 		change = 0;
721 	else {
722 		register struct fs *fs = ip->i_fs;
723 
724 		if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
725 			register off_t size;
726 
727 			size = blkroundup(fs, ip->i_size) - change;
728 			change += size;
729 			change += fs->fs_bsize;
730 			/* This assumes NIADDR <= 2 */
731 			if (size > NINDIR(fs) * fs->fs_bsize)
732 				change += fs->fs_bsize;
733 		} else
734 			change = fragroundup(fs, ip->i_size);
735 		change /= DEV_BSIZE;
736 	}
737 	chkdq(ip, -change, 1);
738 	chkiq(ip->i_dev, ip, ip->i_uid, 1);
739 	dqrele(ip->i_dquot);
740 #endif
741 	/*
742 	 * keep uid/gid's in sane range - no err, so chown(file, uid, -1)
743 	 * will do something useful
744 	 */
745 	if (uap->uid >= 0 && uap->uid <= 32767)	/* should have a const	*/
746 		ip->i_uid = uap->uid;
747 	if (uap->gid >= 0 && uap->gid <= 32767)	/* same here		*/
748 		ip->i_gid = uap->gid;
749 	ip->i_flag |= ICHG;
750 	if (u.u_ruid != 0)
751 		ip->i_mode &= ~(ISUID|ISGID);
752 #if	QUOTA
753 	ip->i_dquot = inoquota(ip);
754 	chkdq(ip, change, 1);
755 	chkiq(ip->i_dev, NULL, uap->uid, 1);
756 #endif
757 	iput(ip);
758 }
759 
760 /*
761  * Set IUPD and IACC times on file.
762  * Can't set ICHG.
763  */
764 utime()
765 {
766 	register struct a {
767 		char	*fname;
768 		time_t	*tptr;
769 	} *uap;
770 	register struct inode *ip;
771 	time_t tv[2];
772 
773 	uap = (struct a *)u.u_ap;
774 	if ((ip = owner(1)) == NULL)
775 		return;
776 	if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
777 		u.u_error = EFAULT;
778 	} else {
779 #ifdef EFS
780 		if (efsinode(ip)) {
781 			dev_t ndev = ip->i_rdev;
782 
783 			iput(ip);
784 			efsutime(ndev, uap->fname, tv);
785 			if (u.u_error != EEXIST)
786 				return;
787 			u.u_error = 0;
788 			u.u_dirp = (caddr_t)u.u_arg[0];
789 			ip = owner(1);
790 		}
791 #endif
792 		ip->i_flag |= IACC|IUPD|ICHG;
793 		iupdat(ip, &tv[0], &tv[1], 0);
794 	}
795 	iput(ip);
796 }
797 
798 sync()
799 {
800 
801 	update(0);
802 }
803