1 /* $NetBSD: irix_fcntl.c,v 1.25 2008/04/28 20:23:41 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2001-2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: irix_fcntl.c,v 1.25 2008/04/28 20:23:41 martin Exp $");
34
35 #include <sys/types.h>
36 #include <sys/signal.h>
37 #include <sys/param.h>
38 #include <sys/mount.h>
39 #include <sys/proc.h>
40 #include <sys/conf.h>
41 #include <sys/malloc.h>
42 #include <sys/vnode.h>
43 #include <sys/file.h>
44 #include <sys/filedesc.h>
45 #include <sys/systm.h>
46 #include <sys/fcntl.h>
47 #include <sys/syscallargs.h>
48
49 #include <miscfs/specfs/specdev.h>
50
51 #include <compat/irix/irix_types.h>
52 #include <compat/irix/irix_signal.h>
53 #include <compat/irix/irix_fcntl.h>
54 #include <compat/irix/irix_usema.h>
55 #include <compat/irix/irix_syscallargs.h>
56
57 #include <compat/svr4/svr4_types.h>
58 #include <compat/svr4/svr4_signal.h>
59 #include <compat/svr4/svr4_ucontext.h>
60 #include <compat/svr4/svr4_lwp.h>
61 #include <compat/svr4/svr4_fcntl.h>
62 #include <compat/svr4/svr4_syscallargs.h>
63
64 static int fd_truncate(struct lwp *, int, int, off_t, register_t *);
65 static int bsd_to_irix_fcntl_flags(int);
66 static int irix_to_bsd_fcntl_flags(int);
67
68 int
69 irix_sys_lseek64(struct lwp *l, const struct irix_sys_lseek64_args *uap, register_t *retval)
70 {
71 /*
72 * Note: we have an alignement problem here. If pad2, pad3 and pad4
73 * are removed, lseek64 will break, because whence will be wrong.
74 */
75 /* {
76 syscallarg(int) fd;
77 syscallarg(int) pad1;
78 syscallarg(irix_off64_t) offset;
79 syscallarg(int) whence;
80 syscallarg(int) pad2;
81 syscallarg(int) pad3;
82 syscallarg(int) pad4;
83 } */
84
85 struct sys_lseek_args cup;
86
87 #ifdef DEBUG_IRIX
88 printf("irix_sys_lseek64(): fd = %d, pad1 = 0x%08x, offset = 0x%llx\n",
89 SCARG(uap, fd), SCARG(uap, pad1), SCARG(uap, offset));
90 printf("whence = 0x%08x, pad2 = 0x%08x, pad3 = 0x%08x, pad4 = 0x%08x\n",
91 SCARG(uap, whence), SCARG(uap, pad2), SCARG(uap, pad3),
92 SCARG(uap, pad4));
93 #endif
94 SCARG(&cup, fd) = SCARG(uap, fd);
95 SCARG(&cup, pad) = 0;
96 SCARG(&cup, offset) = SCARG(uap, offset);
97 SCARG(&cup, whence) = SCARG(uap, whence);
98
99 return sys_lseek(l, (void *)&cup, retval);
100 }
101
102 int
103 irix_sys_fcntl(struct lwp *l, const struct irix_sys_fcntl_args *uap, register_t *retval)
104 {
105 /* {
106 syscallarg(int) fd;
107 syscallarg(int) cmd;
108 syscallarg(char *)arg;
109 } */
110 struct svr4_sys_fcntl_args cup;
111 struct sys_fcntl_args bsd_ua;
112 int cmd;
113 int error;
114
115 cmd = SCARG(uap, cmd);
116 switch (cmd) {
117 case SVR4_F_FREESP:
118 case SVR4_F_ALLOCSP: {
119 struct svr4_flock fl;
120
121 if ((error = copyin(SCARG(uap, arg), &fl, sizeof(fl))) != 0)
122 return error;
123
124 return fd_truncate(l, SCARG(uap, fd),
125 fl.l_whence, fl.l_start, retval);
126 break;
127 }
128
129 case SVR4_F_FREESP64:
130 case IRIX_F_ALLOCSP64: {
131 struct svr4_flock64 fl;
132
133 if ((error = copyin(SCARG(uap, arg), &fl, sizeof(fl))) != 0)
134 return error;
135
136 return fd_truncate(l, SCARG(uap, fd),
137 fl.l_whence, fl.l_start, retval);
138 break;
139 }
140
141 case IRIX_F_SETBSDLKW:
142 cmd = SVR4_F_SETLKW;
143 break;
144
145 case IRIX_F_SETBSDLK:
146 cmd = SVR4_F_SETLK;
147 break;
148
149 case IRIX_F_GETFL:
150 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
151 SCARG(&bsd_ua, cmd) = F_GETFL;
152 SCARG(&bsd_ua, arg) = SCARG(uap, arg);
153 if ((error = sys_fcntl(l, &bsd_ua, retval)) != 0)
154 return error;
155 *retval = bsd_to_irix_fcntl_flags(*retval);
156 return 0;
157 break;
158
159 case IRIX_F_SETFL:
160 /*
161 * All unsupported flags are silently ignored
162 * except FDIRECT taht will return EINVAL
163 */
164 if ((int)SCARG(uap, arg) & IRIX_FDIRECT)
165 return EINVAL;
166
167 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
168 SCARG(&bsd_ua, arg) =
169 (char *)irix_to_bsd_fcntl_flags((int)SCARG(uap, arg));
170 SCARG(&bsd_ua, cmd) = F_SETFL;
171 return sys_fcntl(l, &bsd_ua, retval);
172 break;
173
174 case SVR4_F_DUPFD:
175 case SVR4_F_GETFD:
176 case SVR4_F_SETFD:
177 case SVR4_F_SETLK:
178 case SVR4_F_SETLKW:
179 case SVR4_F_CHKFL:
180 case SVR4_F_GETLK:
181 case SVR4_F_RSETLK:
182 case SVR4_F_RGETLK:
183 case SVR4_F_RSETLKW:
184 case SVR4_F_GETOWN:
185 case SVR4_F_SETOWN:
186 case SVR4_F_GETLK64:
187 case SVR4_F_SETLK64:
188 case SVR4_F_SETLKW64:
189 break;
190
191 case IRIX_F_CHKLK:
192 case IRIX_F_CHKLKW:
193 case IRIX_F_CLNLK:
194 case IRIX_F_DIOINFO:
195 case IRIX_F_FSGETXATTR:
196 case IRIX_F_FSSETXATTR:
197 case IRIX_F_GETBMAP:
198 case IRIX_F_FSSETDM:
199 case IRIX_F_RESVSP:
200 case IRIX_F_UNRESVSP:
201 case IRIX_F_RESVSP64:
202 case IRIX_F_UNRESVSP64:
203 case IRIX_F_GETBMAPA:
204 case IRIX_F_FSGETXATTRA:
205 case IRIX_F_SETBIOSIZE:
206 case IRIX_F_GETBIOSIZE:
207 case IRIX_F_GETOPS:
208 case IRIX_F_DMAPI:
209 case IRIX_F_FSYNC:
210 case IRIX_F_FSYNC64:
211 case IRIX_F_GETBDSATTR:
212 case IRIX_F_SETBDSATTR:
213 case IRIX_F_GETBMAPX:
214 case IRIX_F_SETPRIO:
215 case IRIX_F_GETPRIO:
216 default:
217 printf("Warning: unimplemented IRIX fcntl() command %d\n",
218 cmd);
219 return EINVAL;
220 break;
221 }
222
223 SCARG(&cup, fd) = SCARG(uap, fd);
224 SCARG(&cup, cmd) = cmd;
225 SCARG(&cup, arg) = SCARG(uap, arg);
226 return svr4_sys_fcntl(l, &cup, retval);
227 }
228
229 static int
230 fd_truncate(struct lwp *l, int fd, int whence, off_t start, register_t *retval)
231 {
232 file_t *fp;
233 struct vnode *vp;
234 struct vattr vattr;
235 struct sys_ftruncate_args ft;
236 int error;
237
238 if ((error = fd_getvnode(fd, &fp)) != 0)
239 return EBADF;
240
241 vp = fp->f_data;
242 if (vp->v_type == VFIFO) {
243 fd_putfile(fd);
244 return ESPIPE;
245 }
246
247 switch (whence) {
248 case SEEK_CUR:
249 SCARG(&ft, length) = fp->f_offset + start;
250 break;
251
252 case SEEK_END:
253 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0)
254 return error;
255 SCARG(&ft, length) = vattr.va_size + start;
256 break;
257
258 case SEEK_SET:
259 SCARG(&ft, length) = start;
260 break;
261
262 default:
263 return EINVAL;
264 break;
265 }
266 fd_putfile(fd);
267
268 SCARG(&ft, fd) = fd;
269 return sys_ftruncate(l, &ft, retval);
270 }
271
272 int
273 irix_sys_open(struct lwp *l, const struct irix_sys_open_args *uap, register_t *retval)
274 {
275 /* {
276 syscallarg(char *) path;
277 syscallarg(int) flags;
278 syscallarg(mode_t) mode;
279 } */
280 extern const struct cdevsw irix_usema_cdevsw;
281 int error;
282 int fd;
283 file_t *fp;
284 struct vnode *vp;
285 struct vnode *nvp;
286
287 if ((error = svr4_sys_open(l, (const void *)uap, retval)) != 0)
288 return error;
289
290 fd = (int)*retval;
291 if ((fp = fd_getfile(fd)) == NULL)
292 return EBADF;
293
294 vp = fp->f_data;
295
296 /*
297 * A special hook for the usemaclone driver: we need to clone
298 * the vnode, because the driver method need a context for each
299 * usemaclone open instance, and because we need to overload
300 * some vnode operations like setattr.
301 * The original vnode is stored in the v_data field of the cloned
302 * vnode.
303 */
304 if (vp->v_type == VCHR &&
305 cdevsw_lookup(vp->v_rdev) == &irix_usema_cdevsw &&
306 minor(vp->v_rdev) == IRIX_USEMACLNDEV_MINOR) {
307 if ((error = getnewvnode(VCHR, vp->v_mount,
308 irix_usema_vnodeop_p,
309 (struct vnode **)&fp->f_data)) != 0) {
310 (void) vn_close(vp, fp->f_flag, fp->f_cred);
311 fd_close(fd);
312 return error;
313 }
314
315 nvp = (struct vnode *)fp->f_data;
316
317 if (SCARG(uap, flags) & O_RDWR || SCARG(uap, flags) & O_WRONLY)
318 nvp->v_writecount++;
319
320 nvp->v_type = VCHR;
321 nvp->v_rdev = vp->v_rdev;
322 nvp->v_specmountpoint = vp->v_specmountpoint;
323
324 nvp->v_data = (void *)vp;
325 vref(vp);
326 }
327 fd_putfile(fd);
328
329 return 0;
330 }
331
332 static int
333 irix_to_bsd_fcntl_flags(int flags)
334 {
335 int ret = 0;
336
337 if (flags & IRIX_FNDELAY) ret |= FNDELAY;
338 if (flags & IRIX_FAPPEND) ret |= FAPPEND;
339 if (flags & IRIX_FSYNC) ret |= FFSYNC;
340 if (flags & IRIX_FDSYNC) ret |= FDSYNC;
341 if (flags & IRIX_FASYNC) ret |= FASYNC;
342 if (flags & IRIX_FRSYNC) ret |= FRSYNC;
343 if (flags & IRIX_FNONBLOCK) ret |= FNONBLOCK;
344 if (flags & IRIX_FLARGEFILE)
345 printf("Warning: ignored fcntl IRIX_FLARGEFILE flag");
346 if (flags & IRIX_FDIRECT)
347 printf("Warning: ignored fcntl IRIX_FDIRECT flag");
348 if (flags & IRIX_FBULK)
349 printf("Warning: ignored fcntl IRIX_FBULK flag");
350 if (flags & IRIX_FLCINVAL)
351 printf("Warning: ignored fcntl IRIX_FLCINVAL flag");
352 if (flags & IRIX_FLCFLUSH)
353 printf("Warning: ignored fcntl IRIX_FLCFLUSH flag");
354
355 return ret;
356 }
357
358 static int
359 bsd_to_irix_fcntl_flags(int flags)
360 {
361 int ret = 0;
362
363 if (flags & FNDELAY) ret |= IRIX_FNDELAY;
364 if (flags & FAPPEND) ret |= IRIX_FAPPEND;
365 if (flags & FFSYNC) ret |= IRIX_FSYNC;
366 if (flags & FDSYNC) ret |= IRIX_FDSYNC;
367 if (flags & FRSYNC) ret |= IRIX_FRSYNC;
368 if (flags & FNONBLOCK) ret |= IRIX_FNONBLOCK;
369 if (flags & FASYNC) ret |= IRIX_FASYNC;
370
371 return ret;
372 }
Cache object: 3e56aae3bfcbd411c245c788fde07e9d
|