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