xref: /original-bsd/sys/ufs/ffs/ffs_vnops.c (revision 2f60f4d7)
1 /*	ffs_vnops.c	4.25	82/06/07	*/
2 
3 #ifdef SIMFS
4 #include "../h/sysrenam.h"
5 #endif
6 #include "../h/param.h"
7 #include "../h/systm.h"
8 #include "../h/dir.h"
9 #include "../h/user.h"
10 #include "../h/file.h"
11 #include "../h/stat.h"
12 #include "../h/inode.h"
13 #include "../h/fs.h"
14 #include "../h/buf.h"
15 #include "../h/proc.h"
16 #include "../h/inline.h"
17 
18 chdir()
19 {
20 
21 	chdirec(&u.u_cdir);
22 }
23 
24 chroot()
25 {
26 
27 	if (suser())
28 		chdirec(&u.u_rdir);
29 }
30 
31 chdirec(ipp)
32 register struct inode **ipp;
33 {
34 	register struct inode *ip;
35 	struct a {
36 		char	*fname;
37 	};
38 
39 	ip = namei(uchar, 0, 1);
40 	if(ip == NULL)
41 		return;
42 	if((ip->i_mode&IFMT) != IFDIR) {
43 		u.u_error = ENOTDIR;
44 		goto bad;
45 	}
46 	if(access(ip, IEXEC))
47 		goto bad;
48 	iunlock(ip);
49 	if (*ipp) {
50 		ilock(*ipp);
51 		iput(*ipp);
52 	}
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 		goto out;
125 	if (trf == 1)
126 		itrunc(ip);
127 	iunlock(ip);
128 	if ((fp = falloc()) == NULL)
129 		goto out;
130 	fp->f_flag = mode&(FREAD|FWRITE);
131 	i = u.u_r.r_val1;
132 	fp->f_inode = ip;
133 	openi(ip, mode&(FREAD|FWRITE));
134 	if (u.u_error == 0)
135 		return;
136 	u.u_ofile[i] = NULL;
137 	fp->f_count--;
138 out:
139 	if (ip != NULL)
140 		iput(ip);
141 }
142 
143 /*
144  * Mknod system call
145  */
146 mknod()
147 {
148 	register struct inode *ip;
149 	register struct a {
150 		char	*fname;
151 		int	fmode;
152 		int	dev;
153 	} *uap;
154 
155 	uap = (struct a *)u.u_ap;
156 	if (suser()) {
157 		ip = namei(uchar, 1, 0);
158 		if (ip != NULL) {
159 			u.u_error = EEXIST;
160 			goto out;
161 		}
162 	}
163 	if (u.u_error)
164 		return;
165 	ip = maknode(uap->fmode);
166 	if (ip == NULL)
167 		return;
168 	if (uap->dev) {
169 		/*
170 		 * Want to be able to use this to make badblock
171 		 * inodes, so don't truncate the dev number.
172 		 */
173 		ip->i_rdev = uap->dev;
174 		ip->i_flag |= IACC|IUPD|ICHG;
175 	}
176 
177 out:
178 	iput(ip);
179 }
180 
181 /*
182  * link system call
183  */
184 link()
185 {
186 	register struct inode *ip, *xp;
187 	register struct a {
188 		char	*target;
189 		char	*linkname;
190 	} *uap;
191 
192 	uap = (struct a *)u.u_ap;
193 	ip = namei(uchar, 0, 1);    /* well, this routine is doomed anyhow */
194 	if (ip == NULL)
195 		return;
196 	if ((ip->i_mode&IFMT)==IFDIR && !suser())
197 		goto out1;
198 	ip->i_nlink++;
199 	ip->i_flag |= ICHG;
200 	iupdat(ip, &time, &time, 1);
201 	iunlock(ip);
202 	u.u_dirp = (caddr_t)uap->linkname;
203 	xp = namei(uchar, 1, 0);
204 	if (xp != NULL) {
205 		u.u_error = EEXIST;
206 		iput(xp);
207 		goto out;
208 	}
209 	if (u.u_error)
210 		goto out;
211 	if (u.u_pdir->i_dev != ip->i_dev) {
212 		iput(u.u_pdir);
213 		u.u_error = EXDEV;
214 		goto out;
215 	}
216 	wdir(ip);
217 out:
218 	if (u.u_error) {
219 		ip->i_nlink--;
220 		ip->i_flag |= ICHG;
221 	}
222 out1:
223 	iput(ip);
224 }
225 
226 /*
227  * symlink -- make a symbolic link
228  */
229 symlink()
230 {
231 	register struct a {
232 		char	*target;
233 		char	*linkname;
234 	} *uap;
235 	register struct inode *ip;
236 	register char *tp;
237 	register c, nc;
238 
239 	uap = (struct a *)u.u_ap;
240 	tp = uap->target;
241 	nc = 0;
242 	while (c = fubyte(tp)) {
243 		if (c < 0) {
244 			u.u_error = EFAULT;
245 			return;
246 		}
247 		tp++;
248 		nc++;
249 	}
250 	u.u_dirp = uap->linkname;
251 	ip = namei(uchar, 1, 0);
252 	if (ip) {
253 		iput(ip);
254 		u.u_error = EEXIST;
255 		return;
256 	}
257 	if (u.u_error)
258 		return;
259 	ip = maknode(IFLNK | 0777);
260 	if (ip == NULL)
261 		return;
262 	u.u_base = uap->target;
263 	u.u_count = nc;
264 	u.u_offset = 0;
265 	u.u_segflg = 0;
266 	writei(ip);
267 	iput(ip);
268 }
269 
270 /*
271  * Unlink system call.
272  * Hard to avoid races here, especially
273  * in unlinking directories.
274  */
275 unlink()
276 {
277 	register struct inode *ip, *pp;
278 	struct a {
279 		char	*fname;
280 	};
281 	struct fs *fs;
282 	struct buf *bp;
283 	int lbn, bn, base;
284 
285 	pp = namei(uchar, 2, 0);
286 	if(pp == NULL)
287 		return;
288 	/*
289 	 * Check for unlink(".")
290 	 * to avoid hanging on the iget
291 	 */
292 	if (pp->i_number == u.u_dent.d_ino) {
293 		ip = pp;
294 		ip->i_count++;
295 	} else
296 		ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
297 	if(ip == NULL)
298 		goto out1;
299 	if((ip->i_mode&IFMT)==IFDIR && !suser())
300 		goto out;
301 	/*
302 	 * Don't unlink a mounted file.
303 	 */
304 	if (ip->i_dev != pp->i_dev) {
305 		u.u_error = EBUSY;
306 		goto out;
307 	}
308 	if (ip->i_flag&ITEXT)
309 		xrele(ip);	/* try once to free text */
310 /*
311 	if ((ip->i_flag&ITEXT) && ip->i_nlink==1) {
312  		u.u_error = ETXTBSY;
313 		goto out;
314 	}
315 */
316 	if (u.u_count == 0) {
317 		/*
318 		 * first entry in block, so set d_ino to zero.
319 		 */
320 		u.u_base = (caddr_t)&u.u_dent;
321 		u.u_count = DIRSIZ(&u.u_dent);
322 		u.u_dent.d_ino = 0;
323 		writei(pp);
324 	} else {
325 		/*
326 		 * updating preceeding entry to skip over current entry.
327 		 */
328 		fs = pp->i_fs;
329 		lbn = lblkno(fs, u.u_offset);
330 		base = blkoff(fs, u.u_offset);
331 		bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
332 		bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
333 		if (bp->b_flags & B_ERROR) {
334 			brelse(bp);
335 			goto out;
336 		}
337 		((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
338 		    u.u_dent.d_reclen;
339 		bwrite(bp);
340 		pp->i_flag |= IUPD|ICHG;
341 	}
342 	ip->i_nlink--;
343 	ip->i_flag |= ICHG;
344 
345 out:
346 	iput(ip);
347 out1:
348 	iput(pp);
349 }
350 
351 /*
352  * Seek system call
353  */
354 seek()
355 {
356 	register struct file *fp;
357 	register struct a {
358 		int	fdes;
359 		off_t	off;
360 		int	sbase;
361 	} *uap;
362 
363 	uap = (struct a *)u.u_ap;
364 	fp = getf(uap->fdes);
365 	if (fp == NULL)
366 		return;
367 	if (fp->f_flag&FSOCKET) {
368 		u.u_error = ESPIPE;
369 		return;
370 	}
371 	if (uap->sbase == 1)
372 		uap->off += fp->f_offset;
373 	else if (uap->sbase == 2)
374 		uap->off += fp->f_inode->i_size;
375 	fp->f_offset = uap->off;
376 	u.u_r.r_off = uap->off;
377 }
378 
379 /*
380  * Access system call
381  */
382 saccess()
383 {
384 	register svuid, svgid;
385 	register struct inode *ip;
386 	register struct a {
387 		char	*fname;
388 		int	fmode;
389 	} *uap;
390 
391 	uap = (struct a *)u.u_ap;
392 	svuid = u.u_uid;
393 	svgid = u.u_gid;
394 	u.u_uid = u.u_ruid;
395 	u.u_gid = u.u_rgid;
396 	ip = namei(uchar, 0, 1);
397 	if (ip != NULL) {
398 		if (uap->fmode&(IREAD>>6))
399 			(void) access(ip, IREAD);
400 		if (uap->fmode&(IWRITE>>6))
401 			(void) access(ip, IWRITE);
402 		if (uap->fmode&(IEXEC>>6))
403 			(void) access(ip, IEXEC);
404 		iput(ip);
405 	}
406 	u.u_uid = svuid;
407 	u.u_gid = svgid;
408 }
409 
410 /*
411  * the fstat system call.
412  */
413 fstat()
414 {
415 	register struct file *fp;
416 	register struct a {
417 		int	fdes;
418 		struct stat *sb;
419 	} *uap;
420 
421 	uap = (struct a *)u.u_ap;
422 	fp = getf(uap->fdes);
423 	if (fp == NULL)
424 		return;
425 	if (fp->f_flag & FSOCKET)
426 		u.u_error = sostat(fp->f_socket, uap->sb);
427 	else
428 		stat1(fp->f_inode, uap->sb);
429 }
430 
431 /*
432  * Stat system call.  This version follows links.
433  */
434 stat()
435 {
436 	register struct inode *ip;
437 	register struct a {
438 		char	*fname;
439 		struct stat *sb;
440 	} *uap;
441 
442 	uap = (struct a *)u.u_ap;
443 	ip = namei(uchar, 0, 1);
444 	if (ip == NULL)
445 		return;
446 	stat1(ip, uap->sb);
447 	iput(ip);
448 }
449 
450 /*
451  * Lstat system call.  This version does not follow links.
452  */
453 lstat()
454 {
455 	register struct inode *ip;
456 	register struct a {
457 		char	*fname;
458 		struct stat *sb;
459 	} *uap;
460 
461 	uap = (struct a *)u.u_ap;
462 	ip = namei(uchar, 0, 0);
463 	if (ip == NULL)
464 		return;
465 	stat1(ip, uap->sb);
466 	iput(ip);
467 }
468 
469 /*
470  * The basic routine for fstat and stat:
471  * get the inode and pass appropriate parts back.
472  */
473 stat1(ip, ub)
474 	register struct inode *ip;
475 	struct stat *ub;
476 {
477 	struct stat ds;
478 
479 	IUPDAT(ip, &time, &time, 0);
480 	/*
481 	 * Copy from inode table
482 	 */
483 	ds.st_dev = ip->i_dev;
484 	ds.st_ino = ip->i_number;
485 	ds.st_mode = ip->i_mode;
486 	ds.st_nlink = ip->i_nlink;
487 	ds.st_uid = ip->i_uid;
488 	ds.st_gid = ip->i_gid;
489 	ds.st_rdev = (dev_t)ip->i_rdev;
490 	ds.st_size = ip->i_size;
491 	ds.st_atime = ip->i_atime;
492 	ds.st_mtime = ip->i_mtime;
493 	ds.st_ctime = ip->i_ctime;
494 	ds.st_blksize = ip->i_fs->fs_bsize;
495 	if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
496 		u.u_error = EFAULT;
497 }
498 
499 /*
500  * Return target name of a symbolic link
501  */
502 readlink()
503 {
504 	register struct inode *ip;
505 	register struct a {
506 		char	*name;
507 		char	*buf;
508 		int	count;
509 	} *uap;
510 
511 	ip = namei(uchar, 0, 0);
512 	if (ip == NULL)
513 		return;
514 	if ((ip->i_mode&IFMT) != IFLNK) {
515 		u.u_error = ENXIO;
516 		goto out;
517 	}
518 	uap = (struct a *)u.u_ap;
519 	u.u_offset = 0;
520 	u.u_base = uap->buf;
521 	u.u_count = uap->count;
522 	u.u_segflg = 0;
523 	readi(ip);
524 out:
525 	iput(ip);
526 	u.u_r.r_val1 = uap->count - u.u_count;
527 }
528 
529 chmod()
530 {
531 	register struct inode *ip;
532 	register struct a {
533 		char	*fname;
534 		int	fmode;
535 	} *uap;
536 
537 	uap = (struct a *)u.u_ap;
538 	if ((ip = owner(1)) == NULL)
539 		return;
540 	ip->i_mode &= ~07777;
541 	if (u.u_uid)
542 		uap->fmode &= ~ISVTX;
543 	ip->i_mode |= uap->fmode&07777;
544 	ip->i_flag |= ICHG;
545 	if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
546 		xrele(ip);
547 	iput(ip);
548 }
549 
550 chown()
551 {
552 	register struct inode *ip;
553 	register struct a {
554 		char	*fname;
555 		int	uid;
556 		int	gid;
557 	} *uap;
558 
559 	uap = (struct a *)u.u_ap;
560 	if (!suser() || (ip = owner(0)) == NULL)
561 		return;
562 	ip->i_uid = uap->uid;
563 	ip->i_gid = uap->gid;
564 	ip->i_flag |= ICHG;
565 	if (u.u_ruid != 0)
566 		ip->i_mode &= ~(ISUID|ISGID);
567 	iput(ip);
568 }
569 
570 /*
571  * Set IUPD and IACC times on file.
572  * Can't set ICHG.
573  */
574 utime()
575 {
576 	register struct a {
577 		char	*fname;
578 		time_t	*tptr;
579 	} *uap;
580 	register struct inode *ip;
581 	time_t tv[2];
582 
583 	uap = (struct a *)u.u_ap;
584 	if ((ip = owner(1)) == NULL)
585 		return;
586 	if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
587 		u.u_error = EFAULT;
588 	} else {
589 		ip->i_flag |= IACC|IUPD|ICHG;
590 		iupdat(ip, &tv[0], &tv[1], 0);
591 	}
592 	iput(ip);
593 }
594 
595 sync()
596 {
597 
598 	update(0);
599 }
600