Merge branch 'master' into cde-next
[oweals/cde.git] / cde / lib / tt / mini_isam / isread.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
24 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
25 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
26 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
27 /*%%  $XConsortium: isread.c /main/3 1995/10/23 11:43:35 rswiston $                                                      */
28 /*
29  * Copyright (c) 1988 by Sun Microsystems, Inc.
30  */
31
32 /*
33  * isread.c
34  *
35  * Description:
36  *      Read a record from ISAM file. 
37  */
38
39
40 #include "isam_impl.h"
41 #include <sys/time.h>
42
43 static int _amread();
44
45 /*
46  * err =  isread(isfd, record, mode)
47  *
48  * Isread() reads a new record from an ISAM file. 
49  *
50  * Current record position is set.
51  * isrecnum is set to indicate the read record.
52  *
53  * If the ISAM file is for variable length records, the isreclen variable
54  * is set to indicate the actual length of the record.
55  *
56  * Returns 0 if successful, or -1 of any error.
57  *
58  * Errors:
59  *      ELOCKED The record or the entire file is locked by another process.
60  *      ENOTOPEN isfd does not correspond to an open ISAM file, or the
61  *              ISAM file was opened with ISOUTPUT mode.
62  *      EBADARG Bad mode parameter.
63  *      ENOCURR Mode is ISCURR and the current record position is not set.
64  *      ENOREC  Specified record cannot be found (random access read)
65  *      EENDFILE The end file of is reached (sequential read).
66  *      EBADKEY Index was deleted by other process (can happen only
67  *              when lock file is purged).
68  */
69
70 int 
71 isread(int isfd, char *record, int mode)
72 {
73     Fab *fab;
74     int                 reclen;
75     Recno               recnum;
76     int                 ret;
77     enum readmode       readmode;
78
79     /*
80      * Get File Access Block.
81      */
82     if ((fab = _isfd_find(isfd)) == NULL) {
83         _setiserrno2(ENOTOPEN, '9', '0');
84         return (ISERROR);
85     }
86
87     /*
88      * Check that the open mode was ISINPUT, or ISINOUT.
89      */
90     if (fab->openmode != OM_INPUT && fab->openmode != OM_INOUT) {
91         _setiserrno2(ENOTOPEN, '9', '0');
92         return (ISERROR);
93     }
94
95     /*
96      * Extract read mode.
97      */
98     if ((readmode = _getreadmode(mode)) == RM_BADMODE) {
99         _setiserrno2(EBADARG, '9', '0');
100         return (ISERROR);
101     }
102
103     /*
104      * All keys must be in the minimum record length.
105      * So send just the minimum length part of the record.
106      */
107     reclen = fab->minreclen;
108
109     /*
110      * Call the Access Method
111      */
112     recnum = isrecnum;
113
114     if ((ret = _amread(&fab->isfhandle, record, &reclen,
115                         readmode, &fab->curpos, &recnum,
116                         &fab->errcode)) == ISOK) {
117         isrecnum = recnum;                   /* Set isrecnum */
118     }
119
120     isreclen = reclen;
121     _seterr_errcode(&fab->errcode);
122
123     return (ret);                            /* Successful read */
124 }
125
126 /*
127  * _amread(isfhandle, record, reclen, readmode, curpos, recnum, errcode)
128  *
129  * _amread() reads a record from ISAM file
130  *
131  * Input params:
132  *      isfhandle       Handle of ISAM file
133  *      readmode        Specifies access mode (random or sequential)
134  *      curpos          current record position
135  *      recnum          copy if isrecnum
136  *
137  * Output params:
138  *      curpos          new current position
139  *      recnum          record number
140  *      errcode         error status of the operation
141  *      reclen          actual length of the record
142  *      record          filled with data
143  *
144  */
145
146 static int
147 _amread(Bytearray *isfhandle, char *record, int *reclen,
148         enum readmode readmode, Bytearray *curpos, Recno *recnum,
149         struct errcode *errcode)
150 {
151     Fcb                 *fcb = NULL;
152     Recno               recnum2;
153     int                 err;
154     Crp                 *crp;
155     Btree               *btree = NULL;
156     Keydesc2            *pkeydesc2;
157     char                keybuf1[MAXKEYSIZE], keybuf2[MAXKEYSIZE];
158     char                *pkey, *pkeynext;
159     int                 skipbytes;
160     int                 ret;
161     Bytearray           oldcurpos;
162     int                 (*rec_read)();
163
164     _isam_entryhook();
165
166     /*
167      * Get FCB corresponding to the isfhandle handle.
168      */
169     if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
170         _isam_exithook();
171         return (ISERROR);
172     }
173
174     rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
175
176     /*
177      * Update information in FCB from CNTL page on the disk
178      */
179     (void)_isfcb_cntlpg_r2(fcb);
180
181     /*
182      * Save the old record position.
183      */
184     oldcurpos = _bytearr_dup(curpos);
185
186     /*
187      * Get info from current record position structure.
188      */
189     crp = (Crp *) curpos->data;
190
191     if (crp->keyid == PHYS_ORDER) {
192         /*
193          * Physical order in use.
194          */
195         
196         switch (readmode) {
197         case RM_EQUAL:
198             recnum2 = *recnum;               /* passed from isrecnum */
199             if ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK) {
200                 _amseterrcode(errcode, ENOREC);
201                 goto ERROR;
202             }
203             break;
204
205         case RM_GREAT:
206             recnum2 = *recnum + 1;
207             if (recnum2 < 1) recnum2 = 1;
208             /*
209              * Skip deleted records.
210              */
211             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
212                    err == ENOREC) 
213                 recnum2++;
214  
215             if (err != ISOK) {
216                 _amseterrcode(errcode, ENOREC);
217                 goto ERROR;
218             }
219             break;
220
221         case RM_GTEQ:
222             recnum2 = *recnum;
223             if (recnum2 < 1) recnum2 = 1;
224             /*
225              * Skip deleted records.
226              */
227             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
228                    err == ENOREC) 
229                 recnum2++;
230  
231             if (err != ISOK) {
232                 _amseterrcode(errcode, ENOREC);
233                 goto ERROR;
234             }
235             break;
236
237         case RM_LESS:
238             recnum2 = *recnum - 1;
239             if (recnum2 > fcb->lastrecno) recnum2 = fcb->lastrecno;
240             /*
241              * Skip deleted records.
242              */
243             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
244                    err == ENOREC) 
245                 recnum2--;
246  
247             if (err != ISOK) {
248                 _amseterrcode(errcode, ENOREC);
249                 goto ERROR;
250             }
251             break;
252
253         case RM_LTEQ:
254             recnum2 = *recnum;
255             if (recnum2 > fcb->lastrecno) recnum2 = fcb->lastrecno;
256             /*
257              * Skip deleted records.
258              */
259             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
260                    err == ENOREC) 
261                 recnum2--;
262  
263             if (err != ISOK) {
264                 _amseterrcode(errcode, ENOREC);
265                 goto ERROR;
266             }
267             break;
268
269         case RM_FIRST:
270             recnum2 = 1;
271             /*
272              * Skip deleted records.
273              */
274             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
275                    err == ENOREC) 
276                 recnum2++;
277  
278             if (err != ISOK) {
279                 _amseterrcode(errcode, EENDFILE);
280                 goto ERROR;
281             }
282             break;
283         case RM_CURR:
284             switch (crp->flag) {
285             case CRP_ON:
286             case CRP_BEFORE:
287             case CRP_AFTER:
288                 recnum2 = crp->recno;
289                 break;
290             case CRP_BEFOREANY:
291                 recnum2 = 1;
292                 break;
293             default:
294                 _amseterrcode(errcode, ENOCURR);
295                 goto ERROR;
296             }
297                 
298             if( rec_read(fcb, record, recnum2, reclen) != ISOK) {
299                 _amseterrcode(errcode, ENOCURR);
300                 goto ERROR;
301             }
302             break;
303         case RM_NEXT:
304             switch (crp->flag) {
305             case CRP_ON:
306             case CRP_AFTER:
307                 recnum2 = crp->recno + 1;
308                 break;
309             case CRP_BEFOREANY:
310                 recnum2 = 1;
311                 break;
312             case CRP_BEFORE:
313                 recnum2 = crp->recno;
314                 break;
315             case CRP_AFTERANY:
316                 _amseterrcode(errcode, EENDFILE);
317                 goto ERROR;
318             default:
319                 _amseterrcode(errcode, ENOCURR);
320                 goto ERROR;
321             }
322                 
323             /*
324              * Skip deleted records.
325              */
326             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
327                    err == ENOREC) 
328                 recnum2++;
329  
330             if (err != ISOK) {
331                 _amseterrcode(errcode, EENDFILE);
332                 goto ERROR;
333             }
334             break;
335         case RM_PREV:
336             switch (crp->flag) {
337             case CRP_ON:
338             case CRP_BEFORE:
339                 recnum2 = crp->recno - 1;
340                 break;
341             case CRP_AFTER:
342                 recnum2 = crp->recno;
343                 break;
344             case CRP_BEFOREANY:
345                 _amseterrcode(errcode, EENDFILE);
346                 goto ERROR;
347             default:
348                 _amseterrcode(errcode, ENOCURR);
349                 goto ERROR;
350             }
351                 
352             /*
353              * Skip deleted records.
354              */
355             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
356                    err == ENOREC) 
357                 recnum2--;
358  
359             if (err != ISOK) {
360                 _amseterrcode(errcode, EENDFILE);
361                 goto ERROR;
362             }
363             break;
364         case RM_LAST:
365             recnum2 = fcb->lastrecno;
366             /*
367              * Skip deleted records.
368              */
369             while ((err = rec_read(fcb, record, recnum2, reclen)) != ISOK &&
370                    err == ENOREC) 
371                 recnum2--;
372
373             if (err != ISOK) {
374                 _amseterrcode(errcode, EENDFILE);
375                 goto ERROR;
376             }
377             break;
378         default:
379             _isfatal_error("Invalid readmode");
380         }
381
382         *recnum = recnum2;
383
384         /*
385          * Set new current record position.
386          */
387          crp->recno = recnum2;
388          crp->flag = CRP_ON;
389
390     } /* physical order */
391     else {
392         /*
393          * Find key descriptor in FCB
394          */
395         if ((pkeydesc2 = _isfcb_indfindkey(fcb, crp->keyid)) == NULL) {
396             _amseterrcode(errcode, EBADKEY);
397             goto ERROR;
398         }
399
400         /*
401          * skipkeybytes is set to the number of bytes in the beginning
402          * of the key:
403          *  RECNOSIZE for ISNODUPS keys to skip recno part
404          *  RECNOSIZE + DUPIDSIZE to skip recno and duplicate serial number
405          */
406         skipbytes = RECNOSIZE;
407         if (ALLOWS_DUPS2(pkeydesc2))
408             skipbytes += DUPIDSIZE;
409                 
410         /*
411          * Create B tree object.
412          */
413         btree = _isbtree_create(fcb, pkeydesc2);
414
415         switch (readmode) {
416         case RM_EQUAL:
417         case RM_GTEQ:
418             /* 
419              * Make sure that you will read the first duplicate. 
420              */
421             _iskey_fillmin(pkeydesc2, keybuf1);
422  
423             /* 
424              * Extract key fields from record. 
425              */
426             _iskey_extract(pkeydesc2, record, keybuf2);
427             memcpy((void *)(keybuf1 + skipbytes),
428                    (const void *)(keybuf2 + skipbytes), crp->matchkeylen);
429
430             /*
431              * Position pointer in the B-tree in before the searched value. 
432              */
433             _isbtree_search(btree, keybuf1);
434         
435             if ((pkey = _isbtree_next(btree)) == NULL) {
436                 _amseterrcode(errcode, ENOREC);
437                 goto ERROR;
438             }
439             
440             if (readmode == RM_EQUAL &&
441                 memcmp(keybuf1 + skipbytes, pkey + skipbytes, 
442                        crp->matchkeylen) != 0) {
443                 _amseterrcode(errcode, ENOREC);
444                 goto ERROR;
445             }
446
447             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
448             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
449                 
450             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
451                 _amseterrcode(errcode, ENOCURR);
452                 goto ERROR;
453             }
454             recnum2 = crp->recno;
455             break;
456
457         case RM_GREAT:
458             /* 
459              * Make sure that you will read past all matching records.
460              */
461             _iskey_fillmax(pkeydesc2, keybuf1);
462  
463             /* 
464              * Extract key fields from record. 
465              */
466             _iskey_extract(pkeydesc2, record, keybuf2);
467             memcpy((void *)(keybuf1 + skipbytes),
468                    (const void *)(keybuf2 + skipbytes), crp->matchkeylen);
469
470             /*
471              * Position pointer in the B-tree in before the searched value. 
472              */
473             _isbtree_search(btree, keybuf1);
474         
475             if ((pkey = _isbtree_next(btree)) == NULL) {
476                 _amseterrcode(errcode, ENOREC);
477                 goto ERROR;
478             }
479             
480             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
481             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
482                 
483             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
484                 _amseterrcode(errcode, ENOCURR);
485                 goto ERROR;
486             }
487             recnum2 = crp->recno;
488             break;
489
490         case RM_LESS:
491             /* 
492              * Make sure that you will read before all matching records.
493              */
494             _iskey_fillmin(pkeydesc2, keybuf1);
495  
496             /* 
497              * Extract key fields from record. 
498              */
499             _iskey_extract(pkeydesc2, record, keybuf2);
500             memcpy((void *)(keybuf1 + skipbytes),
501                    (const void *)(keybuf2 + skipbytes), crp->matchkeylen);
502
503             /*
504              * Position pointer in the B-tree in before the searched value. 
505              */
506             _isbtree_search(btree, keybuf1);
507         
508             if ((pkey = _isbtree_current(btree)) == NULL) {
509                 _amseterrcode(errcode, ENOREC);
510                 goto ERROR;
511             }
512             
513             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
514             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
515                 
516             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
517                 _amseterrcode(errcode, ENOCURR);
518                 goto ERROR;
519             }
520             recnum2 = crp->recno;
521             break;
522
523         case RM_LTEQ:
524             /* 
525              * Make sure that you will read the last duplicate.
526              */
527             _iskey_fillmax(pkeydesc2, keybuf1);
528  
529             /* 
530              * Extract key fields from record. 
531              */
532             _iskey_extract(pkeydesc2, record, keybuf2);
533             memcpy((void *)(keybuf1 + skipbytes),
534                    (const void *)(keybuf2 + skipbytes), crp->matchkeylen);
535
536             /*
537              * Position pointer in the B-tree in before the searched value. 
538              */
539             _isbtree_search(btree, keybuf1);
540         
541             if ((pkey = _isbtree_current(btree)) == NULL) {
542                 _amseterrcode(errcode, ENOREC);
543                 goto ERROR;
544             }
545             
546             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
547             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
548                 
549             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
550                 _amseterrcode(errcode, ENOCURR);
551                 goto ERROR;
552             }
553             recnum2 = crp->recno;
554             break;
555
556         case RM_CURR:
557             switch (crp->flag) {
558             case CRP_ON:
559             case CRP_BEFORE:
560             case CRP_AFTER:
561                 /*
562                  * We have check if the record has not been deleted
563                  * since the current record position was set up.
564                  */
565                 _isbtree_search(btree, crp->key);
566                 pkey = _isbtree_current(btree);
567
568                 if (pkey == NULL || 
569                     ldrecno(pkey + KEY_RECNO_OFF) != crp->recno) {
570                     _amseterrcode(errcode, ENOCURR);
571                     goto ERROR;
572                 }
573                 break;
574             case CRP_BEFOREANY:
575                 _isbtree_search(btree, crp->key);
576                 pkey = _isbtree_next(btree);
577
578                 if (pkey == NULL) {
579                     _amseterrcode(errcode, EENDFILE);
580                     goto ERROR;
581                 }
582            
583                 crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
584                 memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
585                 break;
586             default:
587                 _amseterrcode(errcode, ENOCURR);
588                 goto ERROR;
589             }
590                 
591             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
592                 _amseterrcode(errcode, ENOCURR);
593                 goto ERROR;
594             }
595             recnum2 = crp->recno;
596             break;
597
598         case RM_NEXT:
599
600             /*
601              * Validate that current position has been set.
602              */
603             switch (crp->flag) {
604             case CRP_ON:
605             case CRP_BEFORE:
606             case CRP_BEFOREANY:
607                 break;
608             case CRP_AFTERANY:
609                 _amseterrcode(errcode, EENDFILE);
610                 goto ERROR;
611             default:
612                 _amseterrcode(errcode, ENOCURR);
613                 goto ERROR;
614             }
615  
616             /*
617              * Position pointer to current position.
618              */
619             _isbtree_search(btree, crp->key);
620         
621             if (crp->flag == CRP_BEFORE) 
622                 pkey = _isbtree_current(btree);
623             else                           
624                 /* crp->flag == CRP_ON || crp->flag == CRP_BEFOREANY */
625                 pkey = _isbtree_next(btree);
626
627             if (pkey == NULL) {
628                 _amseterrcode(errcode, EENDFILE);
629                 goto ERROR;
630             }
631            
632             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
633             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
634                 
635             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
636                 _amseterrcode(errcode, ENOCURR);
637                 goto ERROR;
638             }
639             recnum2 = crp->recno;
640             break;
641
642         case RM_PREV:
643
644             /*
645              * Validate that current position has been set.
646              */
647             switch (crp->flag) {
648             case CRP_ON:
649             case CRP_BEFORE:
650                 /*
651                  * To get to the previous record, we must decrement
652                  * the TID part for unique keys, or duplicate serial number 
653                  * for non-unique keys.
654                  */
655                 memcpy((void *)keybuf1,
656                        (const void *)crp->key, pkeydesc2->k2_len);
657                 if (ALLOWS_DUPS2(pkeydesc2)) {
658                     stlong(ldlong(keybuf1 + KEY_DUPS_OFF) - 1, 
659                             keybuf1 + KEY_DUPS_OFF);
660                 }
661                 else {
662                     strecno(ldrecno(keybuf1 + KEY_RECNO_OFF) - 1, 
663                             keybuf1 + KEY_RECNO_OFF);
664                 }
665                 break;
666             case CRP_AFTER:
667                 memcpy((void *)keybuf1, (const void *)crp->key, pkeydesc2->k2_len);
668                 break;
669             case CRP_BEFOREANY:
670                 _amseterrcode(errcode, EENDFILE);
671                 goto ERROR;
672             default:
673                 _amseterrcode(errcode, ENOCURR);
674                 goto ERROR;
675             }
676  
677             /*
678              * Position pointer to current position.
679              */
680             _isbtree_search(btree, keybuf1);
681         
682             pkey = _isbtree_current(btree);
683
684             if (pkey == NULL) {
685                 _amseterrcode(errcode, EENDFILE);
686                 goto ERROR;
687             }
688            
689             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
690             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
691                 
692             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
693                 _amseterrcode(errcode, ENOCURR);
694                 goto ERROR;
695             }
696             recnum2 = crp->recno;
697             break;
698
699         case RM_FIRST:
700             /* 
701              * Fill key buffer with -infinity.
702              */
703             _iskey_fillmin(pkeydesc2, keybuf1);
704  
705             /*
706              * Position pointer in the B-tree before any key entry.
707              */
708             _isbtree_search(btree, keybuf1);
709         
710             if ((pkey = _isbtree_next(btree)) == NULL) {
711                 _amseterrcode(errcode, EENDFILE);
712                 goto ERROR;
713             }
714             
715             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
716             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
717                 
718             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
719                 _amseterrcode(errcode, EENDFILE);
720                 goto ERROR;
721             }
722             recnum2 = crp->recno;
723             break;
724
725         case RM_LAST:
726             /* 
727              * Fill key buffer with +infinity.
728              */
729             _iskey_fillmax(pkeydesc2, keybuf1);
730  
731             /*
732              * Position pointer in the B-tree before any key entry.
733              */
734             _isbtree_search(btree, keybuf1);
735         
736             if ((pkey = _isbtree_current(btree)) == NULL) {
737                 _amseterrcode(errcode, EENDFILE);
738                 goto ERROR;
739             }
740             
741             crp->recno = ldrecno(pkey + KEY_RECNO_OFF);
742             memcpy((void *)crp->key, (const void *)pkey, pkeydesc2->k2_len);
743                 
744             if( rec_read(fcb, record, crp->recno, reclen) != ISOK) {
745                 _amseterrcode(errcode, EENDFILE);
746                 goto ERROR;
747             }
748             recnum2 = crp->recno;
749             break;
750
751         default:
752             _isfatal_error("Invalid readmode");
753         }
754
755         *recnum = recnum2;
756          crp->flag = CRP_ON;
757
758         /*
759          * Set up isdupl to handle isstat2 value for keys that allow
760          * duplicate values.
761          */
762         if (ALLOWS_DUPS2(pkeydesc2) && (pkeynext = _isbtree_next(btree)) &&
763             memcmp(pkey + skipbytes, pkeynext + skipbytes, 
764                    crp->matchkeylen) == 0) {
765             isdupl = 1;
766         }
767
768
769         _isbtree_destroy(btree);
770     }
771
772     _amseterrcode(errcode, ISOK);
773     ret = ISOK;
774
775     /* Clean-up work. */
776     _isdisk_commit();                        /* This will only check
777                                               * that we unfixed all fixed
778                                               * buffers */
779     _isdisk_inval();
780     _bytearr_free(&oldcurpos);
781
782     _isam_exithook();
783     return (ret);
784
785  ERROR:
786
787     *reclen = 0;
788
789     _isdisk_inval();
790
791     _bytearr_free(&oldcurpos);
792
793     /*
794      * If error is ENOREC,  set the current record position undefined.
795      */
796     if (errcode->iserrno == ENOREC || errcode->iserrno == EENDFILE) {
797         ((Crp *)curpos->data)->flag = CRP_UNDEF;
798     }
799
800     if (btree != NULL)
801         _isbtree_destroy(btree);
802
803     _isam_exithook();
804     return (ISERROR);
805 }
806
807