1 /*
2  * locking.c
3  *
4  * This file implements record locking for platforms where the lock(),
5  * unlock() and/or sopen() functions are not available. It also
6  * implements the waitlock() routine, which is the same as lock(), but
7  * waits until the lock can be applied.
8  *
9  * EMX GCC on OS/2:
10  *   lock, unlock: implemented as OS/2 API calls
11  *   sopen: provided by the EMX
12  *
13  * EMX GCC on Windows 32 bit using RSXNT:
14  *   lock, unlock: implemented as Win32 API calls
15  *   sopen: provided by the RSX RTL
16  *
17  * UNIX:
18  *   lock, unlock: implemented as calls to fcntl
19  *   sopen: implemented as open with subsequent shared lock
20  *
21  * OTHER:
22  *   lock, unlock and sopen provieded by the CRTL
23  *   waitlock defined as a loop calling lock and then sleep
24  *
25  * Written by Tobias Ernst @ 2:2476/418, released to the public domain.
26  *
27  */
28 
29 #include "compiler.h"
30 #include "progprot.h"
31 #include "locking.h"
32 #include "unused.h"
33 
34 #ifdef __DJGPP__
35 #include <dpmi.h>
36 
shareloaded(void)37 sword far pascal shareloaded(void)
38 {
39     __dpmi_regs r;
40 
41     r.x.ax = 0x1000;
42     __dpmi_int(0x2f, &r);
43     return r.h.al == 0xff;
44 }
45 
46 #endif
47 
48 #if (defined (__WATCOMC__) || defined (__EMX__) || defined (__IBMC__)) && defined (OS2)
49 
50 #include <os2.h>
51 
lock(int handle,long ofs,long length)52 int lock(int handle, long ofs, long length)
53 {
54     FILELOCK urange, lrange;
55     APIRET apiret;
56 
57     lrange.lOffset = ofs;
58     lrange.lRange  = length;
59     urange.lRange  = urange.lOffset = 0;
60 
61     if((apiret = DosSetFileLocks((HFILE)handle, &urange, &lrange, 0, 0)) != 0)
62     {
63         return -1;
64     }
65 
66     return 0;
67 }
68 
unlock(int handle,long ofs,long length)69 int unlock(int handle, long ofs, long length)
70 {
71     FILELOCK urange, lrange;
72     APIRET apiret;
73 
74     urange.lOffset = ofs;
75     urange.lRange  = length;
76     lrange.lRange  = lrange.lOffset = 0;
77 
78     if((apiret = DosSetFileLocks((HFILE)handle, &urange, &lrange, 0, 0)) != 0)
79     {
80         return -1;
81     }
82 
83     return 0;
84 }
85 
waitlock(int handle,long ofs,long length)86 int waitlock(int handle, long ofs, long length)
87 {
88     FILELOCK urange, lrange;
89     APIRET apiret;
90 
91     lrange.lOffset = ofs;
92     lrange.lRange  = length;
93     urange.lRange  = urange.lOffset = 0;
94 
95     while((apiret = DosSetFileLocks((HFILE)handle, &urange, &lrange, 60000, 0)) != 0)
96     {}
97     return 0;
98 }
99 
waitlock2(int handle,long ofs,long length,long t)100 int waitlock2(int handle, long ofs, long length, long t)
101 {
102     FILELOCK urange, lrange;
103     APIRET apiret;
104 
105     lrange.lOffset = ofs;
106     lrange.lRange  = length;
107     urange.lRange  = urange.lOffset = 0;
108     return DosSetFileLocks((HFILE)handle, &urange, &lrange, t * 1000l, 0);
109 }
110 
111 #elif defined (__RSXNT__)
112 
113 #include <windows.h>
114 #include <emx/syscalls.h>
115 #include <stdlib.h>
116 
117 #ifndef F_GETOSFD
118 #define F_GETOSFD 6
119 #endif
120 
waitlock(int handle,long ofs,long length)121 int waitlock(int handle, long ofs, long length)
122 {
123     int nt_handle = __fcntl(handle, F_GETOSFD, 0);
124 
125     if(nt_handle < 0)
126     {
127         return -1;
128     }
129 
130     while(LockFile(nt_handle, (DWORD)ofs, 0L, (DWORD)length, 0L) == FALSE)
131     {
132         sleep(1);
133     }
134     return 0;
135 }
136 
137 /*
138  *  THERE SHOULD BE A BETTER WAY TO MAKE A TIMED LOCK.
139  */
waitlock2(int handle,long ofs,long length,long t)140 int waitlock2(int handle, long ofs, long length, long t)
141 {
142     int forever = 0;
143     int rc;
144 
145     if(t == 0)
146     {
147         forever = 1;
148     }
149 
150     t *= 10;
151 
152     while((rc = lock(handle, ofs, length)) == -1 && (t > 0 || forever))
153     {
154         tdelay(100);
155         t--;
156     }
157     return rc;
158 }
159 
lock(int handle,long ofs,long length)160 int lock(int handle, long ofs, long length)
161 {
162     int nt_handle = __fcntl(handle, F_GETOSFD, 0);
163 
164     if(nt_handle < 0 || LockFile((DWORD)nt_handle, (DWORD)ofs, 0L, (DWORD)length, 0L) == FALSE)
165     {
166         return -1;
167     }
168 
169     return 0;
170 }
171 
unlock(int handle,long ofs,long length)172 int unlock(int handle, long ofs, long length)
173 {
174     int nt_handle = __fcntl(handle, F_GETOSFD, 0);
175 
176     if(nt_handle < 0 || UnlockFile((DWORD)nt_handle, (DWORD)ofs, 0L, (DWORD)length, 0L) == FALSE)
177     {
178         return -1;
179     }
180 
181     return 0;
182 }
183 
184 #elif defined (__MINGW32__) || (defined (_MSC_VER) && (_MSC_VER >= 1200))
185 
186 #if defined (_MSC_VER) && (_MSC_VER >= 1200)
187     #include <stdio.h>
188 #endif
189 
190 #include <io.h>
191 
waitlock(int handle,long ofs,long length)192 int waitlock(int handle, long ofs, long length)
193 {
194     long offset = tell(handle);
195 
196     if(offset == -1)
197     {
198         return -1;
199     }
200 
201     lseek(handle, ofs, SEEK_SET);
202     _locking(handle, 1, length);
203     lseek(handle, offset, SEEK_SET);
204     return 0;
205 }
206 
lock(int handle,long ofs,long length)207 int lock(int handle, long ofs, long length)
208 {
209     long offset = tell(handle);
210     int r;
211 
212     if(offset == -1)
213     {
214         return -1;
215     }
216 
217     lseek(handle, ofs, SEEK_SET);
218     r = _locking(handle, 2, length);
219     lseek(handle, offset, SEEK_SET);
220 
221     if(r)
222     {
223         return -1;
224     }
225 
226     return 0;
227 }
228 
unlock(int handle,long ofs,long length)229 int unlock(int handle, long ofs, long length)
230 {
231     long offset = tell(handle);
232 
233     if(offset == -1)
234     {
235         return -1;
236     }
237 
238     lseek(handle, ofs, SEEK_SET);
239     _locking(handle, 0, length);
240     lseek(handle, offset, SEEK_SET);
241     return 0;
242 }
243 
244 /*
245  * THERE SHOULD BE A BETTER WAY TO MAKE A TIMED LOCK !!!!
246  */
waitlock2(int handle,long ofs,long length,long t)247 int waitlock2(int handle, long ofs, long length, long t)
248 {
249     int forever = 0;
250     int rc;
251 
252     if(t == 0)
253     {
254         forever = 1;
255     }
256 
257     t *= 10;
258 
259     while((rc = lock(handle, ofs, length)) == -1 && (t > 0 || forever))
260     {
261         tdelay(100);
262         t--;
263     }
264     return rc;
265 }
266 
267 #elif defined (_MSC_VER) && (_MSC_VER < 1200)
268 
269 #include <io.h>
270 #include <stdio.h>
271 
waitlock(int handle,long ofs,long length)272 int waitlock(int handle, long ofs, long length)
273 {
274     while(lock(handle, ofs, length) == -1)
275     {
276         tdelay(100);
277     }
278     return 0;
279 }
280 
waitlock2(int handle,long ofs,long length,long t)281 int waitlock2(int handle, long ofs, long length, long t)
282 {
283     int forever = 0;
284     int rc;
285 
286     if(t == 0)
287     {
288         forever = 1;
289     }
290 
291     t *= 10;
292 
293     while((rc = lock(handle, ofs, length)) == -1 && (t > 0 || forever))
294     {
295         tdelay(100);
296         t--;
297     }
298     return rc;
299 }
300 
lock(int handle,long ofs,long length)301 int lock(int handle, long ofs, long length)
302 {
303     long offset = tell(handle);
304     int r;
305 
306     if(offset == -1)
307     {
308         return -1;
309     }
310 
311     lseek(handle, ofs, SEEK_SET);
312     r = locking(handle, 2, length);
313     lseek(handle, offset, SEEK_SET);
314 
315     if(r)
316     {
317         return -1;
318     }
319 
320     return 0;
321 }
322 
unlock(int handle,long ofs,long length)323 int unlock(int handle, long ofs, long length)
324 {
325     long offset = tell(handle);
326     int r;
327 
328     if(offset == -1)
329     {
330         return -1;
331     }
332 
333     lseek(handle, ofs, SEEK_SET);
334     r = locking(handle, 0, length);
335     lseek(handle, offset, SEEK_SET);
336 
337     if(r)
338     {
339         return -1;
340     }
341 
342     return 0;
343 }
344 
345 #elif defined (UNIX)
346 
347 #include <fcntl.h>
348 #include <unistd.h>
349 
file_lock(short type,long ofs,long length)350 static struct flock * file_lock(short type, long ofs, long length)
351 {
352     static struct flock ret;
353 
354     ret.l_type   = type;
355     ret.l_start  = ofs;
356     ret.l_whence = SEEK_SET;
357     ret.l_len    = length;
358     ret.l_pid    = getpid();
359     return &ret;
360 }
361 
lock(int handle,long ofs,long length)362 int lock(int handle, long ofs, long length)
363 {
364 #ifndef __BEOS__
365     return fcntl(handle, F_SETLK, file_lock(F_WRLCK, ofs, length));
366 
367 #else
368     return 0;
369 
370 #endif
371 }
372 
waitlock(int handle,long ofs,long length)373 int waitlock(int handle, long ofs, long length)
374 {
375 #ifndef __BEOS__
376     return fcntl(handle, F_SETLKW, file_lock(F_WRLCK, ofs, length));
377 
378 #else
379     return 0;
380 
381 #endif
382 }
383 
384 /*
385  * waitlock2() wait <t> seconds for a lock
386  */
waitlock2(int handle,long ofs,long length,long t)387 int waitlock2(int handle, long ofs, long length, long t)
388 {
389 #ifndef __BEOS__
390     int rc;
391     alarm(t);
392     rc = fcntl(handle, F_SETLKW, file_lock(F_WRLCK, ofs, length));
393     alarm(0);
394     return rc;
395 
396 #else
397     return 0;
398 
399 #endif
400 }
401 
unlock(int handle,long ofs,long length)402 int unlock(int handle, long ofs, long length)
403 {
404 #ifndef __BEOS__
405     return fcntl(handle, F_SETLK, file_lock(F_UNLCK, ofs, length));
406 
407 #else
408     return 0;
409 
410 #endif
411 }
412 
413 #include <stdio.h>
414 
sopen(const char * name,int oflag,int ishared,int mode)415 int sopen(const char * name, int oflag, int ishared, int mode)
416 {
417     int fd = open(name, oflag, mode);
418 
419     unused(ishared);
420 
421     /*
422      * I removed this code, 'cause there is no more need for it (i hope so)
423      */
424     /*
425      #ifndef NO_LOCKING
426         if (fd != -1 && fcntl(fd, F_SETLK,
427                   file_lock((ishared == SH_DENYNONE) ? F_RDLCK : F_WRLCK, 0, 0)))
428 
429         {
430             close(fd);
431             return -1;
432         }
433      #endif
434      */
435     return fd;
436 }
437 
438 #else  /* if (defined (__WATCOMC__) || defined (__EMX__) || defined (__IBMC__)) && defined (OS2)
439          */
440 
441 #ifdef OS2
442 #define INCL_DOSDATETIME
443     #include <os2.h>
444 #endif
445 
446 #if defined (__TURBOC__) && defined (__MSDOS__)
447     #include <io.h>
448     #include <dos.h>
449 #endif
450 
451 #ifdef UNIX
452     #include <unistd.h>
453 #endif
454 
waitlock(int handle,long ofs,long length)455 int waitlock(int handle, long ofs, long length)
456 {
457     while(lock(handle, ofs, length) == -1)
458     {
459         tdelay(100);
460     }
461     return 0;
462 }
463 
waitlock2(int handle,long ofs,long length,long t)464 int waitlock2(int handle, long ofs, long length, long t)
465 {
466     int forever = 0;
467     int rc;
468 
469     if(t == 0)
470     {
471         forever = 1;
472     }
473 
474     t *= 10;
475 
476     while((rc = lock(handle, ofs, length)) == -1 && (t > 0 || forever))
477     {
478         tdelay(100);
479         t--;
480     }
481     return rc;
482 }
483 
484 #endif /* if (defined (__WATCOMC__) || defined (__EMX__) || defined (__IBMC__)) && defined (OS2)
485           */
486