extra arg to enlhinit
[unix-history] / usr / src / sys / ufs / ffs / ufs_vnops.c
CommitLineData
3e78e260 1/* ufs_vnops.c 4.21 82/03/18 */
d67a03eb
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
d67a03eb
BJ
5#include "../h/dir.h"
6#include "../h/user.h"
3e78e260 7#include "../h/reg.h"
d67a03eb 8#include "../h/file.h"
3e78e260
BJ
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"
0737b714 16#include "../h/inline.h"
3e78e260 17#include "../h/conf.h"
ae921915
BJ
18#include "../h/socket.h"
19#include "../h/socketvar.h"
3e78e260
BJ
20#include "../h/stat.h"
21
22chdir()
23{
24
25 chdirec(&u.u_cdir);
26}
27
28chroot()
29{
30
31 if (suser())
32 chdirec(&u.u_rdir);
33}
34
35chdirec(ipp)
36register 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
60bad:
61 iput(ip);
62}
63
64/*
65 * Open system call.
66 */
67open()
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 */
85creat()
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 */
111open1(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--;
142out:
143 if (ip != NULL)
144 iput(ip);
145}
146
147/*
148 * Mknod system call
149 */
150mknod()
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
181out:
182 iput(ip);
183}
184
185/*
186 * link system call
187 */
188link()
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);
221out:
222 if (u.u_error) {
223 ip->i_nlink--;
224 ip->i_flag |= ICHG;
225 }
226out1:
227 iput(ip);
228}
229
230/*
231 * symlink -- make a symbolic link
232 */
233symlink()
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 */
279unlink()
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
325out:
326 iput(ip);
327out1:
328 iput(pp);
329}
330
331/*
332 * Seek system call
333 */
334seek()
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 */
362saccess()
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}
d67a03eb
BJ
389
390/*
391 * the fstat system call.
392 */
393fstat()
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);
e92a04af 403 if (fp == NULL)
d67a03eb 404 return;
e92a04af 405 if (fp->f_flag & FSOCKET)
cc15ab5d 406 u.u_error = sostat(fp->f_socket, uap->sb);
e92a04af
BJ
407 else
408 stat1(fp->f_inode, uap->sb);
d67a03eb
BJ
409}
410
411/*
5485e062 412 * Stat system call. This version does not follow links.
d67a03eb
BJ
413 */
414stat()
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;
5485e062 423 ip = namei(uchar, 0, 0);
e92a04af 424 if (ip == NULL)
d67a03eb 425 return;
a3aa7f92 426 stat1(ip, uap->sb);
d67a03eb
BJ
427 iput(ip);
428}
429
5485e062
BJ
430/*
431 * Lstat system call. This version does follow links.
432 */
433lstat()
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, 1);
443 if (ip == NULL)
444 return;
019b08c9 445 stat1(ip, uap->sb);
5485e062
BJ
446 iput(ip);
447}
448
d67a03eb
BJ
449/*
450 * The basic routine for fstat and stat:
451 * get the inode and pass appropriate parts back.
452 */
a3aa7f92 453stat1(ip, ub)
e92a04af
BJ
454 register struct inode *ip;
455 struct stat *ub;
d67a03eb
BJ
456{
457 register struct dinode *dp;
458 register struct buf *bp;
459 struct stat ds;
460
c0bb1685 461 IUPDAT(ip, &time, &time, 0);
d67a03eb 462 /*
e92a04af 463 * First copy from inode table
d67a03eb
BJ
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;
a3aa7f92 472 ds.st_size = ip->i_size;
d67a03eb 473 /*
5485e062 474 * next the dates in the disk
d67a03eb
BJ
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/*
5485e062
BJ
488 * Return target name of a symbolic link
489 */
490readlink()
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);
512out:
513 iput(ip);
514 u.u_r.r_val1 = uap->count - u.u_count;
515}
516
3e78e260 517chmod()
5485e062 518{
3e78e260 519 register struct inode *ip;
5485e062 520 register struct a {
3e78e260
BJ
521 char *fname;
522 int fmode;
5485e062 523 } *uap;
5485e062
BJ
524
525 uap = (struct a *)u.u_ap;
3e78e260 526 if ((ip = owner(1)) == NULL)
5485e062 527 return;
3e78e260
BJ
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);
5485e062
BJ
535 iput(ip);
536}
537
3e78e260 538chown()
d67a03eb 539{
3e78e260 540 register struct inode *ip;
d67a03eb 541 register struct a {
3e78e260
BJ
542 char *fname;
543 int uid;
544 int gid;
d67a03eb 545 } *uap;
d67a03eb
BJ
546
547 uap = (struct a *)u.u_ap;
3e78e260 548 if (!suser() || (ip = owner(0)) == NULL)
d67a03eb 549 return;
3e78e260
BJ
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);
d67a03eb
BJ
556}
557
558/*
3e78e260
BJ
559 * Set IUPD and IACC times on file.
560 * Can't set ICHG.
d67a03eb 561 */
3e78e260 562utime()
e92a04af 563{
d67a03eb 564 register struct a {
3e78e260
BJ
565 char *fname;
566 time_t *tptr;
d67a03eb 567 } *uap;
3e78e260
BJ
568 register struct inode *ip;
569 time_t tv[2];
d67a03eb
BJ
570
571 uap = (struct a *)u.u_ap;
3e78e260 572 if ((ip = owner(1)) == NULL)
d67a03eb 573 return;
3e78e260
BJ
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);
d67a03eb 579 }
d67a03eb
BJ
580 iput(ip);
581}
582
3e78e260 583sync()
d67a03eb 584{
d67a03eb 585
68503f9a 586 update(0);
d67a03eb 587}