1 /* $OpenBSD: ndbm.c,v 1.26 2016/05/07 21:58:06 tedu Exp $ */ 2 3 /*- 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Margo Seltzer. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <limits.h> 38 #include <stdio.h> 39 #include <string.h> 40 41 #include <ndbm.h> 42 #include "hash.h" 43 44 /* 45 * 46 * This package provides dbm and ndbm compatible interfaces to DB. 47 * First are the DBM routines, which call the NDBM routines, and 48 * the NDBM routines, which call the DB routines. 49 */ 50 static DBM *__cur_db; 51 52 static DBM *_dbm_open(const char *, const char *, int, mode_t); 53 54 /* 55 * Returns: 56 * *DBM on success 57 * NULL on failure 58 */ 59 static DBM * 60 _dbm_open(file, suff, flags, mode) 61 const char *file; 62 const char *suff; 63 int flags; 64 mode_t mode; 65 { 66 HASHINFO info; 67 char path[PATH_MAX]; 68 int len; 69 70 len = snprintf(path, sizeof path, "%s%s", file, suff); 71 if (len < 0 || len >= sizeof path) { 72 errno = ENAMETOOLONG; 73 return (NULL); 74 } 75 /* O_WRONLY not supported by db(3) but traditional ndbm allowed it. */ 76 if ((flags & O_ACCMODE) == O_WRONLY) { 77 flags &= ~O_WRONLY; 78 flags |= O_RDWR; 79 } 80 info.bsize = 4096; 81 info.ffactor = 40; 82 info.nelem = 1; 83 info.cachesize = 0; 84 info.hash = NULL; 85 info.lorder = 0; 86 return ((DBM *)__hash_open(path, flags, mode, &info, 0)); 87 } 88 89 /* 90 * Returns: 91 * *DBM on success 92 * NULL on failure 93 */ 94 DBM * 95 dbm_open(file, flags, mode) 96 const char *file; 97 int flags; 98 mode_t mode; 99 { 100 101 return(_dbm_open(file, DBM_SUFFIX, flags, mode)); 102 } 103 104 /* 105 * Returns: 106 * Nothing. 107 */ 108 void 109 dbm_close(db) 110 DBM *db; 111 { 112 113 (void)(db->close)(db); 114 } 115 DEF_WEAK(dbm_close); 116 117 /* 118 * Returns: 119 * DATUM on success 120 * NULL on failure 121 */ 122 datum 123 dbm_fetch(db, key) 124 DBM *db; 125 datum key; 126 { 127 datum retdata; 128 int status; 129 DBT dbtkey, dbtretdata; 130 131 dbtkey.data = key.dptr; 132 dbtkey.size = key.dsize; 133 status = (db->get)(db, &dbtkey, &dbtretdata, 0); 134 if (status) { 135 dbtretdata.data = NULL; 136 dbtretdata.size = 0; 137 } 138 retdata.dptr = dbtretdata.data; 139 retdata.dsize = dbtretdata.size; 140 return (retdata); 141 } 142 DEF_WEAK(dbm_fetch); 143 144 /* 145 * Returns: 146 * DATUM on success 147 * NULL on failure 148 */ 149 datum 150 dbm_firstkey(db) 151 DBM *db; 152 { 153 int status; 154 datum retkey; 155 DBT dbtretkey, dbtretdata; 156 157 status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST); 158 if (status) 159 dbtretkey.data = NULL; 160 retkey.dptr = dbtretkey.data; 161 retkey.dsize = dbtretkey.size; 162 return (retkey); 163 } 164 DEF_WEAK(dbm_firstkey); 165 166 /* 167 * Returns: 168 * DATUM on success 169 * NULL on failure 170 */ 171 datum 172 dbm_nextkey(db) 173 DBM *db; 174 { 175 int status; 176 datum retkey; 177 DBT dbtretkey, dbtretdata; 178 179 status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT); 180 if (status) 181 dbtretkey.data = NULL; 182 retkey.dptr = dbtretkey.data; 183 retkey.dsize = dbtretkey.size; 184 return (retkey); 185 } 186 DEF_WEAK(dbm_nextkey); 187 188 /* 189 * Returns: 190 * 0 on success 191 * <0 on failure 192 */ 193 int 194 dbm_delete(db, key) 195 DBM *db; 196 datum key; 197 { 198 int status; 199 DBT dbtkey; 200 201 dbtkey.data = key.dptr; 202 dbtkey.size = key.dsize; 203 status = (db->del)(db, &dbtkey, 0); 204 if (status) 205 return (-1); 206 else 207 return (0); 208 } 209 DEF_WEAK(dbm_delete); 210 211 /* 212 * Returns: 213 * 0 on success 214 * <0 on failure 215 * 1 if DBM_INSERT and entry exists 216 */ 217 int 218 dbm_store(db, key, data, flags) 219 DBM *db; 220 datum key, data; 221 int flags; 222 { 223 DBT dbtkey, dbtdata; 224 225 dbtkey.data = key.dptr; 226 dbtkey.size = key.dsize; 227 dbtdata.data = data.dptr; 228 dbtdata.size = data.dsize; 229 return ((db->put)(db, &dbtkey, &dbtdata, 230 (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); 231 } 232 DEF_WEAK(dbm_store); 233 234 int 235 dbm_error(db) 236 DBM *db; 237 { 238 HTAB *hp; 239 240 hp = (HTAB *)db->internal; 241 return (hp->err); 242 } 243 244 int 245 dbm_clearerr(db) 246 DBM *db; 247 { 248 HTAB *hp; 249 250 hp = (HTAB *)db->internal; 251 hp->err = 0; 252 return (0); 253 } 254 255 int 256 dbm_dirfno(db) 257 DBM *db; 258 { 259 260 return(((HTAB *)db->internal)->fp); 261 } 262 263 int 264 dbm_rdonly(dbp) 265 DBM *dbp; 266 { 267 HTAB *hashp = (HTAB *)dbp->internal; 268 269 /* Could use DBM_RDONLY instead if we wanted... */ 270 return ((hashp->flags & O_ACCMODE) == O_RDONLY); 271 } 272 DEF_WEAK(dbm_rdonly); 273