1 /* $NetBSD: ypdb.c,v 1.11 2008/02/29 03:00:47 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Margo Seltzer. 10 * 11 * This code is derived from ndbm module of BSD4.4 db (hash) by 12 * Mats O Jansson 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 30 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 __RCSID("$NetBSD: ypdb.c,v 1.11 2008/02/29 03:00:47 lukem Exp $"); 42 #endif 43 44 #include <sys/param.h> 45 #include <sys/types.h> 46 47 #include <db.h> 48 #include <err.h> 49 #include <errno.h> 50 #include <fcntl.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 56 #include <rpcsvc/yp.h> 57 58 #include "ypdb.h" 59 60 static DBM *_ypdb_dbopen(const char *, int, mode_t); 61 62 /* 63 * ypdb_open -- 64 * dbopen(3) file, read-only. 65 * First ensure that file has a suffix of YPDB_SUFFIX. 66 * Try opening as a DB_BTREE first, then DB_HASH. 67 * 68 * Returns: 69 * *DBM on success 70 * NULL on failure 71 */ 72 73 DBM * 74 ypdb_open(const char *file) 75 { 76 char path[MAXPATHLEN]; 77 const char *cp, *suffix; 78 79 cp = strrchr(file, '.'); 80 if (cp != NULL && strcmp(cp, YPDB_SUFFIX) == 0) 81 suffix = ""; 82 else 83 suffix = YPDB_SUFFIX; 84 if (strlen(file) + strlen(suffix) > (sizeof(path) - 1)) { 85 warnx("File name `%s' is too long", file); 86 return (NULL); 87 } 88 snprintf(path, sizeof(path), "%s%s", file, suffix); 89 return _ypdb_dbopen(path, O_RDONLY, 0444); 90 } 91 92 /* 93 * ypdb_mktemp -- 94 * Create a temporary file using mkstemp(3) based on the 95 * template provided in file. 96 * dbopen(3) file, read-write, 0644 (modified by umask(2)). 97 * Try opening as a DB_BTREE first, then DB_HASH. 98 * file won't have YPDB_SUFFIX. 99 * 100 * Returns: 101 * *DBM on success; file now exists. 102 * NULL on failure 103 */ 104 105 DBM * 106 ypdb_mktemp(char *file) 107 { 108 int fd = -1; 109 DBM *db = NULL; 110 mode_t myumask; 111 int save_errno; 112 113 if ((fd = mkstemp(file)) == -1) 114 return NULL; 115 116 myumask = umask(0); 117 (void)umask(myumask); 118 if (fchmod(fd, 0644 & ~myumask) == -1) 119 goto bad; 120 121 (void) close(fd); 122 fd = -1; 123 124 if ((db = _ypdb_dbopen(file, O_RDWR, 0644)) == NULL) 125 goto bad; 126 127 return db; 128 129 bad: 130 save_errno = errno; 131 if (fd != 1) 132 (void) close(fd); 133 (void) unlink(file); 134 errno = save_errno; 135 return NULL; 136 } 137 138 /* 139 * _ypdb_dbopen -- 140 * dbopen(3) path with the flags & mode. 141 * Try opening as a DB_BTREE first, then DB_HASH. 142 */ 143 144 static DBM * 145 _ypdb_dbopen(const char *path, int flags, mode_t mode) 146 { 147 DBM *db; 148 BTREEINFO info; 149 150 /* try our btree format first */ 151 info.flags = 0; 152 info.cachesize = 0; 153 info.maxkeypage = 0; 154 info.minkeypage = 0; 155 info.psize = 0; 156 info.compare = NULL; 157 info.prefix = NULL; 158 info.lorder = 0; 159 db = (DBM *)dbopen(path, flags, mode, DB_BTREE, (void *)&info); 160 if (db != NULL || errno != EFTYPE) 161 return (db); 162 163 /* fallback to standard hash (for sendmail's aliases.db) */ 164 db = (DBM *)dbopen(path, flags, mode, DB_HASH, NULL); 165 return (db); 166 } 167 168 /* 169 * ypdb_close -- 170 * Close the db 171 */ 172 173 void 174 ypdb_close(DBM *db) 175 { 176 (void)(db->close)(db); 177 } 178 179 /* 180 * Returns: 181 * DATUM on success 182 * NULL on failure 183 */ 184 185 datum 186 ypdb_fetch(DBM *db, datum key) 187 { 188 datum retkey; 189 DBT nk, nd; 190 int status; 191 192 nk.data = key.dptr; 193 nk.size = key.dsize; 194 status = (db->get)(db, &nk, &nd, 0); 195 if (status) { 196 retkey.dptr = NULL; 197 retkey.dsize = 0; 198 } else { 199 retkey.dptr = nd.data; 200 retkey.dsize = nd.size; 201 } 202 return (retkey); 203 } 204 205 /* 206 * Returns: 207 * DATUM on success 208 * NULL on failure 209 */ 210 211 datum 212 ypdb_firstkey(DBM *db) 213 { 214 int status; 215 datum retkey; 216 DBT nk, nd; 217 218 status = (db->seq)(db, &nk, &nd, R_FIRST); 219 if (status) { 220 retkey.dptr = NULL; 221 retkey.dsize = 0; 222 } else { 223 retkey.dptr = nk.data; 224 retkey.dsize = nk.size; 225 } 226 return (retkey); 227 } 228 229 /* 230 * Returns: 231 * DATUM on success 232 * NULL on failure 233 */ 234 235 datum 236 ypdb_nextkey(DBM *db) 237 { 238 int status; 239 datum retkey; 240 DBT nk, nd; 241 242 status = (db->seq)(db, &nk, &nd, R_NEXT); 243 if (status) { 244 retkey.dptr = NULL; 245 retkey.dsize = 0; 246 } else { 247 retkey.dptr = nk.data; 248 retkey.dsize = nk.size; 249 } 250 return (retkey); 251 } 252 253 /* 254 * Returns: 255 * DATUM on success 256 * NULL on failure 257 */ 258 259 datum 260 ypdb_setkey(DBM *db, datum key) 261 { 262 int status; 263 DBT nk, nd; 264 265 nk.data = key.dptr; 266 nk.size = key.dsize; 267 status = (db->seq)(db, &nk, &nd, R_CURSOR); 268 if (status) { 269 key.dptr = NULL; 270 key.dsize = 0; 271 } 272 return (key); 273 } 274 275 /* 276 * Returns: 277 * 0 on success 278 * <0 failure 279 */ 280 281 int 282 ypdb_delete(DBM *db, datum key) 283 { 284 int status; 285 DBT nk; 286 287 nk.data = key.dptr; 288 nk.size = key.dsize; 289 status = (db->del)(db, &nk, 0); 290 if (status) 291 return (-1); 292 else 293 return (0); 294 } 295 296 /* 297 * Returns: 298 * 0 on success 299 * <0 failure 300 * 1 if YPDB_INSERT and entry exists 301 */ 302 303 int 304 ypdb_store(DBM *db, datum key, datum content, int flags) 305 { 306 DBT nk, nd; 307 308 if (key.dsize > YPMAXRECORD || content.dsize > YPMAXRECORD) 309 return -1; 310 nk.data = key.dptr; 311 nk.size = key.dsize; 312 nd.data = content.dptr; 313 nd.size = content.dsize; 314 return ((db->put)(db, &nk, &nd, 315 (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0)); 316 } 317