1 /* $NetBSD: sunos32_misc.c,v 1.66 2009/05/16 17:45:23 nakayama Exp $ */
2 /* from :NetBSD: sunos_misc.c,v 1.107 2000/12/01 19:25:10 jdolecek Exp */
5 * Copyright (c) 2001 Matthew R. Green
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Copyright (c) 1992, 1993
32 * The Regents of the University of California. All rights reserved.
34 * This software was developed by the Computer Systems Engineering group
35 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
36 * contributed to Berkeley.
38 * All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Lawrence Berkeley Laboratory.
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * @(#)sunos_misc.c 8.1 (Berkeley) 6/18/93
69 * Header: sunos_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
73 * SunOS compatibility module, 64-bit kernel version
75 * SunOS system calls that are implemented differently in BSD are
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: sunos32_misc.c,v 1.66 2009/05/16 17:45:23 nakayama Exp $");
82 #define COMPAT_SUNOS 1
84 #if defined(_KERNEL_OPT)
85 #include "opt_compat_43.h"
86 #include "opt_compat_netbsd.h"
90 #include <sys/param.h>
91 #include <sys/systm.h>
92 #include <sys/namei.h>
94 #include <sys/dirent.h>
97 #include <sys/filedesc.h>
98 #include <sys/ioctl.h>
99 #include <sys/kernel.h>
100 #include <sys/reboot.h>
101 #include <sys/malloc.h>
102 #include <sys/mbuf.h>
103 #include <sys/mman.h>
104 #include <sys/mount.h>
105 #include <sys/ptrace.h>
106 #include <sys/resource.h>
107 #include <sys/resourcevar.h>
108 #include <sys/signal.h>
109 #include <sys/signalvar.h>
110 #include <sys/socket.h>
112 #include <sys/vnode.h>
114 #include <sys/wait.h>
115 #include <sys/utsname.h>
116 #include <sys/unistd.h>
117 #include <sys/syscall.h>
118 #include <sys/syscallargs.h>
119 #include <sys/conf.h>
120 #include <sys/socketvar.h>
121 #include <sys/exec.h>
122 #include <sys/swap.h>
123 #include <sys/kauth.h>
124 #include <sys/vfs_syscalls.h>
126 #include <compat/netbsd32/netbsd32.h>
127 #include <compat/netbsd32/netbsd32_syscallargs.h>
128 #include <compat/sunos32/sunos32.h>
129 #include <compat/sunos32/sunos32_dirent.h>
130 #include <compat/sunos32/sunos32_syscallargs.h>
131 #include <compat/common/compat_util.h>
132 #include <compat/sys/mount.h>
134 #include <netinet/in.h>
136 #include <miscfs/specfs/specdev.h>
138 #include <nfs/rpcv2.h>
139 #include <nfs/nfsproto.h>
141 #include <nfs/nfsmount.h>
143 static void sunos32_sigvec_to_sigaction(const struct netbsd32_sigvec
*, struct sigaction
*);
144 static void sunos32_sigvec_from_sigaction(struct netbsd32_sigvec
*, const struct sigaction
*);
146 static int sunstatfs(struct statvfs
*, void *);
149 sunos32_sigvec_to_sigaction(const struct netbsd32_sigvec
*sv
, struct sigaction
*sa
)
151 /*XXX*/ extern void compat_43_sigmask_to_sigset(const int *, sigset_t
*);
153 sa
->sa_handler
= NETBSD32PTR64(sv
->sv_handler
);
154 compat_43_sigmask_to_sigset(&sv
->sv_mask
, &sa
->sa_mask
);
155 sa
->sa_flags
= sv
->sv_flags
^ SA_RESTART
;
159 void sunos32_sigvec_from_sigaction(sv
, sa
)
160 struct netbsd32_sigvec
*sv
;
161 const struct sigaction
*sa
;
163 /*XXX*/ extern void compat_43_sigset_to_sigmask(const sigset_t
*, int *);
165 NETBSD32PTR32(sv
->sv_handler
, sa
->sa_handler
);
166 compat_43_sigset_to_sigmask(&sa
->sa_mask
, &sv
->sv_mask
);
167 sv
->sv_flags
= sa
->sa_flags
^ SA_RESTART
;
171 sunos32_sys_stime(struct lwp
*l
, const struct sunos32_sys_stime_args
*uap
, register_t
*retval
)
174 syscallarg(sunos32_time_tp) tp;
176 struct netbsd32_timeval ntv
;
180 error
= copyin(SCARG_P32(uap
, tp
), &ntv
.tv_sec
, sizeof(ntv
.tv_sec
));
183 tv
.tv_sec
= ntv
.tv_sec
;
186 return settimeofday1(&tv
, false, NULL
, l
, true);
190 sunos32_sys_wait4(struct lwp
*l
, const struct sunos32_sys_wait4_args
*uap
, register_t
*retval
)
194 syscallarg(netbsd32_intp) status;
195 syscallarg(int) options;
196 syscallarg(netbsd32_rusagep_t) rusage;
199 struct compat_50_netbsd32_wait4_args bsd_ua
;
201 SCARG(&bsd_ua
, pid
) = SCARG(uap
, pid
) == 0 ? WAIT_ANY
: SCARG(uap
, pid
);
202 SCARG(&bsd_ua
, status
) = SCARG(uap
, status
);
203 SCARG(&bsd_ua
, options
) = SCARG(uap
, options
);
204 SCARG(&bsd_ua
, rusage
) = SCARG(uap
, rusage
);
206 return compat_50_netbsd32_wait4(l
, &bsd_ua
, retval
);
210 sunos32_sys_creat(struct lwp
*l
, const struct sunos32_sys_creat_args
*uap
, register_t
*retval
)
213 syscallarg(const netbsd32_charp) path;
214 syscallarg(int) mode;
216 struct sys_open_args ua
;
218 SUNOS32TOP_UAP(path
, const char);
219 SCARG(&ua
, flags
) = O_WRONLY
| O_CREAT
| O_TRUNC
;
220 SUNOS32TO64_UAP(mode
);
222 return (sys_open(l
, &ua
, retval
));
226 sunos32_sys_access(struct lwp
*l
, const struct sunos32_sys_access_args
*uap
, register_t
*retval
)
229 syscallarg(const netbsd32_charp) path;
230 syscallarg(int) flags;
232 struct sys_access_args ua
;
234 SUNOS32TOP_UAP(path
, const char);
235 SUNOS32TO64_UAP(flags
);
237 return (sys_access(l
, &ua
, retval
));
240 static inline void sunos32_from___stat13(struct stat
*, struct netbsd32_stat43
*);
243 sunos32_from___stat13(struct stat
*sbp
, struct netbsd32_stat43
*sb32p
)
245 sb32p
->st_dev
= sbp
->st_dev
;
246 sb32p
->st_ino
= sbp
->st_ino
;
247 sb32p
->st_mode
= sbp
->st_mode
;
248 sb32p
->st_nlink
= sbp
->st_nlink
;
249 sb32p
->st_uid
= sbp
->st_uid
;
250 sb32p
->st_gid
= sbp
->st_gid
;
251 sb32p
->st_rdev
= sbp
->st_rdev
;
252 if (sbp
->st_size
< (quad_t
)1 << 32)
253 sb32p
->st_size
= sbp
->st_size
;
256 sb32p
->st_atimespec
.tv_sec
= (netbsd32_time_t
)sbp
->st_atimespec
.tv_sec
;
257 sb32p
->st_atimespec
.tv_nsec
= (netbsd32_long
)sbp
->st_atimespec
.tv_nsec
;
258 sb32p
->st_mtimespec
.tv_sec
= (netbsd32_time_t
)sbp
->st_mtimespec
.tv_sec
;
259 sb32p
->st_mtimespec
.tv_nsec
= (netbsd32_long
)sbp
->st_mtimespec
.tv_nsec
;
260 sb32p
->st_ctimespec
.tv_sec
= (netbsd32_time_t
)sbp
->st_ctimespec
.tv_sec
;
261 sb32p
->st_ctimespec
.tv_nsec
= (netbsd32_long
)sbp
->st_ctimespec
.tv_nsec
;
262 sb32p
->st_blksize
= sbp
->st_blksize
;
263 sb32p
->st_blocks
= sbp
->st_blocks
;
264 sb32p
->st_flags
= sbp
->st_flags
;
265 sb32p
->st_gen
= sbp
->st_gen
;
270 sunos32_sys_stat(struct lwp
*l
, const struct sunos32_sys_stat_args
*uap
, register_t
*retval
)
273 syscallarg(const netbsd32_charp) path;
274 syscallarg(netbsd32_stat43p_t) ub;
276 struct netbsd32_stat43 sb32
;
281 path
= SCARG_P32(uap
, path
);
283 error
= do_sys_stat(path
, FOLLOW
, &sb
);
286 sunos32_from___stat13(&sb
, &sb32
);
287 error
= copyout(&sb32
, SCARG_P32(uap
, ub
), sizeof (sb32
));
292 sunos32_sys_lstat(struct lwp
*l
, const struct sunos32_sys_lstat_args
*uap
, register_t
*retval
)
295 syscallarg(const netbsd32_charp) path;
296 syscallarg(netbsd32_stat43p_t) ub;
298 struct vnode
*vp
, *dvp
;
300 struct netbsd32_stat43 sb32
;
306 path
= SCARG_P32(uap
, path
);
308 ndflags
= NOFOLLOW
| LOCKLEAF
| LOCKPARENT
| TRYEMULROOT
;
310 NDINIT(&nd
, LOOKUP
, ndflags
, UIO_USERSPACE
, path
);
311 if ((error
= namei(&nd
))) {
312 if (error
== EISDIR
&& (ndflags
& LOCKPARENT
) != 0) {
314 * Should only happen on '/'. Retry without LOCKPARENT;
315 * this is safe since the vnode won't be a VLNK.
317 ndflags
&= ~LOCKPARENT
;
323 * For symbolic links, always return the attributes of its
324 * containing directory, except for mode, size, and links.
328 if (vp
->v_type
!= VLNK
) {
329 if ((ndflags
& LOCKPARENT
) != 0) {
335 error
= vn_stat(vp
, &sb
);
340 error
= vn_stat(dvp
, &sb
);
346 error
= vn_stat(vp
, &sb1
);
350 sb
.st_mode
&= ~S_IFDIR
;
351 sb
.st_mode
|= S_IFLNK
;
352 sb
.st_nlink
= sb1
.st_nlink
;
353 sb
.st_size
= sb1
.st_size
;
354 sb
.st_blocks
= sb1
.st_blocks
;
356 sunos32_from___stat13(&sb
, &sb32
);
357 error
= copyout((void *)&sb32
, SCARG_P32(uap
, ub
), sizeof (sb32
));
362 sunos32_execve_fetch_element(char * const *array
, size_t index
, char **value
)
365 netbsd32_charp
const *a32
= (void const *)array
;
368 error
= copyin(a32
+ index
, &e
, sizeof(e
));
371 *value
= NETBSD32PTR64(e
);
376 sunos32_sys_execv(struct lwp
*l
, const struct sunos32_sys_execv_args
*uap
, register_t
*retval
)
379 syscallarg(const char *) path;
380 syscallarg(char **) argv;
382 const char *path
= SCARG_P32(uap
, path
);
384 return execve1(l
, path
, SCARG_P32(uap
, argp
), NULL
,
385 sunos32_execve_fetch_element
);
389 sunos32_sys_execve(struct lwp
*l
, const struct sunos32_sys_execve_args
*uap
, register_t
*retval
)
392 syscallarg(const char *) path;
393 syscallarg(char **) argv;
394 syscallarg(char **) envp;
396 const char *path
= SCARG_P32(uap
, path
);
398 return execve1(l
, path
, SCARG_P32(uap
, argp
),
399 SCARG_P32(uap
, envp
),
400 sunos32_execve_fetch_element
);
404 sunos32_sys_omsync(struct lwp
*l
, const struct sunos32_sys_omsync_args
*uap
, register_t
*retval
)
407 syscallarg(netbsd32_caddr_t) addr;
408 syscallarg(netbsd32_size_t) len;
409 syscallarg(int) flags;
411 struct netbsd32___msync13_args ouap
;
413 SCARG(&ouap
, addr
) = SCARG(uap
, addr
);
414 SCARG(&ouap
, len
) = SCARG(uap
, len
);
415 SCARG(&ouap
, flags
) = SCARG(uap
, flags
);
417 return (netbsd32___msync13(l
, &ouap
, retval
));
421 sunos32_sys_unmount(struct lwp
*l
, const struct sunos32_sys_unmount_args
*uap
, register_t
*retval
)
424 syscallarg(netbsd32_charp) path;
426 struct sys_unmount_args ua
;
428 SUNOS32TOP_UAP(path
, const char);
429 SCARG(&ua
, flags
) = 0;
431 return (sys_unmount(l
, &ua
, retval
));
435 * Conversion table for SunOS NFS mount flags.
440 } sunnfs_flgtab
[] = {
441 { SUNNFS_SOFT
, NFSMNT_SOFT
},
442 { SUNNFS_WSIZE
, NFSMNT_WSIZE
},
443 { SUNNFS_RSIZE
, NFSMNT_RSIZE
},
444 { SUNNFS_TIMEO
, NFSMNT_TIMEO
},
445 { SUNNFS_RETRANS
, NFSMNT_RETRANS
},
446 { SUNNFS_HOSTNAME
, 0 }, /* Ignored */
447 { SUNNFS_INT
, NFSMNT_INT
},
448 { SUNNFS_NOAC
, 0 }, /* Ignored */
449 { SUNNFS_ACREGMIN
, 0 }, /* Ignored */
450 { SUNNFS_ACREGMAX
, 0 }, /* Ignored */
451 { SUNNFS_ACDIRMIN
, 0 }, /* Ignored */
452 { SUNNFS_ACDIRMAX
, 0 }, /* Ignored */
453 { SUNNFS_SECURE
, 0 }, /* Ignored */
454 { SUNNFS_NOCTO
, 0 }, /* Ignored */
455 { SUNNFS_POSIX
, 0 } /* Ignored */
459 sunos32_sys_mount(struct lwp
*l
, const struct sunos32_sys_mount_args
*uap
, register_t
*retval
)
462 syscallarg(netbsd32_charp) type;
463 syscallarg(netbsd32_charp) path;
464 syscallarg(int) flags;
465 syscallarg(netbsd32_caddr_t) data;
467 int oflags
= SCARG(uap
, flags
), nflags
, error
;
468 char fsname
[MFSNAMELEN
];
471 if (oflags
& (SUNM_NOSUB
| SUNM_SYS5
))
473 if ((oflags
& SUNM_NEWTYPE
) == 0)
476 if (oflags
& SUNM_RDONLY
)
477 nflags
|= MNT_RDONLY
;
478 if (oflags
& SUNM_NOSUID
)
479 nflags
|= MNT_NOSUID
;
480 if (oflags
& SUNM_REMOUNT
)
481 nflags
|= MNT_UPDATE
;
483 error
= copyinstr(SCARG_P32(uap
, type
), fsname
, sizeof fsname
, NULL
);
487 if (strncmp(fsname
, "nfs", sizeof fsname
) == 0) {
488 struct sunos_nfs_args sna
;
489 struct nfs_args na
; /* XXX */
492 error
= copyin(SCARG_P32(uap
, data
), &sna
, sizeof sna
);
495 /* sa.sa_len = sizeof(sain); */
496 na
.version
= NFS_ARGSVERSION
;
497 na
.addr
= (void *)sna
.addr
;
498 na
.addrlen
= sizeof(struct sockaddr
);
499 na
.sotype
= SOCK_DGRAM
;
500 na
.proto
= IPPROTO_UDP
;
502 na
.fhsize
= NFSX_V2FH
;
504 n
= sizeof(sunnfs_flgtab
) / sizeof(sunnfs_flgtab
[0]);
506 if (sna
.flags
& sunnfs_flgtab
[n
].sun_flg
)
507 na
.flags
|= sunnfs_flgtab
[n
].bsd_flg
;
508 na
.wsize
= sna
.wsize
;
509 na
.rsize
= sna
.rsize
;
510 if (na
.flags
& NFSMNT_RSIZE
) {
511 na
.flags
|= NFSMNT_READDIRSIZE
;
512 na
.readdirsize
= na
.rsize
;
514 na
.timeo
= sna
.timeo
;
515 na
.retrans
= sna
.retrans
;
516 na
.hostname
= (char *)(u_long
)sna
.hostname
;
518 return do_sys_mount(l
, vfs_getopsbyname("nfs"), NULL
,
519 SCARG_P32(uap
, path
), nflags
, &na
, UIO_SYSSPACE
, sizeof na
,
523 if (strcmp(fsname
, "4.2") == 0)
524 strcpy(fsname
, "ffs");
526 return do_sys_mount(l
, vfs_getopsbyname(fsname
), NULL
,
527 SCARG_P32(uap
, path
), nflags
, SCARG_P32(uap
, data
), UIO_USERSPACE
,
533 async_daemon(struct lwp
*l
, const void *v
, register_t
*retval
)
535 struct netbsd32_nfssvc_args ouap
;
537 SCARG(&ouap
, flag
) = NFSSVC_BIOD
;
538 NETBSD32PTR32(SCARG(&ouap
, argp
), 0);
540 return (netbsd32_nfssvc(l
, &ouap
, retval
));
544 void native_to_sunos_sigset(const sigset_t
*, int *);
545 void sunos_to_native_sigset(const int, sigset_t
*);
548 native_to_sunos_sigset(const sigset_t
*ss
, int *mask
)
550 *mask
= ss
->__bits
[0];
554 sunos_to_native_sigset(const int mask
, sigset_t
*ss
)
557 ss
->__bits
[0] = mask
;
564 sunos32_sys_sigpending(struct lwp
*l
, const struct sunos32_sys_sigpending_args
*uap
, register_t
*retval
)
567 syscallarg(netbsd32_intp) mask;
573 native_to_sunos_sigset(&ss
, &mask
);
575 return (copyout((void *)(u_long
)&mask
, SCARG_P32(uap
, mask
), sizeof(int)));
579 sunos32_sys_sigsuspend(struct lwp
*l
, const struct sunos32_sys_sigsuspend_args
*uap
, register_t
*retval
)
582 syscallarg(int) mask;
587 mask
= SCARG(uap
, mask
);
588 sunos_to_native_sigset(mask
, &ss
);
589 return (sigsuspend1(l
, &ss
));
593 * Read Sun-style directory entries. We suck them into kernel space so
594 * that they can be massaged before being copied out to user code. Like
595 * SunOS, we squish out `empty' entries.
597 * This is quite ugly, but what do you expect from compatibility code?
600 sunos32_sys_getdents(struct lwp
*l
, const struct sunos32_sys_getdents_args
*uap
, register_t
*retval
)
604 syscallarg(netbsd32_charp) buf;
605 syscallarg(int) nbytes;
609 char *inp
, *sbuf
; /* BSD-format */
610 int len
, reclen
; /* BSD-format */
611 char *outp
; /* Sun-format */
612 int resid
, sunos_reclen
;/* Sun-format */
616 struct sunos32_dirent idb
;
617 off_t off
; /* true file offset */
618 int buflen
, error
, eofflag
;
619 off_t
*cookiebuf
, *cookie
;
622 /* fd_getvnode() will use the descriptor for us */
623 if ((error
= fd_getvnode(SCARG(uap
, fd
), &fp
)) != 0)
626 if ((fp
->f_flag
& FREAD
) == 0) {
632 if (vp
->v_type
!= VDIR
) {
637 buflen
= min(MAXBSIZE
, SCARG(uap
, nbytes
));
638 sbuf
= malloc(buflen
, M_TEMP
, M_WAITOK
);
639 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
642 aiov
.iov_base
= sbuf
;
643 aiov
.iov_len
= buflen
;
644 auio
.uio_iov
= &aiov
;
646 auio
.uio_rw
= UIO_READ
;
647 auio
.uio_resid
= buflen
;
648 auio
.uio_offset
= off
;
649 UIO_SETUP_SYSSPACE(&auio
);
651 * First we read into the malloc'ed buffer, then
652 * we massage it into user space, one record at a time.
654 error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
, &cookiebuf
,
660 outp
= SCARG_P32(uap
, buf
);
661 resid
= SCARG(uap
, nbytes
);
662 if ((len
= buflen
- auio
.uio_resid
) == 0)
665 for (cookie
= cookiebuf
; len
> 0; len
-= reclen
) {
666 bdp
= (struct dirent
*)inp
;
667 reclen
= bdp
->d_reclen
;
669 panic("sunos_getdents");
670 if (cookie
&& (*cookie
>> 32) != 0) {
671 compat_offseterr(vp
, "sunos_getdents");
675 if (bdp
->d_fileno
== 0) {
676 inp
+= reclen
; /* it is a hole; squish it out */
683 sunos_reclen
= SUNOS32_RECLEN(&idb
, bdp
->d_namlen
);
684 if (reclen
> len
|| resid
< sunos_reclen
) {
685 /* entry too big for buffer, so just stop */
690 off
= *cookie
++; /* each entry points to next */
694 * Massage in place to make a Sun-shaped dirent (otherwise
695 * we have to worry about touching user memory outside of
696 * the copyout() call).
698 idb
.d_fileno
= bdp
->d_fileno
;
700 idb
.d_reclen
= sunos_reclen
;
701 idb
.d_namlen
= bdp
->d_namlen
;
702 strlcpy(idb
.d_name
, bdp
->d_name
, sizeof(idb
.d_name
));
703 if ((error
= copyout((void *)&idb
, outp
, sunos_reclen
)) != 0)
705 /* advance past this real entry */
707 /* advance output past Sun-shaped entry */
708 outp
+= sunos_reclen
;
709 resid
-= sunos_reclen
;
712 /* if we squished out the whole block, try again */
713 if (outp
== SCARG_P32(uap
, buf
))
715 fp
->f_offset
= off
; /* update the vnode offset */
718 *retval
= SCARG(uap
, nbytes
) - resid
;
721 free(cookiebuf
, M_TEMP
);
724 fd_putfile(SCARG(uap
, fd
));
728 #define SUNOS32__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */
731 sunos32_sys_mmap(struct lwp
*l
, const struct sunos32_sys_mmap_args
*uap
, register_t
*retval
)
734 syscallarg(netbsd32_voidp) addr;
735 syscallarg(netbsd32_size_t) len;
736 syscallarg(int) prot;
737 syscallarg(int) flags;
739 syscallarg(netbsd32_long) pos;
741 struct sys_mmap_args ua
;
745 * Verify the arguments.
747 if (SCARG(uap
, prot
) & ~(PROT_READ
|PROT_WRITE
|PROT_EXEC
))
748 return (EINVAL
); /* XXX still needed? */
750 if ((SCARG(uap
, flags
) & SUNOS32__MAP_NEW
) == 0)
753 SUNOS32TOP_UAP(addr
, void);
754 SUNOS32TOX_UAP(len
, size_t);
755 SUNOS32TO64_UAP(prot
);
756 SCARG(&ua
, flags
) = SCARG(uap
, flags
) & ~SUNOS32__MAP_NEW
;
759 SUNOS32TOX_UAP(pos
, off_t
);
761 error
= sys_mmap(l
, &ua
, retval
);
762 if ((u_long
)*retval
> (u_long
)UINT_MAX
) {
763 printf("sunos32_mmap: retval out of range: 0x%lx",
765 /* Should try to recover and return an error here. */
775 #define MC_UNLOCKAS 6
778 sunos32_sys_mctl(struct lwp
*l
, const struct sunos32_sys_mctl_args
*uap
, register_t
*retval
)
781 syscallarg(netbsd32_voidp) addr;
783 syscallarg(int) func;
784 syscallarg(netbsd32_voidp) arg;
787 switch (SCARG(uap
, func
)) {
788 case MC_ADVISE
: /* ignore for now */
790 case MC_SYNC
: /* translate to msync */
791 return (netbsd32___msync13(l
, (const void *)uap
, retval
));
798 sunos32_sys_setsockopt(struct lwp
*l
, const struct sunos32_sys_setsockopt_args
*uap
, register_t
*retval
)
802 syscallarg(int) level;
803 syscallarg(int) name;
804 syscallarg(netbsd32_caddr_t) val;
805 syscallarg(int) valsize;
809 int name
= SCARG(uap
, name
);
812 /* fd_getsock() will use the descriptor for us */
813 if ((error
= fd_getsock(SCARG(uap
, s
), &so
)) != 0)
815 #define SO_DONTLINGER (~SO_LINGER)
816 if (name
== SO_DONTLINGER
) {
820 error
= so_setsockopt(l
, so
, SCARG(uap
, level
), SO_LINGER
,
824 if (SCARG(uap
, level
) == IPPROTO_IP
) {
825 #define SUNOS_IP_MULTICAST_IF 2
826 #define SUNOS_IP_MULTICAST_TTL 3
827 #define SUNOS_IP_MULTICAST_LOOP 4
828 #define SUNOS_IP_ADD_MEMBERSHIP 5
829 #define SUNOS_IP_DROP_MEMBERSHIP 6
830 static const int ipoptxlat
[] = {
837 if (name
>= SUNOS_IP_MULTICAST_IF
&&
838 name
<= SUNOS_IP_DROP_MEMBERSHIP
) {
839 name
= ipoptxlat
[name
- SUNOS_IP_MULTICAST_IF
];
842 if (SCARG(uap
, valsize
) > MLEN
) {
846 sockopt_init(&sopt
, SCARG(uap
, level
), name
, SCARG(uap
, valsize
));
847 if (SCARG_P32(uap
, val
)) {
848 error
= copyin(SCARG_P32(uap
, val
), sopt
.sopt_data
,
849 (u_int
)SCARG(uap
, valsize
));
852 error
= sosetopt(so
, &sopt
);
853 sockopt_destroy(&sopt
);
855 fd_putfile(SCARG(uap
, s
));
859 static inline int sunos32_sys_socket_common(struct lwp
*, register_t
*,
862 sunos32_sys_socket_common(struct lwp
*l
, register_t
*retval
, int type
)
867 /* fd_getsock() will use the descriptor for us */
869 if ((error
= fd_getsock(fd
, &so
)) == 0) {
870 if (type
== SOCK_DGRAM
)
871 so
->so_options
|= SO_BROADCAST
;
878 sunos32_sys_socket(struct lwp
*l
, const struct sunos32_sys_socket_args
*uap
, register_t
*retval
)
881 syscallarg(int) domain;
882 syscallarg(int) type;
883 syscallarg(int) protocol;
887 error
= netbsd32___socket30(l
, (const void *)uap
, retval
);
890 return sunos32_sys_socket_common(l
, retval
, SCARG(uap
, type
));
894 sunos32_sys_socketpair(struct lwp
*l
, const struct sunos32_sys_socketpair_args
*uap
, register_t
*retval
)
897 syscallarg(int) domain;
898 syscallarg(int) type;
899 syscallarg(int) protocol;
900 syscallarg(int *) rsv;
904 error
= netbsd32_socketpair(l
, (const void *)uap
, retval
);
907 return sunos32_sys_socket_common(l
, retval
, SCARG(uap
, type
));
912 * XXX: This needs cleaning up.
915 sunos32_sys_auditsys(struct lwp
*l
, const struct sunos32_sys_auditsys_args
*uap
, register_t
*retval
)
921 sunos32_sys_uname(struct lwp
*l
, const struct sunos32_sys_uname_args
*uap
, register_t
*retval
)
924 syscallarg(sunos32_utsnamep_t) name;
926 struct sunos_utsname sut
;
928 memset(&sut
, 0, sizeof(sut
));
930 memcpy(sut
.sysname
, ostype
, sizeof(sut
.sysname
) - 1);
931 memcpy(sut
.nodename
, hostname
, sizeof(sut
.nodename
));
932 sut
.nodename
[sizeof(sut
.nodename
)-1] = '\0';
933 memcpy(sut
.release
, osrelease
, sizeof(sut
.release
) - 1);
934 memcpy(sut
.version
, "1", sizeof(sut
.version
) - 1);
935 memcpy(sut
.machine
, machine
, sizeof(sut
.machine
) - 1);
937 return copyout((void *)&sut
, SCARG_P32(uap
, name
),
938 sizeof(struct sunos_utsname
));
942 sunos32_sys_setpgrp(struct lwp
*l
, const struct sunos32_sys_setpgrp_args
*uap
, register_t
*retval
)
946 syscallarg(int) pgid;
948 struct proc
*p
= l
->l_proc
;
951 * difference to our setpgid call is to include backwards
952 * compatibility to pre-setsid() binaries. Do setsid()
953 * instead of setpgid() in those cases where the process
954 * tries to create a new session the old way.
956 if (!SCARG(uap
, pgid
) &&
957 (!SCARG(uap
, pid
) || SCARG(uap
, pid
) == p
->p_pid
))
958 return sys_setsid(l
, NULL
, retval
);
960 return netbsd32_setpgid(l
, (const void *)uap
, retval
);
964 sunos32_sys_open(struct lwp
*l
, const struct sunos32_sys_open_args
*uap
, register_t
*retval
)
967 syscallarg(const netbsd32_charp) path;
968 syscallarg(int) flags;
969 syscallarg(int) mode;
971 struct proc
*p
= l
->l_proc
;
972 struct sys_open_args ua
;
977 /* convert mode into NetBSD mode */
978 lf
= SCARG(uap
, flags
);
979 noctty
= lf
& 0x8000;
980 r
= (lf
& (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800));
981 r
|= ((lf
& (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK
: 0);
982 r
|= ((lf
& 0x0080) ? O_SHLOCK
: 0);
983 r
|= ((lf
& 0x0100) ? O_EXLOCK
: 0);
984 r
|= ((lf
& 0x2000) ? O_FSYNC
: 0);
986 SUNOS32TOP_UAP(path
, const char);
987 SCARG(&ua
, flags
) = r
;
988 SUNOS32TO64_UAP(mode
);
990 ret
= sys_open(l
, &ua
, retval
);
992 /* XXXSMP unlocked */
993 if (!ret
&& !noctty
&& SESS_LEADER(p
) && !(p
->p_lflag
& PL_CONTROLT
)) {
1000 /* ignore any error, just give it a try */
1002 if (fp
->f_type
== DTYPE_VNODE
)
1003 (fp
->f_ops
->fo_ioctl
)(fp
, TIOCSCTTY
, NULL
);
1011 sunos32_sys_nfssvc(struct lwp
*l
, const struct sunos32_sys_nfssvc_args
*uap
, register_t
*retval
)
1014 struct emul
*e
= p
->p_emul
;
1015 struct sys_nfssvc_args outuap
;
1018 void *sg
= stackgap_init(p
, 0);
1020 memset(&outuap
, 0, sizeof outuap
);
1021 SCARG(&outuap
, fd
) = SCARG(uap
, fd
);
1022 SCARG(&outuap
, mskval
) = stackgap_alloc(p
, &sg
, sizeof(sa
));
1023 SCARG(&outuap
, msklen
) = sizeof(sa
);
1024 SCARG(&outuap
, mtchval
) = stackgap_alloc(p
, &sg
, sizeof(sa
));
1025 SCARG(&outuap
, mtchlen
) = sizeof(sa
);
1027 memset(&sa
, 0, sizeof sa
);
1028 if (error
= copyout(&sa
, SCARG(&outuap
, mskval
), SCARG(&outuap
, msklen
)))
1030 if (error
= copyout(&sa
, SCARG(&outuap
, mtchval
), SCARG(&outuap
, mtchlen
)))
1033 return nfssvc(l
, &outuap
, retval
);
1040 sunos32_sys_ustat(struct lwp
*l
, const struct sunos32_sys_ustat_args
*uap
, register_t
*retval
)
1043 syscallarg(int) dev;
1044 syscallarg(sunos32_ustatp_t) buf;
1046 struct sunos_ustat us
;
1049 memset(&us
, 0, sizeof us
);
1052 * XXX: should set f_tfree and f_tinode at least
1053 * How do we translate dev -> fstat? (and then to sunos_ustat)
1056 if ((error
= copyout(&us
, SCARG_P32(uap
, buf
), sizeof us
)) != 0)
1062 sunos32_sys_quotactl(struct lwp
*l
, const struct sunos32_sys_quotactl_args
*uap
, register_t
*retval
)
1069 sunos32_sys_vhangup(struct lwp
*l
, const void *v
, register_t
*retval
)
1071 struct proc
*p
= l
->l_proc
;
1072 struct session
*sp
= p
->p_session
;
1074 if (sp
->s_ttyvp
== 0)
1077 if (sp
->s_ttyp
&& sp
->s_ttyp
->t_session
== sp
&& sp
->s_ttyp
->t_pgrp
)
1078 pgsignal(sp
->s_ttyp
->t_pgrp
, SIGHUP
, 1);
1080 (void) ttywait(sp
->s_ttyp
);
1082 VOP_REVOKE(sp
->s_ttyvp
, REVOKEALL
);
1091 sunstatfs(struct statvfs
*sp
, void *sbuf
)
1093 struct sunos_statfs ssfs
;
1095 memset(&ssfs
, 0, sizeof ssfs
);
1097 ssfs
.f_bsize
= sp
->f_bsize
;
1098 ssfs
.f_blocks
= sp
->f_blocks
;
1099 ssfs
.f_bfree
= sp
->f_bfree
;
1100 ssfs
.f_bavail
= sp
->f_bavail
;
1101 ssfs
.f_files
= sp
->f_files
;
1102 ssfs
.f_ffree
= sp
->f_ffree
;
1103 ssfs
.f_fsid
= sp
->f_fsidx
;
1104 return copyout((void *)&ssfs
, sbuf
, sizeof ssfs
);
1108 sunos32_sys_statfs(struct lwp
*l
, const struct sunos32_sys_statfs_args
*uap
, register_t
*retval
)
1111 syscallarg(const netbsd32_charp) path;
1112 syscallarg(sunos32_statfsp_t) buf;
1118 struct sys_statvfs1_args ua
;
1120 SUNOS32TOP_UAP(path
, const char);
1122 error
= namei_simple_user(SCARG(&ua
, path
),
1123 NSM_FOLLOW_TRYEMULROOT
, &vp
);
1129 if ((error
= VFS_STATVFS(mp
, sp
)) != 0)
1131 sp
->f_flag
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
1132 return sunstatfs(sp
, SCARG_P32(uap
, buf
));
1136 sunos32_sys_fstatfs(struct lwp
*l
, const struct sunos32_sys_fstatfs_args
*uap
, register_t
*retval
)
1140 syscallarg(sunos32_statfsp_t) buf;
1147 /* fd_getvnode() will use the descriptor for us */
1148 if ((error
= fd_getvnode(SCARG(uap
, fd
), &fp
)) != 0)
1150 mp
= ((struct vnode
*)fp
->f_data
)->v_mount
;
1152 if ((error
= VFS_STATVFS(mp
, sp
)) != 0)
1154 sp
->f_flag
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
1155 error
= sunstatfs(sp
, SCARG_P32(uap
, buf
));
1157 fd_putfile(SCARG(uap
, fd
));
1162 sunos32_sys_exportfs(struct lwp
*l
, const struct sunos32_sys_exportfs_args
*uap
, register_t
*retval
)
1165 * XXX: should perhaps translate into a mount(2)
1166 * with MOUNT_EXPORT?
1172 sunos32_sys_mknod(struct lwp
*l
, const struct sunos32_sys_mknod_args
*uap
, register_t
*retval
)
1175 syscallarg(const netbsd32_charp) path;
1176 syscallarg(int) mode;
1177 syscallarg(int) dev;
1180 if (S_ISFIFO(SCARG(uap
, mode
)))
1181 return netbsd32_mkfifo(l
, (const struct netbsd32_mkfifo_args
*)uap
, retval
);
1183 return compat_50_netbsd32_mknod(l
, (const struct compat_50_netbsd32_mknod_args
*)uap
, retval
);
1186 #define SUNOS_SC_ARG_MAX 1
1187 #define SUNOS_SC_CHILD_MAX 2
1188 #define SUNOS_SC_CLK_TCK 3
1189 #define SUNOS_SC_NGROUPS_MAX 4
1190 #define SUNOS_SC_OPEN_MAX 5
1191 #define SUNOS_SC_JOB_CONTROL 6
1192 #define SUNOS_SC_SAVED_IDS 7
1193 #define SUNOS_SC_VERSION 8
1196 sunos32_sys_sysconf(struct lwp
*l
, const struct sunos32_sys_sysconf_args
*uap
, register_t
*retval
)
1199 syscallarg(int) name;
1201 extern u_int maxfiles
;
1203 switch(SCARG(uap
, name
)) {
1204 case SUNOS_SC_ARG_MAX
:
1207 case SUNOS_SC_CHILD_MAX
:
1210 case SUNOS_SC_CLK_TCK
:
1211 *retval
= 60; /* should this be `hz', ie. 100? */
1213 case SUNOS_SC_NGROUPS_MAX
:
1214 *retval
= NGROUPS_MAX
;
1216 case SUNOS_SC_OPEN_MAX
:
1219 case SUNOS_SC_JOB_CONTROL
:
1222 case SUNOS_SC_SAVED_IDS
:
1223 #ifdef _POSIX_SAVED_IDS
1229 case SUNOS_SC_VERSION
:
1238 #define SUNOS_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */
1239 #define SUNOS_RLIM_NLIMITS 7
1242 sunos32_sys_getrlimit(struct lwp
*l
, const struct sunos32_sys_getrlimit_args
*uap
, register_t
*retval
)
1245 syscallarg(u_int) which;
1246 syscallarg(netbsd32_orlimitp_t) rlp;
1248 struct compat_43_netbsd32_ogetrlimit_args ua_43
;
1250 if (SCARG(uap
, which
) >= SUNOS_RLIM_NLIMITS
)
1253 SCARG(&ua_43
, which
) = SCARG(uap
, which
) == SUNOS_RLIMIT_NOFILE
? RLIMIT_NOFILE
: SCARG(uap
, which
);
1254 SCARG(&ua_43
, rlp
) = SCARG(uap
, rlp
);
1256 return compat_43_netbsd32_ogetrlimit(l
, &ua_43
, retval
);
1260 sunos32_sys_setrlimit(struct lwp
*l
, const struct sunos32_sys_setrlimit_args
*uap
, register_t
*retval
)
1263 syscallarg(u_int) which;
1264 syscallarg(netbsd32_orlimitp_t) rlp;
1266 struct compat_43_netbsd32_osetrlimit_args ua_43
;
1268 if (SCARG(uap
, which
) >= SUNOS_RLIM_NLIMITS
)
1271 SCARG(&ua_43
, which
) = SCARG(uap
, which
) == SUNOS_RLIMIT_NOFILE
? RLIMIT_NOFILE
: SCARG(uap
, which
);
1272 SCARG(&ua_43
, rlp
) = SCARG(uap
, rlp
);
1274 return compat_43_netbsd32_osetrlimit(l
, &ua_43
, retval
);
1277 /* for the m68k machines */
1278 #ifndef PT_GETFPREGS
1279 #define PT_GETFPREGS -1
1281 #ifndef PT_SETFPREGS
1282 #define PT_SETFPREGS -1
1285 static const int sreq2breq
[] = {
1286 PT_TRACE_ME
, PT_READ_I
, PT_READ_D
, -1,
1287 PT_WRITE_I
, PT_WRITE_D
, -1, PT_CONTINUE
,
1288 PT_KILL
, -1, PT_ATTACH
, PT_DETACH
,
1289 PT_GETREGS
, PT_SETREGS
, PT_GETFPREGS
, PT_SETFPREGS
1291 static const int nreqs
= sizeof(sreq2breq
) / sizeof(sreq2breq
[0]);
1294 sunos32_sys_ptrace(struct lwp
*l
, const struct sunos32_sys_ptrace_args
*uap
, register_t
*retval
)
1297 syscallarg(int) req;
1298 syscallarg(pid_t) pid;
1299 syscallarg(netbsd32_caddr_t) addr;
1300 syscallarg(int) data;
1301 syscallarg(netbsd32_charp) addr2;
1303 struct netbsd32_ptrace_args pa
;
1306 #define sys_ptrace sysent[SYS_ptrace].sy_call
1307 if (sys_ptrace
== sys_nosys
)
1310 req
= SCARG(uap
, req
);
1311 if ((unsigned int)req
>= nreqs
)
1314 req
= sreq2breq
[req
];
1318 SCARG(&pa
, req
) = req
;
1319 SCARG(&pa
, pid
) = (pid_t
)SCARG(uap
, pid
);
1320 SCARG(&pa
, addr
) = SCARG(uap
, addr
);
1321 SCARG(&pa
, data
) = SCARG(uap
, data
);
1323 return netbsd32_ptrace(l
, &pa
, retval
);
1327 * SunOS reboot system call (for compatibility).
1328 * Sun lets you pass in a boot string which the PROM
1329 * saves and provides to the next boot program.
1332 #define SUNOS_RB_ASKNAME 0x001
1333 #define SUNOS_RB_SINGLE 0x002
1334 #define SUNOS_RB_NOSYNC 0x004
1335 #define SUNOS_RB_HALT 0x008
1336 #define SUNOS_RB_DUMP 0x080
1337 #define SUNOS_RB_STRING 0x200
1339 static struct sunos_howto_conv
{
1342 } sunos_howto_conv
[] = {
1343 { SUNOS_RB_ASKNAME
, RB_ASKNAME
},
1344 { SUNOS_RB_SINGLE
, RB_SINGLE
},
1345 { SUNOS_RB_NOSYNC
, RB_NOSYNC
},
1346 { SUNOS_RB_HALT
, RB_HALT
},
1347 { SUNOS_RB_DUMP
, RB_DUMP
},
1348 { SUNOS_RB_STRING
, RB_STRING
},
1353 sunos32_sys_reboot(struct lwp
*l
, const struct sunos32_sys_reboot_args
*uap
, register_t
*retval
)
1356 syscallarg(int) howto;
1357 syscallarg(netbsd32_charp) bootstr;
1359 struct sys_reboot_args ua
;
1360 struct sunos_howto_conv
*convp
;
1361 int error
, bsd_howto
, sun_howto
;
1364 if ((error
= kauth_authorize_system(l
->l_cred
,
1365 KAUTH_SYSTEM_REBOOT
, 0, NULL
, NULL
, NULL
)) != 0)
1369 * Convert howto bits to BSD format.
1371 sun_howto
= SCARG(uap
, howto
);
1373 convp
= sunos_howto_conv
;
1374 while (convp
->sun_howto
) {
1375 if (sun_howto
& convp
->sun_howto
)
1376 bsd_howto
|= convp
->bsd_howto
;
1381 * Sun RB_STRING (Get user supplied bootstring.)
1382 * If the machine supports passing a string to the
1383 * next booted kernel.
1385 if (sun_howto
& SUNOS_RB_STRING
)
1386 bootstr
= SCARG_P32(uap
, bootstr
);
1390 SCARG(&ua
, opt
) = bsd_howto
;
1391 SCARG(&ua
, bootstr
) = bootstr
;
1392 return (sys_reboot(l
, &ua
, retval
));
1396 * Generalized interface signal handler, 4.3-compatible.
1400 sunos32_sys_sigvec(struct lwp
*l
, const struct sunos32_sys_sigvec_args
*uap
, register_t
*retval
)
1403 syscallarg(int) signum;
1404 syscallarg(struct sigvec *) nsv;
1405 syscallarg(struct sigvec *) osv;
1407 struct netbsd32_sigvec sv
;
1408 struct sigaction nsa
, osa
;
1411 if (SCARG_P32(uap
, nsv
)) {
1412 error
= copyin(SCARG_P32(uap
, nsv
), &sv
, sizeof(sv
));
1417 * SunOS uses the mask 0x0004 as SV_RESETHAND
1418 * meaning: `reset to SIG_DFL on delivery'.
1419 * We support only the bits in: 0xF
1420 * (those bits are the same as ours)
1422 if (sv
.sv_flags
& ~0xF)
1425 sunos32_sigvec_to_sigaction(&sv
, &nsa
);
1427 error
= sigaction1(l
, SCARG(uap
, signum
),
1428 SCARG_P32(uap
, nsv
) ? &nsa
: 0,
1429 SCARG_P32(uap
, osv
) ? &osa
: 0,
1434 if (SCARG_P32(uap
, osv
)) {
1435 sunos32_sigvec_from_sigaction(&sv
, &osa
);
1436 error
= copyout(&sv
, SCARG_P32(uap
, osv
), sizeof(sv
));