rec_get.c revision 165903
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_get.c	8.9 (Berkeley) 8/18/94";
32#endif /* LIBC_SCCS and not lint */
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/lib/libc/db/recno/rec_get.c 165903 2007-01-09 00:28:16Z imp $");
35
36#include <sys/types.h>
37
38#include <errno.h>
39#include <stddef.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45#include <db.h>
46#include "recno.h"
47
48/*
49 * __REC_GET -- Get a record from the btree.
50 *
51 * Parameters:
52 *	dbp:	pointer to access method
53 *	key:	key to find
54 *	data:	data to return
55 *	flag:	currently unused
56 *
57 * Returns:
58 *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
59 */
60int
61__rec_get(dbp, key, data, flags)
62	const DB *dbp;
63	const DBT *key;
64	DBT *data;
65	u_int flags;
66{
67	BTREE *t;
68	EPG *e;
69	recno_t nrec;
70	int status;
71
72	t = dbp->internal;
73
74	/* Toss any page pinned across calls. */
75	if (t->bt_pinned != NULL) {
76		mpool_put(t->bt_mp, t->bt_pinned, 0);
77		t->bt_pinned = NULL;
78	}
79
80	/* Get currently doesn't take any flags, and keys of 0 are illegal. */
81	if (flags || (nrec = *(recno_t *)key->data) == 0) {
82		errno = EINVAL;
83		return (RET_ERROR);
84	}
85
86	/*
87	 * If we haven't seen this record yet, try to find it in the
88	 * original file.
89	 */
90	if (nrec > t->bt_nrecs) {
91		if (F_ISSET(t, R_EOF | R_INMEM))
92			return (RET_SPECIAL);
93		if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
94			return (status);
95	}
96
97	--nrec;
98	if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
99		return (RET_ERROR);
100
101	status = __rec_ret(t, e, 0, NULL, data);
102	if (F_ISSET(t, B_DB_LOCK))
103		mpool_put(t->bt_mp, e->page, 0);
104	else
105		t->bt_pinned = e->page;
106	return (status);
107}
108
109/*
110 * __REC_FPIPE -- Get fixed length records from a pipe.
111 *
112 * Parameters:
113 *	t:	tree
114 *	cnt:	records to read
115 *
116 * Returns:
117 *	RET_ERROR, RET_SUCCESS
118 */
119int
120__rec_fpipe(t, top)
121	BTREE *t;
122	recno_t top;
123{
124	DBT data;
125	recno_t nrec;
126	size_t len;
127	int ch;
128	u_char *p;
129
130	if (t->bt_rdata.size < t->bt_reclen) {
131		t->bt_rdata.data = t->bt_rdata.data == NULL ?
132		    malloc(t->bt_reclen) :
133		    reallocf(t->bt_rdata.data, t->bt_reclen);
134		if (t->bt_rdata.data == NULL)
135			return (RET_ERROR);
136		t->bt_rdata.size = t->bt_reclen;
137	}
138	data.data = t->bt_rdata.data;
139	data.size = t->bt_reclen;
140
141	for (nrec = t->bt_nrecs; nrec < top;) {
142		len = t->bt_reclen;
143		for (p = t->bt_rdata.data;; *p++ = ch)
144			if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
145				if (ch != EOF)
146					*p = ch;
147				if (len != 0)
148					memset(p, t->bt_bval, len);
149				if (__rec_iput(t,
150				    nrec, &data, 0) != RET_SUCCESS)
151					return (RET_ERROR);
152				++nrec;
153				break;
154			}
155		if (ch == EOF)
156			break;
157	}
158	if (nrec < top) {
159		F_SET(t, R_EOF);
160		return (RET_SPECIAL);
161	}
162	return (RET_SUCCESS);
163}
164
165/*
166 * __REC_VPIPE -- Get variable length records from a pipe.
167 *
168 * Parameters:
169 *	t:	tree
170 *	cnt:	records to read
171 *
172 * Returns:
173 *	RET_ERROR, RET_SUCCESS
174 */
175int
176__rec_vpipe(t, top)
177	BTREE *t;
178	recno_t top;
179{
180	DBT data;
181	recno_t nrec;
182	size_t len;
183	size_t sz;
184	int bval, ch;
185	u_char *p;
186
187	bval = t->bt_bval;
188	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
189		for (p = t->bt_rdata.data,
190		    sz = t->bt_rdata.size;; *p++ = ch, --sz) {
191			if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
192				data.data = t->bt_rdata.data;
193				data.size = p - (u_char *)t->bt_rdata.data;
194				if (ch == EOF && data.size == 0)
195					break;
196				if (__rec_iput(t, nrec, &data, 0)
197				    != RET_SUCCESS)
198					return (RET_ERROR);
199				break;
200			}
201			if (sz == 0) {
202				len = p - (u_char *)t->bt_rdata.data;
203				t->bt_rdata.size += (sz = 256);
204				t->bt_rdata.data = t->bt_rdata.data == NULL ?
205				    malloc(t->bt_rdata.size) :
206				    reallocf(t->bt_rdata.data, t->bt_rdata.size);
207				if (t->bt_rdata.data == NULL)
208					return (RET_ERROR);
209				p = (u_char *)t->bt_rdata.data + len;
210			}
211		}
212		if (ch == EOF)
213			break;
214	}
215	if (nrec < top) {
216		F_SET(t, R_EOF);
217		return (RET_SPECIAL);
218	}
219	return (RET_SUCCESS);
220}
221
222/*
223 * __REC_FMAP -- Get fixed length records from a file.
224 *
225 * Parameters:
226 *	t:	tree
227 *	cnt:	records to read
228 *
229 * Returns:
230 *	RET_ERROR, RET_SUCCESS
231 */
232int
233__rec_fmap(t, top)
234	BTREE *t;
235	recno_t top;
236{
237	DBT data;
238	recno_t nrec;
239	u_char *sp, *ep, *p;
240	size_t len;
241
242	if (t->bt_rdata.size < t->bt_reclen) {
243		t->bt_rdata.data = t->bt_rdata.data == NULL ?
244		    malloc(t->bt_reclen) :
245		    reallocf(t->bt_rdata.data, t->bt_reclen);
246		if (t->bt_rdata.data == NULL)
247			return (RET_ERROR);
248		t->bt_rdata.size = t->bt_reclen;
249	}
250	data.data = t->bt_rdata.data;
251	data.size = t->bt_reclen;
252
253	sp = (u_char *)t->bt_cmap;
254	ep = (u_char *)t->bt_emap;
255	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
256		if (sp >= ep) {
257			F_SET(t, R_EOF);
258			return (RET_SPECIAL);
259		}
260		len = t->bt_reclen;
261		for (p = t->bt_rdata.data;
262		    sp < ep && len > 0; *p++ = *sp++, --len);
263		if (len != 0)
264			memset(p, t->bt_bval, len);
265		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
266			return (RET_ERROR);
267	}
268	t->bt_cmap = (caddr_t)sp;
269	return (RET_SUCCESS);
270}
271
272/*
273 * __REC_VMAP -- Get variable length records from a file.
274 *
275 * Parameters:
276 *	t:	tree
277 *	cnt:	records to read
278 *
279 * Returns:
280 *	RET_ERROR, RET_SUCCESS
281 */
282int
283__rec_vmap(t, top)
284	BTREE *t;
285	recno_t top;
286{
287	DBT data;
288	u_char *sp, *ep;
289	recno_t nrec;
290	int bval;
291
292	sp = (u_char *)t->bt_cmap;
293	ep = (u_char *)t->bt_emap;
294	bval = t->bt_bval;
295
296	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
297		if (sp >= ep) {
298			F_SET(t, R_EOF);
299			return (RET_SPECIAL);
300		}
301		for (data.data = sp; sp < ep && *sp != bval; ++sp);
302		data.size = sp - (u_char *)data.data;
303		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
304			return (RET_ERROR);
305		++sp;
306	}
307	t->bt_cmap = (caddr_t)sp;
308	return (RET_SUCCESS);
309}
310