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