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