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