/*-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* This code is derived from software contributed to Berkeley by7* Mike Olson.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#include <sys/param.h>3536#include <stdio.h>37#include <stdlib.h>38#include <string.h>3940#include <db.h>41#include "btree.h"4243/*44* __bt_ret --45* Build return key/data pair.46*47* Parameters:48* t: tree49* e: key/data pair to be returned50* key: user's key structure (NULL if not to be filled in)51* rkey: memory area to hold key52* data: user's data structure (NULL if not to be filled in)53* rdata: memory area to hold data54* copy: always copy the key/data item55*56* Returns:57* RET_SUCCESS, RET_ERROR.58*/59int60__bt_ret(BTREE *t, EPG *e, DBT *key, DBT *rkey, DBT *data, DBT *rdata, int copy)61{62BLEAF *bl;63void *p;6465bl = GETBLEAF(e->page, e->index);6667/*68* We must copy big keys/data to make them contiguous. Otherwise,69* leave the page pinned and don't copy unless the user specified70* concurrent access.71*/72if (key == NULL)73goto dataonly;7475if (bl->flags & P_BIGKEY) {76if (__ovfl_get(t, bl->bytes,77&key->size, &rkey->data, &rkey->size))78return (RET_ERROR);79key->data = rkey->data;80} else if (copy || F_ISSET(t, B_DB_LOCK)) {81if (bl->ksize > rkey->size) {82p = realloc(rkey->data, bl->ksize);83if (p == NULL)84return (RET_ERROR);85rkey->data = p;86rkey->size = bl->ksize;87}88memmove(rkey->data, bl->bytes, bl->ksize);89key->size = bl->ksize;90key->data = rkey->data;91} else {92key->size = bl->ksize;93key->data = bl->bytes;94}9596dataonly:97if (data == NULL)98return (RET_SUCCESS);99100if (bl->flags & P_BIGDATA) {101if (__ovfl_get(t, bl->bytes + bl->ksize,102&data->size, &rdata->data, &rdata->size))103return (RET_ERROR);104data->data = rdata->data;105} else if (copy || F_ISSET(t, B_DB_LOCK)) {106/* Use +1 in case the first record retrieved is 0 length. */107if (bl->dsize + 1 > rdata->size) {108p = realloc(rdata->data, bl->dsize + 1);109if (p == NULL)110return (RET_ERROR);111rdata->data = p;112rdata->size = bl->dsize + 1;113}114memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);115data->size = bl->dsize;116data->data = rdata->data;117} else {118data->size = bl->dsize;119data->data = bl->bytes + bl->ksize;120}121122return (RET_SUCCESS);123}124125/*126* __BT_CMP -- Compare a key to a given record.127*128* Parameters:129* t: tree130* k1: DBT pointer of first arg to comparison131* e: pointer to EPG for comparison132*133* Returns:134* < 0 if k1 is < record135* = 0 if k1 is = record136* > 0 if k1 is > record137*/138int139__bt_cmp(BTREE *t, const DBT *k1, EPG *e)140{141BINTERNAL *bi;142BLEAF *bl;143DBT k2;144PAGE *h;145void *bigkey;146147/*148* The left-most key on internal pages, at any level of the tree, is149* guaranteed by the following code to be less than any user key.150* This saves us from having to update the leftmost key on an internal151* page when the user inserts a new key in the tree smaller than152* anything we've yet seen.153*/154h = e->page;155if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))156return (1);157158bigkey = NULL;159if (h->flags & P_BLEAF) {160bl = GETBLEAF(h, e->index);161if (bl->flags & P_BIGKEY)162bigkey = bl->bytes;163else {164k2.data = bl->bytes;165k2.size = bl->ksize;166}167} else {168bi = GETBINTERNAL(h, e->index);169if (bi->flags & P_BIGKEY)170bigkey = bi->bytes;171else {172k2.data = bi->bytes;173k2.size = bi->ksize;174}175}176177if (bigkey) {178if (__ovfl_get(t, bigkey,179&k2.size, &t->bt_rdata.data, &t->bt_rdata.size))180return (RET_ERROR);181k2.data = t->bt_rdata.data;182}183return ((*t->bt_cmp)(k1, &k2));184}185186/*187* __BT_DEFCMP -- Default comparison routine.188*189* Parameters:190* a: DBT #1191* b: DBT #2192*193* Returns:194* < 0 if a is < b195* = 0 if a is = b196* > 0 if a is > b197*/198int199__bt_defcmp(const DBT *a, const DBT *b)200{201size_t len;202u_char *p1, *p2;203204/*205* XXX206* If a size_t doesn't fit in an int, this routine can lose.207* What we need is an integral type which is guaranteed to be208* larger than a size_t, and there is no such thing.209*/210len = MIN(a->size, b->size);211for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)212if (*p1 != *p2)213return ((int)*p1 - (int)*p2);214return ((int)a->size - (int)b->size);215}216217/*218* __BT_DEFPFX -- Default prefix routine.219*220* Parameters:221* a: DBT #1222* b: DBT #2223*224* Returns:225* Number of bytes needed to distinguish b from a.226*/227size_t228__bt_defpfx(const DBT *a, const DBT *b)229{230u_char *p1, *p2;231size_t cnt, len;232233cnt = 1;234len = MIN(a->size, b->size);235for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)236if (*p1 != *p2)237return (cnt);238239/* a->size must be <= b->size, or they wouldn't be in this order. */240return (a->size < b->size ? a->size + 1 : a->size);241}242243244