1 /*
2 * Copyright 2001-2004 Brandon Long
3 * All Rights Reserved.
4 *
5 * ClearSilver Templating System
6 *
7 * This code is made available under the terms of the ClearSilver License.
8 * http://www.clearsilver.net/license.hdf
9 *
10 */
11
12 #include "cs_config.h"
13
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <errno.h>
20
21 #include "neo_misc.h"
22 #include "neo_err.h"
23 #include "neo_files.h"
24 #include "ulocks.h"
25
fCreate(int * plock,const char * file)26 NEOERR *fCreate(int *plock, const char *file)
27 {
28 NEOERR *err;
29 int lock;
30 char *p;
31
32 *plock = -1;
33
34 /* note the default mode of 666 is possibly a security hole in that
35 * someone else can grab your lock and DoS you. For internal use, who
36 * cares?
37 */
38 if((lock = open(file, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT|O_EXCL, 0666)) < 0)
39 {
40 if (errno == ENOENT)
41 {
42 p = strrchr (file, '/');
43 if (p != NULL)
44 {
45 *p = '\0';
46 err = ne_mkdirs(file, 0777);
47 *p = '/';
48 if (err != STATUS_OK) return nerr_pass(err);
49 lock = open(file, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0666);
50 }
51 }
52 if (errno == EEXIST)
53 return nerr_pass(fFind(plock, file));
54
55 if (lock < 0)
56 return nerr_raise_errno (NERR_IO, "Unable to open lock file %s", file);
57 }
58
59 *plock = lock;
60
61 return STATUS_OK;
62 }
63
fDestroy(int lock)64 void fDestroy(int lock)
65 {
66
67 if(lock < 0)
68 return;
69
70 close(lock);
71
72 return;
73 }
74
fFind(int * plock,const char * file)75 NEOERR *fFind(int *plock, const char *file)
76 {
77 int lock;
78
79 *plock = -1;
80
81 if((lock = open(file, O_WRONLY|O_NDELAY|O_APPEND, 0666)) < 0) {
82 if (errno == ENOENT)
83 return nerr_raise (NERR_NOT_FOUND, "Unable to find lock file %s", file);
84 return nerr_raise_errno (NERR_IO, "Unable to open lock file %s", file);
85 }
86
87 *plock = lock;
88
89 return STATUS_OK;
90 }
91
fLock(int lock)92 NEOERR *fLock(int lock)
93 {
94
95 if(lockf(lock, F_LOCK, 0) < 0)
96 return nerr_raise_errno (NERR_LOCK, "File lock failed");
97
98 return STATUS_OK;
99 }
100
fUnlock(int lock)101 void fUnlock(int lock)
102 {
103
104 if(lock < 0)
105 return;
106
107 lockf(lock, F_ULOCK, 0);
108
109 return;
110 }
111
112 #ifdef HAVE_PTHREADS
113
mCreate(pthread_mutex_t * mutex)114 NEOERR *mCreate(pthread_mutex_t *mutex)
115 {
116 int err;
117
118 if((err = pthread_mutex_init(mutex, NULL))) {
119 return nerr_raise (NERR_LOCK, "Unable to initialize mutex: %s",
120 strerror(err));
121 }
122
123 return STATUS_OK;
124 }
125
mDestroy(pthread_mutex_t * mutex)126 void mDestroy(pthread_mutex_t *mutex)
127 {
128
129 pthread_mutex_destroy(mutex);
130
131 return;
132 }
133
mLock(pthread_mutex_t * mutex)134 NEOERR *mLock(pthread_mutex_t *mutex)
135 {
136 int err;
137
138 if((err = pthread_mutex_lock(mutex)))
139 return nerr_raise(NERR_LOCK, "Mutex lock failed: %s", strerror(err));
140
141 return STATUS_OK;
142 }
143
mUnlock(pthread_mutex_t * mutex)144 NEOERR *mUnlock(pthread_mutex_t *mutex)
145 {
146 int err;
147
148 if((err = pthread_mutex_unlock(mutex)))
149 return nerr_raise(NERR_LOCK, "Mutex unlock failed: %s", strerror(err));
150
151 return STATUS_OK;
152 }
153
cCreate(pthread_cond_t * cond)154 NEOERR *cCreate(pthread_cond_t *cond)
155 {
156 int err;
157
158 if((err = pthread_cond_init(cond, NULL))) {
159 return nerr_raise(NERR_LOCK, "Unable to initialize condition variable: %s",
160 strerror(err));
161 }
162
163 return STATUS_OK;
164 }
165
cDestroy(pthread_cond_t * cond)166 void cDestroy(pthread_cond_t *cond)
167 {
168 pthread_cond_destroy(cond);
169
170 return;
171 }
172
cWait(pthread_cond_t * cond,pthread_mutex_t * mutex)173 NEOERR *cWait(pthread_cond_t *cond, pthread_mutex_t *mutex)
174 {
175 int err;
176
177 if((err = pthread_cond_wait(cond, mutex)))
178 return nerr_raise(NERR_LOCK, "Condition wait failed: %s", strerror(err));
179
180 return STATUS_OK;
181 }
182
cBroadcast(pthread_cond_t * cond)183 NEOERR *cBroadcast(pthread_cond_t *cond)
184 {
185 int err;
186
187 if((err = pthread_cond_broadcast(cond)))
188 return nerr_raise(NERR_LOCK, "Condition broadcast failed: %s",
189 strerror(err));
190
191 return STATUS_OK;
192 }
193
cSignal(pthread_cond_t * cond)194 NEOERR *cSignal(pthread_cond_t *cond)
195 {
196 int err;
197
198 if((err = pthread_cond_signal(cond)))
199 return nerr_raise (NERR_LOCK, "Condition signal failed: %s", strerror(err));
200
201 return STATUS_OK;
202 }
203
204 #endif
205