GnuCOBOL  2.0
A free COBOL compiler
vblowlevel.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003 Trevor van Bremen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2.1,
7  * or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; see the file COPYING.LIB. If
16  * not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor
17  * Boston, MA 02110-1301 USA
18  */
19 
20 #include "isinternal.h"
21 
22 /* Globals */
25 
26 static int iinitialized = 0;
27 
28 /* Activate to define LockFileEx locking */
29 #define USE_LOCKFILE_EX
30 
31 int
32 ivbopen (const char *pcfilename, const int iflags, const mode_t tmode)
33 {
34  int iloop;
35  struct stat sstat;
36 
37  if (!iinitialized) {
38  memset ((void *)&svbfile[0], 0, sizeof (svbfile));
39  iinitialized = 1;
40  }
41  if (stat (pcfilename, &sstat)) {
42  if (!iflags & O_CREAT) {
43  return -1;
44  }
45  } else {
46  for (iloop = 0; iloop < VB_MAX_FILES * 3; iloop++) {
47  if (svbfile[iloop].irefcount
48  && svbfile[iloop].tdevice == sstat.st_dev
49 #ifdef _WIN32
50  && !strcmp(svbfile[iloop].cfilename, pcfilename)) {
51 #else
52  && svbfile[iloop].tinode == sstat.st_ino) {
53 #endif
54  svbfile[iloop].irefcount++;
55  return iloop;
56  }
57  }
58  }
59  for (iloop = 0; iloop < VB_MAX_FILES * 3; iloop++) {
60  if (svbfile[iloop].irefcount == 0) {
61  svbfile[iloop].ihandle = open (pcfilename, iflags | O_BINARY, tmode);
62  if (svbfile[iloop].ihandle == -1) {
63  break;
64  }
65  if ((iflags & O_CREAT) && stat (pcfilename, &sstat)) {
66  close (svbfile[iloop].ihandle);
67  return -1;
68  }
69 #ifdef _WIN32
70  svbfile[iloop].tinode = 0;
71  if (svbfile[iloop].cfilename) {
72  free (svbfile[iloop].cfilename);
73  }
74  svbfile[iloop].whandle = (HANDLE)_get_osfhandle (svbfile[iloop].ihandle);
75  if (svbfile[iloop].whandle == INVALID_HANDLE_VALUE) {
76  close (svbfile[iloop].ihandle);
77  return -1;
78  }
79  svbfile[iloop].cfilename = strdup (pcfilename);
80 #else
81  svbfile[iloop].tinode = sstat.st_ino;
82 #endif
83  svbfile[iloop].tdevice = sstat.st_dev;
84  svbfile[iloop].irefcount++;
85  return iloop;
86  }
87  }
88  errno = ENOENT;
89  return -1;
90 }
91 
92 int
93 ivbclose (const int ihandle)
94 {
95  if (!svbfile[ihandle].irefcount) {
96  errno = ENOENT;
97  return -1;
98  }
99  svbfile[ihandle].irefcount--;
100  if (!svbfile[ihandle].irefcount) {
101  return close (svbfile[ihandle].ihandle);
102  }
103  return 0;
104 }
105 
106 off_t
107 tvblseek (const int ihandle, off_t toffset, const int iwhence)
108 {
109  if (unlikely(!svbfile[ihandle].irefcount)) {
110  errno = ENOENT;
111  return -1;
112  }
113  return lseek (svbfile[ihandle].ihandle, toffset, iwhence);
114 }
115 
116 ssize_t
117 tvbread (const int ihandle, void *pvbuffer, const size_t tcount)
118 {
119  if (unlikely(!svbfile[ihandle].irefcount)) {
120  errno = ENOENT;
121  return -1;
122  }
123  return read (svbfile[ihandle].ihandle, pvbuffer, tcount);
124 }
125 
126 ssize_t
127 tvbwrite (const int ihandle, const void *pvbuffer, const size_t tcount)
128 {
129  if (unlikely(!svbfile[ihandle].irefcount)) {
130  errno = ENOENT;
131  return -1;
132  }
133  return write (svbfile[ihandle].ihandle, pvbuffer, tcount);
134 }
135 
136 int
137 ivbblockread (const int ihandle, const int iisindex, const off_t tblocknumber, char *cbuffer)
138 {
139  struct DICTINFO *psvbptr;
140  off_t toffset;
141  ssize_t tresult;
142  int thandle;
143 
144  psvbptr = psvbfile[ihandle];
145  toffset = (off_t) ((tblocknumber - 1) * psvbptr->inodesize);
146  if (iisindex) {
147  thandle = psvbptr->iindexhandle;
148  } else {
149  thandle = psvbptr->idatahandle;
150  }
151  if (tvblseek (thandle, toffset, SEEK_SET) != toffset) {
152  return EIO;
153  }
154 
155  tresult = tvbread (thandle, cbuffer, (size_t) psvbptr->inodesize);
156  if (!iisindex && tresult == 0) {
157  tresult = (ssize_t) psvbptr->inodesize;
158  memset (cbuffer, 0, (size_t)psvbptr->inodesize);
159  }
160  if (tresult != (ssize_t)psvbptr->inodesize) {
161  return EIO;
162  }
163  return 0;
164 }
165 
166 int
167 ivbblockwrite (const int ihandle, const int iisindex, const off_t tblocknumber, const char *cbuffer)
168 {
169  struct DICTINFO *psvbptr;
170  off_t toffset;
171  ssize_t tresult;
172  int thandle;
173 
174  psvbptr = psvbfile[ihandle];
175  toffset = (off_t) ((tblocknumber - 1) * psvbptr->inodesize);
176  if (iisindex) {
177  thandle = psvbptr->iindexhandle;
178  } else {
179  thandle = psvbptr->idatahandle;
180  }
181 /* RXW
182  tresult = tvblseek (thandle, toffset, SEEK_SET);
183  if (tresult == (off_t) -1) {
184 */
185  if (tvblseek (thandle, toffset, SEEK_SET) != toffset) {
186  return EIO;
187  }
188 
189  tresult = tvbwrite (thandle, cbuffer, (size_t) psvbptr->inodesize);
190  if (tresult != (ssize_t)psvbptr->inodesize) {
191  return EIO;
192  }
193  return 0;
194 }
195 
196 int
197 ivblock (const int ihandle, const off_t toffset, const off_t tlength, const int imode)
198 {
199 #ifdef _WIN32
200 #ifdef USE_LOCKFILE_EX
201 
202  OVERLAPPED toverlapped;
203  DWORD tflags = 0;
204  DWORD winerrno = 0;
205  int bunlock = 0;
206 
207  if (!svbfile[ihandle].irefcount) {
208  errno = ENOENT;
209  return -1;
210  }
211 
212  switch (imode) {
213  case VBUNLOCK:
214  bunlock = 1;
215  break;
216 
217  case VBRDLOCK:
218  tflags = LOCKFILE_FAIL_IMMEDIATELY;
219  break;
220 
221  case VBRDLCKW:
222  tflags = 0;
223  break;
224 
225  case VBWRLOCK:
226  tflags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
227  break;
228 
229  case VBWRLCKW:
230  tflags = LOCKFILE_EXCLUSIVE_LOCK;
231  break;
232 
233  default:
234  errno = EBADARG;
235  return -1;
236  }
237 
238  memset (&toverlapped, 0, sizeof(OVERLAPPED));
239  toverlapped.Offset = (DWORD)(toffset & 0xffffffff);
240  toverlapped.OffsetHigh = (DWORD)(toffset >> 32);
241  errno = 0;
242  if (!bunlock) {
243  if (LockFileEx (svbfile[ihandle].whandle, tflags, 0, (int)(tlength & 0xffffffff),
244  (int)(tlength >> 32), &toverlapped)) {
245  return 0;
246  }
247  } else {
248  if (UnlockFileEx (svbfile[ihandle].whandle, 0, (int)(tlength & 0xffffffff),
249  (int)(tlength >> 32), &toverlapped)) {
250  return 0;
251  }
252  winerrno = GetLastError ();
253  if (winerrno == ERROR_NOT_LOCKED) {
254  //ALREADY UNLOCKED **SAME FCNTL**
255  return 0;
256  }
257  }
258 
259  errno = EBADARG;
260  return -1;
261 #else
262 /* This will probably not work correctly - 64 bit */
263  int itype, iresult = -1;
264  off_t soffset;
265  off_t tempoffset;
266 
267  if (!svbfile[ihandle].irefcount) {
268  errno = ENOENT;
269  return -1;
270  }
271  switch (imode) {
272  case VBUNLOCK:
273  itype = _LK_UNLCK;
274  break;
275 
276  case VBRDLOCK:
277  itype = _LK_NBRLCK;
278  break;
279 
280  case VBRDLCKW:
281  itype = _LK_RLCK;
282  break;
283 
284  case VBWRLOCK:
285  itype = _LK_NBLCK;
286  break;
287 
288  case VBWRLCKW:
289  itype = _LK_LOCK;
290  break;
291 
292  default:
293  errno = EBADARG;
294  return -1;
295  }
296  soffset = lseek (svbfile[ihandle].ihandle, 0, SEEK_CUR);
297  if (soffset == -1) {
298  errno = 172;
299  return -1;
300  }
301  tempoffset = lseek (svbfile[ihandle].ihandle, toffset, SEEK_SET);
302  if (tempoffset == -1) {
303  errno = 172;
304  return -1;
305  }
306  errno = 0;
307  iresult = _locking (svbfile[ihandle].ihandle, itype, (long)tlength);
308  /* Something weird going on here */
309  if (errno == 22) {
310  errno = 0;
311  iresult = 0;
312  }
313  lseek (svbfile[ihandle].ihandle, soffset, SEEK_SET);
314  return iresult;
315 #endif
316 #else
317  int icommand, itype, iresult;
318  struct flock sflock;
319 
320  if (!svbfile[ihandle].irefcount) {
321  errno = ENOENT;
322  return -1;
323  }
324  switch (imode) {
325  case VBUNLOCK:
326  icommand = F_SETLK;
327  itype = F_UNLCK;
328  break;
329 
330  case VBRDLOCK:
331  icommand = F_SETLK;
332  itype = F_RDLCK;
333  break;
334 
335  case VBRDLCKW:
336  icommand = F_SETLKW;
337  itype = F_RDLCK;
338  break;
339 
340  case VBWRLOCK:
341  icommand = F_SETLK;
342  itype = F_WRLCK;
343  break;
344 
345  case VBWRLCKW:
346  icommand = F_SETLKW;
347  itype = F_WRLCK;
348  break;
349 
350  default:
351  errno = EBADARG;
352  return -1;
353  }
354  sflock.l_type = itype;
355  sflock.l_whence = SEEK_SET;
356  sflock.l_start = toffset;
357  sflock.l_len = tlength;
358  sflock.l_pid = 0;
359  do {
360  iresult = fcntl (svbfile[ihandle].ihandle, icommand, &sflock);
361  } while (iresult && errno == EINTR);
362 
363  return iresult;
364 #endif
365 }
int ivblock(const int ihandle, const off_t toffset, const off_t tlength, const int imode)
Definition: vblowlevel.c:197
int ivbopen(const char *pcfilename, const int iflags, const mode_t tmode)
Definition: vblowlevel.c:32
ssize_t tvbwrite(const int ihandle, const void *pvbuffer, const size_t tcount)
Definition: vblowlevel.c:127
int ivbclose(const int ihandle)
Definition: vblowlevel.c:93
#define VBRDLOCK
Definition: isinternal.h:295
int ihandle
Definition: isinternal.h:456
int iindexhandle
Definition: isinternal.h:406
int ivbblockwrite(const int ihandle, const int iisindex, const off_t tblocknumber, const char *cbuffer)
Definition: vblowlevel.c:167
#define O_BINARY
Definition: fileio.c:90
ino_t tinode
Definition: isinternal.h:459
int ivbblockread(const int ihandle, const int iisindex, const off_t tblocknumber, char *cbuffer)
Definition: vblowlevel.c:137
#define unlikely(x)
Definition: common.h:437
#define VBWRLCKW
Definition: isinternal.h:298
off_t tvblseek(const int ihandle, off_t toffset, const int iwhence)
Definition: vblowlevel.c:107
int irefcount
Definition: isinternal.h:457
#define VB_MAX_FILES
Definition: isinternal.h:120
#define VBWRLOCK
Definition: isinternal.h:297
#define VBRDLCKW
Definition: isinternal.h:296
struct VBFILE svbfile[128 *3]
Definition: vblowlevel.c:24
#define VBUNLOCK
Definition: isinternal.h:294
dev_t tdevice
Definition: isinternal.h:458
ssize_t tvbread(const int ihandle, void *pvbuffer, const size_t tcount)
Definition: vblowlevel.c:117
int idatahandle
Definition: isinternal.h:405
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
static int iinitialized
Definition: vblowlevel.c:26
int inodesize
Definition: isinternal.h:402