1/* $NetBSD: netbsd32_compat_30.c,v 1.31 2014/12/05 17:26:21 maxv Exp $ */
2
3/*
4 * Copyright (c) 1998, 2001 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_30.c,v 1.31 2014/12/05 17:26:21 maxv Exp $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/mount.h>
35#include <sys/socket.h>
36#include <sys/socketvar.h>
37#include <sys/stat.h>
38#include <sys/time.h>
39#include <sys/ktrace.h>
40#include <sys/resourcevar.h>
41#include <sys/vnode.h>
42#include <sys/file.h>
43#include <sys/filedesc.h>
44#include <sys/namei.h>
45#include <sys/statvfs.h>
46#include <sys/syscallargs.h>
47#include <sys/proc.h>
48#include <sys/dirent.h>
49#include <sys/kauth.h>
50#include <sys/vfs_syscalls.h>
51
52#include <compat/netbsd32/netbsd32.h>
53#include <compat/netbsd32/netbsd32_syscallargs.h>
54#include <compat/netbsd32/netbsd32_conv.h>
55#include <compat/sys/mount.h>
56
57
58int
59compat_30_netbsd32_getdents(struct lwp *l, const struct compat_30_netbsd32_getdents_args *uap, register_t *retval)
60{
61 /* {
62 syscallarg(int) fd;
63 syscallarg(netbsd32_charp) buf;
64 syscallarg(netbsd32_size_t) count;
65 } */
66 file_t *fp;
67 int error, done;
68 char *buf;
69 netbsd32_size_t count;
70
71 /* Limit the size on any kernel buffers used by VOP_READDIR */
72 count = min(MAXBSIZE, SCARG(uap, count));
73
74 /* fd_getvnode() will use the descriptor for us */
75 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
76 return (error);
77 if ((fp->f_flag & FREAD) == 0) {
78 error = EBADF;
79 goto out;
80 }
81 if (count == 0)
82 goto out;
83
84 buf = kmem_alloc(count, KM_SLEEP);
85 error = vn_readdir(fp, buf, UIO_SYSSPACE, count, &done, l, 0, 0);
86 if (error == 0) {
87 *retval = netbsd32_to_dirent12(buf, done);
88 error = copyout(buf, SCARG_P32(uap, buf), *retval);
89 }
90 kmem_free(buf, count);
91 out:
92 fd_putfile(SCARG(uap, fd));
93 return (error);
94}
95
96int
97compat_30_netbsd32___stat13(struct lwp *l, const struct compat_30_netbsd32___stat13_args *uap, register_t *retval)
98{
99 /* {
100 syscallarg(const netbsd32_charp) path;
101 syscallarg(netbsd32_stat13p_t) ub;
102 } */
103 struct netbsd32_stat13 sb32;
104 struct stat sb;
105 int error;
106 const char *path;
107
108 path = SCARG_P32(uap, path);
109
110 error = do_sys_stat(path, FOLLOW, &sb);
111 if (error)
112 return (error);
113 netbsd32_from___stat13(&sb, &sb32);
114 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
115 return (error);
116}
117
118int
119compat_30_netbsd32___fstat13(struct lwp *l, const struct compat_30_netbsd32___fstat13_args *uap, register_t *retval)
120{
121 /* {
122 syscallarg(int) fd;
123 syscallarg(netbsd32_stat13p_t) sb;
124 } */
125 struct netbsd32_stat13 sb32;
126 struct stat ub;
127 int error;
128
129 error = do_sys_fstat(SCARG(uap, fd), &ub);
130 if (error == 0) {
131 netbsd32_from___stat13(&ub, &sb32);
132 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
133 }
134 return (error);
135}
136
137int
138compat_30_netbsd32___lstat13(struct lwp *l, const struct compat_30_netbsd32___lstat13_args *uap, register_t *retval)
139{
140 /* {
141 syscallarg(const netbsd32_charp) path;
142 syscallarg(netbsd32_stat13p_t) ub;
143 } */
144 struct netbsd32_stat13 sb32;
145 struct stat sb;
146 int error;
147 const char *path;
148
149 path = SCARG_P32(uap, path);
150
151 error = do_sys_stat(path, NOFOLLOW, &sb);
152 if (error)
153 return (error);
154 netbsd32_from___stat13(&sb, &sb32);
155 error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
156 return (error);
157}
158
159int
160compat_30_netbsd32_fhstat(struct lwp *l, const struct compat_30_netbsd32_fhstat_args *uap, register_t *retval)
161{
162 /* {
163 syscallarg(const netbsd32_fhandlep_t) fhp;
164 syscallarg(netbsd32_stat13p_t) sb;
165 } */
166 struct stat sb;
167 struct netbsd32_stat13 sb32;
168 int error;
169 struct compat_30_fhandle fh;
170 struct mount *mp;
171 struct vnode *vp;
172
173 /*
174 * Must be super user
175 */
176 if ((error = kauth_authorize_system(l->l_cred,
177 KAUTH_SYSTEM_FILEHANDLE, 0, NULL, NULL, NULL)))
178 return (error);
179
180 if ((error = copyin(SCARG_P32(uap, fhp), &fh, sizeof(fh))) != 0)
181 return (error);
182
183 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
184 return (ESTALE);
185 if (mp->mnt_op->vfs_fhtovp == NULL)
186 return EOPNOTSUPP;
187 if ((error = VFS_FHTOVP(mp, (struct fid*)&fh.fh_fid, &vp)))
188 return (error);
189 error = vn_stat(vp, &sb);
190 vput(vp);
191 if (error)
192 return (error);
193 netbsd32_from___stat13(&sb, &sb32);
194 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
195 return (error);
196}
197
198int
199compat_30_netbsd32_fhstatvfs1(struct lwp *l, const struct compat_30_netbsd32_fhstatvfs1_args *uap, register_t *retval)
200{
201 /* {
202 syscallarg(const netbsd32_fhandlep_t) fhp;
203 syscallarg(netbsd32_statvfsp_t) buf;
204 syscallarg(int) flags;
205 } */
206 struct statvfs *sbuf;
207 struct netbsd32_statvfs *s32;
208 int error;
209
210 sbuf = STATVFSBUF_GET();
211 error = do_fhstatvfs(l, SCARG_P32(uap, fhp), FHANDLE_SIZE_COMPAT, sbuf,
212 SCARG(uap, flags));
213
214 if (error != 0) {
215 s32 = kmem_alloc(sizeof(*s32), KM_SLEEP);
216 netbsd32_from_statvfs(sbuf, s32);
217 error = copyout(s32, SCARG_P32(uap, buf), sizeof *s32);
218 kmem_free(s32, sizeof(*s32));
219 }
220 STATVFSBUF_PUT(sbuf);
221
222 return (error);
223}
224
225int
226compat_30_netbsd32_socket(struct lwp *l, const struct compat_30_netbsd32_socket_args *uap, register_t *retval)
227{
228 /* {
229 syscallarg(int) domain;
230 syscallarg(int) type;
231 syscallarg(int) protocol;
232 } */
233 struct compat_30_sys_socket_args ua;
234
235 NETBSD32TO64_UAP(domain);
236 NETBSD32TO64_UAP(type);
237 NETBSD32TO64_UAP(protocol);
238 return (compat_30_sys_socket(l, &ua, retval));
239}
240
241int
242compat_30_netbsd32_getfh(struct lwp *l, const struct compat_30_netbsd32_getfh_args *uap, register_t *retval)
243{
244 /* {
245 syscallarg(const netbsd32_charp) fname;
246 syscallarg(netbsd32_compat_30_fhandlep_t) fhp;
247 } */
248 struct compat_30_sys_getfh_args ua;
249
250 NETBSD32TOP_UAP(fname, const char);
251 NETBSD32TOP_UAP(fhp, struct compat_30_fhandle);
252 /* Lucky for us a fhandle_t doesn't change sizes */
253 return (compat_30_sys_getfh(l, &ua, retval));
254}
255
256
257int
258compat_30_netbsd32___fhstat30(struct lwp *l, const struct compat_30_netbsd32___fhstat30_args *uap, register_t *retval)
259{
260 /* {
261 syscallarg(const netbsd32_fhandlep_t) fhp;
262 syscallarg(netbsd32_statp_t) sb;
263 } */
264 struct stat sb;
265 struct netbsd32_stat50 sb32;
266 int error;
267
268 error = do_fhstat(l, SCARG_P32(uap, fhp), FHANDLE_SIZE_COMPAT, &sb);
269 if (error)
270 return error;
271
272 netbsd32_from___stat50(&sb, &sb32);
273 error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
274 return error;
275}
276
277/*
278 * Open a file given a file handle.
279 *
280 * Check permissions, allocate an open file structure,
281 * and call the device open routine if any.
282 */
283int
284compat_30_netbsd32_fhopen(struct lwp *l, const struct compat_30_netbsd32_fhopen_args *uap, register_t *retval)
285{
286 /* {
287 syscallarg(const fhandle_t *) fhp;
288 syscallarg(int) flags;
289 } */
290 struct compat_30_sys_fhopen_args ua;
291
292 NETBSD32TOP_UAP(fhp, struct compat_30_fhandle);
293 NETBSD32TO64_UAP(flags);
294 return (compat_30_sys_fhopen(l, &ua, retval));
295}
296