1169689Skan/* $NetBSD: rec_get.c,v 1.15 2008/09/10 17:52:36 joerg Exp $ */ 2169689Skan 3169689Skan/*- 4169689Skan * Copyright (c) 1990, 1993, 1994 5169689Skan * The Regents of the University of California. All rights reserved. 6169689Skan * 7169689Skan * Redistribution and use in source and binary forms, with or without 8169689Skan * modification, are permitted provided that the following conditions 9169689Skan * are met: 10169689Skan * 1. Redistributions of source code must retain the above copyright 11169689Skan * notice, this list of conditions and the following disclaimer. 12169689Skan * 2. Redistributions in binary form must reproduce the above copyright 13169689Skan * notice, this list of conditions and the following disclaimer in the 14169689Skan * documentation and/or other materials provided with the distribution. 15169689Skan * 3. Neither the name of the University nor the names of its contributors 16169689Skan * may be used to endorse or promote products derived from this software 17169689Skan * without specific prior written permission. 18169689Skan * 19169689Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29169689Skan * SUCH DAMAGE. 30169689Skan */ 31169689Skan 32169689Skan#if HAVE_NBTOOL_CONFIG_H 33169689Skan#include "nbtool_config.h" 34169689Skan#endif 35169689Skan 36169689Skan#include <sys/cdefs.h> 37169689Skan__RCSID("$NetBSD: rec_get.c,v 1.15 2008/09/10 17:52:36 joerg Exp $"); 38169689Skan 39169689Skan#include "namespace.h" 40169689Skan#include <sys/types.h> 41169689Skan 42169689Skan#include <assert.h> 43169689Skan#include <errno.h> 44169689Skan#include <stddef.h> 45169689Skan#include <stdio.h> 46169689Skan#include <stdlib.h> 47169689Skan#include <string.h> 48169689Skan#include <unistd.h> 49169689Skan 50169689Skan#include <db.h> 51169689Skan#include "recno.h" 52169689Skan 53169689Skan/* 54169689Skan * __REC_GET -- Get a record from the btree. 55169689Skan * 56169689Skan * Parameters: 57169689Skan * dbp: pointer to access method 58169689Skan * key: key to find 59169689Skan * data: data to return 60169689Skan * flag: currently unused 61169689Skan * 62169689Skan * Returns: 63169689Skan * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. 64169689Skan */ 65169689Skanint 66169689Skan__rec_get(const DB *dbp, const DBT *key, DBT *data, u_int flags) 67169689Skan{ 68169689Skan BTREE *t; 69169689Skan EPG *e; 70169689Skan recno_t nrec; 71169689Skan int status; 72169689Skan 73169689Skan t = dbp->internal; 74169689Skan 75169689Skan /* Toss any page pinned across calls. */ 76169689Skan if (t->bt_pinned != NULL) { 77169689Skan mpool_put(t->bt_mp, t->bt_pinned, 0); 78169689Skan t->bt_pinned = NULL; 79169689Skan } 80169689Skan 81169689Skan /* Get currently doesn't take any flags, and keys of 0 are illegal. */ 82169689Skan if (flags || (nrec = *(recno_t *)key->data) == 0) { 83169689Skan errno = EINVAL; 84169689Skan return (RET_ERROR); 85169689Skan } 86169689Skan 87169689Skan /* 88169689Skan * If we haven't seen this record yet, try to find it in the 89169689Skan * original file. 90169689Skan */ 91169689Skan if (nrec > t->bt_nrecs) { 92169689Skan if (F_ISSET(t, R_EOF | R_INMEM)) 93169689Skan return (RET_SPECIAL); 94169689Skan if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS) 95169689Skan return (status); 96169689Skan } 97169689Skan 98169689Skan --nrec; 99169689Skan if ((e = __rec_search(t, nrec, SEARCH)) == NULL) 100169689Skan return (RET_ERROR); 101169689Skan 102169689Skan status = __rec_ret(t, e, 0, NULL, data); 103169689Skan if (F_ISSET(t, B_DB_LOCK)) 104169689Skan mpool_put(t->bt_mp, e->page, 0); 105169689Skan else 106169689Skan t->bt_pinned = e->page; 107169689Skan return (status); 108169689Skan} 109169689Skan 110169689Skan/* 111169689Skan * __REC_FPIPE -- Get fixed length records from a pipe. 112169689Skan * 113169689Skan * Parameters: 114169689Skan * t: tree 115169689Skan * cnt: records to read 116169689Skan * 117169689Skan * Returns: 118169689Skan * RET_ERROR, RET_SUCCESS 119169689Skan */ 120169689Skanint 121169689Skan__rec_fpipe(BTREE *t, recno_t top) 122169689Skan{ 123169689Skan DBT data; 124169689Skan recno_t nrec; 125169689Skan size_t len; 126169689Skan int ch; 127169689Skan uint8_t *p; 128169689Skan 129169689Skan if (t->bt_rdata.size < t->bt_reclen) { 130169689Skan t->bt_rdata.data = t->bt_rdata.data == NULL ? 131169689Skan malloc(t->bt_reclen) : 132169689Skan realloc(t->bt_rdata.data, t->bt_reclen); 133169689Skan if (t->bt_rdata.data == NULL) 134169689Skan return (RET_ERROR); 135169689Skan t->bt_rdata.size = t->bt_reclen; 136169689Skan } 137169689Skan data.data = t->bt_rdata.data; 138169689Skan data.size = t->bt_reclen; 139169689Skan 140169689Skan for (nrec = t->bt_nrecs; nrec < top;) { 141169689Skan len = t->bt_reclen; 142169689Skan for (p = t->bt_rdata.data;; *p++ = ch) 143169689Skan if ((ch = getc(t->bt_rfp)) == EOF || !--len) { 144169689Skan if (ch != EOF) 145169689Skan *p = ch; 146169689Skan if (len != 0) 147169689Skan memset(p, t->bt_bval, len); 148169689Skan if (__rec_iput(t, 149169689Skan nrec, &data, 0) != RET_SUCCESS) 150169689Skan return (RET_ERROR); 151169689Skan ++nrec; 152169689Skan break; 153169689Skan } 154169689Skan if (ch == EOF) 155169689Skan break; 156169689Skan } 157169689Skan if (nrec < top) { 158169689Skan F_SET(t, R_EOF); 159169689Skan return (RET_SPECIAL); 160169689Skan } 161169689Skan return (RET_SUCCESS); 162169689Skan} 163169689Skan 164169689Skan/* 165169689Skan * __REC_VPIPE -- Get variable length records from a pipe. 166169689Skan * 167169689Skan * Parameters: 168169689Skan * t: tree 169169689Skan * cnt: records to read 170169689Skan * 171169689Skan * Returns: 172169689Skan * RET_ERROR, RET_SUCCESS 173169689Skan */ 174169689Skanint 175169689Skan__rec_vpipe(BTREE *t, recno_t top) 176169689Skan{ 177169689Skan DBT data; 178169689Skan recno_t nrec; 179169689Skan ptrdiff_t len; 180169689Skan size_t sz; 181169689Skan int bval, ch; 182169689Skan uint8_t *p; 183169689Skan 184169689Skan bval = t->bt_bval; 185169689Skan for (nrec = t->bt_nrecs; nrec < top; ++nrec) { 186169689Skan for (p = t->bt_rdata.data, 187169689Skan sz = t->bt_rdata.size;; *p++ = ch, --sz) { 188169689Skan if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) { 189169689Skan data.data = t->bt_rdata.data; 190169689Skan data.size = p - (uint8_t *)t->bt_rdata.data; 191169689Skan if (ch == EOF && data.size == 0) 192169689Skan break; 193169689Skan if (__rec_iput(t, nrec, &data, 0) 194169689Skan != RET_SUCCESS) 195169689Skan return (RET_ERROR); 196169689Skan break; 197169689Skan } 198169689Skan if (sz == 0) { 199169689Skan len = p - (uint8_t *)t->bt_rdata.data; 200169689Skan t->bt_rdata.size += (sz = 256); 201169689Skan t->bt_rdata.data = t->bt_rdata.data == NULL ? 202169689Skan malloc(t->bt_rdata.size) : 203169689Skan realloc(t->bt_rdata.data, t->bt_rdata.size); 204169689Skan if (t->bt_rdata.data == NULL) 205169689Skan return (RET_ERROR); 206169689Skan p = (uint8_t *)t->bt_rdata.data + len; 207169689Skan } 208169689Skan } 209169689Skan if (ch == EOF) 210169689Skan break; 211169689Skan } 212169689Skan if (nrec < top) { 213169689Skan F_SET(t, R_EOF); 214169689Skan return (RET_SPECIAL); 215169689Skan } 216169689Skan return (RET_SUCCESS); 217169689Skan} 218169689Skan 219169689Skan/* 220169689Skan * __REC_FMAP -- Get fixed length records from a file. 221169689Skan * 222169689Skan * Parameters: 223169689Skan * t: tree 224169689Skan * cnt: records to read 225169689Skan * 226169689Skan * Returns: 227169689Skan * RET_ERROR, RET_SUCCESS 228169689Skan */ 229169689Skanint 230169689Skan__rec_fmap(BTREE *t, recno_t top) 231169689Skan{ 232169689Skan DBT data; 233169689Skan recno_t nrec; 234169689Skan uint8_t *sp, *ep, *p; 235169689Skan size_t len; 236169689Skan 237169689Skan if (t->bt_rdata.size < t->bt_reclen) { 238169689Skan t->bt_rdata.data = t->bt_rdata.data == NULL ? 239169689Skan malloc(t->bt_reclen) : 240169689Skan realloc(t->bt_rdata.data, t->bt_reclen); 241169689Skan if (t->bt_rdata.data == NULL) 242169689Skan return (RET_ERROR); 243169689Skan t->bt_rdata.size = t->bt_reclen; 244169689Skan } 245169689Skan data.data = t->bt_rdata.data; 246169689Skan data.size = t->bt_reclen; 247169689Skan 248169689Skan sp = (uint8_t *)t->bt_cmap; 249169689Skan ep = (uint8_t *)t->bt_emap; 250169689Skan for (nrec = t->bt_nrecs; nrec < top; ++nrec) { 251169689Skan if (sp >= ep) { 252169689Skan F_SET(t, R_EOF); 253169689Skan return (RET_SPECIAL); 254169689Skan } 255169689Skan len = t->bt_reclen; 256169689Skan for (p = t->bt_rdata.data; 257169689Skan sp < ep && len > 0; *p++ = *sp++, --len); 258169689Skan if (len != 0) 259169689Skan memset(p, t->bt_bval, len); 260169689Skan if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) 261169689Skan return (RET_ERROR); 262169689Skan } 263169689Skan t->bt_cmap = (caddr_t)sp; 264169689Skan return (RET_SUCCESS); 265169689Skan} 266169689Skan 267169689Skan/* 268169689Skan * __REC_VMAP -- Get variable length records from a file. 269169689Skan * 270169689Skan * Parameters: 271169689Skan * t: tree 272169689Skan * cnt: records to read 273169689Skan * 274169689Skan * Returns: 275169689Skan * RET_ERROR, RET_SUCCESS 276169689Skan */ 277169689Skanint 278169689Skan__rec_vmap(BTREE *t, recno_t top) 279169689Skan{ 280169689Skan DBT data; 281169689Skan uint8_t *sp, *ep; 282169689Skan recno_t nrec; 283169689Skan int bval; 284169689Skan 285169689Skan sp = (uint8_t *)t->bt_cmap; 286169689Skan ep = (uint8_t *)t->bt_emap; 287169689Skan bval = t->bt_bval; 288169689Skan 289169689Skan for (nrec = t->bt_nrecs; nrec < top; ++nrec) { 290169689Skan if (sp >= ep) { 291169689Skan F_SET(t, R_EOF); 292169689Skan return (RET_SPECIAL); 293169689Skan } 294169689Skan for (data.data = sp; sp < ep && *sp != bval; ++sp); 295169689Skan data.size = sp - (uint8_t *)data.data; 296169689Skan if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) 297169689Skan return (RET_ERROR); 298169689Skan ++sp; 299169689Skan } 300169689Skan t->bt_cmap = (caddr_t)sp; 301169689Skan return (RET_SUCCESS); 302169689Skan} 303169689Skan