Update.
[glibc.git] / db2 / db / db_ret.c
blob9d9b599ad6a157a20e3b0c42749b4419c2ceb6c6
1 /*-
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "@(#)db_ret.c 10.13 (Sleepycat) 5/7/98";
12 #endif /* not lint */
14 #ifndef NO_SYSTEM_INCLUDES
15 #include <sys/types.h>
17 #include <errno.h>
18 #include <string.h>
19 #endif
21 #include "db_int.h"
22 #include "db_page.h"
23 #include "btree.h"
24 #include "db_am.h"
27 * __db_ret --
28 * Build return DBT.
30 * PUBLIC: int __db_ret __P((DB *,
31 * PUBLIC: PAGE *, u_int32_t, DBT *, void **, u_int32_t *));
33 int
34 __db_ret(dbp, h, indx, dbt, memp, memsize)
35 DB *dbp;
36 PAGE *h;
37 u_int32_t indx;
38 DBT *dbt;
39 void **memp;
40 u_int32_t *memsize;
42 BKEYDATA *bk;
43 HOFFPAGE ho;
44 BOVERFLOW *bo;
45 u_int32_t len;
46 u_int8_t *hk;
47 void *data;
49 switch (TYPE(h)) {
50 case P_HASH:
51 hk = P_ENTRY(h, indx);
52 if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
53 memcpy(&ho, hk, sizeof(HOFFPAGE));
54 return (__db_goff(dbp, dbt,
55 ho.tlen, ho.pgno, memp, memsize));
57 len = LEN_HKEYDATA(h, dbp->pgsize, indx);
58 data = HKEYDATA_DATA(hk);
59 break;
60 case P_DUPLICATE:
61 case P_LBTREE:
62 case P_LRECNO:
63 bk = GET_BKEYDATA(h, indx);
64 if (B_TYPE(bk->type) == B_OVERFLOW) {
65 bo = (BOVERFLOW *)bk;
66 return (__db_goff(dbp, dbt,
67 bo->tlen, bo->pgno, memp, memsize));
69 len = bk->len;
70 data = bk->data;
71 break;
72 default:
73 return (__db_pgfmt(dbp, h->pgno));
76 return (__db_retcopy(dbt, data, len, memp, memsize,
77 F_ISSET(dbt, DB_DBT_INTERNAL) ? NULL : dbp->db_malloc));
81 * __db_retcopy --
82 * Copy the returned data into the user's DBT, handling special flags.
84 * PUBLIC: int __db_retcopy __P((DBT *,
85 * PUBLIC: void *, u_int32_t, void **, u_int32_t *, void *(*)(size_t)));
87 int
88 __db_retcopy(dbt, data, len, memp, memsize, db_malloc)
89 DBT *dbt;
90 void *data;
91 u_int32_t len;
92 void **memp;
93 u_int32_t *memsize;
94 void *(*db_malloc) __P((size_t));
96 /* If returning a partial record, reset the length. */
97 if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
98 data = (u_int8_t *)data + dbt->doff;
99 if (len > dbt->doff) {
100 len -= dbt->doff;
101 if (len > dbt->dlen)
102 len = dbt->dlen;
103 } else
104 len = 0;
108 * Return the length of the returned record in the DBT size field.
109 * This satisfies the requirement that if we're using user memory
110 * and insufficient memory was provided, return the amount necessary
111 * in the size field.
113 dbt->size = len;
116 * Allocate memory to be owned by the application: DB_DBT_MALLOC.
118 * !!!
119 * We always allocate memory, even if we're copying out 0 bytes. This
120 * guarantees consistency, i.e., the application can always free memory
121 * without concern as to how many bytes of the record were requested.
123 * XXX
124 * Never allocate 0 bytes, it's known to make malloc/realloc unhappy.
126 * Use the memory specified by the application: DB_DBT_USERMEM.
128 * !!!
129 * If the length we're going to copy is 0, the application-supplied
130 * memory pointer is allowed to be NULL.
132 if (F_ISSET(dbt, DB_DBT_MALLOC)) {
133 dbt->data = db_malloc == NULL ?
134 (void *)__db_malloc(len) :
135 (void *)db_malloc(len + 1);
136 if (dbt->data == NULL)
137 return (ENOMEM);
138 } else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
139 if (len != 0 && (dbt->data == NULL || dbt->ulen < len))
140 return (ENOMEM);
141 } else if (memp == NULL || memsize == NULL) {
142 return (EINVAL);
143 } else {
144 if (len != 0 && (*memsize == 0 || *memsize < len)) {
145 *memp = *memp == NULL ?
146 (void *)__db_malloc(len) :
147 (void *)__db_realloc(*memp, len);
148 if (*memp == NULL) {
149 *memsize = 0;
150 return (ENOMEM);
152 *memsize = len;
154 dbt->data = *memp;
157 if (len != 0)
158 memcpy(dbt->data, data, len);
159 return (0);