GnuCOBOL  2.0
A free COBOL compiler
isread.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 /* Local functions */
23 
24 static int
25 istartrownumber (const int ihandle, const int imode, const int iisread)
26 {
27  struct DICTINFO *psvbptr;
28  int ibias = 1, ideleted = 1, ilockresult = 0, iresult = 0;
29 
30  psvbptr = psvbfile[ihandle];
31  switch (imode) {
32  case ISFIRST:
33  psvbptr->iisdisjoint = 1;
34  isrecnum = 1;
35  break;
36 
37  case ISLAST:
39  ibias = -1;
40  break;
41 
42  case ISNEXT: /* Falls thru to next case! */
43  if (unlikely(!iisread)) {
44  iserrno = EBADARG;
45  return -1;
46  }
47  isrecnum = psvbptr->trownumber;
48  if (psvbptr->iisdisjoint) {
49  ibias = 0;
50  break;
51  }
52  case ISGREAT: /* Falls thru to next case! */
53  isrecnum++;
54  case ISGTEQ:
55  break;
56 
57  case ISCURR: /* Falls thru to next case! */
58  if (unlikely(!iisread)) {
59  iserrno = EBADARG;
60  return -1;
61  }
62  case ISEQUAL:
63  ibias = 0;
64  break;
65 
66  case ISPREV:
67  if (unlikely(!iisread)) {
68  iserrno = EBADARG;
69  return -1;
70  }
71  isrecnum = psvbptr->trownumber;
72  isrecnum--;
73  ibias = -1;
74  break;
75 
76  default:
77  iserrno = EBADARG;
78  return -1;
79  }
80 
81  iserrno = ENOREC;
82  while (ideleted) {
83  if (isrecnum > 0
84  && isrecnum <= inl_ldquad (psvbptr->sdictnode.cdatacount)) {
85  if (psvbptr->iopenmode & ISAUTOLOCK || imode & ISLOCK) {
86  if (ivbdatalock (ihandle, imode & ISWAIT ? VBWRLCKW : VBWRLOCK, (off_t)isrecnum)) {
87  ilockresult = ELOCKED;
88  iresult = -1;
89  }
90  }
91  if (!ilockresult) {
92  iresult = ivbdataread (ihandle,
93  (void *)psvbptr->ppcrowbuffer,
94  &ideleted, (off_t)isrecnum);
95  }
96  if (iresult) {
97  isrecnum = 0;
98  iserrno = EBADFILE;
99  return -1;
100  }
101  }
102  if (!ideleted) {
103  psvbptr->trownumber = isrecnum;
104  iserrno = 0;
105  return 0;
106  }
107  if (!ibias) {
108  isrecnum = 0;
109  return -1;
110  }
111  isrecnum += ibias;
112  if (isrecnum < 1
113  || isrecnum > inl_ldquad (psvbptr->sdictnode.cdatacount)) {
114  isrecnum = 0;
115  return -1;
116  }
117  }
118  return 0;
119 }
120 
121 /* Global functions */
122 
123 int
124 ivbcheckkey (const int ihandle, struct keydesc *pskey, const int imode,
125  int irowlength, const int iisbuild)
126 {
127  struct DICTINFO *psvbptr;
128  struct keydesc *pslocalkey;
129  struct keypart *pskptr;
130  struct keypart *psklptr;
131  int iloop, ipart, itype, ilocalkeylength;
132 
133  psvbptr = psvbfile[ihandle];
134  if (imode) {
135  irowlength = psvbptr->iminrowlength;
136  }
137  if (imode < 2) {
138  /* Basic key validity test */
139  pskey->k_len = 0;
140  if (pskey->k_flags < 0 || pskey->k_flags > COMPRESS + ISDUPS) {
141  goto vbcheckkey_exit;
142  }
143  if (pskey->k_nparts >= NPARTS || pskey->k_nparts < 0) {
144  goto vbcheckkey_exit;
145  }
146  if (pskey->k_nparts == 0 && !iisbuild) {
147  goto vbcheckkey_exit;
148  }
149  for (ipart = 0; ipart < pskey->k_nparts; ipart++) {
150  /* Wierdly enough, a single keypart CAN span multiple instances */
151  /* EG: Part number 1 might contain 4 long values */
152  pskptr = &pskey->k_part[ipart];
153  pskey->k_len += pskptr->kp_leng;
154  if (pskey->k_len > VB_MAX_KEYLEN) {
155  goto vbcheckkey_exit;
156  }
157  itype = pskptr->kp_type & ~ISDESC;
158  switch (itype) {
159  case CHARTYPE:
160  break;
161 
162  case INTTYPE:
163  if (pskptr->kp_leng % INTSIZE) {
164  goto vbcheckkey_exit;
165  }
166  break;
167 
168  case LONGTYPE:
169  if (pskptr->kp_leng % LONGSIZE) {
170  goto vbcheckkey_exit;
171  }
172  break;
173 
174  case QUADTYPE:
175  if (pskptr->kp_leng % QUADSIZE) {
176  goto vbcheckkey_exit;
177  }
178  break;
179 
180  case FLOATTYPE:
181  if (pskptr->kp_leng % FLOATSIZE) {
182  goto vbcheckkey_exit;
183  }
184  break;
185 
186  case DOUBLETYPE:
187  if (pskptr->kp_leng % DOUBLESIZE) {
188  goto vbcheckkey_exit;
189  }
190  break;
191 
192  default:
193  goto vbcheckkey_exit;
194  }
195  if (pskptr->kp_start + pskptr->kp_leng > irowlength) {
196  goto vbcheckkey_exit;
197  }
198  if (pskptr->kp_start < 0) {
199  goto vbcheckkey_exit;
200  }
201  }
202  if (!imode) {
203  return 0;
204  }
205  }
206 
207  /* Check whether the key already exists */
208  for (iloop = 0; iloop < psvbptr->inkeys; iloop++) {
209  pslocalkey = psvbptr->pskeydesc[iloop];
210  if (pslocalkey->k_nparts != pskey->k_nparts) {
211  continue;
212  }
213  ilocalkeylength = 0;
214  for (ipart = 0; ipart < pslocalkey->k_nparts; ipart++) {
215  pskptr = &pskey->k_part[ipart];
216  psklptr = &pslocalkey->k_part[ipart];
217  if (psklptr->kp_start != pskptr->kp_start) {
218  break;
219  }
220  if (psklptr->kp_leng != pskptr->kp_leng) {
221  break;
222  }
223  if (psklptr->kp_type != pskptr->kp_type) {
224  break;
225  }
226  ilocalkeylength += pskptr->kp_leng;
227  }
228  if (ipart == pslocalkey->k_nparts) {
229  pskey->k_len = ilocalkeylength;
230  break; /* found */
231  }
232  }
233  if (iloop == psvbptr->inkeys) {
234  if (imode == 2) {
235  goto vbcheckkey_exit;
236  }
237  return iloop;
238  }
239  if (imode == 1) {
240  goto vbcheckkey_exit;
241  }
242  return iloop;
243 
244 vbcheckkey_exit:
245  iserrno = EBADKEY;
246  return -1;
247 }
248 
249 int
250 isread (const int ihandle, char *pcrow, int imode)
251 {
252  struct VBKEY *pskey;
253  struct DICTINFO *psvbptr;
254  int ideleted = 0, ikeynumber, ilockresult = 0;
255  int ireadmode, iresult = -1;
256  unsigned char ckeyvalue[VB_MAX_KEYLEN];
257 
258  if (ivbenter (ihandle, 0, 0)) {
259  return -1;
260  }
261 
262  iserrno = EBADKEY;
263  psvbptr = psvbfile[ihandle];
264  ikeynumber = psvbptr->iactivekey;
265 
266  if (psvbptr->iopenmode & ISAUTOLOCK) {
267  isrelease (ihandle);
268  }
269 
270  ireadmode = imode & BYTEMASK;
271 
272  if (ikeynumber == -1 || !psvbptr->pskeydesc[ikeynumber]->k_nparts) {
273  /*
274  * This code relies on the fact that istartrownumber will
275  * populate the global VBISAM pcrowbuffer with the fixed-length
276  * portion of the row on success.
277  */
278  iresult = istartrownumber (ihandle, ireadmode, 1);
279  if (!iresult) {
280  memcpy (pcrow, psvbptr->ppcrowbuffer, (size_t)psvbptr->iminrowlength);
281  psvbptr->iisdisjoint = 0;
282  }
283  goto read_exit;
284  }
285  iserrno = 0;
286  isrecnum = 0;
287  switch (ireadmode) {
288  case ISFIRST:
289  /* ckeyvalue is just a placeholder for ISFIRST */
290  iresult = ivbkeysearch (ihandle, ISFIRST, ikeynumber, 0, ckeyvalue, (off_t)0);
291  if (iresult < 0) {
292  break;
293  }
294  if (iresult == 2) {
295  iserrno = EENDFILE;
296  } else {
297  iresult = 0;
298  }
299  break;
300 
301  case ISLAST:
302  /*
303  * ckeyvalue is just a placeholder for ISLAST
304  * Note that the KeySearch (ISLAST) will position the pointer onto the
305  * LAST key of the LAST tree which, by definition, is a DUMMY key
306  */
307  iresult = ivbkeysearch (ihandle, ISLAST, ikeynumber, 0, ckeyvalue, (off_t)0);
308  if (iresult < 0) {
309  break;
310  }
311  if (iresult == 2) {
312  iserrno = EENDFILE;
313  } else {
314  iresult = 0;
315  iserrno = ivbkeyload (ihandle, ikeynumber, ISPREV, 1, &pskey);
316  if (iserrno) {
317  iresult = -1;
318  }
319  }
320  break;
321 
322  case ISEQUAL:
323  vvbmakekey (psvbptr->pskeydesc[ikeynumber], pcrow, ckeyvalue);
324  iresult = ivbkeysearch (ihandle, ISGTEQ, ikeynumber, 0, ckeyvalue, (off_t)0);
325  if (iresult == -1) { /* Error */
326  break;
327  }
328  if (iresult == 1) { /* Found it! */
329  iresult = 0;
330  } else {
331  if (psvbptr->pskeycurr[ikeynumber]->iisdummy) {
332  iresult = ivbkeyload (ihandle, ikeynumber, ISNEXT, 1, &pskey);
333  if (iresult == EENDFILE) {
334  iresult = -1;
335  iserrno = ENOREC;
336  break;
337  }
338  iserrno = 0;
339  }
340  if (memcmp (ckeyvalue, psvbptr->pskeycurr[ikeynumber]->ckey,
341  (size_t)psvbptr->pskeydesc[ikeynumber]->k_len)) {
342  iresult = -1;
343  iserrno = ENOREC;
344  } else {
345  iresult = 0;
346  }
347  }
348  break;
349 
350  case ISGREAT:
351  case ISGTEQ:
352  vvbmakekey (psvbptr->pskeydesc[ikeynumber], pcrow, ckeyvalue);
353  iresult = ivbkeysearch (ihandle, ireadmode, ikeynumber, 0, ckeyvalue, (off_t)0);
354  if (iresult < 0) { /* Error is always error */
355  break;
356  }
357  if (iresult == 2) {
358  iserrno = EENDFILE;
359  break;
360  }
361  if (iresult == 1) {
362  iresult = 0;
363  } else {
364  iresult = 0;
365  if (psvbptr->pskeycurr[ikeynumber]->iisdummy) {
366  iserrno = EENDFILE;
367  iresult = -1;
368  }
369  }
370  break;
371 
372  case ISPREV:
373  if (psvbptr->trowstart) {
374  iresult = ivbkeylocaterow (ihandle, ikeynumber,
375  psvbptr->trowstart);
376  } else if (psvbptr->trownumber) {
377  iresult = ivbkeylocaterow (ihandle, ikeynumber,
378  psvbptr->trownumber);
379  } else {
380  iserrno = ENOCURR;
381  iresult = -1;
382  break;
383  }
384  if (iresult) {
385  iserrno = ENOCURR;
386  } else {
387  iresult = 0;
388  iserrno = ivbkeyload (ihandle, ikeynumber, ISPREV, 1, &pskey);
389  if (iserrno) {
390  iresult = -1;
391  }
392  }
393  break;
394 
395  case ISNEXT: /* Might fall thru to ISCURR */
396  if (!psvbptr->iisdisjoint) {
397  if (psvbptr->trowstart) {
398  iresult = ivbkeylocaterow (ihandle, ikeynumber,
399  psvbptr->trowstart);
400  } else if (psvbptr->trownumber) {
401  iresult = ivbkeylocaterow (ihandle, ikeynumber,
402  psvbptr->trownumber);
403  } else {
404  iserrno = ENOCURR;
405  iresult = -1;
406  break;
407  }
408  if (iresult) {
409  iserrno = EENDFILE;
410  } else {
411  iresult = 0;
412  iserrno = ivbkeyload (ihandle, ikeynumber, ISNEXT, 1, &pskey);
413  if (iserrno) {
414  iresult = -1;
415  }
416  }
417  break; /* Exit the switch case */
418  }
419  case ISCURR:
420  if (psvbptr->trowstart) {
421  iresult = ivbkeylocaterow (ihandle, ikeynumber, psvbptr->trowstart);
422  } else if (psvbptr->trownumber) {
423  iresult = ivbkeylocaterow (ihandle, ikeynumber,
424  psvbptr->trownumber);
425  } else {
426  iserrno = ENOCURR;
427  iresult = -1;
428  break;
429  }
430  if (iresult) {
431  iserrno = ENOCURR;
432  }
433  break;
434 
435  default:
436  iserrno = EBADARG;
437  iresult = -1;
438  }
439  /* By the time we get here, we're done with index positioning... */
440  /* If iresult == 0 then we have a valid row to read in */
441  if (!iresult) {
442  psvbptr->trowstart = 0;
443  if (imode & ISLOCK || psvbptr->iopenmode & ISAUTOLOCK) {
444  if (ivbdatalock
445  (ihandle, imode & ISWAIT ? VBWRLCKW : VBWRLOCK,
446  psvbptr->pskeycurr[ikeynumber]->trownode)) {
447  iresult = -1;
448  iserrno = ilockresult = ELOCKED;
449  }
450  }
451  if (!ilockresult) {
452  iresult = ivbdataread (ihandle, pcrow, &ideleted,
453  psvbptr->pskeycurr[ikeynumber]->trownode);
454  }
455  if (!iresult && (!ilockresult || (imode & ISSKIPLOCK && iserrno == ELOCKED))) {
456  isrecnum = psvbptr->pskeycurr[ikeynumber]->trownode;
457  psvbptr->trownumber = isrecnum;
458  psvbptr->iisdisjoint = 0;
459  }
460  }
461 
462 read_exit:
463  psvbptr->iisdictlocked |= 0x04;
464  ivbexit (ihandle);
465  return iresult;
466 }
467 
468 int
469 isstart (const int ihandle, struct keydesc *pskeydesc, int ilength, char *pcrow, int imode)
470 {
471  struct VBKEY *pskey;
472  struct DICTINFO *psvbptr;
473  int ikeynumber, iresult;
474  unsigned char ckeyvalue[VB_MAX_KEYLEN];
475  unsigned char ckeyvalue2[VB_MAX_KEYLEN];
476 
477  if (ivbenter (ihandle, 0, 0)) {
478  return -1;
479  }
480 
481  psvbptr = psvbfile[ihandle];
482  ikeynumber = ivbcheckkey (ihandle, pskeydesc, 2, 0, 0);
483  iresult = -1;
484  if (ikeynumber == -1 && pskeydesc->k_nparts) {
485  goto startexit;
486  }
487  if (ilength < 1 || ilength > psvbptr->pskeydesc[ikeynumber]->k_len) {
488  ilength = pskeydesc->k_len;
489  }
490  psvbptr->iactivekey = ikeynumber;
491  if (!(imode & ISKEEPLOCK)) {
492  isrelease (ihandle);
493  }
494  imode &= BYTEMASK;
495  if (!pskeydesc->k_nparts) {
496  iresult = istartrownumber (ihandle, imode, 0);
497  if (iresult && iserrno == ENOREC && imode <= ISLAST) {
498  iresult = 0;
499  iserrno = 0;
500  }
501  goto startexit;
502  }
503  iserrno = 0;
504  switch (imode) {
505  case ISFIRST: /* ckeyvalue is just a placeholder for 1st/last */
506  psvbptr->iisdisjoint = 1;
507  iresult = ivbkeysearch (ihandle, ISFIRST, ikeynumber, 0, ckeyvalue, (off_t)0);
508  if (iresult < 0) {
509  break;
510  }
511  iresult = 0;
512  break;
513 
514  case ISLAST: /* ckeyvalue is just a placeholder for 1st/last */
515  psvbptr->iisdisjoint = 0;
516  iresult = ivbkeysearch (ihandle, ISLAST, ikeynumber, 0, ckeyvalue, (off_t)0);
517  if (iresult < 0 || iresult > 2) {
518  iresult = -1;
519  break;
520  }
521  iserrno = ivbkeyload (ihandle, ikeynumber, ISPREV, 1, &pskey);
522  if (iserrno) {
523  iresult = -1;
524  }
525  break;
526 
527  case ISEQUAL:
528  psvbptr->iisdisjoint = 1;
529  vvbmakekey (psvbptr->pskeydesc[ikeynumber], pcrow, ckeyvalue2);
530  memset (ckeyvalue, 0, sizeof (ckeyvalue));
531  memcpy (ckeyvalue, ckeyvalue2, (size_t)ilength);
532  if (ilength < pskeydesc->k_len) {
533  iresult = ivbkeysearch (ihandle, ISGTEQ, ikeynumber, 0, ckeyvalue, (off_t)0);
534  } else {
535  iresult = ivbkeysearch (ihandle, ISEQUAL, ikeynumber, ilength, ckeyvalue, (off_t)0);
536  }
537  iserrno = EBADFILE;
538  if (iresult == -1) { /* Error */
539  break;
540  }
541  /* Map EQUAL onto OK and LESS THAN onto OK if the basekey is == */
542  if (iresult == 1) {
543  iresult = 0;
544  } else if (iresult == 0
545  && memcmp (ckeyvalue,
546  psvbptr->pskeycurr[psvbptr->iactivekey]->ckey,
547  (size_t)ilength)) {
548  iserrno = ENOREC;
549  iresult = -1;
550  }
551  break;
552 
553  case ISGREAT:
554  case ISGTEQ:
555  psvbptr->iisdisjoint = 1;
556  vvbmakekey (psvbptr->pskeydesc[ikeynumber], pcrow, ckeyvalue2);
557  if (ilength < pskeydesc->k_len && imode == ISGREAT) {
558  memset (ckeyvalue, 255, sizeof (ckeyvalue));
559  } else {
560  memset (ckeyvalue, 0, sizeof (ckeyvalue));
561  }
562  memcpy (ckeyvalue, ckeyvalue2, (size_t)ilength);
563  iresult = ivbkeysearch (ihandle, imode, ikeynumber, 0, ckeyvalue, (off_t)0);
564  if (iserrno == EENDFILE) {
565  iserrno = ENOREC;
566  iresult = -1;
567  break;
568  }
569  if (iresult < 0) { /* Error is always error */
570  break;
571  }
572  if (iresult < 2) {
573  iresult = 0;
574  break;
575  }
576  iserrno = EENDFILE;
577  iresult = -1;
578  break;
579 
580  default:
581  iserrno = EBADARG;
582  iresult = -1;
583  }
584  if (!iresult) {
585  iserrno = 0;
586  isrecnum = psvbptr->pskeycurr[ikeynumber]->trownode;
587  psvbptr->trowstart = isrecnum;
588  } else {
589  psvbptr->trowstart = 0;
590  iresult = -1;
591  }
592 startexit:
593  psvbptr->iisdictlocked |= 0x04;
594  ivbexit (ihandle);
595  return iresult;
596 }
static int istartrownumber(const int ihandle, const int imode, const int iisread)
Definition: isread.c:25
int inkeys
Definition: isinternal.h:400
int ivbkeysearch(const int ihandle, const int imode, const int ikeynumber, int ilength, unsigned char *pckeyvalue, off_t tdupnumber)
Definition: vbkeysio.c:372
unsigned char ckey[1]
Definition: isinternal.h:334
int ivbkeylocaterow(const int ihandle, const int ikeynumber, off_t trownumber)
Definition: vbkeysio.c:435
int ivbcheckkey(const int ihandle, struct keydesc *pskey, const int imode, int irowlength, const int iisbuild)
Definition: isread.c:124
int ivbenter(const int ihandle, const unsigned int imodifying, const unsigned int ispecial)
Definition: vblocking.c:178
unsigned char iisdummy
Definition: isinternal.h:332
int ivbkeyload(const int ihandle, const int ikeynumber, const int imode, const int isetcurr, struct VBKEY **ppskey)
Definition: vbkeysio.c:503
int iminrowlength
Definition: isinternal.h:403
int isstart(const int ihandle, struct keydesc *pskeydesc, int ilength, char *pcrow, int imode)
Definition: isread.c:469
char cdatacount[8]
Definition: isinternal.h:375
#define unlikely(x)
Definition: common.h:437
#define VBWRLCKW
Definition: isinternal.h:298
unsigned char iisdictlocked
Definition: isinternal.h:427
off_t trowstart
Definition: isinternal.h:418
int ivbdatalock(const int ihandle, const int imode, const off_t trownumber)
Definition: vblocking.c:432
struct VBKEY * pskeycurr[32]
Definition: isinternal.h:448
struct DICTNODE sdictnode
Definition: isinternal.h:444
off_t trownode
Definition: isinternal.h:328
void vvbmakekey(const struct keydesc *pskeydesc, char *pcrow_buffer, unsigned char *pckeyvalue)
Definition: vbkeysio.c:212
int ivbdataread(const int ihandle, char *pcbuffer, int *pideletedrow, const off_t trownumber)
Definition: vbdataio.c:493
#define VBWRLOCK
Definition: isinternal.h:297
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
#define QUADSIZE
Definition: isinternal.h:108
int iactivekey
Definition: isinternal.h:401
int ivbexit(const int ihandle)
Definition: vblocking.c:290
int iopenmode
Definition: isinternal.h:412
int isread(const int ihandle, char *pcrow, int imode)
Definition: isread.c:250
unsigned char iisdisjoint
Definition: isinternal.h:425
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
static off_t inl_ldquad(void *pclocation)
Definition: isinternal.h:238
int isrelease(const int ihandle)
Definition: ishelper.c:126
off_t trownumber
Definition: isinternal.h:416
char * ppcrowbuffer
Definition: isinternal.h:423
int iserrno
Definition: vbmemio.c:27
int isrecnum
Definition: vbmemio.c:30