1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 43 * 44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 45 * $Id: sunos_misc.c,v 1.24 1994/05/24 02:15:18 deraadt Exp $ 46 */ 47 48 /* 49 * SunOS compatibility module. 50 * 51 * SunOS system calls that are implemented differently in BSD are 52 * handled here. 53 */ 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/namei.h> 58 #include <ufs/dir.h> 59 #include <sys/proc.h> 60 #include <sys/file.h> 61 #include <sys/stat.h> 62 #include <sys/filedesc.h> 63 #include <sys/ioctl.h> 64 #include <sys/kernel.h> 65 #include <sys/exec.h> 66 #include <sys/malloc.h> 67 #include <sys/mbuf.h> 68 #include <sys/mman.h> 69 #include <sys/mount.h> 70 #include <sys/resource.h> 71 #include <sys/resourcevar.h> 72 #include <sys/signal.h> 73 #include <sys/signalvar.h> 74 #include <sys/socket.h> 75 #include <sys/vnode.h> 76 #include <sys/uio.h> 77 #include <sys/wait.h> 78 #include <sys/utsname.h> 79 #include <sys/unistd.h> 80 81 #include <netinet/in.h> 82 83 #include <miscfs/specfs/specdev.h> 84 85 #include <vm/vm.h> 86 87 struct sun_wait4_args { 88 int pid; 89 int *status; 90 int options; 91 struct rusage *rusage; 92 }; 93 sun_wait4(p, uap, retval) 94 struct proc *p; 95 struct sun_wait4_args *uap; 96 int *retval; 97 { 98 99 if (uap->pid == 0) 100 uap->pid = WAIT_ANY; 101 return (wait4(p, uap, retval)); 102 } 103 104 struct sun_creat_args { 105 char *fname; 106 int fmode; 107 }; 108 sun_creat(p, uap, retval) 109 struct proc *p; 110 struct sun_creat_args *uap; 111 int *retval; 112 { 113 struct args { 114 char *fname; 115 int mode; 116 int crtmode; 117 } openuap; 118 119 openuap.fname = uap->fname; 120 openuap.crtmode = uap->fmode; 121 openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 122 return (open(p, &openuap, retval)); 123 } 124 125 struct sun_execv_args { 126 char *fname; 127 char **argp; 128 char **envp; /* pseudo */ 129 }; 130 sun_execv(p, uap, retval) 131 struct proc *p; 132 struct sun_execv_args *uap; 133 int *retval; 134 { 135 136 uap->envp = NULL; 137 return (execve(p, uap, retval)); 138 } 139 140 struct sun_omsync_args { 141 caddr_t addr; 142 int len; 143 int flags; 144 }; 145 sun_omsync(p, uap, retval) 146 struct proc *p; 147 struct sun_omsync_args *uap; 148 int *retval; 149 { 150 151 if (uap->flags) 152 return (EINVAL); 153 return (msync(p, uap, retval)); 154 } 155 156 struct sun_unmount_args { 157 char *name; 158 int flags; /* pseudo */ 159 }; 160 sun_unmount(p, uap, retval) 161 struct proc *p; 162 struct sun_unmount_args *uap; 163 int *retval; 164 { 165 166 uap->flags = 0; 167 return (unmount(p, uap, retval)); 168 } 169 170 #define SUNM_RDONLY 0x01 /* mount fs read-only */ 171 #define SUNM_NOSUID 0x02 /* mount fs with setuid disallowed */ 172 #define SUNM_NEWTYPE 0x04 /* type is string (char *), not int */ 173 #define SUNM_GRPID 0x08 /* (bsd semantics; ignored) */ 174 #define SUNM_REMOUNT 0x10 /* update existing mount */ 175 #define SUNM_NOSUB 0x20 /* prevent submounts (rejected) */ 176 #define SUNM_MULTI 0x40 /* (ignored) */ 177 #define SUNM_SYS5 0x80 /* Sys 5-specific semantics (rejected) */ 178 179 struct sun_nfs_args { 180 struct sockaddr_in *addr; /* file server address */ 181 caddr_t fh; /* file handle to be mounted */ 182 int flags; /* flags */ 183 int wsize; /* write size in bytes */ 184 int rsize; /* read size in bytes */ 185 int timeo; /* initial timeout in .1 secs */ 186 int retrans; /* times to retry send */ 187 char *hostname; /* server's hostname */ 188 int acregmin; /* attr cache file min secs */ 189 int acregmax; /* attr cache file max secs */ 190 int acdirmin; /* attr cache dir min secs */ 191 int acdirmax; /* attr cache dir max secs */ 192 char *netname; /* server's netname */ 193 struct pathcnf *pathconf; /* static pathconf kludge */ 194 }; 195 196 struct sun_mount_args { 197 char *type; 198 char *dir; 199 int flags; 200 caddr_t data; 201 }; 202 sun_mount(p, uap, retval) 203 struct proc *p; 204 struct sun_mount_args *uap; 205 int *retval; 206 { 207 int oflags = uap->flags, nflags, error; 208 extern char sigcode[], esigcode[]; 209 char fsname[MFSNAMELEN]; 210 211 #define szsigcode (esigcode - sigcode) 212 213 if (oflags & (SUNM_NOSUB | SUNM_SYS5)) 214 return (EINVAL); 215 if ((oflags & SUNM_NEWTYPE) == 0) 216 return (EINVAL); 217 nflags = 0; 218 if (oflags & SUNM_RDONLY) 219 nflags |= MNT_RDONLY; 220 if (oflags & SUNM_NOSUID) 221 nflags |= MNT_NOSUID; 222 if (oflags & SUNM_REMOUNT) 223 nflags |= MNT_UPDATE; 224 uap->flags = nflags; 225 226 if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, (u_int *)0)) 227 return (error); 228 229 if (strcmp(fsname, "4.2") == 0) { 230 uap->type = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN); 231 if (error = copyout("ufs", uap->type, sizeof("ufs"))) 232 return (error); 233 } else if (strcmp(fsname, "nfs") == 0) { 234 struct sun_nfs_args sna; 235 struct sockaddr_in sain; 236 struct nfs_args na; 237 struct sockaddr sa; 238 239 if (error = copyin(uap->data, &sna, sizeof sna)) 240 return (error); 241 if (error = copyin(sna.addr, &sain, sizeof sain)) 242 return (error); 243 bcopy(&sain, &sa, sizeof sa); 244 sa.sa_len = sizeof(sain); 245 uap->data = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN); 246 na.addr = (struct sockaddr *)((int)uap->data + sizeof na); 247 na.sotype = SOCK_DGRAM; 248 na.proto = IPPROTO_UDP; 249 na.fh = (nfsv2fh_t *)sna.fh; 250 na.flags = sna.flags; 251 na.wsize = sna.wsize; 252 na.rsize = sna.rsize; 253 na.timeo = sna.timeo; 254 na.retrans = sna.retrans; 255 na.hostname = sna.hostname; 256 257 if (error = copyout(&sa, na.addr, sizeof sa)) 258 return (error); 259 if (error = copyout(&na, uap->data, sizeof na)) 260 return (error); 261 } 262 return (mount(p, uap, retval)); 263 } 264 265 struct sun_sigpending_args { 266 int *mask; 267 }; 268 sun_sigpending(p, uap, retval) 269 struct proc *p; 270 struct sun_sigpending_args *uap; 271 int *retval; 272 { 273 int mask = p->p_siglist & p->p_sigmask; 274 275 return (copyout((caddr_t)&mask, (caddr_t)uap->mask, sizeof(int))); 276 } 277 278 /* XXX: Temporary until sys/dir.h, include/dirent.h and sys/dirent.h are fixed */ 279 struct dirent { 280 u_long d_fileno; /* file number of entry */ 281 u_short d_reclen; /* length of this record */ 282 u_short d_namlen; /* length of string in d_name */ 283 char d_name[255 + 1]; /* name must be no longer than this */ 284 }; 285 286 /* 287 * Here is the sun layout. (Compare the BSD layout in <sys/dirent.h>.) 288 * We can assume big-endian, so the BSD d_type field is just the high 289 * byte of the SunOS d_namlen field, after adjusting for the extra "long". 290 */ 291 struct sun_dirent { 292 long d_off; 293 u_long d_fileno; 294 u_short d_reclen; 295 u_short d_namlen; 296 char d_name[256]; 297 }; 298 299 /* 300 * Read Sun-style directory entries. We suck them into kernel space so 301 * that they can be massaged before being copied out to user code. Like 302 * SunOS, we squish out `empty' entries. 303 * 304 * This is quite ugly, but what do you expect from compatibility code? 305 */ 306 struct sun_getdents_args { 307 int fd; 308 char *buf; 309 int nbytes; 310 }; 311 sun_getdents(p, uap, retval) 312 struct proc *p; 313 register struct sun_getdents_args *uap; 314 int *retval; 315 { 316 register struct vnode *vp; 317 register caddr_t inp, buf; /* BSD-format */ 318 register int len, reclen; /* BSD-format */ 319 register caddr_t outp; /* Sun-format */ 320 register int resid; /* Sun-format */ 321 struct file *fp; 322 struct uio auio; 323 struct iovec aiov; 324 off_t off; /* true file offset */ 325 long soff; /* Sun file offset */ 326 int buflen, error, eofflag; 327 #define BSD_DIRENT(cp) ((struct dirent *)(cp)) 328 #define SUN_RECLEN(reclen) (reclen + sizeof(long)) 329 330 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 331 return (error); 332 if ((fp->f_flag & FREAD) == 0) 333 return (EBADF); 334 vp = (struct vnode *)fp->f_data; 335 if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */ 336 return (EINVAL); 337 buflen = min(MAXBSIZE, uap->nbytes); 338 buf = malloc(buflen, M_TEMP, M_WAITOK); 339 VOP_LOCK(vp); 340 off = fp->f_offset; 341 again: 342 aiov.iov_base = buf; 343 aiov.iov_len = buflen; 344 auio.uio_iov = &aiov; 345 auio.uio_iovcnt = 1; 346 auio.uio_rw = UIO_READ; 347 auio.uio_segflg = UIO_SYSSPACE; 348 auio.uio_procp = p; 349 auio.uio_resid = buflen; 350 auio.uio_offset = off; 351 /* 352 * First we read into the malloc'ed buffer, then 353 * we massage it into user space, one record at a time. 354 */ 355 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, 0)) 356 goto out; 357 inp = buf; 358 outp = uap->buf; 359 resid = uap->nbytes; 360 if ((len = buflen - auio.uio_resid) == 0) 361 goto eof; 362 for (; len > 0; len -= reclen) { 363 reclen = ((struct dirent *)inp)->d_reclen; 364 if (reclen & 3) 365 panic("sun_getdents"); 366 off += reclen; /* each entry points to next */ 367 if (BSD_DIRENT(inp)->d_fileno == 0) { 368 inp += reclen; /* it is a hole; squish it out */ 369 continue; 370 } 371 if (reclen > len || resid < SUN_RECLEN(reclen)) { 372 /* entry too big for buffer, so just stop */ 373 outp++; 374 break; 375 } 376 /* 377 * Massage in place to make a Sun-shaped dirent (otherwise 378 * we have to worry about touching user memory outside of 379 * the copyout() call). 380 */ 381 BSD_DIRENT(inp)->d_reclen = SUN_RECLEN(reclen); 382 #if notdef 383 BSD_DIRENT(inp)->d_type = 0; /* 4.4 specific */ 384 #endif 385 soff = off; 386 if ((error = copyout((caddr_t)&soff, outp, sizeof soff)) != 0 || 387 (error = copyout(inp, outp + sizeof soff, reclen)) != 0) 388 goto out; 389 /* advance past this real entry */ 390 inp += reclen; 391 /* advance output past Sun-shaped entry */ 392 outp += SUN_RECLEN(reclen); 393 resid -= SUN_RECLEN(reclen); 394 } 395 /* if we squished out the whole block, try again */ 396 if (outp == uap->buf) 397 goto again; 398 fp->f_offset = off; /* update the vnode offset */ 399 eof: 400 *retval = uap->nbytes - resid; 401 out: 402 VOP_UNLOCK(vp); 403 free(buf, M_TEMP); 404 return (error); 405 } 406 407 #define SUN__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */ 408 409 struct sun_mmap_args { 410 caddr_t addr; 411 size_t len; 412 int prot; 413 int flags; 414 int fd; 415 long off; /* not off_t! */ 416 off_t qoff; /* created here and fed to mmap() */ 417 }; 418 sun_mmap(p, uap, retval) 419 register struct proc *p; 420 register struct sun_mmap_args *uap; 421 int *retval; 422 { 423 register struct filedesc *fdp; 424 register struct file *fp; 425 register struct vnode *vp; 426 427 /* 428 * Verify the arguments. 429 */ 430 if (uap->prot & ~(PROT_READ|PROT_WRITE|PROT_EXEC)) 431 return (EINVAL); /* XXX still needed? */ 432 433 if ((uap->flags & SUN__MAP_NEW) == 0) 434 return (EINVAL); 435 uap->flags &= ~SUN__MAP_NEW; 436 437 if ((uap->flags & MAP_FIXED) == 0 && 438 uap->addr != 0 && 439 uap->addr < (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ)) 440 uap->addr = (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ); 441 442 /* 443 * Special case: if fd refers to /dev/zero, map as MAP_ANON. (XXX) 444 */ 445 fdp = p->p_fd; 446 if ((unsigned)uap->fd < fdp->fd_nfiles && /*XXX*/ 447 (fp = fdp->fd_ofiles[uap->fd]) != NULL && /*XXX*/ 448 fp->f_type == DTYPE_VNODE && /*XXX*/ 449 (vp = (struct vnode *)fp->f_data)->v_type == VCHR && /*XXX*/ 450 iszerodev(vp->v_rdev)) { /*XXX*/ 451 uap->flags |= MAP_ANON; 452 uap->fd = -1; 453 } 454 455 uap->qoff = uap->off; 456 return (mmap(p, uap, retval)); 457 } 458 459 #define MC_SYNC 1 460 #define MC_LOCK 2 461 #define MC_UNLOCK 3 462 #define MC_ADVISE 4 463 #define MC_LOCKAS 5 464 #define MC_UNLOCKAS 6 465 466 struct sun_mctl_args { 467 caddr_t addr; 468 size_t len; 469 int func; 470 void *arg; 471 }; 472 sun_mctl(p, uap, retval) 473 register struct proc *p; 474 register struct sun_mctl_args *uap; 475 int *retval; 476 { 477 478 switch (uap->func) { 479 480 case MC_ADVISE: /* ignore for now */ 481 return (0); 482 483 case MC_SYNC: /* translate to msync */ 484 return (msync(p, uap, retval)); 485 486 default: 487 return (EINVAL); 488 } 489 } 490 491 struct sun_setsockopt_args { 492 int s; 493 int level; 494 int name; 495 caddr_t val; 496 int valsize; 497 }; 498 sun_setsockopt(p, uap, retval) 499 struct proc *p; 500 register struct sun_setsockopt_args *uap; 501 int *retval; 502 { 503 struct file *fp; 504 struct mbuf *m = NULL; 505 int error; 506 507 if (error = getsock(p->p_fd, uap->s, &fp)) 508 return (error); 509 #define SO_DONTLINGER (~SO_LINGER) 510 if (uap->name == SO_DONTLINGER) { 511 m = m_get(M_WAIT, MT_SOOPTS); 512 if (m == NULL) 513 return (ENOBUFS); 514 mtod(m, struct linger *)->l_onoff = 0; 515 m->m_len = sizeof(struct linger); 516 return (sosetopt((struct socket *)fp->f_data, uap->level, 517 SO_LINGER, m)); 518 } 519 if (uap->valsize > MLEN) 520 return (EINVAL); 521 if (uap->val) { 522 m = m_get(M_WAIT, MT_SOOPTS); 523 if (m == NULL) 524 return (ENOBUFS); 525 if (error = copyin(uap->val, mtod(m, caddr_t), 526 (u_int)uap->valsize)) { 527 (void) m_free(m); 528 return (error); 529 } 530 m->m_len = uap->valsize; 531 } 532 return (sosetopt((struct socket *)fp->f_data, uap->level, 533 uap->name, m)); 534 } 535 536 struct sun_fchroot_args { 537 int fdes; 538 }; 539 sun_fchroot(p, uap, retval) 540 register struct proc *p; 541 register struct sun_fchroot_args *uap; 542 int *retval; 543 { 544 register struct filedesc *fdp = p->p_fd; 545 register struct vnode *vp; 546 struct file *fp; 547 int error; 548 549 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 550 return (error); 551 if ((error = getvnode(fdp, uap->fdes, &fp)) != 0) 552 return (error); 553 vp = (struct vnode *)fp->f_data; 554 VOP_LOCK(vp); 555 if (vp->v_type != VDIR) 556 error = ENOTDIR; 557 else 558 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 559 VOP_UNLOCK(vp); 560 if (error) 561 return (error); 562 VREF(vp); 563 if (fdp->fd_rdir != NULL) 564 vrele(fdp->fd_rdir); 565 fdp->fd_rdir = vp; 566 return (0); 567 } 568 569 /* 570 * XXX: This needs cleaning up. 571 */ 572 sun_auditsys(...) 573 { 574 return 0; 575 } 576 577 struct sun_utsname { 578 char sysname[9]; 579 char nodename[9]; 580 char nodeext[65-9]; 581 char release[9]; 582 char version[9]; 583 char machine[9]; 584 }; 585 586 struct sun_uname_args { 587 struct sun_utsname *name; 588 }; 589 sun_uname(p, uap, retval) 590 struct proc *p; 591 struct sun_uname_args *uap; 592 int *retval; 593 { 594 struct sun_utsname sut; 595 extern char ostype[], machine[], osrelease[]; 596 597 bzero(&sut, sizeof(sut)); 598 599 bcopy(ostype, sut.sysname, sizeof(sut.sysname) - 1); 600 bcopy(hostname, sut.nodename, sizeof(sut.nodename)); 601 sut.nodename[sizeof(sut.nodename)-1] = '\0'; 602 bcopy(osrelease, sut.release, sizeof(sut.release) - 1); 603 bcopy("1", sut.version, sizeof(sut.version) - 1); 604 bcopy(machine, sut.machine, sizeof(sut.machine) - 1); 605 606 return copyout((caddr_t)&sut, (caddr_t)uap->name, sizeof(struct sun_utsname)); 607 } 608 609 struct sun_setpgid_args { 610 int pid; /* target process id */ 611 int pgid; /* target pgrp id */ 612 }; 613 int 614 sun_setpgid(p, uap, retval) 615 struct proc *p; 616 struct sun_setpgid_args *uap; 617 int *retval; 618 { 619 /* 620 * difference to our setpgid call is to include backwards 621 * compatibility to pre-setsid() binaries. Do setsid() 622 * instead of setpgid() in those cases where the process 623 * tries to create a new session the old way. 624 */ 625 if (!uap->pgid && (!uap->pid || uap->pid == p->p_pid)) 626 return setsid(p, uap, retval); 627 else 628 return setpgid(p, uap, retval); 629 } 630 631 struct sun_open_args { 632 char *fname; 633 int fmode; 634 int crtmode; 635 }; 636 sun_open(p, uap, retval) 637 struct proc *p; 638 struct sun_open_args *uap; 639 int *retval; 640 { 641 int l, r; 642 int noctty = uap->fmode & 0x8000; 643 int ret; 644 645 /* convert mode into NetBSD mode */ 646 l = uap->fmode; 647 r = (l & (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800)); 648 r |= ((l & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0); 649 r |= ((l & 0x0080) ? O_SHLOCK : 0); 650 r |= ((l & 0x0100) ? O_EXLOCK : 0); 651 r |= ((l & 0x2000) ? O_FSYNC : 0); 652 653 uap->fmode = r; 654 ret = open(p, uap, retval); 655 656 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 657 struct filedesc *fdp = p->p_fd; 658 struct file *fp = fdp->fd_ofiles[*retval]; 659 660 /* ignore any error, just give it a try */ 661 if (fp->f_type == DTYPE_VNODE) 662 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p); 663 } 664 return ret; 665 } 666 667 #if defined (NFSSERVER) 668 struct nfssvc_args { 669 int fd; 670 caddr_t mskval; 671 int msklen; 672 caddr_t mtchval; 673 int mtchlen; 674 }; 675 struct sun_nfssvc_args { 676 int fd; 677 }; 678 sun_nfssvc(p, uap, retval) 679 struct proc *p; 680 struct sun_nfssvc_args *uap; 681 int *retval; 682 { 683 struct nfssvc_args outuap; 684 struct sockaddr sa; 685 int error; 686 extern char sigcode[], esigcode[]; 687 688 bzero(&outuap, sizeof outuap); 689 outuap.fd = uap->fd; 690 outuap.mskval = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN); 691 outuap.msklen = sizeof sa; 692 outuap.mtchval = outuap.mskval + sizeof sa; 693 outuap.mtchlen = sizeof sa; 694 695 bzero(&sa, sizeof sa); 696 if (error = copyout(&sa, outuap.mskval, outuap.msklen)) 697 return (error); 698 if (error = copyout(&sa, outuap.mtchval, outuap.mtchlen)) 699 return (error); 700 701 return nfssvc(p, &outuap, retval); 702 } 703 #endif /* NFSSERVER */ 704 705 struct sun_ustat { 706 daddr_t f_tfree; /* total free */ 707 ino_t f_tinode; /* total inodes free */ 708 char f_fname[6]; /* filsys name */ 709 char f_fpack[6]; /* filsys pack name */ 710 }; 711 struct sun_ustat_args { 712 int dev; 713 struct sun_ustat *buf; 714 }; 715 sun_ustat(p, uap, retval) 716 struct proc *p; 717 struct sun_ustat_args *uap; 718 int *retval; 719 { 720 struct sun_ustat us; 721 int error; 722 723 bzero(&us, sizeof us); 724 725 /* 726 * XXX: should set f_tfree and f_tinode at least 727 * How do we translate dev -> fstat? (and then to sun_ustat) 728 */ 729 730 if (error = copyout(&us, uap->buf, sizeof us)) 731 return (error); 732 return 0; 733 } 734 735 struct sun_quotactl_args { 736 int cmd; 737 char *special; 738 int uid; 739 caddr_t addr; 740 }; 741 sun_quotactl(p, uap, retval) 742 struct proc *p; 743 struct sun_quotactl_args *uap; 744 int *retval; 745 { 746 return EINVAL; 747 } 748 749 sun_vhangup(p, uap, retval) 750 struct proc *p; 751 void *uap; 752 int *retval; 753 { 754 return 0; 755 } 756 757 struct sun_statfs { 758 long f_type; /* type of info, zero for now */ 759 long f_bsize; /* fundamental file system block size */ 760 long f_blocks; /* total blocks in file system */ 761 long f_bfree; /* free blocks */ 762 long f_bavail; /* free blocks available to non-super-user */ 763 long f_files; /* total file nodes in file system */ 764 long f_ffree; /* free file nodes in fs */ 765 fsid_t f_fsid; /* file system id */ 766 long f_spare[7]; /* spare for later */ 767 }; 768 static 769 sunstatfs(sp, buf) 770 struct statfs *sp; 771 caddr_t buf; 772 { 773 struct sun_statfs ssfs; 774 775 bzero(&ssfs, sizeof ssfs); 776 ssfs.f_type = 0; 777 ssfs.f_bsize = sp->f_bsize; 778 ssfs.f_blocks = sp->f_blocks; 779 ssfs.f_bfree = sp->f_bfree; 780 ssfs.f_bavail = sp->f_bavail; 781 ssfs.f_files = sp->f_files; 782 ssfs.f_ffree = sp->f_ffree; 783 ssfs.f_fsid = sp->f_fsid; 784 return copyout((caddr_t)&ssfs, buf, sizeof ssfs); 785 } 786 787 struct sun_statfs_args { 788 char *path; 789 struct sun_statfs *buf; 790 }; 791 sun_statfs(p, uap, retval) 792 struct proc *p; 793 struct sun_statfs_args *uap; 794 int *retval; 795 { 796 register struct mount *mp; 797 register struct nameidata *ndp; 798 register struct statfs *sp; 799 int error; 800 struct nameidata nd; 801 802 ndp = &nd; 803 ndp->ni_nameiop = LOOKUP | FOLLOW; 804 ndp->ni_segflg = UIO_USERSPACE; 805 ndp->ni_dirp = uap->path; 806 if (error = namei(ndp, p)) 807 return (error); 808 mp = ndp->ni_vp->v_mount; 809 sp = &mp->mnt_stat; 810 vrele(ndp->ni_vp); 811 if (error = VFS_STATFS(mp, sp, p)) 812 return (error); 813 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 814 return sunstatfs(sp, (caddr_t)uap->buf); 815 } 816 817 struct sun_fstatfs_args { 818 int fd; 819 struct sun_statfs *buf; 820 }; 821 sun_fstatfs(p, uap, retval) 822 struct proc *p; 823 struct sun_fstatfs_args *uap; 824 int *retval; 825 { 826 struct file *fp; 827 struct mount *mp; 828 register struct statfs *sp; 829 int error; 830 831 if (error = getvnode(p->p_fd, uap->fd, &fp)) 832 return (error); 833 mp = ((struct vnode *)fp->f_data)->v_mount; 834 sp = &mp->mnt_stat; 835 if (error = VFS_STATFS(mp, sp, p)) 836 return (error); 837 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 838 return sunstatfs(sp, (caddr_t)uap->buf); 839 } 840 841 struct sun_exportfs_args { 842 char *path; 843 char *ex; /* struct sun_export * */ 844 }; 845 sun_exportfs(p, uap, retval) 846 struct proc *p; 847 struct sun_exportfs_args *uap; 848 int *retval; 849 { 850 /* 851 * XXX: should perhaps translate into a mount(2) 852 * with MOUNT_EXPORT? 853 */ 854 return 0; 855 } 856 857 struct sun_mknod_args { 858 char *fname; 859 int fmode; 860 int dev; 861 }; 862 863 sun_mknod(p, uap, retval) 864 struct proc *p; 865 struct sun_mknod_args *uap; 866 int *retval; 867 { 868 if (S_ISFIFO(uap->fmode)) 869 return mkfifo(p, uap, retval); 870 871 return mknod(p, uap, retval); 872 } 873 874 #define SUN_SC_ARG_MAX 1 875 #define SUN_SC_CHILD_MAX 2 876 #define SUN_SC_CLK_TCK 3 877 #define SUN_SC_NGROUPS_MAX 4 878 #define SUN_SC_OPEN_MAX 5 879 #define SUN_SC_JOB_CONTROL 6 880 #define SUN_SC_SAVED_IDS 7 881 #define SUN_SC_VERSION 8 882 883 struct sun_sysconf_args { 884 int name; 885 }; 886 887 sun_sysconf(p, uap, retval) 888 struct proc *p; 889 struct sun_sysconf_args *uap; 890 int *retval; 891 { 892 extern int maxfiles; 893 894 switch(uap->name) { 895 case SUN_SC_ARG_MAX: 896 *retval = ARG_MAX; 897 break; 898 case SUN_SC_CHILD_MAX: 899 *retval = maxproc; 900 break; 901 case SUN_SC_CLK_TCK: 902 *retval = 60; /* should this be `hz', ie. 100? */ 903 break; 904 case SUN_SC_NGROUPS_MAX: 905 *retval = NGROUPS_MAX; 906 break; 907 case SUN_SC_OPEN_MAX: 908 *retval = maxfiles; 909 break; 910 case SUN_SC_JOB_CONTROL: 911 *retval = 1; 912 break; 913 case SUN_SC_SAVED_IDS: 914 #ifdef _POSIX_SAVED_IDS 915 *retval = 1; 916 #else 917 *retval = 0; 918 #endif 919 break; 920 case SUN_SC_VERSION: 921 *retval = 198808; 922 break; 923 default: 924 return EINVAL; 925 } 926 return 0; 927 } 928 929 #define SUN_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */ 930 #define SUN_RLIM_NLIMITS 7 931 932 struct sun_getrlimit_args { 933 int which; 934 struct orlimit *rlp; 935 }; 936 937 sun_getrlimit(p, uap, retval) 938 struct proc *p; 939 struct sun_getrlimit_args *uap; 940 int *retval; 941 { 942 if (uap->which >= SUN_RLIM_NLIMITS) 943 return EINVAL; 944 945 if (uap->which == SUN_RLIMIT_NOFILE) 946 uap->which = RLIMIT_NOFILE; 947 948 return ogetrlimit(p, uap, retval); 949 } 950 951 struct sun_setrlimit_args { 952 int which; 953 struct orlimit *rlp; 954 }; 955 956 sun_setrlimit(p, uap, retval) 957 struct proc *p; 958 struct sun_getrlimit_args *uap; 959 int *retval; 960 { 961 if (uap->which >= SUN_RLIM_NLIMITS) 962 return EINVAL; 963 964 if (uap->which == SUN_RLIMIT_NOFILE) 965 uap->which = RLIMIT_NOFILE; 966 967 return osetrlimit(p, uap, retval); 968 } 969