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