1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997, 1998 5 * Sleepycat Software. All rights reserved. 6 */ 7 8 #include "config.h" 9 10 #ifndef lint 11 static const char sccsid[] = "@(#)os_alloc.c 10.10 (Sleepycat) 10/12/98"; 12 #endif /* not lint */ 13 14 #ifndef NO_SYSTEM_INCLUDES 15 #include <sys/types.h> 16 17 #include <errno.h> 18 #include <string.h> 19 #include <stdlib.h> 20 #endif 21 22 #include "db_int.h" 23 #include "os_jump.h" 24 25 /* 26 * !!! 27 * Correct for systems that return NULL when you allocate 0 bytes of memory. 28 * There are several places in DB where we allocate the number of bytes held 29 * by the key/data item, and it can be 0. Correct here so that malloc never 30 * returns a NULL for that reason (which behavior is permitted by ANSI). We 31 * could make these calls macros on non-Alpha architectures (that's where we 32 * saw the problem), but it's probably not worth the autoconf complexity. 33 * 34 * !!! 35 * Correct for systems that don't set errno when malloc and friends fail. 36 * 37 * Out of memory. 38 * We wish to hold the whole sky, 39 * But we never will. 40 */ 41 42 /* 43 * __os_strdup -- 44 * The strdup(3) function for DB. 45 * 46 * PUBLIC: int __os_strdup __P((const char *, void *)); 47 */ 48 int 49 __os_strdup(str, storep) 50 const char *str; 51 void *storep; 52 { 53 size_t size; 54 int ret; 55 void *p; 56 57 *(void **)storep = NULL; 58 59 size = strlen(str) + 1; 60 if ((ret = __os_malloc(size, NULL, &p)) != 0) 61 return (ret); 62 63 memcpy(p, str, size); 64 65 *(void **)storep = p; 66 return (0); 67 } 68 69 /* 70 * __os_calloc -- 71 * The calloc(3) function for DB. 72 * 73 * PUBLIC: int __os_calloc __P((size_t, size_t, void *)); 74 */ 75 int 76 __os_calloc(num, size, storep) 77 size_t num, size; 78 void *storep; 79 { 80 void *p; 81 int ret; 82 83 size *= num; 84 if ((ret = __os_malloc(size, NULL, &p)) != 0) 85 return (ret); 86 87 memset(p, 0, size); 88 *(void **)storep = p; 89 90 return (0); 91 } 92 93 /* 94 * __os_malloc -- 95 * The malloc(3) function for DB. 96 * 97 * PUBLIC: int __os_malloc __P((size_t, void *(*)(size_t), void *)); 98 */ 99 int 100 __os_malloc(size, db_malloc, storep) 101 size_t size; 102 void *(*db_malloc) __P((size_t)), *storep; 103 { 104 void *p; 105 106 *(void **)storep = NULL; 107 108 /* Never allocate 0 bytes -- some C libraries don't like it. */ 109 if (size == 0) 110 ++size; 111 112 /* Some C libraries don't correctly set errno when malloc(3) fails. */ 113 errno = 0; 114 if (db_malloc != NULL) 115 p = db_malloc(size); 116 else if (__db_jump.j_malloc != NULL) 117 p = __db_jump.j_malloc(size); 118 else 119 p = malloc(size); 120 if (p == NULL) { 121 if (errno == 0) 122 errno = ENOMEM; 123 return (errno); 124 } 125 126 #ifdef DIAGNOSTIC 127 memset(p, 0xdb, size); 128 #endif 129 *(void **)storep = p; 130 131 return (0); 132 } 133 134 /* 135 * __os_realloc -- 136 * The realloc(3) function for DB. 137 * 138 * PUBLIC: int __os_realloc __P((void *, size_t)); 139 */ 140 int 141 __os_realloc(storep, size) 142 void *storep; 143 size_t size; 144 { 145 void *p, *ptr; 146 147 ptr = *(void **)storep; 148 149 /* If we haven't yet allocated anything yet, simply call malloc. */ 150 if (ptr == NULL) 151 return (__os_malloc(size, NULL, storep)); 152 153 /* Never allocate 0 bytes -- some C libraries don't like it. */ 154 if (size == 0) 155 ++size; 156 157 /* 158 * Some C libraries don't correctly set errno when realloc(3) fails. 159 * 160 * Don't overwrite the original pointer, there are places in DB we 161 * try to continue after realloc fails. 162 */ 163 errno = 0; 164 if (__db_jump.j_realloc != NULL) 165 p = __db_jump.j_realloc(ptr, size); 166 else 167 p = realloc(ptr, size); 168 if (p == NULL) { 169 if (errno == 0) 170 errno = ENOMEM; 171 return (errno); 172 } 173 174 *(void **)storep = p; 175 176 return (0); 177 } 178 179 /* 180 * __os_free -- 181 * The free(3) function for DB. 182 * 183 * PUBLIC: void __os_free __P((void *, size_t)); 184 */ 185 void 186 __os_free(ptr, size) 187 void *ptr; 188 size_t size; 189 { 190 #ifdef DIAGNOSTIC 191 if (size != 0) 192 memset(ptr, 0xdb, size); 193 #endif 194 195 if (__db_jump.j_free != NULL) 196 __db_jump.j_free(ptr); 197 else 198 free(ptr); 199 } 200 201 /* 202 * __os_freestr -- 203 * The free(3) function for DB, freeing a string. 204 * 205 * PUBLIC: void __os_freestr __P((void *)); 206 */ 207 void 208 __os_freestr(ptr) 209 void *ptr; 210 { 211 #ifdef DIAGNOSTIC 212 memset(ptr, 0xdb, strlen(ptr) + 1); 213 #endif 214 215 if (__db_jump.j_free != NULL) 216 __db_jump.j_free(ptr); 217 else 218 free(ptr); 219 } 220