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