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