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