1/*-
2 * Copyright (c) 1990, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char sccsid[] = "@(#)rec_utils.c	8.6 (Berkeley) 7/16/94";
32#endif /* LIBC_SCCS and not lint */
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD$");
35
36#include <sys/param.h>
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41
42#include <db.h>
43#include "recno.h"
44
45/*
46 * __rec_ret --
47 *	Build return data.
48 *
49 * Parameters:
50 *	t:	tree
51 *	e:	key/data pair to be returned
52 *   nrec:	record number
53 *    key:	user's key structure
54 *   data:	user's data structure
55 *
56 * Returns:
57 *	RET_SUCCESS, RET_ERROR.
58 */
59int
60__rec_ret(BTREE *t, EPG *e, recno_t nrec, DBT *key, DBT *data)
61{
62	RLEAF *rl;
63	void *p;
64
65	if (key == NULL)
66		goto dataonly;
67
68	/* We have to copy the key, it's not on the page. */
69	if (sizeof(recno_t) > t->bt_rkey.size) {
70		p = realloc(t->bt_rkey.data, sizeof(recno_t));
71		if (p == NULL)
72			return (RET_ERROR);
73		t->bt_rkey.data = p;
74		t->bt_rkey.size = sizeof(recno_t);
75	}
76	memmove(t->bt_rkey.data, &nrec, sizeof(recno_t));
77	key->size = sizeof(recno_t);
78	key->data = t->bt_rkey.data;
79
80dataonly:
81	if (data == NULL)
82		return (RET_SUCCESS);
83
84	/*
85	 * We must copy big keys/data to make them contigous.  Otherwise,
86	 * leave the page pinned and don't copy unless the user specified
87	 * concurrent access.
88	 */
89	rl = GETRLEAF(e->page, e->index);
90	if (rl->flags & P_BIGDATA) {
91		if (__ovfl_get(t, rl->bytes,
92		    &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
93			return (RET_ERROR);
94		data->data = t->bt_rdata.data;
95	} else if (F_ISSET(t, B_DB_LOCK)) {
96		/* Use +1 in case the first record retrieved is 0 length. */
97		if (rl->dsize + 1 > t->bt_rdata.size) {
98			p = realloc(t->bt_rdata.data, rl->dsize + 1);
99			if (p == NULL)
100				return (RET_ERROR);
101			t->bt_rdata.data = p;
102			t->bt_rdata.size = rl->dsize + 1;
103		}
104		memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
105		data->size = rl->dsize;
106		data->data = t->bt_rdata.data;
107	} else {
108		data->size = rl->dsize;
109		data->data = rl->bytes;
110	}
111	return (RET_SUCCESS);
112}
113