new fs system calls prior to truncate and rename
[unix-history] / usr / src / sys / kern / vfs_syscalls.c
CommitLineData
528f664c 1/* vfs_syscalls.c 4.32 82/08/10 */
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;
538 u.u_offset = 0;
539 u.u_base = uap->buf;
540 u.u_count = uap->count;
541 u.u_segflg = 0;
542 readi(ip);
543out:
544 iput(ip);
545 u.u_r.r_val1 = uap->count - u.u_count;
546}
547
3e78e260 548chmod()
5485e062 549{
528f664c
SL
550 struct inode *ip;
551 struct a {
3e78e260
BJ
552 char *fname;
553 int fmode;
5485e062 554 } *uap;
5485e062
BJ
555
556 uap = (struct a *)u.u_ap;
3e78e260 557 if ((ip = owner(1)) == NULL)
5485e062 558 return;
528f664c
SL
559 chmod1(ip, uap->fmode);
560}
f94ceb3b 561
528f664c
SL
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;
f94ceb3b 578 }
528f664c
SL
579 ip = fp->f_inode;
580 ilock(ip);
581 if (u.u_uid != ip->i_uid && !suser()) {
582 iunlock(ip);
583 return;
584 }
585 chmod1(ip, uap->fmode);
586}
587
588chmod1(ip, mode)
589 register struct inode *ip;
590 register int mode;
591{
3e78e260 592 ip->i_mode &= ~07777;
f94ceb3b 593 if (u.u_uid) {
528f664c 594 mode &= ~ISVTX;
f94ceb3b
BJ
595 if (ip->i_gid >= NGRPS ||
596 (u.u_grps[ip->i_gid/(sizeof(int)*8)] &
597 (1 << ip->i_gid%(sizeof(int)*8))) == 0)
528f664c
SL
598 mode &= ~ISGID;
599#ifdef MUSH
0a77f278
RE
600 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
601 (ip->i_mode & IFMT) != IFCHR)
528f664c 602 mode &= ~u.u_cmask;
0a77f278 603#endif
f94ceb3b 604 }
528f664c 605 ip->i_mode |= mode&07777;
3e78e260
BJ
606 ip->i_flag |= ICHG;
607 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
608 xrele(ip);
5485e062
BJ
609 iput(ip);
610}
611
3e78e260 612chown()
d67a03eb 613{
528f664c
SL
614 struct inode *ip;
615 struct a {
3e78e260
BJ
616 char *fname;
617 int uid;
618 int gid;
d67a03eb 619 } *uap;
d67a03eb
BJ
620
621 uap = (struct a *)u.u_ap;
3e78e260 622 if (!suser() || (ip = owner(0)) == NULL)
d67a03eb 623 return;
528f664c
SL
624 chown1(ip, uap->uid, uap->gid);
625}
f94ceb3b 626
528f664c
SL
627fchown()
628{
629 struct a {
630 int fd;
631 int uid;
632 int gid;
633 } *uap;
634 register struct inode *ip;
635 register struct file *fp;
636
637 uap = (struct a *)u.u_ap;
638 fp = getf(uap->fd);
639 if (fp == NULL)
640 return;
641 if (fp->f_type == DTYPE_SOCKET) {
642 u.u_error = EINVAL;
643 return;
f94ceb3b 644 }
528f664c
SL
645 ip = fp->f_inode;
646 ilock(ip);
647 if (!suser()) {
648 iunlock(ip);
649 return;
650 }
651 chown1(ip, uap->uid, uap->gid);
652}
653
654/*
655 * Perform chown operation on inode ip;
656 * inode must be locked prior to call.
657 */
658chown1(ip, uid, gid)
659 register struct inode *ip;
660 int uid, gid;
661{
662#ifdef QUOTA
663 register long change;
664
0a77f278
RE
665 /*
666 * This doesn't allow for holes in files (which hopefully don't
667 * happen often in files that we chown), and is not accurate anyway
668 * (eg: it totally ignores 3 level indir blk files - but hopefully
669 * noone who can make a file that big will have a quota)
670 */
528f664c 671 if (ip->i_uid == uid)
0a77f278
RE
672 change = 0;
673 else {
674 register struct fs *fs = ip->i_fs;
675
676 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
677 register off_t size;
678
679 size = blkroundup(fs, ip->i_size) - change;
680 change += size;
681 change += fs->fs_bsize;
528f664c 682 /* this assumes NIADDR <= 2 */
0a77f278
RE
683 if (size > NINDIR(fs) * fs->fs_bsize)
684 change += fs->fs_bsize;
685 } else
686 change = fragroundup(fs, ip->i_size);
687 change /= DEV_BSIZE;
688 }
689 chkdq(ip, -change, 1);
690 chkiq(ip->i_dev, ip, ip->i_uid, 1);
691 dqrele(ip->i_dquot);
f94ceb3b
BJ
692#endif
693 /*
528f664c
SL
694 * keep uid/gid's in sane range -- no err,
695 * so chown(file, uid, -1) will do something useful
f94ceb3b 696 */
528f664c
SL
697 if (uid >= 0 && uid <= 32767) /* should have a constant */
698 ip->i_uid = uid;
699 if (gid >= 0 && gid <= 32767) /* same here */
700 ip->i_gid = gid;
3e78e260
BJ
701 ip->i_flag |= ICHG;
702 if (u.u_ruid != 0)
703 ip->i_mode &= ~(ISUID|ISGID);
528f664c 704#ifdef QUOTA
0a77f278
RE
705 ip->i_dquot = inoquota(ip);
706 chkdq(ip, change, 1);
528f664c 707 chkiq(ip->i_dev, NULL, uid, 1);
0a77f278 708#endif
3e78e260 709 iput(ip);
d67a03eb
BJ
710}
711
712/*
3e78e260
BJ
713 * Set IUPD and IACC times on file.
714 * Can't set ICHG.
d67a03eb 715 */
3e78e260 716utime()
e92a04af 717{
d67a03eb 718 register struct a {
3e78e260
BJ
719 char *fname;
720 time_t *tptr;
d67a03eb 721 } *uap;
3e78e260
BJ
722 register struct inode *ip;
723 time_t tv[2];
d67a03eb
BJ
724
725 uap = (struct a *)u.u_ap;
3e78e260 726 if ((ip = owner(1)) == NULL)
d67a03eb 727 return;
3e78e260
BJ
728 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
729 u.u_error = EFAULT;
730 } else {
731 ip->i_flag |= IACC|IUPD|ICHG;
732 iupdat(ip, &tv[0], &tv[1], 0);
d67a03eb 733 }
d67a03eb
BJ
734 iput(ip);
735}
736
3e78e260 737sync()
d67a03eb 738{
d67a03eb 739
68503f9a 740 update(0);
d67a03eb 741}
64d3a787 742
528f664c
SL
743flock()
744{
745 struct a {
746 int fd;
747 int how;
748 } *uap;
749 register struct file *fp;
750 register int cmd, flags;
751
752 uap = (struct a *)u.u_ap;
753 fp = getf(uap->fd);
754 if (fp == NULL)
755 return;
756 if (fp->f_type == DTYPE_SOCKET) { /* XXX */
757 u.u_error = EINVAL;
758 return;
759 }
760 cmd = uap->how;
761 flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK);
762 if (cmd&FUNLOCK) {
763 if (flags == 0) {
764 u.u_error = EINVAL;
765 return;
766 }
767 funlocki(fp->f_inode, flags);
768 u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK);
769 return;
770 }
771 /*
772 * No reason to write lock a file we've already
773 * write locked, similarly with a read lock.
774 */
775 if ((flags&WRLOCK) && (cmd&FWRLOCK) ||
776 (flags&RDLOCK) && (cmd&FRDLOCK))
777 return;
778 u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd);
779}
780
781truncate()
782{
783 struct a {
784 char *fname;
785 int length;
786 } *uap;
787 struct inode *ip;
788
789 ip = namei(uchar, 0, 1);
790 if (ip == NULL)
791 return;
792 if (access(ip, IWRITE))
793 goto bad;
794 if ((ip->i_mode&IFMT) == IFDIR) {
795 u.u_error = EISDIR;
796 goto bad;
797 }
798 itrunc(ip, uap->length);
799 return;
800bad:
801 iput(ip);
802}
803
804ftruncate()
805{
806 struct a {
807 int fd;
808 int length;
809 } *uap;
810 struct inode *ip;
811 struct file *fp;
812
813 fp = getf(uap->fd);
814 if (fp == NULL)
815 return;
816 if (fp->f_type == DTYPE_SOCKET) {
817 u.u_error = EINVAL;
818 return;
819 }
820 if ((fp->f_flag&FWRITE) == 0) {
821 u.u_error = EINVAL;
822 return;
823 }
824 ip = fp->f_inode;
825 ilock(ip);
826 itrunc(ip, uap->length);
827}
828
829rename()
830{
831 struct a {
832 char *from;
833 char *to;
834 } *uap;
835
836}
837
64d3a787
BJ
838/*
839 * Make a new file.
840 */
841struct inode *
842maknode(mode)
843 int mode;
844{
845 register struct inode *ip;
846 ino_t ipref;
847
848 if ((mode & IFMT) == IFDIR)
849 ipref = dirpref(u.u_pdir->i_fs);
850 else
851 ipref = u.u_pdir->i_number;
852 ip = ialloc(u.u_pdir, ipref, mode);
853 if (ip == NULL) {
854 iput(u.u_pdir);
528f664c 855 return (NULL);
64d3a787 856 }
528f664c 857#ifdef QUOTA
64d3a787
BJ
858 if (ip->i_dquot != NODQUOT)
859 panic("maknode: dquot");
860#endif
861 ip->i_flag |= IACC|IUPD|ICHG;
862 if ((mode & IFMT) == 0)
863 mode |= IFREG;
864 ip->i_mode = mode & ~u.u_cmask;
865 ip->i_nlink = 1;
866 ip->i_uid = u.u_uid;
867 ip->i_gid = u.u_pdir->i_gid;
528f664c 868#ifdef QUOTA
64d3a787
BJ
869 ip->i_dquot = inoquota(ip);
870#endif
871
872 /*
873 * Make sure inode goes to disk before directory entry.
874 */
875 iupdat(ip, &time, &time, 1);
876 direnter(ip);
877 if (u.u_error) {
878 /*
879 * write error occurred trying to update directory
880 * so must deallocate the inode
881 */
882 ip->i_nlink = 0;
883 ip->i_flag |= ICHG;
884 iput(ip);
528f664c 885 return (NULL);
64d3a787 886 }
528f664c 887 return (ip);
64d3a787 888}