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