Annotation of sys/compat/ibcs2/ibcs2_fcntl.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ibcs2_fcntl.c,v 1.9 2002/03/14 01:26:50 millert Exp $ */
2: /* $NetBSD: ibcs2_fcntl.c,v 1.6 1996/05/03 17:05:20 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1997 Theo de Raadt
6: * Copyright (c) 1995 Scott Bartram
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: #include <sys/param.h>
33: #include <sys/systm.h>
34: #include <sys/namei.h>
35: #include <sys/proc.h>
36: #include <sys/file.h>
37: #include <sys/stat.h>
38: #include <sys/filedesc.h>
39: #include <sys/ioctl.h>
40: #include <sys/kernel.h>
41: #include <sys/mount.h>
42: #include <sys/malloc.h>
43: #include <sys/syscallargs.h>
44: #include <sys/vnode.h>
45:
46: #include <compat/ibcs2/ibcs2_types.h>
47: #include <compat/ibcs2/ibcs2_fcntl.h>
48: #include <compat/ibcs2/ibcs2_unistd.h>
49: #include <compat/ibcs2/ibcs2_signal.h>
50: #include <compat/ibcs2/ibcs2_syscallargs.h>
51: #include <compat/ibcs2/ibcs2_util.h>
52:
53: static int cvt_o_flags(int);
54: static void cvt_flock2iflock(struct flock *, struct ibcs2_flock *);
55: static void cvt_iflock2flock(struct ibcs2_flock *, struct flock *);
56: static int ioflags2oflags(int);
57: static int oflags2ioflags(int);
58:
59: static int
60: cvt_o_flags(flags)
61: 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_SYNC;
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
78: cvt_flock2iflock(flp, iflp)
79: struct flock *flp;
80: struct ibcs2_flock *iflp;
81: {
82: switch (flp->l_type) {
83: case F_RDLCK:
84: iflp->l_type = IBCS2_F_RDLCK;
85: break;
86: case F_WRLCK:
87: iflp->l_type = IBCS2_F_WRLCK;
88: break;
89: case F_UNLCK:
90: iflp->l_type = IBCS2_F_UNLCK;
91: break;
92: }
93: iflp->l_whence = (short)flp->l_whence;
94: iflp->l_start = (ibcs2_off_t)flp->l_start;
95: iflp->l_len = (ibcs2_off_t)flp->l_len;
96: iflp->l_sysid = 0;
97: iflp->l_pid = (ibcs2_pid_t)flp->l_pid;
98: }
99:
100: static void
101: cvt_iflock2flock(iflp, flp)
102: struct ibcs2_flock *iflp;
103: struct flock *flp;
104: {
105: flp->l_start = (off_t)iflp->l_start;
106: flp->l_len = (off_t)iflp->l_len;
107: flp->l_pid = (pid_t)iflp->l_pid;
108: switch (iflp->l_type) {
109: case IBCS2_F_RDLCK:
110: flp->l_type = F_RDLCK;
111: break;
112: case IBCS2_F_WRLCK:
113: flp->l_type = F_WRLCK;
114: break;
115: case IBCS2_F_UNLCK:
116: flp->l_type = F_UNLCK;
117: break;
118: }
119: flp->l_whence = iflp->l_whence;
120: }
121:
122: /* convert iBCS2 mode into NetBSD mode */
123: static int
124: ioflags2oflags(flags)
125: int flags;
126: {
127: int r = 0;
128:
129: if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
130: if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
131: if (flags & IBCS2_O_RDWR) r |= O_RDWR;
132: if (flags & IBCS2_O_NDELAY) r |= O_NONBLOCK;
133: if (flags & IBCS2_O_APPEND) r |= O_APPEND;
134: if (flags & IBCS2_O_SYNC) r |= O_SYNC;
135: if (flags & IBCS2_O_NONBLOCK) r |= O_NONBLOCK;
136: if (flags & IBCS2_O_CREAT) r |= O_CREAT;
137: if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
138: if (flags & IBCS2_O_EXCL) r |= O_EXCL;
139: if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
140: return r;
141: }
142:
143: /* convert NetBSD mode into iBCS2 mode */
144: static int
145: oflags2ioflags(flags)
146: int flags;
147: {
148: int r = 0;
149:
150: if (flags & O_RDONLY) r |= IBCS2_O_RDONLY;
151: if (flags & O_WRONLY) r |= IBCS2_O_WRONLY;
152: if (flags & O_RDWR) r |= IBCS2_O_RDWR;
153: if (flags & O_NDELAY) r |= IBCS2_O_NONBLOCK;
154: if (flags & O_APPEND) r |= IBCS2_O_APPEND;
155: if (flags & O_SYNC) r |= IBCS2_O_SYNC;
156: if (flags & O_NONBLOCK) r |= IBCS2_O_NONBLOCK;
157: if (flags & O_CREAT) r |= IBCS2_O_CREAT;
158: if (flags & O_TRUNC) r |= IBCS2_O_TRUNC;
159: if (flags & O_EXCL) r |= IBCS2_O_EXCL;
160: if (flags & O_NOCTTY) r |= IBCS2_O_NOCTTY;
161: return r;
162: }
163:
164: int
165: ibcs2_sys_open(p, v, retval)
166: struct proc *p;
167: void *v;
168: register_t *retval;
169: {
170: struct ibcs2_sys_open_args /* {
171: syscallarg(char *) path;
172: syscallarg(int) flags;
173: syscallarg(int) mode;
174: } */ *uap = v;
175: int noctty = SCARG(uap, flags) & IBCS2_O_NOCTTY;
176: int ret;
177: caddr_t sg = stackgap_init(p->p_emul);
178:
179: SCARG(uap, flags) = cvt_o_flags(SCARG(uap, flags));
180: if (SCARG(uap, flags) & O_CREAT)
181: IBCS2_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
182: else
183: IBCS2_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
184: ret = sys_open(p, uap, retval);
185:
186: if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
187: struct filedesc *fdp = p->p_fd;
188: struct file *fp;
189:
190: if ((fp = fd_getfile(fdp, *retval)) == NULL)
191: return EBADF;
192: FREF(fp);
193: if (fp->f_type == DTYPE_VNODE)
194: (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
195: FRELE(fp);
196: }
197: return ret;
198: }
199:
200: int
201: ibcs2_sys_creat(p, v, retval)
202: struct proc *p;
203: void *v;
204: register_t *retval;
205: {
206: struct ibcs2_sys_creat_args /* {
207: syscallarg(char *) path;
208: syscallarg(int) mode;
209: } */ *uap = v;
210: struct sys_open_args cup;
211: caddr_t sg = stackgap_init(p->p_emul);
212:
213: IBCS2_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
214: SCARG(&cup, path) = SCARG(uap, path);
215: SCARG(&cup, mode) = SCARG(uap, mode);
216: SCARG(&cup, flags) = O_WRONLY | O_CREAT | O_TRUNC;
217: return sys_open(p, &cup, retval);
218: }
219:
220: int
221: ibcs2_sys_access(p, v, retval)
222: struct proc *p;
223: void *v;
224: register_t *retval;
225: {
226: struct ibcs2_sys_access_args /* {
227: syscallarg(char *) path;
228: syscallarg(int) flags;
229: } */ *uap = v;
230: struct sys_access_args cup;
231: caddr_t sg = stackgap_init(p->p_emul);
232:
233: IBCS2_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
234: SCARG(&cup, path) = SCARG(uap, path);
235: SCARG(&cup, flags) = SCARG(uap, flags);
236: return sys_access(p, &cup, retval);
237: }
238:
239: int
240: ibcs2_sys_eaccess(p, v, retval)
241: struct proc *p;
242: void *v;
243: register_t *retval;
244: {
245: register struct ibcs2_sys_eaccess_args /* {
246: syscallarg(char *) path;
247: syscallarg(int) flags;
248: } */ *uap = v;
249: register struct ucred *cred = p->p_ucred;
250: register struct vnode *vp;
251: int error, flags;
252: struct nameidata nd;
253: caddr_t sg = stackgap_init(p->p_emul);
254:
255: IBCS2_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
256:
257: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
258: SCARG(uap, path), p);
259: if ((error = namei(&nd)) != 0)
260: return error;
261: vp = nd.ni_vp;
262:
263: /* Flags == 0 means only check for existence. */
264: if (SCARG(uap, flags)) {
265: flags = 0;
266: if (SCARG(uap, flags) & IBCS2_R_OK)
267: flags |= VREAD;
268: if (SCARG(uap, flags) & IBCS2_W_OK)
269: flags |= VWRITE;
270: if (SCARG(uap, flags) & IBCS2_X_OK)
271: flags |= VEXEC;
272: if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
273: error = VOP_ACCESS(vp, flags, cred, p);
274: }
275: vput(vp);
276: return error;
277: }
278:
279: int
280: ibcs2_sys_fcntl(p, v, retval)
281: struct proc *p;
282: void *v;
283: register_t *retval;
284: {
285: struct ibcs2_sys_fcntl_args /* {
286: syscallarg(int) fd;
287: syscallarg(int) cmd;
288: syscallarg(char *) arg;
289: } */ *uap = v;
290: int error;
291: struct sys_fcntl_args fa;
292: struct flock *flp;
293: struct ibcs2_flock ifl;
294:
295: switch(SCARG(uap, cmd)) {
296: case IBCS2_F_DUPFD:
297: SCARG(&fa, fd) = SCARG(uap, fd);
298: SCARG(&fa, cmd) = F_DUPFD;
299: SCARG(&fa, arg) = SCARG(uap, arg);
300: return sys_fcntl(p, &fa, retval);
301: case IBCS2_F_GETFD:
302: SCARG(&fa, fd) = SCARG(uap, fd);
303: SCARG(&fa, cmd) = F_GETFD;
304: SCARG(&fa, arg) = SCARG(uap, arg);
305: return sys_fcntl(p, &fa, retval);
306: case IBCS2_F_SETFD:
307: SCARG(&fa, fd) = SCARG(uap, fd);
308: SCARG(&fa, cmd) = F_SETFD;
309: SCARG(&fa, arg) = SCARG(uap, arg);
310: return sys_fcntl(p, &fa, retval);
311: case IBCS2_F_GETFL:
312: SCARG(&fa, fd) = SCARG(uap, fd);
313: SCARG(&fa, cmd) = F_GETFL;
314: SCARG(&fa, arg) = SCARG(uap, arg);
315: error = sys_fcntl(p, &fa, retval);
316: if (error)
317: return error;
318: *retval = oflags2ioflags(*retval);
319: return error;
320: case IBCS2_F_SETFL:
321: SCARG(&fa, fd) = SCARG(uap, fd);
322: SCARG(&fa, cmd) = F_SETFL;
323: SCARG(&fa, arg) = (void *)ioflags2oflags((int) SCARG(uap, arg));
324: return sys_fcntl(p, &fa, retval);
325:
326: case IBCS2_F_GETLK:
327: {
328: caddr_t sg = stackgap_init(p->p_emul);
329: flp = stackgap_alloc(&sg, sizeof(*flp));
330: error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
331: ibcs2_flock_len);
332: if (error)
333: return error;
334: cvt_iflock2flock(&ifl, flp);
335: SCARG(&fa, fd) = SCARG(uap, fd);
336: SCARG(&fa, cmd) = F_GETLK;
337: SCARG(&fa, arg) = (void *)flp;
338: error = sys_fcntl(p, &fa, retval);
339: if (error)
340: return error;
341: cvt_flock2iflock(flp, &ifl);
342: return copyout((caddr_t)&ifl, (caddr_t)SCARG(uap, arg),
343: ibcs2_flock_len);
344: }
345:
346: case IBCS2_F_SETLK:
347: {
348: caddr_t sg = stackgap_init(p->p_emul);
349: flp = stackgap_alloc(&sg, sizeof(*flp));
350: error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
351: ibcs2_flock_len);
352: if (error)
353: return error;
354: cvt_iflock2flock(&ifl, flp);
355: SCARG(&fa, fd) = SCARG(uap, fd);
356: SCARG(&fa, cmd) = F_SETLK;
357: SCARG(&fa, arg) = (void *)flp;
358: return sys_fcntl(p, &fa, retval);
359: }
360:
361: case IBCS2_F_SETLKW:
362: {
363: caddr_t sg = stackgap_init(p->p_emul);
364: flp = stackgap_alloc(&sg, sizeof(*flp));
365: error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
366: ibcs2_flock_len);
367: if (error)
368: return error;
369: cvt_iflock2flock(&ifl, flp);
370: SCARG(&fa, fd) = SCARG(uap, fd);
371: SCARG(&fa, cmd) = F_SETLKW;
372: SCARG(&fa, arg) = (void *)flp;
373: return sys_fcntl(p, &fa, retval);
374: }
375: case IBCS2_F_FREESP:
376: {
377: struct ibcs2_flock ifl;
378: off_t off, cur;
379: caddr_t sg = stackgap_init(p->p_emul);
380: struct sys_fstat_args ofst;
381: struct stat ost;
382: struct sys_lseek_args ols;
383: struct sys_ftruncate_args /* {
384: syscallarg(int) fd;
385: syscallarg(int) pad;
386: syscallarg(off_t) length;
387: } */ nuap;
388:
389: error = copyin(SCARG(uap, arg), &ifl, sizeof ifl);
390: if (error)
391: return error;
392:
393: SCARG(&ofst, fd) = SCARG(uap, fd);
394: SCARG(&ofst, sb) = stackgap_alloc(&sg,
395: sizeof(struct stat));
396: if ((error = sys_fstat(p, &ofst, retval)) != 0)
397: return error;
398: if ((error = copyin(SCARG(&ofst, sb), &ost,
399: sizeof ost)) != 0)
400: return error;
401:
402: SCARG(&ols, fd) = SCARG(uap, fd);
403: SCARG(&ols, whence) = SEEK_CUR;
404: SCARG(&ols, offset) = 0;
405: if ((error = sys_lseek(p, &ols, (register_t *)&cur)) != 0)
406: return error;
407:
408: off = (off_t)ifl.l_start;
409: switch (ifl.l_whence) {
410: case 0:
411: off = (off_t)ifl.l_start;
412: break;
413: case 1:
414: off = ost.st_size + (off_t)ifl.l_start;
415: break;
416: case 2:
417: off = cur - (off_t)ifl.l_start;
418: break;
419: default:
420: return EINVAL;
421: }
422:
423: if (ifl.l_len != 0 && off + ifl.l_len != ost.st_size)
424: return EINVAL; /* Sorry, cannot truncate in middle */
425:
426: SCARG(&nuap, fd) = SCARG(uap, fd);
427: SCARG(&nuap, length) = off;
428: return (sys_ftruncate(p, &nuap, retval));
429: }
430: }
431: return ENOSYS;
432: }
CVSweb