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