f91f25bd133e81a74015e716a4cedcaedac6201a
[idzebra-moved-to-github.git] / util / flock.c
1 /* $Id: flock.c,v 1.6 2006-04-13 12:42:57 mike Exp $
2    Copyright (C) 1995-2005
3    Index Data ApS
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24 #include <stdio.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #ifdef WIN32
31 #include <io.h>
32 #include <sys/locking.h>
33 #endif
34 #if HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <idzebra/flock.h>
39 #include <yaz/xmalloc.h>
40 #include <yaz/log.h>
41
42 struct zebra_lock_info {
43     int fd;
44     char *fname;
45 };
46
47 static int log_level = 0 /* YLOG_LOG|YLOG_FLUSH */;
48
49 char *zebra_mk_fname (const char *dir, const char *name)
50 {
51     int dlen = dir ? strlen(dir) : 0;
52     char *fname = xmalloc (dlen + strlen(name) + 3);
53
54 #ifdef WIN32
55     if (dlen)
56     {
57         int last_one = dir[dlen-1];
58
59         if (!strchr ("/\\:", last_one))
60             sprintf (fname, "%s\\%s", dir, name);
61         else
62             sprintf (fname, "%s%s", dir, name);
63     }
64     else
65         sprintf (fname, "%s", name);
66 #else
67     if (dlen)
68     {
69         int last_one = dir[dlen-1];
70
71         if (!strchr ("/", last_one))
72             sprintf (fname, "%s/%s", dir, name);
73         else
74             sprintf (fname, "%s%s", dir, name);
75     }
76     else
77         sprintf (fname, "%s", name);
78 #endif
79     return fname;
80 }
81
82 ZebraLockHandle zebra_lock_create (const char *dir, const char *name)
83 {
84     char *fname = zebra_mk_fname(dir, name);
85     ZebraLockHandle h = (ZebraLockHandle) xmalloc (sizeof(*h));
86
87     h->fd = -1;
88 #ifdef WIN32
89     h->fd = open (name, O_BINARY|O_RDONLY);
90     if (h->fd == -1)
91         h->fd = open (fname, (O_BINARY|O_CREAT|O_RDWR), 0666);
92 #else
93     h->fd= open (fname, (O_BINARY|O_CREAT|O_RDWR), 0666);
94 #endif
95     if (h->fd == -1)
96     {
97         xfree (h);
98         yaz_log(YLOG_WARN | YLOG_ERRNO, "zebra_lock_create fail fname=%s", fname);
99         return 0;
100     }
101     h->fname = fname;
102     yaz_log(log_level, "zebra_lock_create fd=%d p=%p fname=%s", h->fd, h, h->fname);
103     return h;
104 }
105
106 void zebra_lock_destroy (ZebraLockHandle h)
107 {
108     if (!h)
109         return;
110     yaz_log(log_level, "zebra_lock_destroy fd=%d p=%p fname=%s", h->fd, h, h->fname);
111     if (h->fd != -1)
112         close (h->fd);
113     xfree (h->fname);
114     xfree (h);
115 }
116
117 #ifndef WIN32
118 static int unixLock (int fd, int type, int cmd)
119 {
120     struct flock area;
121     area.l_type = type;
122     area.l_whence = SEEK_SET;
123     area.l_len = area.l_start = 0L;
124     return fcntl (fd, cmd, &area);
125 }
126 #endif
127
128 int zebra_lock_w (ZebraLockHandle h)
129 {
130     int r;
131     yaz_log(log_level, "zebra_lock_w fd=%d p=%p fname=%s", h->fd, h, h->fname);
132 #ifdef WIN32
133     while ((r = _locking (h->fd, _LK_LOCK, 1)))
134         ;
135 #else
136     r = unixLock (h->fd, F_WRLCK, F_SETLKW);
137 #endif
138     yaz_log(log_level, "zebra_lock_w fd=%d p=%p fname=%s OK", h->fd, h, h->fname);
139     return r;
140 }
141
142 int zebra_lock_r (ZebraLockHandle h)
143 {
144     int r;
145     yaz_log(log_level, "zebra_lock_r fd=%d p=%p fname=%s", h->fd, h, h->fname);
146 #ifdef WIN32
147     while ((r = _locking (h->fd, _LK_LOCK, 1)))
148         ;
149 #else
150     r = unixLock (h->fd, F_RDLCK, F_SETLKW);
151 #endif
152     yaz_log(log_level, "zebra_lock_r fd=%d p=%p fname=%s OK", h->fd, h, h->fname);
153     return r;
154 }
155
156 int zebra_unlock (ZebraLockHandle h)
157 {
158     yaz_log(log_level, "zebra_unlock fd=%d p=%p fname=%s", h->fd, h, h->fname);
159 #ifdef WIN32
160     return _locking (h->fd, _LK_UNLCK, 1);
161 #else
162     return unixLock (h->fd, F_UNLCK, F_SETLKW);
163 #endif
164 }
165