1/* $NetBSD: ypdb.c,v 1.10 2005/06/20 00:29:42 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.10 2005/06/20 00:29:42 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 60static 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 73DBM * 74ypdb_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 105DBM * 106ypdb_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 144static 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 173void 174ypdb_close(DBM *db) 175{ 176 (void)(db->close)(db); 177} 178 179/* 180 * Returns: 181 * DATUM on success 182 * NULL on failure 183 */ 184 185datum 186ypdb_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 211datum 212ypdb_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 235datum 236ypdb_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 259datum 260ypdb_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 281int 282ypdb_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 303int 304ypdb_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