summaryrefslogtreecommitdiff
path: root/jni/ruby/missing/flock.c
blob: 829f431ddc95b2dfb4b00ad1e6e88051a05cf69d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "ruby/config.h"
#include "ruby/ruby.h"

#if defined _WIN32
#elif defined HAVE_FCNTL && defined HAVE_FCNTL_H && !defined(__native_client__)

/* These are the flock() constants.  Since this systems doesn't have
   flock(), the values of the constants are probably not available.
*/
# ifndef LOCK_SH
#  define LOCK_SH 1
# endif
# ifndef LOCK_EX
#  define LOCK_EX 2
# endif
# ifndef LOCK_NB
#  define LOCK_NB 4
# endif
# ifndef LOCK_UN
#  define LOCK_UN 8
# endif

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int
flock(int fd, int operation)
{
    struct flock lock;

    switch (operation & ~LOCK_NB) {
    case LOCK_SH:
        lock.l_type = F_RDLCK;
        break;
    case LOCK_EX:
        lock.l_type = F_WRLCK;
        break;
    case LOCK_UN:
        lock.l_type = F_UNLCK;
        break;
    default:
        errno = EINVAL;
        return -1;
    }
    lock.l_whence = SEEK_SET;
    lock.l_start = lock.l_len = 0L;

    return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &lock);
}

#elif defined(HAVE_LOCKF)

#include <unistd.h>
#include <errno.h>

/*  Emulate flock() with lockf() or fcntl().  This is just to increase
    portability of scripts.  The calls might not be completely
    interchangeable.  What's really needed is a good file
    locking module.
*/

# ifndef F_ULOCK
#  define F_ULOCK       0       /* Unlock a previously locked region */
# endif
# ifndef F_LOCK
#  define F_LOCK        1       /* Lock a region for exclusive use */
# endif
# ifndef F_TLOCK
#  define F_TLOCK       2       /* Test and lock a region for exclusive use */
# endif
# ifndef F_TEST
#  define F_TEST        3       /* Test a region for other processes locks */
# endif

/* These are the flock() constants.  Since this systems doesn't have
   flock(), the values of the constants are probably not available.
*/
# ifndef LOCK_SH
#  define LOCK_SH 1
# endif
# ifndef LOCK_EX
#  define LOCK_EX 2
# endif
# ifndef LOCK_NB
#  define LOCK_NB 4
# endif
# ifndef LOCK_UN
#  define LOCK_UN 8
# endif

int
flock(int fd, int operation)
{
    switch (operation) {

        /* LOCK_SH - get a shared lock */
      case LOCK_SH:
        rb_notimplement();
        return -1;
        /* LOCK_EX - get an exclusive lock */
      case LOCK_EX:
        return lockf (fd, F_LOCK, 0);

        /* LOCK_SH|LOCK_NB - get a non-blocking shared lock */
      case LOCK_SH|LOCK_NB:
        rb_notimplement();
        return -1;
        /* LOCK_EX|LOCK_NB - get a non-blocking exclusive lock */
      case LOCK_EX|LOCK_NB:
        return lockf (fd, F_TLOCK, 0);

        /* LOCK_UN - unlock */
      case LOCK_UN:
        return lockf (fd, F_ULOCK, 0);

        /* Default - can't decipher operation */
      default:
        errno = EINVAL;
        return -1;
    }
}
#else
int
flock(int fd, int operation)
{
    rb_notimplement();
    return -1;
}
#endif