/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- flock_allocate
- Scm_MakeSysFlock
- flag_name
- Scm_SysFcntl
- Scm_Init_fcntl
1 /*
2 * fcntl.c - fcntl interface
3 *
4 * Copyright (c) 2000-2003 Shiro Kawai, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the authors nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id: fcntl.c,v 1.17 2005/07/22 09:26:54 shirok Exp $
34 */
35
36 #define _GNU_SOURCE /* for Linux, this enables additional features */
37
38 #include <string.h>
39 #include <errno.h>
40 #include <gauche.h>
41 #include <gauche/class.h>
42 #include <gauche/extend.h>
43
44 #undef SCM_EXTERN
45 #define SCM_EXTERN extern
46 #include "gauche/fcntl.h"
47
48 /* struct flock */
49
50 static ScmObj flock_allocate(ScmClass *klass, ScmObj initargs);
51
52 SCM_DEFINE_BUILTIN_CLASS(Scm_SysFlockClass,
53 NULL, NULL, NULL,
54 flock_allocate,
55 NULL);
56
57 static ScmObj flock_allocate(ScmClass *klass, ScmObj initargs)
58 {
59 ScmSysFlock *f = SCM_NEW(ScmSysFlock);
60 SCM_SET_CLASS(f, SCM_CLASS_SYS_FLOCK);
61 memset(&f->lock, 0, sizeof(f->lock));
62 return SCM_OBJ(f);
63 }
64
65 #define FLOCK_GET_N_SET(name, type) \
66 static ScmObj SCM_CPP_CAT3(flock_, name, _get)(ScmSysFlock* t) \
67 { return Scm_MakeInteger(t->lock.name); } \
68 static void SCM_CPP_CAT3(flock_, name, _set)(ScmSysFlock* t, ScmObj v) \
69 { \
70 if (!SCM_INTEGERP(v)) Scm_Error("integer required, but got %S", v); \
71 t->lock.name = (type)Scm_GetInteger(v); \
72 }
73
74 FLOCK_GET_N_SET(l_type, short)
75 FLOCK_GET_N_SET(l_whence, short)
76 FLOCK_GET_N_SET(l_start, off_t)
77 FLOCK_GET_N_SET(l_len, off_t)
78 FLOCK_GET_N_SET(l_pid, pid_t)
79
80 static ScmClassStaticSlotSpec flock_slots[] = {
81 SCM_CLASS_SLOT_SPEC("type", flock_l_type_get, flock_l_type_set),
82 SCM_CLASS_SLOT_SPEC("whence", flock_l_whence_get, flock_l_whence_set),
83 SCM_CLASS_SLOT_SPEC("start", flock_l_start_get, flock_l_start_set),
84 SCM_CLASS_SLOT_SPEC("len", flock_l_len_get, flock_l_len_set),
85 SCM_CLASS_SLOT_SPEC("pid", flock_l_pid_get, flock_l_pid_set),
86 { NULL }
87 };
88
89 ScmObj Scm_MakeSysFlock(void)
90 {
91 return flock_allocate(SCM_CLASS_SYS_FLOCK, SCM_NIL);
92 }
93
94 /*
95 * Fcntl bridge
96 */
97 static const char *flag_name(int flag)
98 {
99 #define FLAG_NAME(n) case n: return #n
100 switch (flag) {
101 FLAG_NAME(F_GETFD);
102 FLAG_NAME(F_SETFD);
103 FLAG_NAME(F_GETFL);
104 FLAG_NAME(F_SETFL);
105 FLAG_NAME(F_DUPFD);
106 FLAG_NAME(F_GETLK);
107 FLAG_NAME(F_SETLK);
108 FLAG_NAME(F_SETLKW);
109 #if defined(F_GETOWN)
110 FLAG_NAME(F_GETOWN);
111 #endif
112 #if defined(F_SETOWN)
113 FLAG_NAME(F_SETOWN);
114 #endif
115 #if defined(F_GETSIG)
116 FLAG_NAME(F_GETSIG);
117 #endif
118 #if defined(F_SETSIG)
119 FLAG_NAME(F_SETSIG);
120 #endif
121 #if defined(F_GETLEASE)
122 FLAG_NAME(F_GETLEASE);
123 #endif
124 #if defined(F_SETLEASE)
125 FLAG_NAME(F_SETLEASE);
126 #endif
127 #if defined(F_NOTIFY)
128 FLAG_NAME(F_NOTIFY);
129 #endif
130 }
131 return "(unknown flag)";
132 #undef FLAG_NAME
133 }
134
135 ScmObj Scm_SysFcntl(ScmObj port_or_fd, int op, ScmObj arg)
136 {
137 #ifndef __MINGW32__
138 int fd = Scm_GetPortFd(port_or_fd, TRUE), r;
139 ScmSysFlock *fl;
140
141 switch (op) {
142 case F_GETFD:; case F_GETFL:;
143 #if defined(F_GETOWN) /* BSD and Linux specific */
144 case F_GETOWN:;
145 #endif /*F_GETOWN*/
146 #if defined(F_GETSIG) /* Linux specific */
147 case F_GETSIG:;
148 #endif /*F_GETSIG */
149 #if defined(F_GETLEASE) /* Linux specific */
150 case F_GETLEASE:;
151 #endif /*F_GETLEASE */
152 SCM_SYSCALL(r, fcntl(fd, op));
153 if (r == -1) { /*NB: F_GETOWN may return a negative value on success*/
154 Scm_SysError("fcntl(%s) failed", flag_name(op));
155 }
156 return Scm_MakeInteger(r);
157 case F_SETFD:; case F_SETFL:; case F_DUPFD:;
158 #if defined(F_SETOWN) /* BSD and Linux specific */
159 case F_SETOWN:;
160 #endif /*F_SETOWN*/
161 #if defined(F_SETSIG) /* Linux specific */
162 case F_SETSIG:;
163 #endif /*F_SETSIG */
164 #if defined(F_SETLEASE) /* Linux specific */
165 case F_SETLEASE:;
166 #endif /*F_SETLEASE */
167 #if defined(F_NOTIFY) /* Linux specific */
168 case F_NOTIFY:;
169 #endif /*F_NOTIFY */
170 if (!SCM_EXACTP(arg)) {
171 Scm_Error("exact integer required for fcntl(%s), but got %S",
172 flag_name(op), arg);
173 }
174 SCM_SYSCALL(r, fcntl(fd, op, Scm_GetInteger(arg)));
175 if (r < 0) {
176 Scm_SysError("fcntl(%s) failed", flag_name(op));
177 }
178 return Scm_MakeInteger(r);
179 case F_GETLK:; case F_SETLK:; case F_SETLKW:;
180 if (!SCM_SYS_FLOCK_P(arg)) {
181 Scm_Error("flock object required for fcntl(%s), but got %S",
182 flag_name(op), arg);
183 }
184 fl = SCM_SYS_FLOCK(arg);
185 SCM_SYSCALL(r, fcntl(fd, op, &fl->lock));
186 if (op == F_SETLK) {
187 if (r >= 0) return SCM_TRUE;
188 if (errno == EAGAIN) return SCM_FALSE;
189 }
190 if (r < 0) Scm_SysError("fcntl(%s) failed", flag_name(op));
191 return SCM_TRUE;
192 default:
193 Scm_Error("unknown operation code (%d) for fcntl", op);
194 return SCM_UNDEFINED; /* dummy */
195 }
196 #else /*__MINGW32__*/
197 Scm_Error("fcntl not supported on MinGW port");
198 return SCM_UNDEFINED; /*dummy*/
199 #endif /*__MINGW32__*/
200 }
201
202 /*
203 * Initialization
204 */
205
206 extern void Scm_Init_fcntlib(ScmModule *mod);
207
208 void Scm_Init_fcntl(void)
209 {
210 ScmModule *mod;
211
212 SCM_INIT_EXTENSION(fcntl);
213 mod = SCM_FIND_MODULE("gauche.fcntl", SCM_FIND_MODULE_CREATE);
214 Scm_InitStaticClass(&Scm_SysFlockClass, "<sys-flock>",
215 mod, flock_slots, 0);
216 Scm_Init_fcntlib(mod);
217 }
218