rec_get.c revision 68455
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 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)rec_get.c	8.9 (Berkeley) 8/18/94";
36#endif /* LIBC_SCCS and not lint */
37
38#if !defined(lint)
39static char rcsid[] = "@(#)$FreeBSD: head/lib/libc/db/recno/rec_get.c 68455 2000-11-07 22:19:23Z obrien $";
40#endif
41
42#include <sys/types.h>
43
44#include <errno.h>
45#include <stddef.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50
51#include <db.h>
52#include "recno.h"
53
54/*
55 * __REC_GET -- Get a record from the btree.
56 *
57 * Parameters:
58 *	dbp:	pointer to access method
59 *	key:	key to find
60 *	data:	data to return
61 *	flag:	currently unused
62 *
63 * Returns:
64 *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
65 */
66int
67__rec_get(dbp, key, data, flags)
68	const DB *dbp;
69	const DBT *key;
70	DBT *data;
71	u_int flags;
72{
73	BTREE *t;
74	EPG *e;
75	recno_t nrec;
76	int status;
77
78	t = dbp->internal;
79
80	/* Toss any page pinned across calls. */
81	if (t->bt_pinned != NULL) {
82		mpool_put(t->bt_mp, t->bt_pinned, 0);
83		t->bt_pinned = NULL;
84	}
85
86	/* Get currently doesn't take any flags, and keys of 0 are illegal. */
87	if (flags || (nrec = *(recno_t *)key->data) == 0) {
88		errno = EINVAL;
89		return (RET_ERROR);
90	}
91
92	/*
93	 * If we haven't seen this record yet, try to find it in the
94	 * original file.
95	 */
96	if (nrec > t->bt_nrecs) {
97		if (F_ISSET(t, R_EOF | R_INMEM))
98			return (RET_SPECIAL);
99		if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
100			return (status);
101	}
102
103	--nrec;
104	if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
105		return (RET_ERROR);
106
107	status = __rec_ret(t, e, 0, NULL, data);
108	if (F_ISSET(t, B_DB_LOCK))
109		mpool_put(t->bt_mp, e->page, 0);
110	else
111		t->bt_pinned = e->page;
112	return (status);
113}
114
115/*
116 * __REC_FPIPE -- Get fixed length records from a pipe.
117 *
118 * Parameters:
119 *	t:	tree
120 *	cnt:	records to read
121 *
122 * Returns:
123 *	RET_ERROR, RET_SUCCESS
124 */
125int
126__rec_fpipe(t, top)
127	BTREE *t;
128	recno_t top;
129{
130	DBT data;
131	recno_t nrec;
132	size_t len;
133	int ch;
134	u_char *p;
135
136	if (t->bt_rdata.size < t->bt_reclen) {
137		t->bt_rdata.data = t->bt_rdata.data == NULL ?
138		    malloc(t->bt_reclen) :
139		    reallocf(t->bt_rdata.data, t->bt_reclen);
140		if (t->bt_rdata.data == NULL)
141			return (RET_ERROR);
142		t->bt_rdata.size = t->bt_reclen;
143	}
144	data.data = t->bt_rdata.data;
145	data.size = t->bt_reclen;
146
147	for (nrec = t->bt_nrecs; nrec < top;) {
148		len = t->bt_reclen;
149		for (p = t->bt_rdata.data;; *p++ = ch)
150			if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
151				if (ch != EOF)
152					*p = ch;
153				if (len != 0)
154					memset(p, t->bt_bval, len);
155				if (__rec_iput(t,
156				    nrec, &data, 0) != RET_SUCCESS)
157					return (RET_ERROR);
158				++nrec;
159				break;
160			}
161		if (ch == EOF)
162			break;
163	}
164	if (nrec < top) {
165		F_SET(t, R_EOF);
166		return (RET_SPECIAL);
167	}
168	return (RET_SUCCESS);
169}
170
171/*
172 * __REC_VPIPE -- Get variable length records from a pipe.
173 *
174 * Parameters:
175 *	t:	tree
176 *	cnt:	records to read
177 *
178 * Returns:
179 *	RET_ERROR, RET_SUCCESS
180 */
181int
182__rec_vpipe(t, top)
183	BTREE *t;
184	recno_t top;
185{
186	DBT data;
187	recno_t nrec;
188	size_t len;
189	size_t sz;
190	int bval, ch;
191	u_char *p;
192
193	bval = t->bt_bval;
194	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
195		for (p = t->bt_rdata.data,
196		    sz = t->bt_rdata.size;; *p++ = ch, --sz) {
197			if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
198				data.data = t->bt_rdata.data;
199				data.size = p - (u_char *)t->bt_rdata.data;
200				if (ch == EOF && data.size == 0)
201					break;
202				if (__rec_iput(t, nrec, &data, 0)
203				    != RET_SUCCESS)
204					return (RET_ERROR);
205				break;
206			}
207			if (sz == 0) {
208				len = p - (u_char *)t->bt_rdata.data;
209				t->bt_rdata.size += (sz = 256);
210				t->bt_rdata.data = t->bt_rdata.data == NULL ?
211				    malloc(t->bt_rdata.size) :
212				    reallocf(t->bt_rdata.data, t->bt_rdata.size);
213				if (t->bt_rdata.data == NULL)
214					return (RET_ERROR);
215				p = (u_char *)t->bt_rdata.data + len;
216			}
217		}
218		if (ch == EOF)
219			break;
220	}
221	if (nrec < top) {
222		F_SET(t, R_EOF);
223		return (RET_SPECIAL);
224	}
225	return (RET_SUCCESS);
226}
227
228/*
229 * __REC_FMAP -- Get fixed length records from a file.
230 *
231 * Parameters:
232 *	t:	tree
233 *	cnt:	records to read
234 *
235 * Returns:
236 *	RET_ERROR, RET_SUCCESS
237 */
238int
239__rec_fmap(t, top)
240	BTREE *t;
241	recno_t top;
242{
243	DBT data;
244	recno_t nrec;
245	u_char *sp, *ep, *p;
246	size_t len;
247
248	if (t->bt_rdata.size < t->bt_reclen) {
249		t->bt_rdata.data = t->bt_rdata.data == NULL ?
250		    malloc(t->bt_reclen) :
251		    reallocf(t->bt_rdata.data, t->bt_reclen);
252		if (t->bt_rdata.data == NULL)
253			return (RET_ERROR);
254		t->bt_rdata.size = t->bt_reclen;
255	}
256	data.data = t->bt_rdata.data;
257	data.size = t->bt_reclen;
258
259	sp = (u_char *)t->bt_cmap;
260	ep = (u_char *)t->bt_emap;
261	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
262		if (sp >= ep) {
263			F_SET(t, R_EOF);
264			return (RET_SPECIAL);
265		}
266		len = t->bt_reclen;
267		for (p = t->bt_rdata.data;
268		    sp < ep && len > 0; *p++ = *sp++, --len);
269		if (len != 0)
270			memset(p, t->bt_bval, len);
271		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
272			return (RET_ERROR);
273	}
274	t->bt_cmap = (caddr_t)sp;
275	return (RET_SUCCESS);
276}
277
278/*
279 * __REC_VMAP -- Get variable length records from a file.
280 *
281 * Parameters:
282 *	t:	tree
283 *	cnt:	records to read
284 *
285 * Returns:
286 *	RET_ERROR, RET_SUCCESS
287 */
288int
289__rec_vmap(t, top)
290	BTREE *t;
291	recno_t top;
292{
293	DBT data;
294	u_char *sp, *ep;
295	recno_t nrec;
296	int bval;
297
298	sp = (u_char *)t->bt_cmap;
299	ep = (u_char *)t->bt_emap;
300	bval = t->bt_bval;
301
302	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
303		if (sp >= ep) {
304			F_SET(t, R_EOF);
305			return (RET_SPECIAL);
306		}
307		for (data.data = sp; sp < ep && *sp != bval; ++sp);
308		data.size = sp - (u_char *)data.data;
309		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
310			return (RET_ERROR);
311		++sp;
312	}
313	t->bt_cmap = (caddr_t)sp;
314	return (RET_SUCCESS);
315}
316