check delete permission on source before doing any work
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
... / ...
CommitLineData
1/* lfs_vnops.c 4.52 83/03/21 */
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/kernel.h"
8#include "../h/file.h"
9#include "../h/stat.h"
10#include "../h/inode.h"
11#include "../h/fs.h"
12#include "../h/buf.h"
13#include "../h/proc.h"
14#include "../h/quota.h"
15#include "../h/descrip.h"
16#include "../h/uio.h"
17#include "../h/socket.h"
18#include "../h/socketvar.h"
19#include "../h/nami.h"
20
21/*
22 * Change current working directory (``.'').
23 */
24chdir()
25{
26
27 chdirec(&u.u_cdir);
28}
29
30/*
31 * Change notion of root (``/'') directory.
32 */
33chroot()
34{
35
36 if (suser())
37 chdirec(&u.u_rdir);
38}
39
40/*
41 * Common routine for chroot and chdir.
42 */
43chdirec(ipp)
44 register struct inode **ipp;
45{
46 register struct inode *ip;
47 struct a {
48 char *fname;
49 };
50
51 ip = namei(uchar, LOOKUP, 1);
52 if (ip == NULL)
53 return;
54 if ((ip->i_mode&IFMT) != IFDIR) {
55 u.u_error = ENOTDIR;
56 goto bad;
57 }
58 if (access(ip, IEXEC))
59 goto bad;
60 iunlock(ip);
61 if (*ipp)
62 irele(*ipp);
63 *ipp = ip;
64 return;
65
66bad:
67 iput(ip);
68}
69
70/*
71 * Open system call.
72 */
73open()
74{
75 register struct inode *ip;
76 register struct a {
77 char *fname;
78 int flags;
79 int mode;
80 } *uap;
81 int checkpermissions = 1, flags;
82
83 uap = (struct a *)u.u_ap;
84 flags = uap->flags + 1;
85 if ((flags&FTRUNCATE) && (flags&FWRITE) == 0) {
86 u.u_error = EINVAL;
87 return;
88 }
89 if (flags&FCREATE) {
90 ip = namei(uchar, CREATE, 1);
91 if (ip == NULL) {
92 if (u.u_error)
93 return;
94 ip = maknode(uap->mode&07777&(~ISVTX));
95 checkpermissions = 0;
96 flags &= ~FTRUNCATE;
97 }
98 } else
99 ip = namei(uchar, LOOKUP, 1);
100 if (ip == NULL)
101 return;
102 open1(ip, flags, checkpermissions);
103}
104
105#ifndef NOCOMPAT
106/*
107 * Creat system call.
108 */
109ocreat()
110{
111 register struct inode *ip;
112 register struct a {
113 char *fname;
114 int fmode;
115 } *uap;
116
117 uap = (struct a *)u.u_ap;
118 ip = namei(uchar, CREATE, 1);
119 if (ip == NULL) {
120 if (u.u_error)
121 return;
122 ip = maknode(uap->fmode&07777&(~ISVTX));
123 if (ip == NULL)
124 return;
125 open1(ip, FWRITE, 0);
126 } else
127 open1(ip, FWRITE|FTRUNCATE, 1);
128}
129#endif
130
131/*
132 * Common code for open and creat.
133 * Check permissions (if we haven't done so already),
134 * allocate an open file structure, and call
135 * the device open routine, if any.
136 */
137open1(ip, mode, checkpermissions)
138 register struct inode *ip;
139 register mode;
140{
141 register struct file *fp;
142 int i, flags;
143
144 if (checkpermissions) {
145 if (mode&FREAD)
146 if (access(ip, IREAD))
147 goto bad;
148 if (mode&FWRITE) {
149 if (access(ip, IWRITE))
150 goto bad;
151 if ((ip->i_mode&IFMT) == IFDIR) {
152 u.u_error = EISDIR;
153 goto bad;
154 }
155 }
156 }
157
158 /*
159 * Check locking on inode. Release "inode lock"
160 * while doing so in case we block inside flocki.
161 */
162 flags = 0;
163 if (mode&(FSHLOCK|FEXLOCK)) {
164 iunlock(ip);
165 flags = flocki(ip, 0, mode);
166 ilock(ip);
167 if (u.u_error)
168 goto bad;
169 }
170 if (mode&FTRUNCATE)
171 itrunc(ip, (u_long)0);
172 iunlock(ip);
173 if ((fp = falloc()) == NULL)
174 goto out;
175 fp->f_flag = mode & FMODES;
176 fp->f_type = DTYPE_FILE;
177 i = u.u_r.r_val1;
178 fp->f_inode = ip;
179 u.u_error = openi(ip, mode);
180 if (u.u_error == 0) {
181 u.u_pofile[i] = flags;
182 return;
183 }
184 u.u_ofile[i] = NULL;
185 fp->f_count--;
186out:
187 irele(ip);
188 return;
189bad:
190 iput(ip);
191}
192
193/*
194 * Mknod system call
195 */
196mknod()
197{
198 register struct inode *ip;
199 register struct a {
200 char *fname;
201 int fmode;
202 int dev;
203 } *uap;
204
205 uap = (struct a *)u.u_ap;
206 if (suser()) {
207 ip = namei(uchar, CREATE, 0);
208 if (ip != NULL) {
209 u.u_error = EEXIST;
210 goto out;
211 }
212 }
213 if (u.u_error)
214 return;
215 ip = maknode(uap->fmode);
216 if (ip == NULL)
217 return;
218 if (uap->dev) {
219 /*
220 * Want to be able to use this to make badblock
221 * inodes, so don't truncate the dev number.
222 */
223 ip->i_rdev = uap->dev;
224 ip->i_flag |= IACC|IUPD|ICHG;
225 }
226
227out:
228 iput(ip);
229}
230
231/*
232 * link system call
233 */
234link()
235{
236 register struct inode *ip, *xp;
237 register struct a {
238 char *target;
239 char *linkname;
240 } *uap;
241
242 uap = (struct a *)u.u_ap;
243 ip = namei(uchar, LOOKUP, 1); /* well, this routine is doomed anyhow */
244 if (ip == NULL)
245 return;
246 if ((ip->i_mode&IFMT) == IFDIR && !suser()) {
247 iput(ip);
248 return;
249 }
250 ip->i_nlink++;
251 ip->i_flag |= ICHG;
252 iupdat(ip, &time, &time, 1);
253 iunlock(ip);
254 u.u_dirp = (caddr_t)uap->linkname;
255 xp = namei(uchar, CREATE, 0);
256 if (xp != NULL) {
257 u.u_error = EEXIST;
258 iput(xp);
259 goto out;
260 }
261 if (u.u_error)
262 goto out;
263 if (u.u_pdir->i_dev != ip->i_dev) {
264 iput(u.u_pdir);
265 u.u_error = EXDEV;
266 goto out;
267 }
268 u.u_error = direnter(ip);
269out:
270 if (u.u_error) {
271 ip->i_nlink--;
272 ip->i_flag |= ICHG;
273 }
274 irele(ip);
275}
276
277/*
278 * symlink -- make a symbolic link
279 */
280symlink()
281{
282 register struct a {
283 char *target;
284 char *linkname;
285 } *uap;
286 register struct inode *ip;
287 register char *tp;
288 register c, nc;
289
290 uap = (struct a *)u.u_ap;
291 tp = uap->target;
292 nc = 0;
293 while (c = fubyte(tp)) {
294 if (c < 0) {
295 u.u_error = EFAULT;
296 return;
297 }
298 tp++;
299 nc++;
300 }
301 u.u_dirp = uap->linkname;
302 ip = namei(uchar, CREATE, 0);
303 if (ip) {
304 iput(ip);
305 u.u_error = EEXIST;
306 return;
307 }
308 if (u.u_error)
309 return;
310 ip = maknode(IFLNK | 0777);
311 if (ip == NULL)
312 return;
313 u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0);
314 /* handle u.u_error != 0 */
315 iput(ip);
316}
317
318/*
319 * Unlink system call.
320 * Hard to avoid races here, especially
321 * in unlinking directories.
322 */
323unlink()
324{
325 struct a {
326 char *fname;
327 };
328 register struct inode *ip, *dp;
329
330 ip = namei(uchar, DELETE | LOCKPARENT, 0);
331 if (ip == NULL)
332 return;
333 dp = u.u_pdir;
334 if ((ip->i_mode&IFMT) == IFDIR && !suser())
335 goto out;
336 /*
337 * Don't unlink a mounted file.
338 */
339 if (ip->i_dev != dp->i_dev) {
340 u.u_error = EBUSY;
341 goto out;
342 }
343 if (ip->i_flag&ITEXT)
344 xrele(ip); /* try once to free text */
345 if (dirremove()) {
346 ip->i_nlink--;
347 ip->i_flag |= ICHG;
348 }
349out:
350 if (dp == ip)
351 irele(ip);
352 else
353 iput(ip);
354 iput(dp);
355}
356
357/*
358 * Seek system call
359 */
360lseek()
361{
362 register struct file *fp;
363 register struct a {
364 int fd;
365 off_t off;
366 int sbase;
367 } *uap;
368
369 uap = (struct a *)u.u_ap;
370 fp = getf(uap->fd);
371 if (fp == NULL)
372 return;
373 if (fp->f_type == DTYPE_SOCKET) {
374 u.u_error = ESPIPE;
375 return;
376 }
377 if (uap->sbase == FSEEK_RELATIVE)
378 uap->off += fp->f_offset;
379 else if (uap->sbase == FSEEK_EOF)
380 uap->off += fp->f_inode->i_size;
381 fp->f_offset = uap->off;
382 u.u_r.r_off = uap->off;
383}
384
385/*
386 * Access system call
387 */
388saccess()
389{
390 register svuid, svgid;
391 register struct inode *ip;
392 register struct a {
393 char *fname;
394 int fmode;
395 } *uap;
396
397 uap = (struct a *)u.u_ap;
398 svuid = u.u_uid;
399 svgid = u.u_gid;
400 u.u_uid = u.u_ruid;
401 u.u_gid = u.u_rgid;
402 ip = namei(uchar, LOOKUP, 1);
403 if (ip != NULL) {
404 if ((uap->fmode&FACCESS_READ) && access(ip, IREAD))
405 goto done;
406 if ((uap->fmode&FACCESS_WRITE) && access(ip, IWRITE))
407 goto done;
408 if ((uap->fmode&FACCESS_EXECUTE) && access(ip, IEXEC))
409 goto done;
410done:
411 iput(ip);
412 }
413 u.u_uid = svuid;
414 u.u_gid = svgid;
415}
416
417/*
418 * the fstat system call.
419 */
420fstat()
421{
422 register struct file *fp;
423 register struct a {
424 int fd;
425 struct stat *sb;
426 } *uap;
427
428 uap = (struct a *)u.u_ap;
429 fp = getf(uap->fd);
430 if (fp == NULL)
431 return;
432 if (fp->f_type == DTYPE_SOCKET)
433 u.u_error = sostat(fp->f_socket, uap->sb);
434 else
435 stat1(fp->f_inode, uap->sb);
436}
437
438/*
439 * Stat system call. This version follows links.
440 */
441stat()
442{
443 register struct inode *ip;
444 register struct a {
445 char *fname;
446 struct stat *sb;
447 } *uap;
448
449 uap = (struct a *)u.u_ap;
450 ip = namei(uchar, LOOKUP, 1);
451 if (ip == NULL)
452 return;
453 stat1(ip, uap->sb);
454 iput(ip);
455}
456
457/*
458 * Lstat system call. This version does not follow links.
459 */
460lstat()
461{
462 register struct inode *ip;
463 register struct a {
464 char *fname;
465 struct stat *sb;
466 } *uap;
467
468 uap = (struct a *)u.u_ap;
469 ip = namei(uchar, LOOKUP, 0);
470 if (ip == NULL)
471 return;
472 stat1(ip, uap->sb);
473 iput(ip);
474}
475
476/*
477 * The basic routine for fstat and stat:
478 * get the inode and pass appropriate parts back.
479 */
480stat1(ip, ub)
481 register struct inode *ip;
482 struct stat *ub;
483{
484 struct stat ds;
485
486 IUPDAT(ip, &time, &time, 0);
487 /*
488 * Copy from inode table
489 */
490 ds.st_dev = ip->i_dev;
491 ds.st_ino = ip->i_number;
492 ds.st_mode = ip->i_mode;
493 ds.st_nlink = ip->i_nlink;
494 ds.st_uid = ip->i_uid;
495 ds.st_gid = ip->i_gid;
496 ds.st_rdev = (dev_t)ip->i_rdev;
497 ds.st_size = ip->i_size;
498 ds.st_atime = ip->i_atime;
499 ds.st_spare1 = 0;
500 ds.st_mtime = ip->i_mtime;
501 ds.st_spare2 = 0;
502 ds.st_ctime = ip->i_ctime;
503 ds.st_spare3 = 0;
504 /* this doesn't belong here */
505 if ((ip->i_mode&IFMT) == IFBLK)
506 ds.st_blksize = BLKDEV_IOSIZE;
507 else if ((ip->i_mode&IFMT) == IFCHR)
508 ds.st_blksize = MAXBSIZE;
509 else
510 ds.st_blksize = ip->i_fs->fs_bsize;
511 ds.st_spare4[0] = ds.st_spare4[1] = ds.st_spare4[2] = 0;
512 u.u_error = copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds));
513}
514
515/*
516 * Return target name of a symbolic link
517 */
518readlink()
519{
520 register struct inode *ip;
521 register struct a {
522 char *name;
523 char *buf;
524 int count;
525 } *uap = (struct a *)u.u_ap;
526 int resid;
527
528 ip = namei(uchar, LOOKUP, 0);
529 if (ip == NULL)
530 return;
531 if ((ip->i_mode&IFMT) != IFLNK) {
532 u.u_error = ENXIO;
533 goto out;
534 }
535 u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid);
536out:
537 iput(ip);
538 u.u_r.r_val1 = uap->count - resid;
539}
540
541/*
542 * Change mode of a file given path name.
543 */
544chmod()
545{
546 struct inode *ip;
547 struct a {
548 char *fname;
549 int fmode;
550 } *uap;
551
552 uap = (struct a *)u.u_ap;
553 if ((ip = owner(1)) == NULL)
554 return;
555 chmod1(ip, uap->fmode);
556 iput(ip);
557}
558
559/*
560 * Change mode of a file given a file descriptor.
561 */
562fchmod()
563{
564 struct a {
565 int fd;
566 int fmode;
567 } *uap;
568 register struct inode *ip;
569 register struct file *fp;
570
571 uap = (struct a *)u.u_ap;
572 fp = getf(uap->fd);
573 if (fp == NULL)
574 return;
575 if (fp->f_type == DTYPE_SOCKET) {
576 u.u_error = EINVAL;
577 return;
578 }
579 ip = fp->f_inode;
580 if (u.u_uid != ip->i_uid && !suser())
581 return;
582 ilock(ip);
583 chmod1(ip, uap->fmode);
584 iunlock(ip);
585}
586
587/*
588 * Change the mode on a file.
589 * Inode must be locked before calling.
590 */
591chmod1(ip, mode)
592 register struct inode *ip;
593 register int mode;
594{
595 register int *gp;
596
597 ip->i_mode &= ~07777;
598 if (u.u_uid) {
599 mode &= ~ISVTX;
600 if (u.u_gid == ip->i_gid)
601 goto ok;
602 for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
603 if (*gp == ip->i_gid)
604 goto ok;
605 mode &= ~ISGID;
606ok:
607 ;
608#ifdef MUSH
609 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
610 (ip->i_mode & IFMT) != IFCHR)
611 mode &= ~u.u_cmask;
612#endif
613 }
614 ip->i_mode |= mode&07777;
615 ip->i_flag |= ICHG;
616 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
617 xrele(ip);
618}
619
620/*
621 * Set ownership given a path name.
622 */
623chown()
624{
625 struct inode *ip;
626 struct a {
627 char *fname;
628 int uid;
629 int gid;
630 } *uap;
631
632 uap = (struct a *)u.u_ap;
633 if (!suser() || (ip = owner(0)) == NULL)
634 return;
635 chown1(ip, uap->uid, uap->gid);
636 iput(ip);
637}
638
639/*
640 * Set ownership given a file descriptor.
641 */
642fchown()
643{
644 struct a {
645 int fd;
646 int uid;
647 int gid;
648 } *uap;
649 register struct inode *ip;
650 register struct file *fp;
651
652 uap = (struct a *)u.u_ap;
653 fp = getf(uap->fd);
654 if (fp == NULL)
655 return;
656 if (fp->f_type == DTYPE_SOCKET) {
657 u.u_error = EINVAL;
658 return;
659 }
660 ip = fp->f_inode;
661 if (!suser())
662 return;
663 ilock(ip);
664 chown1(ip, uap->uid, uap->gid);
665 iunlock(ip);
666}
667
668/*
669 * Perform chown operation on inode ip;
670 * inode must be locked prior to call.
671 */
672chown1(ip, uid, gid)
673 register struct inode *ip;
674 int uid, gid;
675{
676#ifdef QUOTA
677 register long change;
678
679 /*
680 * This doesn't allow for holes in files (which hopefully don't
681 * happen often in files that we chown), and is not accurate anyway
682 * (eg: it totally ignores 3 level indir blk files - but hopefully
683 * noone who can make a file that big will have a quota)
684 */
685 if (ip->i_uid == uid)
686 change = 0;
687 else {
688 register struct fs *fs = ip->i_fs;
689
690 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
691 register off_t size;
692
693 size = blkroundup(fs, ip->i_size) - change;
694 change += size;
695 change += fs->fs_bsize;
696 /* this assumes NIADDR <= 2 */
697 if (size > NINDIR(fs) * fs->fs_bsize)
698 change += fs->fs_bsize;
699 } else
700 change = fragroundup(fs, ip->i_size);
701 change /= DEV_BSIZE;
702 }
703 (void)chkdq(ip, -change, 1);
704 (void)chkiq(ip->i_dev, ip, ip->i_uid, 1);
705 dqrele(ip->i_dquot);
706#endif
707 /*
708 * keep uid/gid's in sane range -- no err,
709 * so chown(file, uid, -1) will do something useful
710 */
711 if (uid >= 0 && uid <= 32767) /* should have a constant */
712 ip->i_uid = uid;
713 if (gid >= 0 && gid <= 32767) /* same here */
714 ip->i_gid = gid;
715 ip->i_flag |= ICHG;
716 if (u.u_ruid != 0)
717 ip->i_mode &= ~(ISUID|ISGID);
718#ifdef QUOTA
719 ip->i_dquot = inoquota(ip);
720 (void)chkdq(ip, change, 1);
721 (void)chkiq(ip->i_dev, (struct inode *)NULL, uid, 1);
722#endif
723}
724
725/*
726 * Set IUPD and IACC times on file.
727 * Can't set ICHG.
728 */
729outime()
730{
731 register struct a {
732 char *fname;
733 time_t *tptr;
734 } *uap;
735 register struct inode *ip;
736 time_t tv[2];
737 struct timeval tv0, tv1;
738
739 uap = (struct a *)u.u_ap;
740 if ((ip = owner(1)) == NULL)
741 return;
742 u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv));
743 if (u.u_error == 0) {
744 ip->i_flag |= IACC|IUPD|ICHG;
745 tv0.tv_sec = tv[0]; tv0.tv_usec = 0;
746 tv1.tv_sec = tv[1]; tv1.tv_usec = 0;
747 iupdat(ip, &tv0, &tv1, 0);
748 }
749 iput(ip);
750}
751
752/*
753 * Flush any pending I/O.
754 */
755sync()
756{
757
758 update();
759}
760
761/*
762 * Apply an advisory lock on a file descriptor.
763 */
764flock()
765{
766 struct a {
767 int fd;
768 int how;
769 } *uap;
770 register struct file *fp;
771 register int cmd, flags;
772
773 uap = (struct a *)u.u_ap;
774 fp = getf(uap->fd);
775 if (fp == NULL)
776 return;
777 if (fp->f_type == DTYPE_SOCKET) { /* XXX */
778 u.u_error = EINVAL;
779 return;
780 }
781 cmd = uap->how;
782 flags = u.u_pofile[uap->fd] & (UF_SHLOCK|UF_EXLOCK);
783 if (cmd&FUNLOCK) {
784 if (flags == 0) {
785 u.u_error = EINVAL;
786 return;
787 }
788 funlocki(fp->f_inode, flags);
789 u.u_pofile[uap->fd] &= ~(UF_SHLOCK|UF_EXLOCK);
790 return;
791 }
792 /*
793 * No reason to write lock a file we've already
794 * write locked, similarly with a read lock.
795 */
796 if ((flags&UF_EXLOCK) && (cmd&FEXLOCK) ||
797 (flags&UF_SHLOCK) && (cmd&FSHLOCK))
798 return;
799 u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd);
800}
801
802/*
803 * Truncate a file given its path name.
804 */
805truncate()
806{
807 struct a {
808 char *fname;
809 u_long length;
810 } *uap = (struct a *)u.u_ap;
811 struct inode *ip;
812
813 ip = namei(uchar, LOOKUP, 1);
814 if (ip == NULL)
815 return;
816 if (access(ip, IWRITE))
817 goto bad;
818 if ((ip->i_mode&IFMT) == IFDIR) {
819 u.u_error = EISDIR;
820 goto bad;
821 }
822 itrunc(ip, uap->length);
823bad:
824 iput(ip);
825}
826
827/*
828 * Truncate a file given a file descriptor.
829 */
830ftruncate()
831{
832 struct a {
833 int fd;
834 u_long length;
835 } *uap = (struct a *)u.u_ap;
836 struct inode *ip;
837 struct file *fp;
838
839 fp = getf(uap->fd);
840 if (fp == NULL)
841 return;
842 if (fp->f_type == DTYPE_SOCKET) {
843 u.u_error = EINVAL;
844 return;
845 }
846 if ((fp->f_flag&FWRITE) == 0) {
847 u.u_error = EINVAL;
848 return;
849 }
850 ip = fp->f_inode;
851 ilock(ip);
852 itrunc(ip, uap->length);
853 iunlock(ip);
854}
855
856/*
857 * Synch an open file.
858 */
859fsync()
860{
861 struct a {
862 int fd;
863 } *uap = (struct a *)u.u_ap;
864 struct inode *ip;
865 struct file *fp;
866
867 fp = getf(uap->fd);
868 if (fp == NULL)
869 return;
870 if (fp->f_type == DTYPE_SOCKET) {
871 u.u_error = EINVAL;
872 return;
873 }
874 ip = fp->f_inode;
875 ilock(ip);
876 syncip(ip);
877 iunlock(ip);
878}
879
880/*
881 * Rename system call.
882 * rename("foo", "bar");
883 * is essentially
884 * unlink("bar");
885 * link("foo", "bar");
886 * unlink("foo");
887 * but ``atomically''. Can't do full commit without saving state in the
888 * inode on disk which isn't feasible at this time. Best we can do is
889 * always guarantee the target exists.
890 *
891 * Basic algorithm is:
892 *
893 * 1) Bump link count on source while we're linking it to the
894 * target. This also insure the inode won't be deleted out
895 * from underneath us while we work.
896 * 2) Link source to destination. If destination already exists,
897 * delete it first.
898 * 3) Unlink source reference to inode if still around.
899 * 4) If a directory was moved and the parent of the destination
900 * is different from the source, patch the ".." entry in the
901 * directory.
902 *
903 * Source and destination must either both be directories, or both
904 * not be directories. If target is a directory, it must be empty.
905 */
906rename()
907{
908 struct a {
909 char *from;
910 char *to;
911 } *uap;
912 register struct inode *ip, *xp, *dp;
913 int oldparent, parentdifferent, doingdirectory;
914 int error = 0;
915
916 uap = (struct a *)u.u_ap;
917 ip = namei(uchar, DELETE | LOCKPARENT, 0);
918 if (ip == NULL)
919 return;
920 dp = u.u_pdir;
921 oldparent = 0, doingdirectory = 0;
922 if ((ip->i_mode&IFMT) == IFDIR) {
923 register struct direct *d;
924
925 d = &u.u_dent;
926 /*
927 * Avoid ".", "..", and aliases of "." for obvious reasons.
928 */
929 if ((d->d_namlen == 1 && d->d_name[0] == '.') ||
930 (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) ||
931 (dp == ip)) {
932 iput(dp);
933 if (dp == ip)
934 irele(ip);
935 else
936 iput(ip);
937 u.u_error = EINVAL;
938 return;
939 }
940 oldparent = dp->i_number;
941 doingdirectory++;
942 }
943 iput(dp);
944
945 /*
946 * 1) Bump link count while we're moving stuff
947 * around. If we crash somewhere before
948 * completing our work, the link count
949 * may be wrong, but correctable.
950 */
951 ip->i_nlink++;
952 ip->i_flag |= ICHG;
953 iupdat(ip, &time, &time, 1);
954 iunlock(ip);
955
956 /*
957 * When the target exists, both the directory
958 * and target inodes are returned locked.
959 */
960 u.u_dirp = (caddr_t)uap->to;
961 xp = namei(uchar, CREATE | LOCKPARENT, 0);
962 if (u.u_error) {
963 error = u.u_error;
964 goto out;
965 }
966 dp = u.u_pdir;
967 /*
968 * If ".." must be changed (ie the directory gets a new
969 * parent) then the user must have write permission.
970 */
971 parentdifferent = oldparent != dp->i_number;
972 if (parentdifferent && access(ip, IWRITE))
973 goto bad;
974 /*
975 * 2) If target doesn't exist, link the target
976 * to the source and unlink the source.
977 * Otherwise, rewrite the target directory
978 * entry to reference the source inode and
979 * expunge the original entry's existence.
980 */
981 if (xp == NULL) {
982 if (dp->i_dev != ip->i_dev) {
983 error = EXDEV;
984 goto bad;
985 }
986 /*
987 * Disallow rename(foo, foo/bar).
988 */
989 if (dp->i_number == ip->i_number) {
990 error = EEXIST;
991 goto bad;
992 }
993 /*
994 * Account for ".." in directory.
995 * When source and destination have the
996 * same parent we don't fool with the
997 * link count -- this isn't required
998 * because we do a similar check below.
999 */
1000 if (doingdirectory && parentdifferent) {
1001 dp->i_nlink++;
1002 dp->i_flag |= ICHG;
1003 iupdat(dp, &time, &time, 1);
1004 }
1005 error = direnter(ip);
1006 if (error)
1007 goto out;
1008 } else {
1009 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) {
1010 error = EXDEV;
1011 goto bad;
1012 }
1013 /*
1014 * Short circuit rename(foo, foo).
1015 */
1016 if (xp->i_number == ip->i_number)
1017 goto bad;
1018 /*
1019 * Target must be empty if a directory
1020 * and have no links to it.
1021 * Also, insure source and target are
1022 * compatible (both directories, or both
1023 * not directories).
1024 */
1025 if ((xp->i_mode&IFMT) == IFDIR) {
1026 if (!dirempty(xp) || xp->i_nlink > 2) {
1027 error = ENOTEMPTY;
1028 goto bad;
1029 }
1030 if (!doingdirectory) {
1031 error = ENOTDIR;
1032 goto bad;
1033 }
1034 } else if (doingdirectory) {
1035 error = EISDIR;
1036 goto bad;
1037 }
1038 dirrewrite(dp, ip);
1039 if (u.u_error) {
1040 error = u.u_error;
1041 goto bad1;
1042 }
1043 /*
1044 * Adjust the link count of the target to
1045 * reflect the dirrewrite above. If this is
1046 * a directory it is empty and there are
1047 * no links to it, so we can squash the inode and
1048 * any space associated with it. We disallowed
1049 * renaming over top of a directory with links to
1050 * it above, as we've no way to determine if
1051 * we've got a link or the directory itself, and
1052 * if we get a link, then ".." will be screwed up.
1053 */
1054 xp->i_nlink--;
1055 if (doingdirectory) {
1056 if (--xp->i_nlink != 0)
1057 panic("rename: linked directory");
1058 itrunc(xp, (u_long)0);
1059 }
1060 xp->i_flag |= ICHG;
1061 iput(xp);
1062 xp = NULL;
1063 }
1064
1065 /*
1066 * 3) Unlink the source.
1067 */
1068 u.u_dirp = uap->from;
1069 dp = namei(uchar, DELETE, 0);
1070 /*
1071 * Insure directory entry still exists and
1072 * has not changed since the start of all
1073 * this. If either has occured, forget about
1074 * about deleting the original entry and just
1075 * adjust the link count in the inode.
1076 */
1077 if (dp == NULL || u.u_dent.d_ino != ip->i_number) {
1078 ip->i_nlink--;
1079 ip->i_flag |= ICHG;
1080 } else {
1081 /*
1082 * If source is a directory, must adjust
1083 * link count of parent directory also.
1084 * If target didn't exist and source and
1085 * target have the same parent, then we
1086 * needn't touch the link count, it all
1087 * balances out in the end. Otherwise, we
1088 * must do so to reflect deletion of ".."
1089 * done above.
1090 */
1091 if (doingdirectory && (xp != NULL || parentdifferent)) {
1092 dp->i_nlink--;
1093 dp->i_flag |= ICHG;
1094 }
1095 if (dirremove()) {
1096 ip->i_nlink--;
1097 ip->i_flag |= ICHG;
1098 }
1099 if (error == 0) /* conservative */
1100 error = u.u_error;
1101 }
1102 irele(ip);
1103 if (dp)
1104 iput(dp);
1105
1106 /*
1107 * 4) Renaming a directory with the parent
1108 * different requires ".." to be rewritten.
1109 * The window is still there for ".." to
1110 * be inconsistent, but this is unavoidable,
1111 * and a lot shorter than when it was done
1112 * in a user process.
1113 */
1114 if (doingdirectory && parentdifferent && error == 0) {
1115 struct dirtemplate dirbuf;
1116
1117 u.u_dirp = uap->to;
1118 ip = namei(uchar, LOOKUP | LOCKPARENT, 0);
1119 if (ip == NULL) {
1120 printf("rename: .. went away\n");
1121 return;
1122 }
1123 dp = u.u_pdir;
1124 if ((ip->i_mode&IFMT) != IFDIR) {
1125 printf("rename: .. not a directory\n");
1126 goto stuck;
1127 }
1128 error = rdwri(UIO_READ, ip, (caddr_t)&dirbuf,
1129 sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
1130 if (error == 0) {
1131 dirbuf.dotdot_ino = dp->i_number;
1132 (void) rdwri(UIO_WRITE, ip, (caddr_t)&dirbuf,
1133 sizeof (struct dirtemplate), (off_t)0, 1, (int *)0);
1134 }
1135stuck:
1136 irele(dp);
1137 iput(ip);
1138 }
1139 goto done;
1140
1141bad:
1142 iput(dp);
1143bad1:
1144 if (xp)
1145 iput(xp);
1146out:
1147 ip->i_nlink--;
1148 ip->i_flag |= ICHG;
1149 irele(ip);
1150done:
1151 if (error)
1152 u.u_error = error;
1153}
1154
1155/*
1156 * Make a new file.
1157 */
1158struct inode *
1159maknode(mode)
1160 int mode;
1161{
1162 register struct inode *ip;
1163 ino_t ipref;
1164
1165 if ((mode & IFMT) == IFDIR)
1166 ipref = dirpref(u.u_pdir->i_fs);
1167 else
1168 ipref = u.u_pdir->i_number;
1169 ip = ialloc(u.u_pdir, ipref, mode);
1170 if (ip == NULL) {
1171 iput(u.u_pdir);
1172 return (NULL);
1173 }
1174#ifdef QUOTA
1175 if (ip->i_dquot != NODQUOT)
1176 panic("maknode: dquot");
1177#endif
1178 ip->i_flag |= IACC|IUPD|ICHG;
1179 if ((mode & IFMT) == 0)
1180 mode |= IFREG;
1181 ip->i_mode = mode & ~u.u_cmask;
1182 ip->i_nlink = 1;
1183 ip->i_uid = u.u_uid;
1184 ip->i_gid = u.u_pdir->i_gid;
1185#ifdef QUOTA
1186 ip->i_dquot = inoquota(ip);
1187#endif
1188
1189 /*
1190 * Make sure inode goes to disk before directory entry.
1191 */
1192 iupdat(ip, &time, &time, 1);
1193 u.u_error = direnter(ip);
1194 if (u.u_error) {
1195 /*
1196 * Write error occurred trying to update directory
1197 * so must deallocate the inode.
1198 */
1199 ip->i_nlink = 0;
1200 ip->i_flag |= ICHG;
1201 iput(ip);
1202 return (NULL);
1203 }
1204 return (ip);
1205}