GnuCOBOL  2.0
A free COBOL compiler
vbdataio.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 struct SVARLEN {
23  char crfu[INTSIZE]; /* Always 0x0000 */
24  char cconst[INTSIZE]; /* Always 0x7e26 */
25  char cfreenext[QUADSIZE]; /* Pointer to next in group with space */
26  char cfreeprev[QUADSIZE]; /* Pointer to prev in group with space */
27  char cfreethis[INTSIZE]; /* Free space in THIS node */
28  char cfreeoffset[INTSIZE]; /* Position in node of free space */
29  char cfreecont[QUADSIZE]; /* Continuation node (Only on FULL node) */
30  char cflag; /* Unknown, set to 0x00 */
31 #if ISAMMODE == 1
32  char cusedcount[INTSIZE]; /* Number of slots in use */
33 #else
34  char cusedcount; /* Number of slots in use */
35 #endif
36  char cgroup; /* Used as a reference in dictionary */
37 };
38 
39 #if ISAMMODE == 1
40 static const int igroupsize[] = {
41  QUADSIZE, 16, 32, 64, 128, 256, 512, 1024, 2048, MAX_NODE_LENGTH
42 };
43 #else
44 static const int igroupsize[] = {
45  QUADSIZE, 8, 32, 128, 512, MAX_NODE_LENGTH
46 };
47 #endif
48 
49 static char cnode[VB_NODE_MAX];
50 static struct SVARLEN *psvarlenheader = (struct SVARLEN *)cnode;
51 
52 /* Local functions */
53 
54 /* Locate space for, and fill in the tail content. */
55 /* Write out the tail node, and return the tail node number. */
56 /* Fill in the slot number used in the tail node */
57 
58 static off_t
59 ttailnode (const int ihandle, char *pcbuffer, const int ilength, int *pislotnumber)
60 {
61  struct DICTINFO *psvbptr;
62  char *pcnodeptr;
63  struct SVARLEN *pshdr;
64  struct SVARLEN *psnphdr;
65  off_t tnodenumber = 0, tnodenext, tnodeprev;
66  int ifreethis, ifreeoffset, igroup, islotnumber;
67  int inodesize;
68  int n;
69  char clclnode[VB_NODE_MAX];
70  char cnextprev[VB_NODE_MAX];
71 
72  psvbptr = psvbfile[ihandle];
73  pshdr = (struct SVARLEN *)clclnode;
74  psnphdr = (struct SVARLEN *)cnextprev;
75  inodesize = psvbptr->inodesize;
76  /* Determine which group to START with */
77  for (igroup = 0; igroupsize[igroup] < ilength + INTSIZE + INTSIZE; igroup++) {
78  ; /* Do nothing! */
79  }
80  if (igroup) {
81  igroup--;
82  }
83  while (!tnodenumber) {
84  tnodenumber =
85  inl_ldquad (psvbptr->sdictnode.cvarleng0 + (igroup * QUADSIZE));
86  while (tnodenumber) {
87  if (ivbblockread (ihandle, 1, tnodenumber, clclnode)) {
88  return -1;
89  }
90  if (inl_ldint (pshdr->cfreethis) < (ilength + INTSIZE + INTSIZE)) {
91  tnodenumber = inl_ldquad (pshdr->cfreenext);
92  } else {
93  break;
94  }
95  }
96  if (tnodenumber) {
97  break;
98  }
99  if (igroupsize[igroup] >= MAX_NODE_LENGTH) {
100  break;
101  }
102  igroup++;
103  }
104  if (!tnodenumber) {
105  tnodenumber = tvbnodecountgetnext (ihandle);
106  if (tnodenumber == -1) {
107  return tnodenumber;
108  }
109  memset (clclnode, 0, VB_NODE_MAX);
110  inl_stint (0x7e26, pshdr->cconst);
111  inl_stint (inodesize -
112  (sizeof (struct SVARLEN) + 3 + INTSIZE + INTSIZE), pshdr->cfreethis);
113  inl_stint (sizeof (struct SVARLEN), pshdr->cfreeoffset);
114  pshdr->cgroup = -1;
115  clclnode[inodesize - 3] = 0x7c;
116  *pislotnumber = 0;
117 #if ISAMMODE == 1
118  inl_stint (1, pshdr->cusedcount);
119 #else
120  pshdr->cusedcount = 1;
121 #endif
122  } else {
123  *pislotnumber = -1;
124  pcnodeptr = clclnode + inodesize - (3 + INTSIZE + INTSIZE);
125 #if ISAMMODE == 1
126  n = inl_ldint (pshdr->cusedcount);
127 #else
128  n = pshdr->cusedcount;
129 #endif
130  for (islotnumber = 0; islotnumber < n; islotnumber++) {
131  if (inl_ldint (pcnodeptr)) {
132  pcnodeptr -= (INTSIZE * 2);
133  continue;
134  } else {
135  *pislotnumber = islotnumber;
136  break;
137  }
138  }
139  if (*pislotnumber == -1) {
140 #if ISAMMODE == 1
141  *pislotnumber = inl_ldint (pshdr->cusedcount);
142  inl_stint (*(pislotnumber) + 1, pshdr->cusedcount);
143 #else
144  *pislotnumber = pshdr->cusedcount;
145  pshdr->cusedcount++;
146 #endif
147  n = inl_ldint (pshdr->cfreethis) - (INTSIZE * 2);
148  inl_stint (n, pshdr->cfreethis);
149  }
150  }
151  ifreethis = inl_ldint (pshdr->cfreethis);
152  ifreeoffset = inl_ldint (pshdr->cfreeoffset);
153  pcnodeptr = clclnode + inodesize - (3 + INTSIZE + INTSIZE +
154  (*pislotnumber * INTSIZE * 2));
155  inl_stint (ilength, pcnodeptr);
156  inl_stint (ifreeoffset, pcnodeptr + INTSIZE);
157  memcpy (clclnode + ifreeoffset, pcbuffer, (size_t)ilength);
158  ifreethis -= ilength;
159  inl_stint (ifreethis, pshdr->cfreethis);
160  ifreeoffset += ilength;
161  inl_stint (ifreeoffset, pshdr->cfreeoffset);
162  /* Determine which 'group' the node belongs in now */
163  for (igroup = 0; igroupsize[igroup] < ifreethis; igroup++) {
164  ; /* Do nothing! */
165  }
166  if (igroup) {
167  igroup--;
168  }
169  if (igroup != pshdr->cgroup) {
170  tnodenext = inl_ldquad (pshdr->cfreenext);
171  tnodeprev = inl_ldquad (pshdr->cfreeprev);
172  if (tnodeprev) {
173  if (ivbblockread (ihandle, 1, tnodeprev, cnextprev)) {
174  return -1;
175  }
176  inl_stquad (tnodenext, psnphdr->cfreenext);
177  if (ivbblockwrite (ihandle, 1, tnodeprev, cnextprev)) {
178  return -1;
179  }
180  }
181  if (tnodenext) {
182  if (ivbblockread (ihandle, 1, tnodenext, cnextprev)) {
183  return -1;
184  }
185  inl_stquad (tnodeprev, psnphdr->cfreeprev);
186  if (ivbblockwrite (ihandle, 1, tnodenext, cnextprev)) {
187  return -1;
188  }
189  }
190  inl_stquad ((off_t)0, pshdr->cfreeprev);
191  tnodenext =
192  inl_ldquad (psvbptr->sdictnode.cvarleng0 + (igroup * QUADSIZE));
193  inl_stquad (tnodenext, pshdr->cfreenext);
194  if (tnodenext) {
195  if (ivbblockread (ihandle, 1, tnodenext, cnextprev)) {
196  return -1;
197  }
198  inl_stquad (tnodenumber, psnphdr->cfreeprev);
199  if (ivbblockwrite (ihandle, 1, tnodenext, cnextprev)) {
200  return -1;
201  }
202  }
203  if (pshdr->cgroup >= 0) {
204  inl_stquad (tnodenext,
205  psvbptr->sdictnode.cvarleng0 +
206  (pshdr->cgroup * QUADSIZE));
207  }
208  inl_stquad (tnodenumber,
209  psvbptr->sdictnode.cvarleng0 + (igroup * QUADSIZE));
210  psvbptr->iisdictlocked |= 0x02;
211  pshdr->cgroup = igroup;
212  }
213  if (ivbblockwrite (ihandle, 1, tnodenumber, clclnode)) {
214  return -1;
215  }
216  return tnodenumber;
217 }
218 
219 static int
220 ivbvarlenread (const int ihandle, char *pcbuffer, off_t tnodenumber, int islotnumber, int ilength)
221 {
222  char *pcnodeptr;
223  int iresult, islotlength, islotoffset;
224  int inodesize;
225 
226  inodesize = psvbfile[ihandle]->inodesize;
227  while (1) {
228  iresult = ivbblockread (ihandle, 1, tnodenumber, cnode);
229  if (iresult) {
230  return -1;
231  }
232  if (inl_ldint (psvarlenheader->cconst) != 0x7e26) {
233  iserrno = EBADFILE;
234  return -1;
235  }
236  pcnodeptr = cnode + inodesize - 3;
237  if (*pcnodeptr != 0x7c) {
238  iserrno = EBADFILE;
239  return -1;
240  }
241  pcnodeptr -= ((islotnumber + 1) * INTSIZE * 2);
242  islotlength = inl_ldint (pcnodeptr);
243  islotoffset = inl_ldint (pcnodeptr + INTSIZE);
244  if (islotlength <= ilength) {
245  if (inl_ldquad (psvarlenheader->cfreecont) != 0) {
246  iserrno = EBADFILE;
247  return -1;
248  }
249  memcpy (pcbuffer, cnode + islotoffset, (size_t)ilength);
250  return 0;
251  }
252  ilength -= islotlength;
253 #if ISAMMODE == 1
254  islotnumber = inl_ldint (psvarlenheader->cfreecont);
255  islotnumber >>= 6;
256  *(psvarlenheader->cfreecont + 1) &= (unsigned char)0x3f;
257 #else
258  islotnumber = *(psvarlenheader->cfreecont);
259 #endif
260  *(psvarlenheader->cfreecont) = 0;
261  tnodenumber = inl_ldquad (psvarlenheader->cfreecont);
262  }
263  return 0;
264 }
265 
266 /* MUST populate psvbfile [ihandle]->tvarlennode */
267 /* MUST populate psvbfile [ihandle]->ivarlenslot */
268 /* MUST populate psvbfile [ihandle]->ivarlenlength */
269 static int
270 ivbvarlenwrite (const int ihandle, char *pcbuffer, int ilength)
271 {
272  struct DICTINFO *psvbptr;
273  off_t tnewnode, tnodenumber = 0;
274  int islotnumber;
275  int inodesize;
276  int n;
277 
278  psvbptr = psvbfile[ihandle];
279  psvbptr->ivarlenlength = ilength;
280  psvbptr->tvarlennode = 0;
281  inodesize = psvbptr->inodesize;
282  /* Write out 'FULL' nodes first */
283  while (ilength > 0) {
284  if (ilength >
285  (inodesize - (int)(3 + INTSIZE + INTSIZE + sizeof (struct SVARLEN)))) {
286  tnewnode = tvbnodecountgetnext (ihandle);
287  if (tnewnode == -1) {
288  return -1;
289  }
290  if (tnodenumber) {
291  inl_stquad (tnewnode, psvarlenheader->cfreecont);
292  if (ivbblockwrite (ihandle, 1, tnodenumber, cnode)) {
293  return -1;
294  }
295  } else {
296  psvbptr->tvarlennode = tnewnode;
297  psvbptr->ivarlenslot = 0;
298  }
299  inl_stint (0, psvarlenheader->crfu);
300  inl_stint (0x7e26, psvarlenheader->cconst);
301  inl_stquad ((off_t)0, psvarlenheader->cfreenext);
302  inl_stquad ((off_t)0, psvarlenheader->cfreeprev);
303  inl_stint (0, psvarlenheader->cfreethis);
304  inl_stint (inodesize - (3 + INTSIZE + INTSIZE),
305  psvarlenheader->cfreeoffset);
306  psvarlenheader->cflag = 0x01;
307 #if ISAMMODE == 1
308  inl_stint (1, psvarlenheader->cusedcount);
309 #else
310  psvarlenheader->cusedcount = 1;
311 #endif
312  psvarlenheader->cgroup = 0x00;
313  memcpy (&(psvarlenheader->cgroup) + 1, pcbuffer,
314  inodesize - (3 + INTSIZE + INTSIZE +
315  sizeof (struct SVARLEN)));
316  pcbuffer +=
317  inodesize - (3 + INTSIZE + INTSIZE +
318  sizeof (struct SVARLEN));
319  ilength -=
320  inodesize - (3 + INTSIZE + INTSIZE +
321  sizeof (struct SVARLEN));
322  /* Length */
323  inl_stint (inodesize -
324  (3 + INTSIZE + INTSIZE + sizeof (struct SVARLEN)),
325  cnode + inodesize - (3 + INTSIZE + INTSIZE));
326  /* Offset */
327  inl_stint (&(psvarlenheader->cgroup) + 1 - cnode,
328  cnode + inodesize - (3 + INTSIZE));
329  *(cnode + inodesize - 3) = 0x7c;
330  *(cnode + inodesize - 2) = 0x0;
331  *(cnode + inodesize - 1) = 0x0;
332  tnodenumber = tnewnode;
333  continue;
334  }
335  if (!psvbptr->tvarlennode) {
336  psvbptr->tvarlennode = tnodenumber;
337  psvbptr->ivarlenslot = 0;
338  }
339  /* If tnodenumber is != 0, we still need to write it out! */
340  if (tnodenumber && !ilength) {
341  return ivbblockwrite (ihandle, 1, tnodenumber, cnode);
342  }
343  /* Now, to deal with the 'tail' */
344  tnewnode = ttailnode (ihandle, pcbuffer, ilength, &islotnumber);
345  if (tnewnode == -1) {
346  return -1;
347  }
348  if (tnodenumber) {
349  inl_stquad (tnewnode, psvarlenheader->cfreecont);
350 #if ISAMMODE == 1
351  n = (islotnumber << 6) + inl_ldint (psvarlenheader->cfreecont);
352  inl_stint (n, psvarlenheader->cfreecont);
353 #else
354  *psvarlenheader->cfreecont = islotnumber;
355 #endif
356  if (ivbblockwrite (ihandle, 1, tnodenumber, cnode)) {
357  return -1;
358  }
359  if (!psvbptr->tvarlennode) {
360  psvbptr->tvarlennode = tnodenumber;
361  psvbptr->ivarlenslot = 0;
362  }
363  }
364  if (!psvbptr->tvarlennode) {
365  psvbptr->tvarlennode = tnewnode;
366  psvbptr->ivarlenslot = islotnumber;
367  }
368  return 0;
369  }
370  return -1;
371 }
372 
373 /* MUST update the group number (if applicable) */
374 /* MUST update the dictionary node (if applicable) */
375 static int
376 ivbvarlendelete (const int ihandle, off_t tnodenumber, int islotnumber, int ilength)
377 {
378  struct DICTINFO *psvbptr;
379  off_t tnodenext, tnodeprev;
380  int ifreethis, ifreeoffset, igroup,
381  iisanyused, iloop, imovelength,
382  ioffset, ithislength, ithisoffset, iusedcount;
383  int inodesize;
384 
385  psvbptr = psvbfile[ihandle];
386  inodesize = psvbptr->inodesize;
387  while (ilength > 0) {
388  if (ivbblockread (ihandle, 1, tnodenumber, cnode)) {
389  return -1;
390  }
391  ithislength = inl_ldint (cnode + inodesize -
392  (3 + INTSIZE + INTSIZE + (islotnumber * 2 * INTSIZE)));
393  ilength -= ithislength;
394  inl_stint (0, cnode + inodesize -
395  (3 + INTSIZE + INTSIZE + (islotnumber * 2 * INTSIZE)));
396  ithisoffset = inl_ldint (cnode + inodesize -
397  (3 + INTSIZE + (islotnumber * 2 * INTSIZE)));
398  inl_stint (0, cnode + inodesize -
399  (3 + INTSIZE + (islotnumber * 2 * INTSIZE)));
400 #if ISAMMODE == 1
401  iusedcount = inl_ldint (psvarlenheader->cusedcount);
402 #else
403  iusedcount = psvarlenheader->cusedcount;
404 #endif
405  iisanyused = 0;
406  for (iloop = 0; iloop < iusedcount; iloop++) {
407  if (inl_ldint (cnode + inodesize -
408  (3 + INTSIZE + INTSIZE + (iloop * 2 * INTSIZE)))) {
409  iisanyused = 1;
410  break;
411  }
412  }
413  if (!iisanyused) {
414  tnodenext = inl_ldquad (psvarlenheader->cfreenext);
415  tnodeprev = inl_ldquad (psvarlenheader->cfreeprev);
416  igroup = psvarlenheader->cgroup;
417  if (inl_ldquad (psvbptr->sdictnode.cvarleng0 + (igroup * QUADSIZE)) ==
418  tnodenumber) {
419  inl_stquad (tnodenext,
420  psvbptr->sdictnode.cvarleng0 +
421  (igroup * QUADSIZE));
422  }
423  ivbnodefree (ihandle, tnodenumber);
424  tnodenumber = inl_ldquad (psvarlenheader->cfreecont);
425  if (tnodenext) {
426  if (ivbblockread (ihandle, 1, tnodenext, cnode)) {
427  return -1;
428  }
429  inl_stquad (tnodeprev, psvarlenheader->cfreeprev);
430  if (ivbblockwrite (ihandle, 1, tnodenext, cnode)) {
431  return -1;
432  }
433  }
434  if (tnodeprev) {
435  if (ivbblockread (ihandle, 1, tnodeprev, cnode)) {
436  return -1;
437  }
438  inl_stquad (tnodenext, psvarlenheader->cfreenext);
439  if (ivbblockwrite (ihandle, 1, tnodeprev, cnode)) {
440  return -1;
441  }
442  }
443  continue;
444  }
445  ifreethis = inl_ldint (psvarlenheader->cfreethis);
446  ifreeoffset = inl_ldint (psvarlenheader->cfreeoffset);
447  if (islotnumber == iusedcount) {
448  iusedcount--;
449 #if ISAMMODE == 1
450  inl_stint (iusedcount - 1, psvarlenheader->cusedcount);
451 #else
452  psvarlenheader->cusedcount = iusedcount;
453 #endif
454  ifreethis += (INTSIZE * 2);
455  }
456  imovelength = inodesize - (ithisoffset + ithislength);
457  imovelength -= (3 + (iusedcount * INTSIZE * 2));
458  memmove (cnode + ithisoffset, cnode + ithisoffset + ithislength, (size_t)imovelength);
459  ifreeoffset -= ithislength;
460  ifreethis += ithislength;
461  inl_stint (ifreethis, psvarlenheader->cfreethis);
462  inl_stint (ifreeoffset, psvarlenheader->cfreeoffset);
463  memset (cnode + ifreeoffset, 0, (size_t)ifreethis);
464  for (iloop = 0; iloop < iusedcount; iloop++) {
465  ioffset =
466  inl_ldint (cnode + inodesize -
467  (3 + INTSIZE + (iloop * 2 * INTSIZE)));
468  if (ioffset > ithisoffset) {
469  inl_stint (ioffset - ithislength,
470  cnode + inodesize -
471  (3 + INTSIZE + (iloop * 2 * INTSIZE)));
472  }
473  }
474  if (ivbblockwrite (ihandle, 1, tnodenumber, cnode)) {
475  return -1;
476  }
477  tnodenumber = inl_ldquad (psvarlenheader->cfreecont);
478  }
479  psvbptr->tvarlennode = 0;
480  return 0;
481 }
482 
483 /* Global functions */
484 
485  /* Comments:
486  * This function is *NOT* concerned with whether the row is deleted or not
487  * However, it *DOES* set *(pideletedrow) accordingly.
488  * The receiving buffer (pcbuffer) is only guaranteed to be long enough to
489  * hold the MINIMUM row length (exclusive of the 1 byte deleted flag) and
490  * thus we need to jump through hoops to avoid overwriting stuff beyond it.
491  */
492 int
493 ivbdataread (const int ihandle, char *pcbuffer, int *pideletedrow, const off_t trownumber)
494 {
495  struct DICTINFO *psvbptr;
496  off_t tblocknumber, toffset, tsofar;
497  int irowlength;
498  int n;
499  char cfooter[VB_NODE_MAX];
500  char cvbnodetmp[VB_NODE_MAX];
501  char pcreadbuffer[MAX_RESERVED_LENGTH];
502 
503  /* Sanity check - Is ihandle a currently open table? */
504  if (unlikely(ihandle < 0 || ihandle > ivbmaxusedhandle)) {
505  return ENOTOPEN;
506  }
507  if (!psvbfile[ihandle]) {
508  return ENOTOPEN;
509  }
510  if (trownumber < 1) {
511  return EBADARG;
512  }
513  psvbptr = psvbfile[ihandle];
514 
515  irowlength = psvbptr->iminrowlength;
516  irowlength++;
517  if (psvbptr->iopenmode & ISVARLEN) {
518  irowlength += INTSIZE + QUADSIZE;
519  } else {
520 /* RXW */
521  toffset = irowlength * (trownumber - 1);
522  if (tvblseek (psvbptr->idatahandle, toffset, SEEK_SET) != toffset) {
523  return EBADFILE;
524  }
525  memset (pcreadbuffer, 0, irowlength);
526  if (tvbread (psvbptr->idatahandle, pcreadbuffer, (size_t)irowlength) < 0) {
527  return EBADFILE;
528  }
529  memcpy (pcbuffer, pcreadbuffer, (size_t)psvbptr->iminrowlength);
530  if (pcreadbuffer[psvbptr->iminrowlength] == 0) {
531  *pideletedrow = 1;
532  } else {
533  *pideletedrow = 0;
534  }
535  isreclen = psvbptr->iminrowlength;
536  return 0;
537  }
538  toffset = irowlength * (trownumber - 1);
539  tblocknumber = (toffset / psvbptr->inodesize);
540  toffset -= (tblocknumber * psvbptr->inodesize);
541  if (ivbblockread (ihandle, 0, tblocknumber + 1, cvbnodetmp)) {
542  return EBADFILE;
543  }
544  /* Read in the *MINIMUM* rowlength and store it into pcbuffer */
545  tsofar = 0;
546  while (tsofar < psvbptr->iminrowlength) {
547  if ((psvbptr->iminrowlength - tsofar) < (psvbptr->inodesize - toffset)) {
548  memcpy (pcbuffer + tsofar, cvbnodetmp + toffset,
549  (size_t)(psvbptr->iminrowlength - tsofar));
550  toffset += psvbptr->iminrowlength - tsofar;
551  tsofar = psvbptr->iminrowlength;
552  break;
553  }
554  memcpy (pcbuffer + tsofar, cvbnodetmp + toffset, (size_t)(psvbptr->inodesize - toffset));
555  tblocknumber++;
556  tsofar += psvbptr->inodesize - toffset;
557  toffset = 0;
558  if (ivbblockread (ihandle, 0, tblocknumber + 1, cvbnodetmp)) {
559  return EBADFILE;
560  }
561  }
562  pcbuffer += tsofar;
563  /* OK, now for the footer. Either 1 byte or 1 + INTSIZE + QUADSIZE. */
564  while (tsofar < irowlength) {
565  if ((irowlength - tsofar) <= (psvbptr->inodesize - toffset)) {
566  memcpy (cfooter + tsofar - psvbptr->iminrowlength, cvbnodetmp + toffset,
567  (size_t)(irowlength - tsofar));
568  break;
569  }
570  memcpy (cfooter + tsofar - psvbptr->iminrowlength, cvbnodetmp + toffset,
571  (size_t)(psvbptr->inodesize - toffset));
572  tblocknumber++;
573  tsofar += psvbptr->inodesize - toffset;
574  toffset = 0;
575  if (ivbblockread (ihandle, 0, tblocknumber + 1, cvbnodetmp)) {
576  return EBADFILE;
577  }
578  }
579  isreclen = psvbptr->iminrowlength;
580  *pideletedrow = 0;
581  if (cfooter[0] == 0x00) {
582  *pideletedrow = 1;
583  } else {
584  if (psvbptr->iopenmode & ISVARLEN) {
585  psvbptr->ivarlenlength = inl_ldint (cfooter + 1);
586 /* VBISAM in 64 bit mode (4k Nodes) uses a ten bit slot number */
587 /* VBISAM in 32 bit mode (1k Nodes) uses an eight bit slot number */
588 #if ISAMMODE == 1
589  n = inl_ldint (cfooter + 1 + INTSIZE);
590  psvbptr->ivarlenslot = n >> 6;
591  *(cfooter + 1 + INTSIZE + 1) &= (unsigned char)0x3f;
592 #else
593  psvbptr->ivarlenslot = *(cfooter + 1 + INTSIZE);
594 #endif
595  *(cfooter + 1 + INTSIZE) = 0;
596  psvbptr->tvarlennode = inl_ldquad (cfooter + 1 + INTSIZE);
597  if (psvbptr->ivarlenlength) {
598  if (ivbvarlenread (ihandle, (char *)pcbuffer,
599  psvbptr->tvarlennode,
600  psvbptr->ivarlenslot, psvbptr->ivarlenlength)) {
601  return iserrno;
602  }
603  }
604  isreclen += psvbptr->ivarlenlength;
605  }
606  }
607  return 0;
608 }
609 
610 int
611 ivbdatawrite (const int ihandle, char *pcbuffer, int ideletedrow, const off_t trownumber)
612 {
613  struct DICTINFO *psvbptr;
614  char *pctemp;
615  off_t tblocknumber, toffset, tsofar;
616  int irowlength;
617  int n;
618  char cvbnodetmp[VB_NODE_MAX];
620 
621  /* Sanity check - Is ihandle a currently open table? */
622  if (unlikely(ihandle < 0 || ihandle > ivbmaxusedhandle)) {
623  return ENOTOPEN;
624  }
625  if (!psvbfile[ihandle]) {
626  return ENOTOPEN;
627  }
628  if (trownumber < 1) {
629  return EBADARG;
630  }
631  psvbptr = psvbfile[ihandle];
632 
633  irowlength = psvbptr->iminrowlength;
634  toffset = irowlength + 1;
635  if (psvbptr->iopenmode & ISVARLEN) {
636  toffset += INTSIZE + QUADSIZE;
637  } else {
638 /* RXW */
639  toffset *= (trownumber - 1);
640  if (tvblseek (psvbptr->idatahandle, toffset, SEEK_SET) != toffset) {
641  return EBADFILE;
642  }
643  memcpy (pcwritebuffer, pcbuffer, (size_t)irowlength);
644  *(pcwritebuffer + irowlength) = ideletedrow ? 0x00 : 0x0a;
645  irowlength++;
646  if (tvbwrite (psvbptr->idatahandle, pcwritebuffer, (size_t)irowlength) != (ssize_t)irowlength) {
647  return EBADFILE;
648  }
649  return 0;
650  }
651  toffset *= (trownumber - 1);
652  if (psvbptr->iopenmode & ISVARLEN) {
653  if (psvbptr->tvarlennode) {
654  if (ivbvarlendelete (ihandle, psvbptr->tvarlennode, psvbptr->ivarlenslot,
655  psvbptr->ivarlenlength)) {
656  return -69;
657  }
658  }
659  if (isreclen == psvbptr->iminrowlength || ideletedrow) {
660  psvbptr->tvarlennode = 0;
661  psvbptr->ivarlenlength = 0;
662  psvbptr->ivarlenslot = 0;
663  } else {
664  if (ivbvarlenwrite (ihandle, pcbuffer + psvbptr->iminrowlength,
665  isreclen - psvbptr->iminrowlength)) {
666  return iserrno;
667  }
668  }
669  }
670  memcpy (pcwritebuffer, pcbuffer, (size_t)irowlength);
671  *(pcwritebuffer + irowlength) = ideletedrow ? 0x00 : 0x0a;
672  irowlength++;
673  if (psvbptr->iopenmode & ISVARLEN) {
674  inl_stint (psvbptr->ivarlenlength, pcwritebuffer + irowlength);
675  pctemp = pcwritebuffer + irowlength + INTSIZE;
676  inl_stquad (psvbptr->tvarlennode, pctemp);
677 #if ISAMMODE == 1
678  n = (psvbptr->ivarlenslot << 6) + inl_ldint (pctemp);
679  inl_stint (n, pctemp);
680 #else
681  *pctemp = psvbptr->ivarlenslot;
682 #endif
683  irowlength += INTSIZE + QUADSIZE;
684  }
685 
686  tblocknumber = (toffset / psvbptr->inodesize);
687  toffset -= (tblocknumber * psvbptr->inodesize);
688  tsofar = 0;
689  while (tsofar < irowlength) {
690  memset (cvbnodetmp, 0, VB_NODE_MAX);
691  ivbblockread (ihandle, 0, tblocknumber + 1, cvbnodetmp); /* Can fail!! */
692  if ((irowlength - tsofar) <= (psvbptr->inodesize - toffset)) {
693  memcpy (cvbnodetmp + toffset, pcwritebuffer + tsofar,
694  (size_t)(irowlength - tsofar));
695  if (ivbblockwrite (ihandle, 0, tblocknumber + 1, cvbnodetmp)) {
696  return EBADFILE;
697  }
698  break;
699  }
700  memcpy (cvbnodetmp + toffset, pcbuffer + tsofar, (size_t)(psvbptr->inodesize - toffset));
701  if (ivbblockwrite (ihandle, 0, tblocknumber + 1, cvbnodetmp)) {
702  return EBADFILE;
703  }
704  tblocknumber++;
705  tsofar += psvbptr->inodesize - toffset;
706  toffset = 0;
707  }
708  return 0;
709 }
ssize_t tvbwrite(const int ihandle, const void *pvbuffer, const size_t tcount)
Definition: vblowlevel.c:127
static struct SVARLEN * psvarlenheader
Definition: vbdataio.c:50
static int inl_ldint(void *pclocation)
Definition: isinternal.h:170
int ivbdataread(const int ihandle, char *pcbuffer, int *pideletedrow, const off_t trownumber)
Definition: vbdataio.c:493
int ivbblockread(const int ihandle, const int iisindex, const off_t tblocknumber, char *cbuffer)
Definition: vblowlevel.c:137
int isreclen
Definition: vbmemio.c:29
static off_t ttailnode(const int ihandle, char *pcbuffer, const int ilength, int *pislotnumber)
Definition: vbdataio.c:59
int ivarlenslot
Definition: isinternal.h:414
char cflag
Definition: vbdataio.c:30
char cfreethis[2]
Definition: vbdataio.c:27
int iminrowlength
Definition: isinternal.h:403
char cfreeoffset[2]
Definition: vbdataio.c:28
int ivbmaxusedhandle
Definition: vblocking.c:26
off_t tvarlennode
Definition: isinternal.h:421
static int ivbvarlenread(const int ihandle, char *pcbuffer, off_t tnodenumber, int islotnumber, int ilength)
Definition: vbdataio.c:220
#define VB_NODE_MAX
Definition: isinternal.h:288
static void inl_stint(int ivalue, void *pclocation)
Definition: isinternal.h:190
#define unlikely(x)
Definition: common.h:437
unsigned char iisdictlocked
Definition: isinternal.h:427
char cusedcount[2]
Definition: vbdataio.c:32
#define MAX_NODE_LENGTH
Definition: isinternal.h:283
char cfreeprev[8]
Definition: vbdataio.c:26
struct DICTNODE sdictnode
Definition: isinternal.h:444
static int ivbvarlenwrite(const int ihandle, char *pcbuffer, int ilength)
Definition: vbdataio.c:270
static const int igroupsize[]
Definition: vbdataio.c:40
char cfreenext[8]
Definition: vbdataio.c:25
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
#define QUADSIZE
Definition: isinternal.h:108
off_t tvbnodecountgetnext(const int ihandle)
Definition: vbindexio.c:48
int ivbnodefree(const int ihandle, const off_t tnodenumber)
Definition: vbindexio.c:67
int iopenmode
Definition: isinternal.h:412
int ivbblockwrite(const int ihandle, const int iisindex, const off_t tblocknumber, const char *cbuffer)
Definition: vblowlevel.c:167
char cconst[2]
Definition: vbdataio.c:24
char cfreecont[8]
Definition: vbdataio.c:29
#define MAX_RESERVED_LENGTH
Definition: isinternal.h:290
static void inl_stquad(off_t tvalue, void *pclocation)
Definition: isinternal.h:260
char crfu[2]
Definition: vbdataio.c:23
ssize_t tvbread(const int ihandle, void *pvbuffer, const size_t tcount)
Definition: vblowlevel.c:117
static int ivbvarlendelete(const int ihandle, off_t tnodenumber, int islotnumber, int ilength)
Definition: vbdataio.c:376
int ivarlenlength
Definition: isinternal.h:413
int ivbdatawrite(const int ihandle, char *pcbuffer, int ideletedrow, const off_t trownumber)
Definition: vbdataio.c:611
char cgroup
Definition: vbdataio.c:36
static char * cvbnodetmp
Definition: ischeck.c:25
static off_t inl_ldquad(void *pclocation)
Definition: isinternal.h:238
off_t trownumber
Definition: isinternal.h:416
char cvarleng0[8]
Definition: isinternal.h:383
int idatahandle
Definition: isinternal.h:405
int iserrno
Definition: vbmemio.c:27
int inodesize
Definition: isinternal.h:402
static char cnode[4096]
Definition: vbdataio.c:49
static char * pcwritebuffer
Definition: isdelete.c:22
off_t tvblseek(const int ihandle, off_t toffset, const int iwhence)
Definition: vblowlevel.c:107