/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 1990, 1993, 19944* The Regents of the University of California. All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14* 3. Neither the name of the University nor the names of its contributors15* may be used to endorse or promote products derived from this software16* without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*/3031#include <sys/types.h>3233#include <errno.h>34#include <stddef.h>35#include <stdio.h>36#include <stdlib.h>37#include <string.h>38#include <unistd.h>3940#include <db.h>41#include "recno.h"4243/*44* __REC_GET -- Get a record from the btree.45*46* Parameters:47* dbp: pointer to access method48* key: key to find49* data: data to return50* flag: currently unused51*52* Returns:53* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.54*/55int56__rec_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)57{58BTREE *t;59EPG *e;60recno_t nrec;61int status;6263t = dbp->internal;6465/* Toss any page pinned across calls. */66if (t->bt_pinned != NULL) {67mpool_put(t->bt_mp, t->bt_pinned, 0);68t->bt_pinned = NULL;69}7071/* Get currently doesn't take any flags, and keys of 0 are illegal. */72if (flags || (nrec = *(recno_t *)key->data) == 0) {73errno = EINVAL;74return (RET_ERROR);75}7677/*78* If we haven't seen this record yet, try to find it in the79* original file.80*/81if (nrec > t->bt_nrecs) {82if (F_ISSET(t, R_EOF | R_INMEM))83return (RET_SPECIAL);84if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)85return (status);86}8788--nrec;89if ((e = __rec_search(t, nrec, SEARCH)) == NULL)90return (RET_ERROR);9192status = __rec_ret(t, e, 0, NULL, data);93if (F_ISSET(t, B_DB_LOCK))94mpool_put(t->bt_mp, e->page, 0);95else96t->bt_pinned = e->page;97return (status);98}99100/*101* __REC_FPIPE -- Get fixed length records from a pipe.102*103* Parameters:104* t: tree105* cnt: records to read106*107* Returns:108* RET_ERROR, RET_SUCCESS109*/110int111__rec_fpipe(BTREE *t, recno_t top)112{113DBT data;114recno_t nrec;115size_t len;116int ch;117u_char *p;118119if (t->bt_rdata.size < t->bt_reclen) {120t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);121if (t->bt_rdata.data == NULL)122return (RET_ERROR);123t->bt_rdata.size = t->bt_reclen;124}125data.data = t->bt_rdata.data;126data.size = t->bt_reclen;127128for (nrec = t->bt_nrecs; nrec < top;) {129len = t->bt_reclen;130for (p = t->bt_rdata.data;; *p++ = ch)131if ((ch = getc(t->bt_rfp)) == EOF || !--len) {132if (ch != EOF)133*p = ch;134if (len != 0)135memset(p, t->bt_bval, len);136if (__rec_iput(t,137nrec, &data, 0) != RET_SUCCESS)138return (RET_ERROR);139++nrec;140break;141}142if (ch == EOF)143break;144}145if (nrec < top) {146F_SET(t, R_EOF);147return (RET_SPECIAL);148}149return (RET_SUCCESS);150}151152/*153* __REC_VPIPE -- Get variable length records from a pipe.154*155* Parameters:156* t: tree157* cnt: records to read158*159* Returns:160* RET_ERROR, RET_SUCCESS161*/162int163__rec_vpipe(BTREE *t, recno_t top)164{165DBT data;166recno_t nrec;167size_t len;168size_t sz;169int bval, ch;170u_char *p;171172bval = t->bt_bval;173for (nrec = t->bt_nrecs; nrec < top; ++nrec) {174for (p = t->bt_rdata.data,175sz = t->bt_rdata.size;; *p++ = ch, --sz) {176if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {177data.data = t->bt_rdata.data;178data.size = p - (u_char *)t->bt_rdata.data;179if (ch == EOF && data.size == 0)180break;181if (__rec_iput(t, nrec, &data, 0)182!= RET_SUCCESS)183return (RET_ERROR);184break;185}186if (sz == 0) {187len = p - (u_char *)t->bt_rdata.data;188t->bt_rdata.size += (sz = 256);189t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_rdata.size);190if (t->bt_rdata.data == NULL)191return (RET_ERROR);192p = (u_char *)t->bt_rdata.data + len;193}194}195if (ch == EOF)196break;197}198if (nrec < top) {199F_SET(t, R_EOF);200return (RET_SPECIAL);201}202return (RET_SUCCESS);203}204205/*206* __REC_FMAP -- Get fixed length records from a file.207*208* Parameters:209* t: tree210* cnt: records to read211*212* Returns:213* RET_ERROR, RET_SUCCESS214*/215int216__rec_fmap(BTREE *t, recno_t top)217{218DBT data;219recno_t nrec;220u_char *sp, *ep, *p;221size_t len;222223if (t->bt_rdata.size < t->bt_reclen) {224t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);225if (t->bt_rdata.data == NULL)226return (RET_ERROR);227t->bt_rdata.size = t->bt_reclen;228}229data.data = t->bt_rdata.data;230data.size = t->bt_reclen;231232sp = (u_char *)t->bt_cmap;233ep = (u_char *)t->bt_emap;234for (nrec = t->bt_nrecs; nrec < top; ++nrec) {235if (sp >= ep) {236F_SET(t, R_EOF);237return (RET_SPECIAL);238}239len = t->bt_reclen;240for (p = t->bt_rdata.data;241sp < ep && len > 0; *p++ = *sp++, --len);242if (len != 0)243memset(p, t->bt_bval, len);244if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)245return (RET_ERROR);246}247t->bt_cmap = (caddr_t)sp;248return (RET_SUCCESS);249}250251/*252* __REC_VMAP -- Get variable length records from a file.253*254* Parameters:255* t: tree256* cnt: records to read257*258* Returns:259* RET_ERROR, RET_SUCCESS260*/261int262__rec_vmap(BTREE *t, recno_t top)263{264DBT data;265u_char *sp, *ep;266recno_t nrec;267int bval;268269sp = (u_char *)t->bt_cmap;270ep = (u_char *)t->bt_emap;271bval = t->bt_bval;272273for (nrec = t->bt_nrecs; nrec < top; ++nrec) {274if (sp >= ep) {275F_SET(t, R_EOF);276return (RET_SPECIAL);277}278for (data.data = sp; sp < ep && *sp != bval; ++sp);279data.size = sp - (u_char *)data.data;280if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)281return (RET_ERROR);282++sp;283}284t->bt_cmap = (caddr_t)sp;285return (RET_SUCCESS);286}287288289