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