clean up event handling so that events that do longjmp's don't turn
[unix-history] / usr / src / sys / ufs / ffs / ufs_vnops.c
CommitLineData
31949305 1/* ufs_vnops.c 4.34 82/08/22 */
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"
528f664c
SL
14/* no reason to inline expand these guys here */
15#undef ilock
16#undef iunlock
0a77f278 17#include "../h/quota.h"
4147b3f6 18#include "../h/descrip.h"
31949305
BJ
19#include "../h/uio.h"
20#include "../h/socket.h"
3e78e260
BJ
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)
528f664c 36 register struct inode **ipp;
3e78e260
BJ
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;
ca91bded 52 iunlock(ip);
8eee8525
KM
53 if (*ipp)
54 irele(*ipp);
3e78e260
BJ
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;
528f664c
SL
70 int flags;
71 int mode;
3e78e260 72 } *uap;
528f664c 73 int checkpermissions = 1;
3e78e260
BJ
74
75 uap = (struct a *)u.u_ap;
528f664c
SL
76 if (uap->flags&FCREATE) {
77 ip = namei(uchar, 1, 1);
78 if (ip == NULL) {
79 if (u.u_error)
80 return;
81 ip = maknode(uap->mode&07777&(~ISVTX));
82 checkpermissions = 0;
83 uap->flags &= ~FTRUNCATE;
84 }
85 } else
86 ip = namei(uchar, 0, 1);
3e78e260
BJ
87 if (ip == NULL)
88 return;
528f664c 89 open1(ip, ++uap->flags, checkpermissions);
3e78e260
BJ
90}
91
528f664c 92#ifndef NOCOMPAT
3e78e260
BJ
93/*
94 * Creat system call.
95 */
4147b3f6 96ocreat()
3e78e260
BJ
97{
98 register struct inode *ip;
99 register struct a {
100 char *fname;
101 int fmode;
102 } *uap;
103
104 uap = (struct a *)u.u_ap;
105 ip = namei(uchar, 1, 1);
106 if (ip == NULL) {
107 if (u.u_error)
108 return;
109 ip = maknode(uap->fmode&07777&(~ISVTX));
528f664c 110 if (ip == NULL)
3e78e260 111 return;
528f664c 112 open1(ip, FWRITE, 0);
3e78e260 113 } else
528f664c 114 open1(ip, FWRITE|FTRUNCATE, 0);
3e78e260 115}
528f664c 116#endif
3e78e260
BJ
117
118/*
119 * Common code for open and creat.
528f664c
SL
120 * Check permissions (if we haven't done so already),
121 * allocate an open file structure, and call
122 * the device open routine, if any.
3e78e260 123 */
528f664c 124open1(ip, mode, checkpermissions)
3e78e260
BJ
125 register struct inode *ip;
126 register mode;
127{
128 register struct file *fp;
528f664c 129 int i, flags;
3e78e260 130
528f664c 131 if (checkpermissions) {
3e78e260 132 if (mode&FREAD)
528f664c
SL
133 if (access(ip, IREAD))
134 goto bad;
3e78e260 135 if (mode&FWRITE) {
528f664c
SL
136 if (access(ip, IWRITE))
137 goto bad;
138 if ((ip->i_mode&IFMT) == IFDIR) {
3e78e260 139 u.u_error = EISDIR;
528f664c
SL
140 goto bad;
141 }
3e78e260
BJ
142 }
143 }
528f664c
SL
144
145 /*
146 * Check locking on inode. Release "inode lock"
147 * while doing so in case we block inside flocki.
148 */
149 flags = 0;
150 if (mode&(FRDLOCK|FWRLOCK)) {
151 iunlock(ip);
152 flags = flocki(ip, 0, mode);
153 ilock(ip);
154 if (u.u_error)
155 goto bad;
8eee8525 156 }
528f664c
SL
157 if (mode&FTRUNCATE)
158 itrunc(ip, 0);
ca91bded 159 iunlock(ip);
3e78e260
BJ
160 if ((fp = falloc()) == NULL)
161 goto out;
528f664c 162 fp->f_flag = mode & FMODES;
4147b3f6 163 fp->f_type = DTYPE_FILE;
3e78e260
BJ
164 i = u.u_r.r_val1;
165 fp->f_inode = ip;
528f664c
SL
166 openi(ip, mode);
167 if (u.u_error == 0) {
168 u.u_pofile[i] = flags;
3e78e260 169 return;
528f664c 170 }
3e78e260
BJ
171 u.u_ofile[i] = NULL;
172 fp->f_count--;
173out:
8eee8525 174 irele(ip);
528f664c
SL
175 return;
176bad:
177 iput(ip);
3e78e260
BJ
178}
179
180/*
181 * Mknod system call
182 */
183mknod()
184{
185 register struct inode *ip;
186 register struct a {
187 char *fname;
188 int fmode;
189 int dev;
190 } *uap;
191
192 uap = (struct a *)u.u_ap;
193 if (suser()) {
194 ip = namei(uchar, 1, 0);
195 if (ip != NULL) {
196 u.u_error = EEXIST;
197 goto out;
198 }
199 }
200 if (u.u_error)
201 return;
202 ip = maknode(uap->fmode);
203 if (ip == NULL)
204 return;
205 if (uap->dev) {
206 /*
207 * Want to be able to use this to make badblock
208 * inodes, so don't truncate the dev number.
209 */
6459ebe0 210 ip->i_rdev = uap->dev;
3e78e260
BJ
211 ip->i_flag |= IACC|IUPD|ICHG;
212 }
213
214out:
215 iput(ip);
216}
217
218/*
219 * link system call
220 */
221link()
222{
223 register struct inode *ip, *xp;
224 register struct a {
225 char *target;
226 char *linkname;
227 } *uap;
228
229 uap = (struct a *)u.u_ap;
230 ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */
231 if (ip == NULL)
232 return;
f94ceb3b
BJ
233 if ((ip->i_mode&IFMT)==IFDIR && !suser()) {
234 iput(ip);
235 return;
236 }
3e78e260
BJ
237 ip->i_nlink++;
238 ip->i_flag |= ICHG;
239 iupdat(ip, &time, &time, 1);
ca91bded 240 iunlock(ip);
3e78e260
BJ
241 u.u_dirp = (caddr_t)uap->linkname;
242 xp = namei(uchar, 1, 0);
243 if (xp != NULL) {
244 u.u_error = EEXIST;
245 iput(xp);
246 goto out;
247 }
248 if (u.u_error)
249 goto out;
250 if (u.u_pdir->i_dev != ip->i_dev) {
251 iput(u.u_pdir);
252 u.u_error = EXDEV;
253 goto out;
254 }
64d3a787 255 direnter(ip);
3e78e260
BJ
256out:
257 if (u.u_error) {
258 ip->i_nlink--;
259 ip->i_flag |= ICHG;
260 }
8eee8525 261 irele(ip);
3e78e260
BJ
262}
263
264/*
265 * symlink -- make a symbolic link
266 */
267symlink()
268{
269 register struct a {
270 char *target;
271 char *linkname;
272 } *uap;
273 register struct inode *ip;
274 register char *tp;
275 register c, nc;
276
277 uap = (struct a *)u.u_ap;
278 tp = uap->target;
279 nc = 0;
280 while (c = fubyte(tp)) {
281 if (c < 0) {
282 u.u_error = EFAULT;
283 return;
284 }
285 tp++;
286 nc++;
287 }
288 u.u_dirp = uap->linkname;
289 ip = namei(uchar, 1, 0);
290 if (ip) {
291 iput(ip);
292 u.u_error = EEXIST;
293 return;
294 }
295 if (u.u_error)
296 return;
297 ip = maknode(IFLNK | 0777);
298 if (ip == NULL)
299 return;
31949305 300 u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0);
3e78e260
BJ
301 iput(ip);
302}
303
304/*
305 * Unlink system call.
306 * Hard to avoid races here, especially
307 * in unlinking directories.
308 */
309unlink()
310{
311 register struct inode *ip, *pp;
312 struct a {
313 char *fname;
314 };
8eee8525 315 int unlinkingdot = 0;
3e78e260
BJ
316
317 pp = namei(uchar, 2, 0);
64d3a787 318 if (pp == NULL)
3e78e260 319 return;
f94ceb3b 320
3e78e260
BJ
321 /*
322 * Check for unlink(".")
323 * to avoid hanging on the iget
324 */
325 if (pp->i_number == u.u_dent.d_ino) {
326 ip = pp;
327 ip->i_count++;
8eee8525 328 unlinkingdot++;
3e78e260 329 } else
6459ebe0 330 ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
3e78e260
BJ
331 if(ip == NULL)
332 goto out1;
333 if((ip->i_mode&IFMT)==IFDIR && !suser())
334 goto out;
335 /*
336 * Don't unlink a mounted file.
337 */
338 if (ip->i_dev != pp->i_dev) {
339 u.u_error = EBUSY;
340 goto out;
341 }
342 if (ip->i_flag&ITEXT)
343 xrele(ip); /* try once to free text */
64d3a787
BJ
344 if (dirremove()) {
345 ip->i_nlink--;
346 ip->i_flag |= ICHG;
6459ebe0 347 }
3e78e260 348out:
8eee8525
KM
349 if (unlinkingdot)
350 irele(ip);
351 else
352 iput(ip);
3e78e260
BJ
353out1:
354 iput(pp);
355}
356
357/*
358 * Seek system call
359 */
360seek()
361{
362 register struct file *fp;
363 register struct a {
528f664c 364 int fd;
3e78e260
BJ
365 off_t off;
366 int sbase;
367 } *uap;
368
369 uap = (struct a *)u.u_ap;
528f664c 370 fp = getf(uap->fd);
3e78e260
BJ
371 if (fp == NULL)
372 return;
4147b3f6 373 if (fp->f_type == DTYPE_SOCKET) {
3e78e260
BJ
374 u.u_error = ESPIPE;
375 return;
376 }
528f664c 377 if (uap->sbase == FSEEK_RELATIVE)
3e78e260 378 uap->off += fp->f_offset;
528f664c 379 else if (uap->sbase == FSEEK_EOF)
3e78e260
BJ
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, 0, 1);
403 if (ip != NULL) {
528f664c
SL
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:
3e78e260
BJ
411 iput(ip);
412 }
413 u.u_uid = svuid;
414 u.u_gid = svgid;
415}
d67a03eb
BJ
416
417/*
418 * the fstat system call.
419 */
420fstat()
421{
422 register struct file *fp;
423 register struct a {
528f664c 424 int fd;
d67a03eb
BJ
425 struct stat *sb;
426 } *uap;
427
428 uap = (struct a *)u.u_ap;
528f664c 429 fp = getf(uap->fd);
e92a04af 430 if (fp == NULL)
d67a03eb 431 return;
4147b3f6 432 if (fp->f_type == DTYPE_SOCKET)
cc15ab5d 433 u.u_error = sostat(fp->f_socket, uap->sb);
e92a04af
BJ
434 else
435 stat1(fp->f_inode, uap->sb);
d67a03eb
BJ
436}
437
438/*
6459ebe0 439 * Stat system call. This version follows links.
d67a03eb
BJ
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;
66d4ba1b 450 ip = namei(uchar, 0, 1);
e92a04af 451 if (ip == NULL)
d67a03eb 452 return;
a3aa7f92 453 stat1(ip, uap->sb);
d67a03eb
BJ
454 iput(ip);
455}
456
5485e062 457/*
6459ebe0 458 * Lstat system call. This version does not follow links.
5485e062
BJ
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;
66d4ba1b 469 ip = namei(uchar, 0, 0);
5485e062
BJ
470 if (ip == NULL)
471 return;
019b08c9 472 stat1(ip, uap->sb);
5485e062
BJ
473 iput(ip);
474}
475
d67a03eb
BJ
476/*
477 * The basic routine for fstat and stat:
478 * get the inode and pass appropriate parts back.
479 */
a3aa7f92 480stat1(ip, ub)
e92a04af
BJ
481 register struct inode *ip;
482 struct stat *ub;
d67a03eb 483{
d67a03eb
BJ
484 struct stat ds;
485
c0bb1685 486 IUPDAT(ip, &time, &time, 0);
d67a03eb 487 /*
09c42945 488 * Copy from inode table
d67a03eb
BJ
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;
6459ebe0 496 ds.st_rdev = (dev_t)ip->i_rdev;
a3aa7f92 497 ds.st_size = ip->i_size;
6459ebe0
KM
498 ds.st_atime = ip->i_atime;
499 ds.st_mtime = ip->i_mtime;
500 ds.st_ctime = ip->i_ctime;
528f664c
SL
501 /* this doesn't belong here */
502 if ((ip->i_mode&IFMT) == IFBLK)
503 ds.st_blksize = BLKDEV_IOSIZE;
504 else if ((ip->i_mode&IFMT) == IFCHR)
505 ds.st_blksize = MAXBSIZE;
506 else
507 ds.st_blksize = ip->i_fs->fs_bsize;
d67a03eb
BJ
508 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
509 u.u_error = EFAULT;
510}
511
512/*
5485e062
BJ
513 * Return target name of a symbolic link
514 */
515readlink()
516{
517 register struct inode *ip;
518 register struct a {
519 char *name;
520 char *buf;
521 int count;
31949305
BJ
522 } *uap = (struct a *)u.u_ap;
523 int resid;
5485e062
BJ
524
525 ip = namei(uchar, 0, 0);
526 if (ip == NULL)
527 return;
528 if ((ip->i_mode&IFMT) != IFLNK) {
529 u.u_error = ENXIO;
530 goto out;
531 }
31949305 532 u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid);
5485e062
BJ
533out:
534 iput(ip);
31949305 535 u.u_r.r_val1 = uap->count - resid;
5485e062
BJ
536}
537
3e78e260 538chmod()
5485e062 539{
528f664c
SL
540 struct inode *ip;
541 struct a {
3e78e260
BJ
542 char *fname;
543 int fmode;
5485e062 544 } *uap;
5485e062
BJ
545
546 uap = (struct a *)u.u_ap;
3e78e260 547 if ((ip = owner(1)) == NULL)
5485e062 548 return;
528f664c
SL
549 chmod1(ip, uap->fmode);
550}
f94ceb3b 551
528f664c
SL
552fchmod()
553{
554 struct a {
555 int fd;
556 int fmode;
557 } *uap;
558 register struct inode *ip;
559 register struct file *fp;
560
561 uap = (struct a *)u.u_ap;
562 fp = getf(uap->fd);
563 if (fp == NULL)
564 return;
565 if (fp->f_type == DTYPE_SOCKET) {
566 u.u_error = EINVAL;
567 return;
f94ceb3b 568 }
528f664c
SL
569 ip = fp->f_inode;
570 ilock(ip);
571 if (u.u_uid != ip->i_uid && !suser()) {
572 iunlock(ip);
573 return;
574 }
575 chmod1(ip, uap->fmode);
576}
577
578chmod1(ip, mode)
579 register struct inode *ip;
580 register int mode;
581{
3e78e260 582 ip->i_mode &= ~07777;
f94ceb3b 583 if (u.u_uid) {
528f664c 584 mode &= ~ISVTX;
f94ceb3b
BJ
585 if (ip->i_gid >= NGRPS ||
586 (u.u_grps[ip->i_gid/(sizeof(int)*8)] &
587 (1 << ip->i_gid%(sizeof(int)*8))) == 0)
528f664c
SL
588 mode &= ~ISGID;
589#ifdef MUSH
0a77f278
RE
590 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
591 (ip->i_mode & IFMT) != IFCHR)
528f664c 592 mode &= ~u.u_cmask;
0a77f278 593#endif
f94ceb3b 594 }
528f664c 595 ip->i_mode |= mode&07777;
3e78e260
BJ
596 ip->i_flag |= ICHG;
597 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
598 xrele(ip);
5485e062
BJ
599 iput(ip);
600}
601
3e78e260 602chown()
d67a03eb 603{
528f664c
SL
604 struct inode *ip;
605 struct a {
3e78e260
BJ
606 char *fname;
607 int uid;
608 int gid;
d67a03eb 609 } *uap;
d67a03eb
BJ
610
611 uap = (struct a *)u.u_ap;
3e78e260 612 if (!suser() || (ip = owner(0)) == NULL)
d67a03eb 613 return;
528f664c
SL
614 chown1(ip, uap->uid, uap->gid);
615}
f94ceb3b 616
528f664c
SL
617fchown()
618{
619 struct a {
620 int fd;
621 int uid;
622 int gid;
623 } *uap;
624 register struct inode *ip;
625 register struct file *fp;
626
627 uap = (struct a *)u.u_ap;
628 fp = getf(uap->fd);
629 if (fp == NULL)
630 return;
631 if (fp->f_type == DTYPE_SOCKET) {
632 u.u_error = EINVAL;
633 return;
f94ceb3b 634 }
528f664c
SL
635 ip = fp->f_inode;
636 ilock(ip);
637 if (!suser()) {
638 iunlock(ip);
639 return;
640 }
641 chown1(ip, uap->uid, uap->gid);
642}
643
644/*
645 * Perform chown operation on inode ip;
646 * inode must be locked prior to call.
647 */
648chown1(ip, uid, gid)
649 register struct inode *ip;
650 int uid, gid;
651{
652#ifdef QUOTA
653 register long change;
654
0a77f278
RE
655 /*
656 * This doesn't allow for holes in files (which hopefully don't
657 * happen often in files that we chown), and is not accurate anyway
658 * (eg: it totally ignores 3 level indir blk files - but hopefully
659 * noone who can make a file that big will have a quota)
660 */
528f664c 661 if (ip->i_uid == uid)
0a77f278
RE
662 change = 0;
663 else {
664 register struct fs *fs = ip->i_fs;
665
666 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
667 register off_t size;
668
669 size = blkroundup(fs, ip->i_size) - change;
670 change += size;
671 change += fs->fs_bsize;
528f664c 672 /* this assumes NIADDR <= 2 */
0a77f278
RE
673 if (size > NINDIR(fs) * fs->fs_bsize)
674 change += fs->fs_bsize;
675 } else
676 change = fragroundup(fs, ip->i_size);
677 change /= DEV_BSIZE;
678 }
679 chkdq(ip, -change, 1);
680 chkiq(ip->i_dev, ip, ip->i_uid, 1);
681 dqrele(ip->i_dquot);
f94ceb3b
BJ
682#endif
683 /*
528f664c
SL
684 * keep uid/gid's in sane range -- no err,
685 * so chown(file, uid, -1) will do something useful
f94ceb3b 686 */
528f664c
SL
687 if (uid >= 0 && uid <= 32767) /* should have a constant */
688 ip->i_uid = uid;
689 if (gid >= 0 && gid <= 32767) /* same here */
690 ip->i_gid = gid;
3e78e260
BJ
691 ip->i_flag |= ICHG;
692 if (u.u_ruid != 0)
693 ip->i_mode &= ~(ISUID|ISGID);
528f664c 694#ifdef QUOTA
0a77f278
RE
695 ip->i_dquot = inoquota(ip);
696 chkdq(ip, change, 1);
528f664c 697 chkiq(ip->i_dev, NULL, uid, 1);
0a77f278 698#endif
3e78e260 699 iput(ip);
d67a03eb
BJ
700}
701
702/*
3e78e260
BJ
703 * Set IUPD and IACC times on file.
704 * Can't set ICHG.
d67a03eb 705 */
3e78e260 706utime()
e92a04af 707{
d67a03eb 708 register struct a {
3e78e260
BJ
709 char *fname;
710 time_t *tptr;
d67a03eb 711 } *uap;
3e78e260
BJ
712 register struct inode *ip;
713 time_t tv[2];
d67a03eb
BJ
714
715 uap = (struct a *)u.u_ap;
3e78e260 716 if ((ip = owner(1)) == NULL)
d67a03eb 717 return;
3e78e260
BJ
718 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
719 u.u_error = EFAULT;
720 } else {
721 ip->i_flag |= IACC|IUPD|ICHG;
722 iupdat(ip, &tv[0], &tv[1], 0);
d67a03eb 723 }
d67a03eb
BJ
724 iput(ip);
725}
726
3e78e260 727sync()
d67a03eb 728{
d67a03eb 729
68503f9a 730 update(0);
d67a03eb 731}
64d3a787 732
528f664c
SL
733flock()
734{
735 struct a {
736 int fd;
737 int how;
738 } *uap;
739 register struct file *fp;
740 register int cmd, flags;
741
742 uap = (struct a *)u.u_ap;
743 fp = getf(uap->fd);
744 if (fp == NULL)
745 return;
746 if (fp->f_type == DTYPE_SOCKET) { /* XXX */
747 u.u_error = EINVAL;
748 return;
749 }
750 cmd = uap->how;
751 flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK);
752 if (cmd&FUNLOCK) {
753 if (flags == 0) {
754 u.u_error = EINVAL;
755 return;
756 }
757 funlocki(fp->f_inode, flags);
758 u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK);
759 return;
760 }
761 /*
762 * No reason to write lock a file we've already
763 * write locked, similarly with a read lock.
764 */
765 if ((flags&WRLOCK) && (cmd&FWRLOCK) ||
766 (flags&RDLOCK) && (cmd&FRDLOCK))
767 return;
768 u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd);
769}
770
771truncate()
772{
773 struct a {
774 char *fname;
775 int length;
31949305 776 } *uap = (struct a *)u.u_ap;
528f664c
SL
777 struct inode *ip;
778
779 ip = namei(uchar, 0, 1);
780 if (ip == NULL)
781 return;
782 if (access(ip, IWRITE))
783 goto bad;
784 if ((ip->i_mode&IFMT) == IFDIR) {
785 u.u_error = EISDIR;
786 goto bad;
787 }
788 itrunc(ip, uap->length);
789 return;
790bad:
791 iput(ip);
792}
793
794ftruncate()
795{
796 struct a {
797 int fd;
798 int length;
31949305 799 } *uap = (struct a *)u.u_ap;
528f664c
SL
800 struct inode *ip;
801 struct file *fp;
802
803 fp = getf(uap->fd);
804 if (fp == NULL)
805 return;
806 if (fp->f_type == DTYPE_SOCKET) {
807 u.u_error = EINVAL;
808 return;
809 }
810 if ((fp->f_flag&FWRITE) == 0) {
811 u.u_error = EINVAL;
812 return;
813 }
814 ip = fp->f_inode;
815 ilock(ip);
816 itrunc(ip, uap->length);
817}
818
819rename()
820{
31949305 821#ifdef notdef
528f664c
SL
822 struct a {
823 char *from;
824 char *to;
825 } *uap;
31949305 826#endif
528f664c
SL
827
828}
829
64d3a787
BJ
830/*
831 * Make a new file.
832 */
833struct inode *
834maknode(mode)
835 int mode;
836{
837 register struct inode *ip;
838 ino_t ipref;
839
840 if ((mode & IFMT) == IFDIR)
841 ipref = dirpref(u.u_pdir->i_fs);
842 else
843 ipref = u.u_pdir->i_number;
844 ip = ialloc(u.u_pdir, ipref, mode);
845 if (ip == NULL) {
846 iput(u.u_pdir);
528f664c 847 return (NULL);
64d3a787 848 }
528f664c 849#ifdef QUOTA
64d3a787
BJ
850 if (ip->i_dquot != NODQUOT)
851 panic("maknode: dquot");
852#endif
853 ip->i_flag |= IACC|IUPD|ICHG;
854 if ((mode & IFMT) == 0)
855 mode |= IFREG;
856 ip->i_mode = mode & ~u.u_cmask;
857 ip->i_nlink = 1;
858 ip->i_uid = u.u_uid;
859 ip->i_gid = u.u_pdir->i_gid;
528f664c 860#ifdef QUOTA
64d3a787
BJ
861 ip->i_dquot = inoquota(ip);
862#endif
863
864 /*
865 * Make sure inode goes to disk before directory entry.
866 */
867 iupdat(ip, &time, &time, 1);
868 direnter(ip);
869 if (u.u_error) {
870 /*
871 * write error occurred trying to update directory
872 * so must deallocate the inode
873 */
874 ip->i_nlink = 0;
875 ip->i_flag |= ICHG;
876 iput(ip);
528f664c 877 return (NULL);
64d3a787 878 }
528f664c 879 return (ip);
64d3a787 880}