get rid of -g flag
[unix-history] / usr / src / sys / ufs / ufs / ufs_vnops.c
CommitLineData
6459ebe0 1/* ufs_vnops.c 4.23 82/04/19 */
d67a03eb 2
6459ebe0
KM
3/* merged into kernel: @(#)sys3.c 2.2 4/8/82 */
4
5#ifdef SIMFS
6#include "../h/sysrenam.h"
7#endif
d67a03eb
BJ
8#include "../h/param.h"
9#include "../h/systm.h"
d67a03eb
BJ
10#include "../h/dir.h"
11#include "../h/user.h"
d67a03eb 12#include "../h/file.h"
6459ebe0 13#include "../h/stat.h"
3e78e260 14#include "../h/inode.h"
6459ebe0 15#include "../h/fs.h"
3e78e260 16#include "../h/buf.h"
3e78e260 17#include "../h/proc.h"
0737b714 18#include "../h/inline.h"
3e78e260
BJ
19
20chdir()
21{
22
23 chdirec(&u.u_cdir);
24}
25
26chroot()
27{
28
29 if (suser())
30 chdirec(&u.u_rdir);
31}
32
33chdirec(ipp)
34register 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
58bad:
59 iput(ip);
60}
61
62/*
63 * Open system call.
64 */
65open()
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 */
83creat()
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 */
109open1(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--;
140out:
141 if (ip != NULL)
142 iput(ip);
143}
144
145/*
146 * Mknod system call
147 */
148mknod()
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 */
6459ebe0 175 ip->i_rdev = uap->dev;
3e78e260
BJ
176 ip->i_flag |= IACC|IUPD|ICHG;
177 }
178
179out:
180 iput(ip);
181}
182
183/*
184 * link system call
185 */
186link()
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);
219out:
220 if (u.u_error) {
221 ip->i_nlink--;
222 ip->i_flag |= ICHG;
223 }
224out1:
225 iput(ip);
226}
227
228/*
229 * symlink -- make a symbolic link
230 */
231symlink()
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 */
277unlink()
278{
279 register struct inode *ip, *pp;
280 struct a {
281 char *fname;
282 };
6459ebe0
KM
283 struct fs *fs;
284 struct buf *bp;
285 int lbn, bn, base;
3e78e260
BJ
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
6459ebe0 298 ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
3e78e260
BJ
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*/
6459ebe0
KM
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 }
3e78e260
BJ
344 ip->i_nlink--;
345 ip->i_flag |= ICHG;
346
347out:
348 iput(ip);
349out1:
350 iput(pp);
351}
352
353/*
354 * Seek system call
355 */
356seek()
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 */
384saccess()
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}
d67a03eb
BJ
411
412/*
413 * the fstat system call.
414 */
415fstat()
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);
e92a04af 425 if (fp == NULL)
d67a03eb 426 return;
e92a04af 427 if (fp->f_flag & FSOCKET)
cc15ab5d 428 u.u_error = sostat(fp->f_socket, uap->sb);
e92a04af
BJ
429 else
430 stat1(fp->f_inode, uap->sb);
d67a03eb
BJ
431}
432
433/*
6459ebe0 434 * Stat system call. This version follows links.
d67a03eb
BJ
435 */
436stat()
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;
66d4ba1b 445 ip = namei(uchar, 0, 1);
e92a04af 446 if (ip == NULL)
d67a03eb 447 return;
a3aa7f92 448 stat1(ip, uap->sb);
d67a03eb
BJ
449 iput(ip);
450}
451
5485e062 452/*
6459ebe0 453 * Lstat system call. This version does not follow links.
5485e062
BJ
454 */
455lstat()
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;
66d4ba1b 464 ip = namei(uchar, 0, 0);
5485e062
BJ
465 if (ip == NULL)
466 return;
019b08c9 467 stat1(ip, uap->sb);
5485e062
BJ
468 iput(ip);
469}
470
d67a03eb
BJ
471/*
472 * The basic routine for fstat and stat:
473 * get the inode and pass appropriate parts back.
474 */
a3aa7f92 475stat1(ip, ub)
e92a04af
BJ
476 register struct inode *ip;
477 struct stat *ub;
d67a03eb 478{
d67a03eb
BJ
479 struct stat ds;
480
c0bb1685 481 IUPDAT(ip, &time, &time, 0);
d67a03eb 482 /*
e92a04af 483 * First copy from inode table
d67a03eb
BJ
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;
6459ebe0 491 ds.st_rdev = (dev_t)ip->i_rdev;
a3aa7f92 492 ds.st_size = ip->i_size;
6459ebe0
KM
493 ds.st_atime = ip->i_atime;
494 ds.st_mtime = ip->i_mtime;
495 ds.st_ctime = ip->i_ctime;
d67a03eb
BJ
496 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
497 u.u_error = EFAULT;
498}
499
500/*
5485e062
BJ
501 * Return target name of a symbolic link
502 */
503readlink()
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);
525out:
526 iput(ip);
527 u.u_r.r_val1 = uap->count - u.u_count;
528}
529
3e78e260 530chmod()
5485e062 531{
3e78e260 532 register struct inode *ip;
5485e062 533 register struct a {
3e78e260
BJ
534 char *fname;
535 int fmode;
5485e062 536 } *uap;
5485e062
BJ
537
538 uap = (struct a *)u.u_ap;
3e78e260 539 if ((ip = owner(1)) == NULL)
5485e062 540 return;
3e78e260
BJ
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);
5485e062
BJ
548 iput(ip);
549}
550
3e78e260 551chown()
d67a03eb 552{
3e78e260 553 register struct inode *ip;
d67a03eb 554 register struct a {
3e78e260
BJ
555 char *fname;
556 int uid;
557 int gid;
d67a03eb 558 } *uap;
d67a03eb
BJ
559
560 uap = (struct a *)u.u_ap;
3e78e260 561 if (!suser() || (ip = owner(0)) == NULL)
d67a03eb 562 return;
3e78e260
BJ
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);
d67a03eb
BJ
569}
570
571/*
3e78e260
BJ
572 * Set IUPD and IACC times on file.
573 * Can't set ICHG.
d67a03eb 574 */
3e78e260 575utime()
e92a04af 576{
d67a03eb 577 register struct a {
3e78e260
BJ
578 char *fname;
579 time_t *tptr;
d67a03eb 580 } *uap;
3e78e260
BJ
581 register struct inode *ip;
582 time_t tv[2];
d67a03eb
BJ
583
584 uap = (struct a *)u.u_ap;
3e78e260 585 if ((ip = owner(1)) == NULL)
d67a03eb 586 return;
3e78e260
BJ
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);
d67a03eb 592 }
d67a03eb
BJ
593 iput(ip);
594}
595
3e78e260 596sync()
d67a03eb 597{
d67a03eb 598
68503f9a 599 update(0);
d67a03eb 600}