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