first working version (created and removed a file!)
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
CommitLineData
4147b3f6 1/* lfs_vnops.c 4.30 82/07/24 */
6459ebe0 2
d67a03eb
BJ
3#include "../h/param.h"
4#include "../h/systm.h"
d67a03eb
BJ
5#include "../h/dir.h"
6#include "../h/user.h"
d67a03eb 7#include "../h/file.h"
6459ebe0 8#include "../h/stat.h"
3e78e260 9#include "../h/inode.h"
6459ebe0 10#include "../h/fs.h"
3e78e260 11#include "../h/buf.h"
3e78e260 12#include "../h/proc.h"
0737b714 13#include "../h/inline.h"
f94ceb3b
BJ
14#ifdef EFS
15#include "../net/in.h"
16#include "../h/efs.h"
17#endif
0a77f278 18#include "../h/quota.h"
4147b3f6 19#include "../h/descrip.h"
3e78e260
BJ
20
21chdir()
22{
23
24 chdirec(&u.u_cdir);
25}
26
27chroot()
28{
29
30 if (suser())
31 chdirec(&u.u_rdir);
32}
33
34chdirec(ipp)
35register struct inode **ipp;
36{
37 register struct inode *ip;
38 struct a {
39 char *fname;
40 };
41
42 ip = namei(uchar, 0, 1);
43 if(ip == NULL)
44 return;
45 if((ip->i_mode&IFMT) != IFDIR) {
46 u.u_error = ENOTDIR;
47 goto bad;
48 }
49 if(access(ip, IEXEC))
50 goto bad;
ca91bded 51 iunlock(ip);
8eee8525
KM
52 if (*ipp)
53 irele(*ipp);
3e78e260
BJ
54 *ipp = ip;
55 return;
56
57bad:
58 iput(ip);
59}
60
61/*
62 * Open system call.
63 */
64open()
65{
66 register struct inode *ip;
67 register struct a {
68 char *fname;
69 int rwmode;
70 } *uap;
71
72 uap = (struct a *)u.u_ap;
73 ip = namei(uchar, 0, 1);
74 if (ip == NULL)
75 return;
76 open1(ip, ++uap->rwmode, 0);
77}
78
79/*
80 * Creat system call.
81 */
4147b3f6 82ocreat()
3e78e260
BJ
83{
84 register struct inode *ip;
85 register struct a {
86 char *fname;
87 int fmode;
88 } *uap;
89
90 uap = (struct a *)u.u_ap;
91 ip = namei(uchar, 1, 1);
92 if (ip == NULL) {
93 if (u.u_error)
94 return;
95 ip = maknode(uap->fmode&07777&(~ISVTX));
96 if (ip==NULL)
97 return;
98 open1(ip, FWRITE, 2);
99 } else
100 open1(ip, FWRITE, 1);
101}
102
103/*
104 * Common code for open and creat.
105 * Check permissions, allocate an open file structure,
106 * and call the device open routine if any.
107 */
108open1(ip, mode, trf)
109 register struct inode *ip;
110 register mode;
111{
112 register struct file *fp;
113 int i;
114
115 if (trf != 2) {
116 if (mode&FREAD)
117 (void) access(ip, IREAD);
118 if (mode&FWRITE) {
119 (void) access(ip, IWRITE);
120 if ((ip->i_mode&IFMT) == IFDIR)
121 u.u_error = EISDIR;
122 }
123 }
8eee8525
KM
124 if (u.u_error) {
125 iput(ip);
126 return;
127 }
3e78e260
BJ
128 if (trf == 1)
129 itrunc(ip);
ca91bded 130 iunlock(ip);
3e78e260
BJ
131 if ((fp = falloc()) == NULL)
132 goto out;
133 fp->f_flag = mode&(FREAD|FWRITE);
4147b3f6 134 fp->f_type = DTYPE_FILE;
3e78e260
BJ
135 i = u.u_r.r_val1;
136 fp->f_inode = ip;
f94ceb3b
BJ
137#ifdef EFS
138 openi(ip, mode&(FREAD|FWRITE), trf);
139#else
3e78e260 140 openi(ip, mode&(FREAD|FWRITE));
f94ceb3b 141#endif
3e78e260
BJ
142 if (u.u_error == 0)
143 return;
144 u.u_ofile[i] = NULL;
145 fp->f_count--;
146out:
8eee8525 147 irele(ip);
3e78e260
BJ
148}
149
150/*
151 * Mknod system call
152 */
153mknod()
154{
155 register struct inode *ip;
156 register struct a {
157 char *fname;
158 int fmode;
159 int dev;
160 } *uap;
161
162 uap = (struct a *)u.u_ap;
163 if (suser()) {
164 ip = namei(uchar, 1, 0);
165 if (ip != NULL) {
166 u.u_error = EEXIST;
167 goto out;
168 }
169 }
170 if (u.u_error)
171 return;
172 ip = maknode(uap->fmode);
173 if (ip == NULL)
174 return;
175 if (uap->dev) {
176 /*
177 * Want to be able to use this to make badblock
178 * inodes, so don't truncate the dev number.
179 */
6459ebe0 180 ip->i_rdev = uap->dev;
3e78e260
BJ
181 ip->i_flag |= IACC|IUPD|ICHG;
182 }
183
184out:
185 iput(ip);
186}
187
188/*
189 * link system call
190 */
191link()
192{
193 register struct inode *ip, *xp;
194 register struct a {
195 char *target;
196 char *linkname;
197 } *uap;
198
199 uap = (struct a *)u.u_ap;
200 ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */
201 if (ip == NULL)
202 return;
f94ceb3b
BJ
203 if ((ip->i_mode&IFMT)==IFDIR && !suser()) {
204 iput(ip);
205 return;
206 }
3e78e260
BJ
207 ip->i_nlink++;
208 ip->i_flag |= ICHG;
209 iupdat(ip, &time, &time, 1);
ca91bded 210 iunlock(ip);
3e78e260
BJ
211 u.u_dirp = (caddr_t)uap->linkname;
212 xp = namei(uchar, 1, 0);
213 if (xp != NULL) {
214 u.u_error = EEXIST;
215 iput(xp);
216 goto out;
217 }
218 if (u.u_error)
219 goto out;
220 if (u.u_pdir->i_dev != ip->i_dev) {
221 iput(u.u_pdir);
222 u.u_error = EXDEV;
223 goto out;
224 }
225 wdir(ip);
226out:
227 if (u.u_error) {
228 ip->i_nlink--;
229 ip->i_flag |= ICHG;
230 }
231out1:
8eee8525 232 irele(ip);
3e78e260
BJ
233}
234
235/*
236 * symlink -- make a symbolic link
237 */
238symlink()
239{
240 register struct a {
241 char *target;
242 char *linkname;
243 } *uap;
244 register struct inode *ip;
245 register char *tp;
246 register c, nc;
247
248 uap = (struct a *)u.u_ap;
249 tp = uap->target;
250 nc = 0;
251 while (c = fubyte(tp)) {
252 if (c < 0) {
253 u.u_error = EFAULT;
254 return;
255 }
256 tp++;
257 nc++;
258 }
259 u.u_dirp = uap->linkname;
260 ip = namei(uchar, 1, 0);
261 if (ip) {
262 iput(ip);
263 u.u_error = EEXIST;
264 return;
265 }
266 if (u.u_error)
267 return;
268 ip = maknode(IFLNK | 0777);
269 if (ip == NULL)
270 return;
271 u.u_base = uap->target;
272 u.u_count = nc;
273 u.u_offset = 0;
274 u.u_segflg = 0;
275 writei(ip);
276 iput(ip);
277}
278
279/*
280 * Unlink system call.
281 * Hard to avoid races here, especially
282 * in unlinking directories.
283 */
284unlink()
285{
286 register struct inode *ip, *pp;
287 struct a {
288 char *fname;
289 };
6459ebe0
KM
290 struct fs *fs;
291 struct buf *bp;
292 int lbn, bn, base;
8eee8525 293 int unlinkingdot = 0;
3e78e260
BJ
294
295 pp = namei(uchar, 2, 0);
296 if(pp == NULL)
297 return;
f94ceb3b
BJ
298#ifdef EFS
299 /* divert to extended file system if off machine. */
300 if (efsinode(pp)) {
301 dev_t ndev = pp->i_rdev;
302
303 iput(pp); /* avoid recursive hang on inode */
304 efsunlink(ndev);
305 if (u.u_error != EEXIST)
306 return;
307
308 /*
309 * If a null pathname remainder, then do
310 * the unlink locally after restoring state.
311 */
312 u.u_error = 0;
313 u.u_dirp = (caddr_t)u.u_arg[0];
314 pp = namei(uchar, 2, 0);
315 }
316#endif
317
3e78e260
BJ
318 /*
319 * Check for unlink(".")
320 * to avoid hanging on the iget
321 */
322 if (pp->i_number == u.u_dent.d_ino) {
323 ip = pp;
324 ip->i_count++;
8eee8525 325 unlinkingdot++;
3e78e260 326 } else
6459ebe0 327 ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
3e78e260
BJ
328 if(ip == NULL)
329 goto out1;
330 if((ip->i_mode&IFMT)==IFDIR && !suser())
331 goto out;
332 /*
333 * Don't unlink a mounted file.
334 */
335 if (ip->i_dev != pp->i_dev) {
336 u.u_error = EBUSY;
337 goto out;
338 }
339 if (ip->i_flag&ITEXT)
340 xrele(ip); /* try once to free text */
341/*
342 if ((ip->i_flag&ITEXT) && ip->i_nlink==1) {
343 u.u_error = ETXTBSY;
344 goto out;
345 }
346*/
6459ebe0
KM
347 if (u.u_count == 0) {
348 /*
349 * first entry in block, so set d_ino to zero.
350 */
4147b3f6
BJ
351/*ZZ*/if(u.u_offset&0x1ff)printf("missed dir compact dir %s/%d off %d file %s\n"
352/*ZZ*/,pp->i_fs->fs_fsmnt,pp->i_number,u.u_offset,u.u_dent.d_name);
6459ebe0
KM
353 u.u_base = (caddr_t)&u.u_dent;
354 u.u_count = DIRSIZ(&u.u_dent);
355 u.u_dent.d_ino = 0;
356 writei(pp);
357 } else {
358 /*
359 * updating preceeding entry to skip over current entry.
360 */
361 fs = pp->i_fs;
362 lbn = lblkno(fs, u.u_offset);
363 base = blkoff(fs, u.u_offset);
364 bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
365 bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
366 if (bp->b_flags & B_ERROR) {
367 brelse(bp);
368 goto out;
369 }
370 ((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
371 u.u_dent.d_reclen;
4147b3f6
BJ
372/*ZZ*/if(((int)(bp->b_un.b_addr + base)&0x1ff)+u.u_dent.d_reclen>512)
373/*ZZ*/ panic("unlink: reclen");
6459ebe0
KM
374 bwrite(bp);
375 pp->i_flag |= IUPD|ICHG;
376 }
3e78e260
BJ
377 ip->i_nlink--;
378 ip->i_flag |= ICHG;
379
380out:
8eee8525
KM
381 if (unlinkingdot)
382 irele(ip);
383 else
384 iput(ip);
3e78e260
BJ
385out1:
386 iput(pp);
387}
388
389/*
390 * Seek system call
391 */
392seek()
393{
394 register struct file *fp;
395 register struct a {
396 int fdes;
397 off_t off;
398 int sbase;
399 } *uap;
400
401 uap = (struct a *)u.u_ap;
402 fp = getf(uap->fdes);
403 if (fp == NULL)
404 return;
4147b3f6 405 if (fp->f_type == DTYPE_SOCKET) {
3e78e260
BJ
406 u.u_error = ESPIPE;
407 return;
408 }
409 if (uap->sbase == 1)
410 uap->off += fp->f_offset;
f94ceb3b
BJ
411 else if (uap->sbase == 2) {
412#ifdef EFS
413 struct inode *ip = fp->f_inode;
414 uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size;
415#else
3e78e260 416 uap->off += fp->f_inode->i_size;
f94ceb3b
BJ
417#endif
418 }
3e78e260
BJ
419 fp->f_offset = uap->off;
420 u.u_r.r_off = uap->off;
421}
422
423/*
424 * Access system call
425 */
426saccess()
427{
428 register svuid, svgid;
429 register struct inode *ip;
430 register struct a {
431 char *fname;
432 int fmode;
433 } *uap;
434
435 uap = (struct a *)u.u_ap;
436 svuid = u.u_uid;
437 svgid = u.u_gid;
438 u.u_uid = u.u_ruid;
439 u.u_gid = u.u_rgid;
440 ip = namei(uchar, 0, 1);
f94ceb3b
BJ
441#ifdef EFS
442 if (efsinode(ip)) {
443 dev_t ndev = ip->i_rdev;
444
445 iput(ip);
446 efssaccess(ndev);
447 if (u.u_error != EEXIST)
448 return;
449 u.u_error = 0;
450 u.u_dirp = (caddr_t)u.u_arg[0];
451 ip = namei(uchar, 0, 1);
452 }
453#endif
3e78e260
BJ
454 if (ip != NULL) {
455 if (uap->fmode&(IREAD>>6))
456 (void) access(ip, IREAD);
457 if (uap->fmode&(IWRITE>>6))
458 (void) access(ip, IWRITE);
459 if (uap->fmode&(IEXEC>>6))
460 (void) access(ip, IEXEC);
461 iput(ip);
462 }
463 u.u_uid = svuid;
464 u.u_gid = svgid;
465}
d67a03eb
BJ
466
467/*
468 * the fstat system call.
469 */
470fstat()
471{
472 register struct file *fp;
473 register struct a {
474 int fdes;
475 struct stat *sb;
476 } *uap;
477
478 uap = (struct a *)u.u_ap;
479 fp = getf(uap->fdes);
e92a04af 480 if (fp == NULL)
d67a03eb 481 return;
f94ceb3b
BJ
482#ifdef EFS
483 if (efsinode(fp->f_inode)) {
484 efsfstat(fp->f_inode->i_rdev, fp);
485 return;
486 }
487#endif
4147b3f6 488 if (fp->f_type == DTYPE_SOCKET)
cc15ab5d 489 u.u_error = sostat(fp->f_socket, uap->sb);
e92a04af
BJ
490 else
491 stat1(fp->f_inode, uap->sb);
d67a03eb
BJ
492}
493
494/*
6459ebe0 495 * Stat system call. This version follows links.
d67a03eb
BJ
496 */
497stat()
498{
499 register struct inode *ip;
500 register struct a {
501 char *fname;
502 struct stat *sb;
503 } *uap;
504
505 uap = (struct a *)u.u_ap;
66d4ba1b 506 ip = namei(uchar, 0, 1);
e92a04af 507 if (ip == NULL)
d67a03eb 508 return;
f94ceb3b
BJ
509#ifdef EFS
510 if (efsinode(ip)) {
511 dev_t ndev = ip->i_rdev;
512
513 iput(ip);
514 efsstat(ndev);
515 if (u.u_error != EEXIST)
516 return;
517 u.u_error = 0;
518 u.u_dirp = (caddr_t)u.u_arg[0];
519 ip = namei(uchar, 0, 1);
520 }
521#endif
a3aa7f92 522 stat1(ip, uap->sb);
d67a03eb
BJ
523 iput(ip);
524}
525
5485e062 526/*
6459ebe0 527 * Lstat system call. This version does not follow links.
5485e062
BJ
528 */
529lstat()
530{
531 register struct inode *ip;
532 register struct a {
533 char *fname;
534 struct stat *sb;
535 } *uap;
536
537 uap = (struct a *)u.u_ap;
66d4ba1b 538 ip = namei(uchar, 0, 0);
5485e062
BJ
539 if (ip == NULL)
540 return;
f94ceb3b
BJ
541#ifdef EFS
542 if (efsinode(ip)) {
543 dev_t ndev = ip->i_rdev;
544
545 iput(ip);
546 efslstat(ndev);
547 if (u.u_error != EEXIST)
548 return;
549 u.u_error = 0;
550 u.u_dirp = (caddr_t)u.u_arg[0];
551 ip = namei(uchar, 0, 0);
552 }
553#endif
019b08c9 554 stat1(ip, uap->sb);
5485e062
BJ
555 iput(ip);
556}
557
d67a03eb
BJ
558/*
559 * The basic routine for fstat and stat:
560 * get the inode and pass appropriate parts back.
561 */
a3aa7f92 562stat1(ip, ub)
e92a04af
BJ
563 register struct inode *ip;
564 struct stat *ub;
d67a03eb 565{
d67a03eb
BJ
566 struct stat ds;
567
c0bb1685 568 IUPDAT(ip, &time, &time, 0);
d67a03eb 569 /*
09c42945 570 * Copy from inode table
d67a03eb
BJ
571 */
572 ds.st_dev = ip->i_dev;
573 ds.st_ino = ip->i_number;
574 ds.st_mode = ip->i_mode;
575 ds.st_nlink = ip->i_nlink;
576 ds.st_uid = ip->i_uid;
577 ds.st_gid = ip->i_gid;
6459ebe0 578 ds.st_rdev = (dev_t)ip->i_rdev;
a3aa7f92 579 ds.st_size = ip->i_size;
6459ebe0
KM
580 ds.st_atime = ip->i_atime;
581 ds.st_mtime = ip->i_mtime;
582 ds.st_ctime = ip->i_ctime;
09c42945 583 ds.st_blksize = ip->i_fs->fs_bsize;
d67a03eb
BJ
584 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
585 u.u_error = EFAULT;
586}
587
588/*
5485e062
BJ
589 * Return target name of a symbolic link
590 */
591readlink()
592{
593 register struct inode *ip;
594 register struct a {
595 char *name;
596 char *buf;
597 int count;
598 } *uap;
599
600 ip = namei(uchar, 0, 0);
601 if (ip == NULL)
602 return;
f94ceb3b
BJ
603#ifdef EFS
604 if (efsinode(ip)) {
605 dev_t ndev = ip->i_rdev;
606
607 iput(ip);
608 efsreadlink(ndev);
609 if (u.u_error != EEXIST)
610 return;
611 u.u_error = 0;
612 u.u_dirp = (caddr_t)u.u_arg[0];
613 ip = namei(uchar, 0, 0);
614 return (0);
615 }
616#endif
5485e062
BJ
617 if ((ip->i_mode&IFMT) != IFLNK) {
618 u.u_error = ENXIO;
619 goto out;
620 }
621 uap = (struct a *)u.u_ap;
622 u.u_offset = 0;
623 u.u_base = uap->buf;
624 u.u_count = uap->count;
625 u.u_segflg = 0;
626 readi(ip);
627out:
628 iput(ip);
629 u.u_r.r_val1 = uap->count - u.u_count;
630}
631
3e78e260 632chmod()
5485e062 633{
3e78e260 634 register struct inode *ip;
5485e062 635 register struct a {
3e78e260
BJ
636 char *fname;
637 int fmode;
5485e062 638 } *uap;
5485e062
BJ
639
640 uap = (struct a *)u.u_ap;
3e78e260 641 if ((ip = owner(1)) == NULL)
5485e062 642 return;
f94ceb3b
BJ
643#ifdef EFS
644 if (efsinode(ip)) {
645 dev_t ndev = ip->i_rdev;
646
647 iput(ip);
648 efschmod(ndev);
649 if (u.u_error != EEXIST)
650 return;
651 u.u_error = 0;
652 u.u_dirp = (caddr_t)u.u_arg[0];
653 ip = owner(1);
654 }
655#endif
3e78e260 656 ip->i_mode &= ~07777;
f94ceb3b 657 if (u.u_uid) {
3e78e260 658 uap->fmode &= ~ISVTX;
f94ceb3b
BJ
659 if (ip->i_gid >= NGRPS ||
660 (u.u_grps[ip->i_gid/(sizeof(int)*8)] &
661 (1 << ip->i_gid%(sizeof(int)*8))) == 0)
662 uap->fmode &= ~ISGID;
0a77f278
RE
663#if MUSH
664 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
665 (ip->i_mode & IFMT) != IFCHR)
666 uap->fmode &= ~u.u_cmask;
667#endif
f94ceb3b 668 }
3e78e260
BJ
669 ip->i_mode |= uap->fmode&07777;
670 ip->i_flag |= ICHG;
671 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
672 xrele(ip);
0a77f278
RE
673#ifdef MELB
674 if ((ip->i_mode & ISUID) && ip->i_uid == 0)
675 printf("%s: ino %d (%s) setuid root\n"
676 , getfs(ip->i_dev)->s_fsmnt
677 , ip->i_number
678 , u.u_dent.d_name
679 );
680#endif
5485e062
BJ
681 iput(ip);
682}
683
3e78e260 684chown()
d67a03eb 685{
3e78e260 686 register struct inode *ip;
d67a03eb 687 register struct a {
3e78e260
BJ
688 char *fname;
689 int uid;
690 int gid;
d67a03eb 691 } *uap;
0a77f278
RE
692#if QUOTA
693 register long change;
694#endif
d67a03eb
BJ
695
696 uap = (struct a *)u.u_ap;
3e78e260 697 if (!suser() || (ip = owner(0)) == NULL)
d67a03eb 698 return;
f94ceb3b
BJ
699#ifdef EFS
700 if (efsinode(ip)) {
701 dev_t ndev = ip->i_rdev;
702
703 iput(ip);
704 efschown(ndev);
705 if (u.u_error != EEXIST)
706 return;
707 u.u_error = 0;
708 u.u_dirp = (caddr_t)u.u_arg[0];
709 ip = owner(0);
710 }
0a77f278
RE
711#endif
712#if QUOTA
713 /*
714 * This doesn't allow for holes in files (which hopefully don't
715 * happen often in files that we chown), and is not accurate anyway
716 * (eg: it totally ignores 3 level indir blk files - but hopefully
717 * noone who can make a file that big will have a quota)
718 */
719 if (ip->i_uid == uap->uid)
720 change = 0;
721 else {
722 register struct fs *fs = ip->i_fs;
723
724 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
725 register off_t size;
726
727 size = blkroundup(fs, ip->i_size) - change;
728 change += size;
729 change += fs->fs_bsize;
730 /* This assumes NIADDR <= 2 */
731 if (size > NINDIR(fs) * fs->fs_bsize)
732 change += fs->fs_bsize;
733 } else
734 change = fragroundup(fs, ip->i_size);
735 change /= DEV_BSIZE;
736 }
737 chkdq(ip, -change, 1);
738 chkiq(ip->i_dev, ip, ip->i_uid, 1);
739 dqrele(ip->i_dquot);
f94ceb3b
BJ
740#endif
741 /*
742 * keep uid/gid's in sane range - no err, so chown(file, uid, -1)
743 * will do something useful
744 */
745 if (uap->uid >= 0 && uap->uid <= 32767) /* should have a const */
746 ip->i_uid = uap->uid;
747 if (uap->gid >= 0 && uap->gid <= 32767) /* same here */
748 ip->i_gid = uap->gid;
3e78e260
BJ
749 ip->i_flag |= ICHG;
750 if (u.u_ruid != 0)
751 ip->i_mode &= ~(ISUID|ISGID);
0a77f278
RE
752#if QUOTA
753 ip->i_dquot = inoquota(ip);
754 chkdq(ip, change, 1);
755 chkiq(ip->i_dev, NULL, uap->uid, 1);
756#endif
3e78e260 757 iput(ip);
d67a03eb
BJ
758}
759
760/*
3e78e260
BJ
761 * Set IUPD and IACC times on file.
762 * Can't set ICHG.
d67a03eb 763 */
3e78e260 764utime()
e92a04af 765{
d67a03eb 766 register struct a {
3e78e260
BJ
767 char *fname;
768 time_t *tptr;
d67a03eb 769 } *uap;
3e78e260
BJ
770 register struct inode *ip;
771 time_t tv[2];
d67a03eb
BJ
772
773 uap = (struct a *)u.u_ap;
3e78e260 774 if ((ip = owner(1)) == NULL)
d67a03eb 775 return;
3e78e260
BJ
776 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
777 u.u_error = EFAULT;
778 } else {
f94ceb3b
BJ
779#ifdef EFS
780 if (efsinode(ip)) {
781 dev_t ndev = ip->i_rdev;
782
783 iput(ip);
784 efsutime(ndev, uap->fname, tv);
785 if (u.u_error != EEXIST)
786 return;
787 u.u_error = 0;
788 u.u_dirp = (caddr_t)u.u_arg[0];
789 ip = owner(1);
790 }
791#endif
3e78e260
BJ
792 ip->i_flag |= IACC|IUPD|ICHG;
793 iupdat(ip, &tv[0], &tv[1], 0);
d67a03eb 794 }
d67a03eb
BJ
795 iput(ip);
796}
797
3e78e260 798sync()
d67a03eb 799{
d67a03eb 800
68503f9a 801 update(0);
d67a03eb 802}