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