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