more lint
[unix-history] / usr / src / sys / kern / vfs_syscalls.c
CommitLineData
b32450f4 1/* vfs_syscalls.c 4.40 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"
b32450f4 18#include "../h/socketvar.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;
f45396c3 164 u.u_error = openi(ip, mode);
528f664c
SL
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;
b32450f4 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 }
8eee8525 259 irele(ip);
3e78e260
BJ
260}
261
262/*
263 * symlink -- make a symbolic link
264 */
265symlink()
266{
267 register struct a {
268 char *target;
269 char *linkname;
270 } *uap;
271 register struct inode *ip;
272 register char *tp;
273 register c, nc;
274
275 uap = (struct a *)u.u_ap;
276 tp = uap->target;
277 nc = 0;
278 while (c = fubyte(tp)) {
279 if (c < 0) {
280 u.u_error = EFAULT;
281 return;
282 }
283 tp++;
284 nc++;
285 }
286 u.u_dirp = uap->linkname;
287 ip = namei(uchar, 1, 0);
288 if (ip) {
289 iput(ip);
290 u.u_error = EEXIST;
291 return;
292 }
293 if (u.u_error)
294 return;
295 ip = maknode(IFLNK | 0777);
296 if (ip == NULL)
297 return;
31949305 298 u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0);
3e78e260
BJ
299 iput(ip);
300}
301
302/*
303 * Unlink system call.
304 * Hard to avoid races here, especially
305 * in unlinking directories.
306 */
307unlink()
308{
309 register struct inode *ip, *pp;
310 struct a {
311 char *fname;
312 };
8eee8525 313 int unlinkingdot = 0;
3e78e260
BJ
314
315 pp = namei(uchar, 2, 0);
64d3a787 316 if (pp == NULL)
3e78e260 317 return;
f94ceb3b 318
3e78e260
BJ
319 /*
320 * Check for unlink(".")
321 * to avoid hanging on the iget
322 */
323 if (pp->i_number == u.u_dent.d_ino) {
324 ip = pp;
325 ip->i_count++;
8eee8525 326 unlinkingdot++;
3e78e260 327 } else
6459ebe0 328 ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
3e78e260
BJ
329 if(ip == NULL)
330 goto out1;
331 if((ip->i_mode&IFMT)==IFDIR && !suser())
332 goto out;
333 /*
334 * Don't unlink a mounted file.
335 */
336 if (ip->i_dev != pp->i_dev) {
337 u.u_error = EBUSY;
338 goto out;
339 }
340 if (ip->i_flag&ITEXT)
341 xrele(ip); /* try once to free text */
64d3a787
BJ
342 if (dirremove()) {
343 ip->i_nlink--;
344 ip->i_flag |= ICHG;
6459ebe0 345 }
3e78e260 346out:
8eee8525
KM
347 if (unlinkingdot)
348 irele(ip);
349 else
350 iput(ip);
3e78e260
BJ
351out1:
352 iput(pp);
353}
354
355/*
356 * Seek system call
357 */
35e7c31a 358lseek()
3e78e260
BJ
359{
360 register struct file *fp;
361 register struct a {
528f664c 362 int fd;
3e78e260
BJ
363 off_t off;
364 int sbase;
365 } *uap;
366
367 uap = (struct a *)u.u_ap;
528f664c 368 fp = getf(uap->fd);
3e78e260
BJ
369 if (fp == NULL)
370 return;
4147b3f6 371 if (fp->f_type == DTYPE_SOCKET) {
3e78e260
BJ
372 u.u_error = ESPIPE;
373 return;
374 }
528f664c 375 if (uap->sbase == FSEEK_RELATIVE)
3e78e260 376 uap->off += fp->f_offset;
528f664c 377 else if (uap->sbase == FSEEK_EOF)
3e78e260
BJ
378 uap->off += fp->f_inode->i_size;
379 fp->f_offset = uap->off;
380 u.u_r.r_off = uap->off;
381}
382
383/*
384 * Access system call
385 */
386saccess()
387{
388 register svuid, svgid;
389 register struct inode *ip;
390 register struct a {
391 char *fname;
392 int fmode;
393 } *uap;
394
395 uap = (struct a *)u.u_ap;
396 svuid = u.u_uid;
397 svgid = u.u_gid;
398 u.u_uid = u.u_ruid;
399 u.u_gid = u.u_rgid;
400 ip = namei(uchar, 0, 1);
401 if (ip != NULL) {
528f664c
SL
402 if (uap->fmode&FACCESS_READ && access(ip, IREAD))
403 goto done;
404 if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE))
405 goto done;
406 if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC))
407 goto done;
408done:
3e78e260
BJ
409 iput(ip);
410 }
411 u.u_uid = svuid;
412 u.u_gid = svgid;
413}
d67a03eb
BJ
414
415/*
416 * the fstat system call.
417 */
418fstat()
419{
420 register struct file *fp;
421 register struct a {
528f664c 422 int fd;
d67a03eb
BJ
423 struct stat *sb;
424 } *uap;
425
426 uap = (struct a *)u.u_ap;
528f664c 427 fp = getf(uap->fd);
e92a04af 428 if (fp == NULL)
d67a03eb 429 return;
4147b3f6 430 if (fp->f_type == DTYPE_SOCKET)
cc15ab5d 431 u.u_error = sostat(fp->f_socket, uap->sb);
e92a04af
BJ
432 else
433 stat1(fp->f_inode, uap->sb);
d67a03eb
BJ
434}
435
436/*
6459ebe0 437 * Stat system call. This version follows links.
d67a03eb
BJ
438 */
439stat()
440{
441 register struct inode *ip;
442 register struct a {
443 char *fname;
444 struct stat *sb;
445 } *uap;
446
447 uap = (struct a *)u.u_ap;
66d4ba1b 448 ip = namei(uchar, 0, 1);
e92a04af 449 if (ip == NULL)
d67a03eb 450 return;
a3aa7f92 451 stat1(ip, uap->sb);
d67a03eb
BJ
452 iput(ip);
453}
454
5485e062 455/*
6459ebe0 456 * Lstat system call. This version does not follow links.
5485e062
BJ
457 */
458lstat()
459{
460 register struct inode *ip;
461 register struct a {
462 char *fname;
463 struct stat *sb;
464 } *uap;
465
466 uap = (struct a *)u.u_ap;
66d4ba1b 467 ip = namei(uchar, 0, 0);
5485e062
BJ
468 if (ip == NULL)
469 return;
019b08c9 470 stat1(ip, uap->sb);
5485e062
BJ
471 iput(ip);
472}
473
d67a03eb
BJ
474/*
475 * The basic routine for fstat and stat:
476 * get the inode and pass appropriate parts back.
477 */
a3aa7f92 478stat1(ip, ub)
e92a04af
BJ
479 register struct inode *ip;
480 struct stat *ub;
d67a03eb 481{
d67a03eb
BJ
482 struct stat ds;
483
b32450f4 484 IUPDAT(ip, time, time, 0);
d67a03eb 485 /*
09c42945 486 * Copy from inode table
d67a03eb
BJ
487 */
488 ds.st_dev = ip->i_dev;
489 ds.st_ino = ip->i_number;
490 ds.st_mode = ip->i_mode;
491 ds.st_nlink = ip->i_nlink;
492 ds.st_uid = ip->i_uid;
493 ds.st_gid = ip->i_gid;
6459ebe0 494 ds.st_rdev = (dev_t)ip->i_rdev;
a3aa7f92 495 ds.st_size = ip->i_size;
6459ebe0
KM
496 ds.st_atime = ip->i_atime;
497 ds.st_mtime = ip->i_mtime;
498 ds.st_ctime = ip->i_ctime;
528f664c
SL
499 /* this doesn't belong here */
500 if ((ip->i_mode&IFMT) == IFBLK)
501 ds.st_blksize = BLKDEV_IOSIZE;
502 else if ((ip->i_mode&IFMT) == IFCHR)
503 ds.st_blksize = MAXBSIZE;
504 else
505 ds.st_blksize = ip->i_fs->fs_bsize;
d67a03eb
BJ
506 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
507 u.u_error = EFAULT;
508}
509
510/*
5485e062
BJ
511 * Return target name of a symbolic link
512 */
513readlink()
514{
515 register struct inode *ip;
516 register struct a {
517 char *name;
518 char *buf;
519 int count;
31949305
BJ
520 } *uap = (struct a *)u.u_ap;
521 int resid;
5485e062
BJ
522
523 ip = namei(uchar, 0, 0);
524 if (ip == NULL)
525 return;
526 if ((ip->i_mode&IFMT) != IFLNK) {
527 u.u_error = ENXIO;
528 goto out;
529 }
31949305 530 u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid);
5485e062
BJ
531out:
532 iput(ip);
31949305 533 u.u_r.r_val1 = uap->count - resid;
5485e062
BJ
534}
535
3e78e260 536chmod()
5485e062 537{
528f664c
SL
538 struct inode *ip;
539 struct a {
3e78e260
BJ
540 char *fname;
541 int fmode;
5485e062 542 } *uap;
5485e062
BJ
543
544 uap = (struct a *)u.u_ap;
3e78e260 545 if ((ip = owner(1)) == NULL)
5485e062 546 return;
528f664c
SL
547 chmod1(ip, uap->fmode);
548}
f94ceb3b 549
528f664c
SL
550fchmod()
551{
552 struct a {
553 int fd;
554 int fmode;
555 } *uap;
556 register struct inode *ip;
557 register struct file *fp;
558
559 uap = (struct a *)u.u_ap;
560 fp = getf(uap->fd);
561 if (fp == NULL)
562 return;
563 if (fp->f_type == DTYPE_SOCKET) {
564 u.u_error = EINVAL;
565 return;
f94ceb3b 566 }
528f664c
SL
567 ip = fp->f_inode;
568 ilock(ip);
569 if (u.u_uid != ip->i_uid && !suser()) {
570 iunlock(ip);
571 return;
572 }
573 chmod1(ip, uap->fmode);
574}
575
576chmod1(ip, mode)
577 register struct inode *ip;
578 register int mode;
579{
197da11b
BJ
580 register int *gp;
581
3e78e260 582 ip->i_mode &= ~07777;
f94ceb3b 583 if (u.u_uid) {
528f664c 584 mode &= ~ISVTX;
197da11b
BJ
585 for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
586 if (*gp == ip->i_gid)
587 goto ok;
588 mode &= ~ISGID;
589ok:
590 ;
528f664c 591#ifdef MUSH
0a77f278
RE
592 if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
593 (ip->i_mode & IFMT) != IFCHR)
528f664c 594 mode &= ~u.u_cmask;
0a77f278 595#endif
f94ceb3b 596 }
528f664c 597 ip->i_mode |= mode&07777;
3e78e260
BJ
598 ip->i_flag |= ICHG;
599 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
600 xrele(ip);
5485e062
BJ
601 iput(ip);
602}
603
3e78e260 604chown()
d67a03eb 605{
528f664c
SL
606 struct inode *ip;
607 struct a {
3e78e260
BJ
608 char *fname;
609 int uid;
610 int gid;
d67a03eb 611 } *uap;
d67a03eb
BJ
612
613 uap = (struct a *)u.u_ap;
3e78e260 614 if (!suser() || (ip = owner(0)) == NULL)
d67a03eb 615 return;
528f664c
SL
616 chown1(ip, uap->uid, uap->gid);
617}
f94ceb3b 618
528f664c
SL
619fchown()
620{
621 struct a {
622 int fd;
623 int uid;
624 int gid;
625 } *uap;
626 register struct inode *ip;
627 register struct file *fp;
628
629 uap = (struct a *)u.u_ap;
630 fp = getf(uap->fd);
631 if (fp == NULL)
632 return;
633 if (fp->f_type == DTYPE_SOCKET) {
634 u.u_error = EINVAL;
635 return;
f94ceb3b 636 }
528f664c
SL
637 ip = fp->f_inode;
638 ilock(ip);
639 if (!suser()) {
640 iunlock(ip);
641 return;
642 }
643 chown1(ip, uap->uid, uap->gid);
644}
645
646/*
647 * Perform chown operation on inode ip;
648 * inode must be locked prior to call.
649 */
650chown1(ip, uid, gid)
651 register struct inode *ip;
652 int uid, gid;
653{
654#ifdef QUOTA
655 register long change;
656
0a77f278
RE
657 /*
658 * This doesn't allow for holes in files (which hopefully don't
659 * happen often in files that we chown), and is not accurate anyway
660 * (eg: it totally ignores 3 level indir blk files - but hopefully
661 * noone who can make a file that big will have a quota)
662 */
528f664c 663 if (ip->i_uid == uid)
0a77f278
RE
664 change = 0;
665 else {
666 register struct fs *fs = ip->i_fs;
667
668 if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
669 register off_t size;
670
671 size = blkroundup(fs, ip->i_size) - change;
672 change += size;
673 change += fs->fs_bsize;
528f664c 674 /* this assumes NIADDR <= 2 */
0a77f278
RE
675 if (size > NINDIR(fs) * fs->fs_bsize)
676 change += fs->fs_bsize;
677 } else
678 change = fragroundup(fs, ip->i_size);
679 change /= DEV_BSIZE;
680 }
681 chkdq(ip, -change, 1);
682 chkiq(ip->i_dev, ip, ip->i_uid, 1);
683 dqrele(ip->i_dquot);
f94ceb3b
BJ
684#endif
685 /*
528f664c
SL
686 * keep uid/gid's in sane range -- no err,
687 * so chown(file, uid, -1) will do something useful
f94ceb3b 688 */
528f664c
SL
689 if (uid >= 0 && uid <= 32767) /* should have a constant */
690 ip->i_uid = uid;
691 if (gid >= 0 && gid <= 32767) /* same here */
692 ip->i_gid = gid;
3e78e260
BJ
693 ip->i_flag |= ICHG;
694 if (u.u_ruid != 0)
695 ip->i_mode &= ~(ISUID|ISGID);
528f664c 696#ifdef QUOTA
0a77f278
RE
697 ip->i_dquot = inoquota(ip);
698 chkdq(ip, change, 1);
528f664c 699 chkiq(ip->i_dev, NULL, uid, 1);
0a77f278 700#endif
3e78e260 701 iput(ip);
d67a03eb
BJ
702}
703
704/*
3e78e260
BJ
705 * Set IUPD and IACC times on file.
706 * Can't set ICHG.
d67a03eb 707 */
bc671164 708outime()
e92a04af 709{
d67a03eb 710 register struct a {
3e78e260
BJ
711 char *fname;
712 time_t *tptr;
d67a03eb 713 } *uap;
3e78e260
BJ
714 register struct inode *ip;
715 time_t tv[2];
b32450f4 716 struct timeval tv0, tv1;
d67a03eb
BJ
717
718 uap = (struct a *)u.u_ap;
3e78e260 719 if ((ip = owner(1)) == NULL)
d67a03eb 720 return;
3e78e260
BJ
721 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
722 u.u_error = EFAULT;
723 } else {
724 ip->i_flag |= IACC|IUPD|ICHG;
b32450f4
BJ
725 tv0.tv_sec = tv[0]; tv0.tv_usec = 0;
726 tv1.tv_sec = tv[1]; tv1.tv_usec = 0;
727 iupdat(ip, &tv0, &tv1, 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 */
b32450f4 872 iupdat(ip, time, time, 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}