root/ext/fcntl/fcntl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. flock_allocate
  2. Scm_MakeSysFlock
  3. flag_name
  4. Scm_SysFcntl
  5. 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 

/* [<][>][^][v][top][bottom][index][help] */