1 /* $NetBSD: ibcs2_fcntl.c,v 1.35 2010/11/19 06:44:36 dholland Exp $ */
2
3 /*
4 * Copyright (c) 1995 Scott Bartram
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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: ibcs2_fcntl.c,v 1.35 2010/11/19 06:44:36 dholland Exp $");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/namei.h>
36 #include <sys/proc.h>
37 #include <sys/file.h>
38 #include <sys/stat.h>
39 #include <sys/filedesc.h>
40 #include <sys/ioctl.h>
41 #include <sys/kernel.h>
42 #include <sys/mount.h>
43 #include <sys/syscallargs.h>
44 #include <sys/vnode.h>
45 #include <sys/kauth.h>
46
47 #include <compat/ibcs2/ibcs2_types.h>
48 #include <compat/ibcs2/ibcs2_fcntl.h>
49 #include <compat/ibcs2/ibcs2_unistd.h>
50 #include <compat/ibcs2/ibcs2_signal.h>
51 #include <compat/ibcs2/ibcs2_syscallargs.h>
52 #include <compat/ibcs2/ibcs2_util.h>
53
54 static int cvt_o_flags(int);
55 static void cvt_flock2iflock(struct flock *, struct ibcs2_flock *);
56 static void cvt_iflock2flock(struct ibcs2_flock *, struct flock *);
57 static int ioflags2oflags(int);
58 static int oflags2ioflags(int);
59
60 static int
cvt_o_flags(int flags)61 cvt_o_flags(int flags)
62 {
63 int r = 0;
64
65 /* convert mode into NetBSD mode */
66 if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
67 if (flags & IBCS2_O_RDWR) r |= O_RDWR;
68 if (flags & (IBCS2_O_NDELAY | IBCS2_O_NONBLOCK)) r |= O_NONBLOCK;
69 if (flags & IBCS2_O_APPEND) r |= O_APPEND;
70 if (flags & IBCS2_O_SYNC) r |= O_FSYNC;
71 if (flags & IBCS2_O_CREAT) r |= O_CREAT;
72 if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
73 if (flags & IBCS2_O_EXCL) r |= O_EXCL;
74 return r;
75 }
76
77 static void
cvt_flock2iflock(struct flock * flp,struct ibcs2_flock * iflp)78 cvt_flock2iflock(struct flock *flp, struct ibcs2_flock *iflp)
79 {
80 switch (flp->l_type) {
81 case F_RDLCK:
82 iflp->l_type = IBCS2_F_RDLCK;
83 break;
84 case F_WRLCK:
85 iflp->l_type = IBCS2_F_WRLCK;
86 break;
87 case F_UNLCK:
88 iflp->l_type = IBCS2_F_UNLCK;
89 break;
90 }
91 iflp->l_whence = (short)flp->l_whence;
92 iflp->l_start = (ibcs2_off_t)flp->l_start;
93 iflp->l_len = (ibcs2_off_t)flp->l_len;
94 iflp->l_sysid = 0;
95 iflp->l_pid = (ibcs2_pid_t)flp->l_pid;
96 }
97
98 static void
cvt_iflock2flock(struct ibcs2_flock * iflp,struct flock * flp)99 cvt_iflock2flock(struct ibcs2_flock *iflp, struct flock *flp)
100 {
101 flp->l_start = (off_t)iflp->l_start;
102 flp->l_len = (off_t)iflp->l_len;
103 flp->l_pid = (pid_t)iflp->l_pid;
104 switch (iflp->l_type) {
105 case IBCS2_F_RDLCK:
106 flp->l_type = F_RDLCK;
107 break;
108 case IBCS2_F_WRLCK:
109 flp->l_type = F_WRLCK;
110 break;
111 case IBCS2_F_UNLCK:
112 flp->l_type = F_UNLCK;
113 break;
114 }
115 flp->l_whence = iflp->l_whence;
116 }
117
118 /* convert iBCS2 mode into NetBSD mode */
119 static int
ioflags2oflags(int flags)120 ioflags2oflags(int flags)
121 {
122 int r = 0;
123
124 if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
125 if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
126 if (flags & IBCS2_O_RDWR) r |= O_RDWR;
127 if (flags & IBCS2_O_NDELAY) r |= O_NONBLOCK;
128 if (flags & IBCS2_O_APPEND) r |= O_APPEND;
129 if (flags & IBCS2_O_SYNC) r |= O_FSYNC;
130 if (flags & IBCS2_O_NONBLOCK) r |= O_NONBLOCK;
131 if (flags & IBCS2_O_CREAT) r |= O_CREAT;
132 if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
133 if (flags & IBCS2_O_EXCL) r |= O_EXCL;
134 if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
135 return r;
136 }
137
138 /* convert NetBSD mode into iBCS2 mode */
139 static int
oflags2ioflags(int flags)140 oflags2ioflags(int flags)
141 {
142 int r = 0;
143
144 if (flags & O_RDONLY) r |= IBCS2_O_RDONLY;
145 if (flags & O_WRONLY) r |= IBCS2_O_WRONLY;
146 if (flags & O_RDWR) r |= IBCS2_O_RDWR;
147 if (flags & O_NDELAY) r |= IBCS2_O_NONBLOCK;
148 if (flags & O_APPEND) r |= IBCS2_O_APPEND;
149 if (flags & O_FSYNC) r |= IBCS2_O_SYNC;
150 if (flags & O_NONBLOCK) r |= IBCS2_O_NONBLOCK;
151 if (flags & O_CREAT) r |= IBCS2_O_CREAT;
152 if (flags & O_TRUNC) r |= IBCS2_O_TRUNC;
153 if (flags & O_EXCL) r |= IBCS2_O_EXCL;
154 if (flags & O_NOCTTY) r |= IBCS2_O_NOCTTY;
155 return r;
156 }
157
158 int
ibcs2_sys_open(struct lwp * l,const struct ibcs2_sys_open_args * uap,register_t * retval)159 ibcs2_sys_open(struct lwp *l, const struct ibcs2_sys_open_args *uap, register_t *retval)
160 {
161 /* {
162 syscallarg(char *) path;
163 syscallarg(int) flags;
164 syscallarg(int) mode;
165 } */
166 struct proc *p = l->l_proc;
167 struct sys_open_args bsd_ua;
168 int noctty = SCARG(uap, flags) & IBCS2_O_NOCTTY;
169 int ret;
170
171 SCARG(&bsd_ua, path) = SCARG(uap, path);
172 SCARG(&bsd_ua, flags) = cvt_o_flags(SCARG(uap, flags));
173 SCARG(&bsd_ua, mode) = SCARG(uap, mode);
174 ret = sys_open(l, &bsd_ua, retval);
175
176 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) {
177 file_t *fp;
178
179 if ((fp = fd_getfile(*retval)) != NULL) {
180 /* ignore any error, just give it a try */
181 if (fp->f_type == DTYPE_VNODE)
182 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, NULL);
183 fd_putfile(*retval);
184 }
185 }
186 return ret;
187 }
188
189 int
ibcs2_sys_creat(struct lwp * l,const struct ibcs2_sys_creat_args * uap,register_t * retval)190 ibcs2_sys_creat(struct lwp *l, const struct ibcs2_sys_creat_args *uap, register_t *retval)
191 {
192 /* {
193 syscallarg(char *) path;
194 syscallarg(int) mode;
195 } */
196 struct sys_open_args cup;
197
198 SCARG(&cup, path) = SCARG(uap, path);
199 SCARG(&cup, mode) = SCARG(uap, mode);
200 SCARG(&cup, flags) = O_WRONLY | O_CREAT | O_TRUNC;
201 return sys_open(l, &cup, retval);
202 }
203
204 int
ibcs2_sys_access(struct lwp * l,const struct ibcs2_sys_access_args * uap,register_t * retval)205 ibcs2_sys_access(struct lwp *l, const struct ibcs2_sys_access_args *uap, register_t *retval)
206 {
207 /* {
208 syscallarg(char *) path;
209 syscallarg(int) flags;
210 } */
211 struct sys_access_args cup;
212
213 SCARG(&cup, path) = SCARG(uap, path);
214 SCARG(&cup, flags) = SCARG(uap, flags);
215 return sys_access(l, &cup, retval);
216 }
217
218 int
ibcs2_sys_eaccess(struct lwp * l,const struct ibcs2_sys_eaccess_args * uap,register_t * retval)219 ibcs2_sys_eaccess(struct lwp *l, const struct ibcs2_sys_eaccess_args *uap, register_t *retval)
220 {
221 /* {
222 syscallarg(char *) path;
223 syscallarg(int) flags;
224 } */
225 struct vnode *vp;
226 int error, flags;
227 struct pathbuf *pb;
228 struct nameidata nd;
229
230 error = pathbuf_copyin(SCARG(uap, path), &pb);
231 if (error != 0) {
232 return error;
233 }
234
235 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
236 if ((error = namei(&nd)) != 0) {
237 pathbuf_destroy(pb);
238 return error;
239 }
240 vp = nd.ni_vp;
241 pathbuf_destroy(pb);
242
243 /* Flags == 0 means only check for existence. */
244 if (SCARG(uap, flags)) {
245 flags = 0;
246 if (SCARG(uap, flags) & IBCS2_R_OK)
247 flags |= VREAD;
248 if (SCARG(uap, flags) & IBCS2_W_OK)
249 flags |= VWRITE;
250 if (SCARG(uap, flags) & IBCS2_X_OK)
251 flags |= VEXEC;
252 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
253 error = VOP_ACCESS(vp, flags, l->l_cred);
254 }
255 vput(vp);
256 return error;
257 }
258
259 int
ibcs2_sys_fcntl(struct lwp * l,const struct ibcs2_sys_fcntl_args * uap,register_t * retval)260 ibcs2_sys_fcntl(struct lwp *l, const struct ibcs2_sys_fcntl_args *uap, register_t *retval)
261 {
262 /* {
263 syscallarg(int) fd;
264 syscallarg(int) cmd;
265 syscallarg(char *) arg;
266 } */
267 struct sys_fcntl_args fa;
268 struct flock fl;
269 struct ibcs2_flock ifl;
270 int error;
271 int cmd;
272
273 switch(SCARG(uap, cmd)) {
274 case IBCS2_F_DUPFD:
275 SCARG(&fa, fd) = SCARG(uap, fd);
276 SCARG(&fa, cmd) = F_DUPFD;
277 SCARG(&fa, arg) = SCARG(uap, arg);
278 return sys_fcntl(l, &fa, retval);
279 case IBCS2_F_GETFD:
280 SCARG(&fa, fd) = SCARG(uap, fd);
281 SCARG(&fa, cmd) = F_GETFD;
282 SCARG(&fa, arg) = SCARG(uap, arg);
283 return sys_fcntl(l, &fa, retval);
284 case IBCS2_F_SETFD:
285 SCARG(&fa, fd) = SCARG(uap, fd);
286 SCARG(&fa, cmd) = F_SETFD;
287 SCARG(&fa, arg) = SCARG(uap, arg);
288 return sys_fcntl(l, &fa, retval);
289 case IBCS2_F_GETFL:
290 SCARG(&fa, fd) = SCARG(uap, fd);
291 SCARG(&fa, cmd) = F_GETFL;
292 SCARG(&fa, arg) = SCARG(uap, arg);
293 error = sys_fcntl(l, &fa, retval);
294 if (error)
295 return error;
296 *retval = oflags2ioflags(*retval);
297 return error;
298 case IBCS2_F_SETFL:
299 SCARG(&fa, fd) = SCARG(uap, fd);
300 SCARG(&fa, cmd) = F_SETFL;
301 SCARG(&fa, arg) = (void *)ioflags2oflags((int) SCARG(uap, arg));
302 return sys_fcntl(l, &fa, retval);
303
304 case IBCS2_F_GETLK:
305 cmd = F_GETLK;
306 goto lock;
307 case IBCS2_F_SETLK:
308 cmd = F_SETLK;
309 goto lock;
310 case IBCS2_F_SETLKW:
311 cmd = F_SETLKW;
312 lock:
313 error = copyin(SCARG(uap, arg), &ifl, ibcs2_flock_len);
314 if (error)
315 return error;
316 cvt_iflock2flock(&ifl, &fl);
317 error = do_fcntl_lock(SCARG(uap, fd), cmd, &fl);
318 if (cmd != F_GETLK || error != 0)
319 return error;
320 cvt_flock2iflock(&fl, &ifl);
321 return copyout(&ifl, SCARG(uap, arg), ibcs2_flock_len);
322
323 default:
324 return ENOSYS;
325 }
326
327 }
328