xref: /netbsd/usr.sbin/ypserv/common/ypdb.c (revision dc3f3e27)
1*dc3f3e27Schristos /*	$NetBSD: ypdb.c,v 1.12 2017/01/10 21:06:17 christos Exp $	*/
260aa689cSthorpej 
360aa689cSthorpej /*
460aa689cSthorpej  * Copyright (c) 1990, 1993
560aa689cSthorpej  *	The Regents of the University of California.  All rights reserved.
660aa689cSthorpej  * All rights reserved.
760aa689cSthorpej  *
860aa689cSthorpej  * This code is derived from software contributed to Berkeley by
960aa689cSthorpej  * Margo Seltzer.
1060aa689cSthorpej  *
1160aa689cSthorpej  * This code is derived from ndbm module of BSD4.4 db (hash) by
1260aa689cSthorpej  * Mats O Jansson
1360aa689cSthorpej  *
1460aa689cSthorpej  * Redistribution and use in source and binary forms, with or without
1560aa689cSthorpej  * modification, are permitted provided that the following conditions
1660aa689cSthorpej  * are met:
1760aa689cSthorpej  * 1. Redistributions of source code must retain the above copyright
1860aa689cSthorpej  *    notice, this list of conditions and the following disclaimer.
1960aa689cSthorpej  * 2. Redistributions in binary form must reproduce the above copyright
2060aa689cSthorpej  *    notice, this list of conditions and the following disclaimer in the
2160aa689cSthorpej  *    documentation and/or other materials provided with the distribution.
22326b2259Sagc  * 3. Neither the name of the University nor the names of its contributors
2360aa689cSthorpej  *    may be used to endorse or promote products derived from this software
2460aa689cSthorpej  *    without specific prior written permission.
2560aa689cSthorpej  *
2660aa689cSthorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
2760aa689cSthorpej  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2860aa689cSthorpej  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2960aa689cSthorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
3060aa689cSthorpej  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3160aa689cSthorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3260aa689cSthorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3360aa689cSthorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3460aa689cSthorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3560aa689cSthorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3660aa689cSthorpej  * SUCH DAMAGE.
3760aa689cSthorpej  */
3860aa689cSthorpej 
39652dc940Slukem #include <sys/cdefs.h>
40652dc940Slukem #ifndef lint
41*dc3f3e27Schristos __RCSID("$NetBSD: ypdb.c,v 1.12 2017/01/10 21:06:17 christos Exp $");
42652dc940Slukem #endif
43652dc940Slukem 
4460aa689cSthorpej #include <sys/param.h>
4560aa689cSthorpej #include <sys/types.h>
46*dc3f3e27Schristos #include <sys/stat.h>
47652dc940Slukem 
48652dc940Slukem #include <db.h>
49aa159e4aSlukem #include <err.h>
50652dc940Slukem #include <errno.h>
51cea4b7cdSlukem #include <fcntl.h>
5260aa689cSthorpej #include <stdio.h>
53cea4b7cdSlukem #include <stdlib.h>
5460aa689cSthorpej #include <string.h>
55cea4b7cdSlukem #include <unistd.h>
5660aa689cSthorpej 
57f4fb444bSlukem #include <rpcsvc/yp.h>
58f4fb444bSlukem 
593d8138fcSthorpej #include "ypdb.h"
6060aa689cSthorpej 
61cea4b7cdSlukem static DBM	*_ypdb_dbopen(const char *, int, mode_t);
62cea4b7cdSlukem 
6360aa689cSthorpej /*
64aa159e4aSlukem  * ypdb_open --
65cea4b7cdSlukem  *	dbopen(3) file, read-only.
66aa159e4aSlukem  *	First ensure that file has a suffix of YPDB_SUFFIX.
67aa159e4aSlukem  *	Try opening as a DB_BTREE first, then DB_HASH.
68aa159e4aSlukem  *
6960aa689cSthorpej  * Returns:
7060aa689cSthorpej  *	*DBM on success
7160aa689cSthorpej  *	 NULL on failure
7260aa689cSthorpej  */
7360aa689cSthorpej 
74c0495ebbSlukem DBM *
ypdb_open(const char * file)75cea4b7cdSlukem ypdb_open(const char *file)
7660aa689cSthorpej {
77aa159e4aSlukem 	char path[MAXPATHLEN];
78aa159e4aSlukem 	const char *cp, *suffix;
7960aa689cSthorpej 
80652dc940Slukem 	cp = strrchr(file, '.');
81aa159e4aSlukem 	if (cp != NULL && strcmp(cp, YPDB_SUFFIX) == 0)
82aa159e4aSlukem 		suffix = "";
83aa159e4aSlukem 	else
84aa159e4aSlukem 		suffix = YPDB_SUFFIX;
85aa159e4aSlukem 	if (strlen(file) + strlen(suffix) > (sizeof(path) - 1)) {
86aa159e4aSlukem 		warnx("File name `%s' is too long", file);
87aa159e4aSlukem 		return (NULL);
88aa159e4aSlukem 	}
89aa159e4aSlukem 	snprintf(path, sizeof(path), "%s%s", file, suffix);
90cea4b7cdSlukem 	return _ypdb_dbopen(path, O_RDONLY, 0444);
91cea4b7cdSlukem }
92cea4b7cdSlukem 
93cea4b7cdSlukem /*
94cea4b7cdSlukem  * ypdb_mktemp --
95cea4b7cdSlukem  *	Create a temporary file using mkstemp(3) based on the
96cea4b7cdSlukem  *	template provided in file.
97cea4b7cdSlukem  *	dbopen(3) file, read-write, 0644 (modified by umask(2)).
98cea4b7cdSlukem  *	Try opening as a DB_BTREE first, then DB_HASH.
99cea4b7cdSlukem  *	file won't have YPDB_SUFFIX.
100cea4b7cdSlukem  *
101cea4b7cdSlukem  * Returns:
102cea4b7cdSlukem  *	*DBM on success; file now exists.
103cea4b7cdSlukem  *	 NULL on failure
104cea4b7cdSlukem  */
105cea4b7cdSlukem 
106cea4b7cdSlukem DBM *
ypdb_mktemp(char * file)107cea4b7cdSlukem ypdb_mktemp(char *file)
108cea4b7cdSlukem {
109cea4b7cdSlukem 	int fd = -1;
110cea4b7cdSlukem 	DBM *db = NULL;
111cea4b7cdSlukem 	mode_t myumask;
112cea4b7cdSlukem 	int save_errno;
113cea4b7cdSlukem 
114cea4b7cdSlukem 	if ((fd = mkstemp(file)) == -1)
115cea4b7cdSlukem 		return NULL;
116cea4b7cdSlukem 
117cea4b7cdSlukem 	myumask = umask(0);
118cea4b7cdSlukem 	(void)umask(myumask);
119cea4b7cdSlukem 	if (fchmod(fd, 0644 & ~myumask) == -1)
120cea4b7cdSlukem 		goto bad;
121cea4b7cdSlukem 
122cea4b7cdSlukem 	(void) close(fd);
123cea4b7cdSlukem 	fd = -1;
124cea4b7cdSlukem 
125cea4b7cdSlukem 	if ((db = _ypdb_dbopen(file, O_RDWR, 0644)) == NULL)
126cea4b7cdSlukem 		goto bad;
127cea4b7cdSlukem 
128cea4b7cdSlukem 	return db;
129cea4b7cdSlukem 
130cea4b7cdSlukem  bad:
131cea4b7cdSlukem 	save_errno = errno;
132cea4b7cdSlukem 	if (fd != 1)
133cea4b7cdSlukem 		(void) close(fd);
134cea4b7cdSlukem 	(void) unlink(file);
135cea4b7cdSlukem 	errno = save_errno;
136cea4b7cdSlukem 	return NULL;
137cea4b7cdSlukem }
138cea4b7cdSlukem 
139cea4b7cdSlukem /*
140cea4b7cdSlukem  * _ypdb_dbopen --
141cea4b7cdSlukem  *	dbopen(3) path with the flags & mode.
142cea4b7cdSlukem  *	Try opening as a DB_BTREE first, then DB_HASH.
143cea4b7cdSlukem  */
144cea4b7cdSlukem 
145cea4b7cdSlukem static DBM *
_ypdb_dbopen(const char * path,int flags,mode_t mode)146cea4b7cdSlukem _ypdb_dbopen(const char *path, int flags, mode_t mode)
147cea4b7cdSlukem {
148cea4b7cdSlukem 	DBM *db;
149cea4b7cdSlukem 	BTREEINFO info;
150652dc940Slukem 
151652dc940Slukem 		/* try our btree format first */
15260aa689cSthorpej 	info.flags = 0;
15360aa689cSthorpej 	info.cachesize = 0;
15460aa689cSthorpej 	info.maxkeypage = 0;
15560aa689cSthorpej 	info.minkeypage = 0;
15660aa689cSthorpej 	info.psize = 0;
15760aa689cSthorpej 	info.compare = NULL;
15860aa689cSthorpej 	info.prefix = NULL;
15960aa689cSthorpej 	info.lorder = 0;
160652dc940Slukem 	db = (DBM *)dbopen(path, flags, mode, DB_BTREE, (void *)&info);
161652dc940Slukem 	if (db != NULL || errno != EFTYPE)
162652dc940Slukem 		return (db);
163652dc940Slukem 
164652dc940Slukem 		/* fallback to standard hash (for sendmail's aliases.db) */
165652dc940Slukem 	db = (DBM *)dbopen(path, flags, mode, DB_HASH, NULL);
166652dc940Slukem 	return (db);
16760aa689cSthorpej }
16860aa689cSthorpej 
169cea4b7cdSlukem /*
170cea4b7cdSlukem  * ypdb_close --
171cea4b7cdSlukem  *	Close the db
172cea4b7cdSlukem  */
173cea4b7cdSlukem 
174c0495ebbSlukem void
ypdb_close(DBM * db)1755c90fa67Swiz ypdb_close(DBM *db)
17660aa689cSthorpej {
17760aa689cSthorpej 	(void)(db->close)(db);
17860aa689cSthorpej }
17960aa689cSthorpej 
18060aa689cSthorpej /*
18160aa689cSthorpej  * Returns:
18260aa689cSthorpej  *	DATUM on success
18360aa689cSthorpej  *	NULL on failure
18460aa689cSthorpej  */
18560aa689cSthorpej 
186c0495ebbSlukem datum
ypdb_fetch(DBM * db,datum key)1875c90fa67Swiz ypdb_fetch(DBM *db, datum key)
18860aa689cSthorpej {
189275da9fcSlukem 	datum retkey;
190275da9fcSlukem 	DBT nk, nd;
19160aa689cSthorpej 	int status;
19260aa689cSthorpej 
193275da9fcSlukem 	nk.data = key.dptr;
19481a3e762Slukem 	nk.size = key.dsize;
195275da9fcSlukem 	status = (db->get)(db, &nk, &nd, 0);
19660aa689cSthorpej 	if (status) {
197275da9fcSlukem 		retkey.dptr = NULL;
198275da9fcSlukem 		retkey.dsize = 0;
199275da9fcSlukem 	} else {
200275da9fcSlukem 		retkey.dptr = nd.data;
20181a3e762Slukem 		retkey.dsize = nd.size;
20260aa689cSthorpej 	}
203275da9fcSlukem 	return (retkey);
20460aa689cSthorpej }
20560aa689cSthorpej 
20660aa689cSthorpej /*
20760aa689cSthorpej  * Returns:
20860aa689cSthorpej  *	DATUM on success
20960aa689cSthorpej  *	NULL on failure
21060aa689cSthorpej  */
21160aa689cSthorpej 
212c0495ebbSlukem datum
ypdb_firstkey(DBM * db)2135c90fa67Swiz ypdb_firstkey(DBM *db)
21460aa689cSthorpej {
21560aa689cSthorpej 	int status;
216275da9fcSlukem 	datum retkey;
217275da9fcSlukem 	DBT nk, nd;
21860aa689cSthorpej 
219275da9fcSlukem 	status = (db->seq)(db, &nk, &nd, R_FIRST);
220275da9fcSlukem 	if (status) {
22160aa689cSthorpej 		retkey.dptr = NULL;
222275da9fcSlukem 		retkey.dsize = 0;
223275da9fcSlukem 	} else {
224275da9fcSlukem 		retkey.dptr = nk.data;
22581a3e762Slukem 		retkey.dsize = nk.size;
226275da9fcSlukem 	}
22760aa689cSthorpej 	return (retkey);
22860aa689cSthorpej }
22960aa689cSthorpej 
23060aa689cSthorpej /*
23160aa689cSthorpej  * Returns:
23260aa689cSthorpej  *	DATUM on success
23360aa689cSthorpej  *	NULL on failure
23460aa689cSthorpej  */
23560aa689cSthorpej 
236c0495ebbSlukem datum
ypdb_nextkey(DBM * db)2375c90fa67Swiz ypdb_nextkey(DBM *db)
23860aa689cSthorpej {
23960aa689cSthorpej 	int status;
240275da9fcSlukem 	datum retkey;
241275da9fcSlukem 	DBT nk, nd;
24260aa689cSthorpej 
243275da9fcSlukem 	status = (db->seq)(db, &nk, &nd, R_NEXT);
244275da9fcSlukem 	if (status) {
24560aa689cSthorpej 		retkey.dptr = NULL;
246275da9fcSlukem 		retkey.dsize = 0;
247275da9fcSlukem 	} else {
248275da9fcSlukem 		retkey.dptr = nk.data;
24981a3e762Slukem 		retkey.dsize = nk.size;
250275da9fcSlukem 	}
25160aa689cSthorpej 	return (retkey);
25260aa689cSthorpej }
25360aa689cSthorpej 
25460aa689cSthorpej /*
25560aa689cSthorpej  * Returns:
25660aa689cSthorpej  *	DATUM on success
25760aa689cSthorpej  *	NULL on failure
25860aa689cSthorpej  */
25960aa689cSthorpej 
260c0495ebbSlukem datum
ypdb_setkey(DBM * db,datum key)2615c90fa67Swiz ypdb_setkey(DBM *db, datum key)
26260aa689cSthorpej {
26360aa689cSthorpej 	int status;
264275da9fcSlukem 	DBT nk, nd;
265275da9fcSlukem 
266275da9fcSlukem 	nk.data = key.dptr;
26781a3e762Slukem 	nk.size = key.dsize;
268275da9fcSlukem 	status = (db->seq)(db, &nk, &nd, R_CURSOR);
269275da9fcSlukem 	if (status) {
27060aa689cSthorpej 		key.dptr = NULL;
271275da9fcSlukem 		key.dsize = 0;
272275da9fcSlukem 	}
27360aa689cSthorpej 	return (key);
27460aa689cSthorpej }
27560aa689cSthorpej 
27660aa689cSthorpej /*
27760aa689cSthorpej  * Returns:
27860aa689cSthorpej  *	 0 on success
27960aa689cSthorpej  *	<0 failure
28060aa689cSthorpej  */
28160aa689cSthorpej 
28260aa689cSthorpej int
ypdb_delete(DBM * db,datum key)2835c90fa67Swiz ypdb_delete(DBM *db, datum key)
28460aa689cSthorpej {
28560aa689cSthorpej 	int status;
286275da9fcSlukem 	DBT nk;
28760aa689cSthorpej 
288275da9fcSlukem 	nk.data = key.dptr;
28981a3e762Slukem 	nk.size = key.dsize;
290275da9fcSlukem 	status = (db->del)(db, &nk, 0);
29160aa689cSthorpej 	if (status)
29260aa689cSthorpej 		return (-1);
29360aa689cSthorpej 	else
29460aa689cSthorpej 		return (0);
29560aa689cSthorpej }
29660aa689cSthorpej 
29760aa689cSthorpej /*
29860aa689cSthorpej  * Returns:
29960aa689cSthorpej  *	 0 on success
30060aa689cSthorpej  *	<0 failure
30160aa689cSthorpej  *	 1 if YPDB_INSERT and entry exists
30260aa689cSthorpej  */
30360aa689cSthorpej 
30460aa689cSthorpej int
ypdb_store(DBM * db,datum key,datum content,int flags)3055c90fa67Swiz ypdb_store(DBM *db, datum key, datum content, int flags)
30660aa689cSthorpej {
307275da9fcSlukem 	DBT nk, nd;
308275da9fcSlukem 
309f4fb444bSlukem 	if (key.dsize > YPMAXRECORD || content.dsize > YPMAXRECORD)
310f4fb444bSlukem 		return -1;
311275da9fcSlukem 	nk.data = key.dptr;
31281a3e762Slukem 	nk.size = key.dsize;
313275da9fcSlukem 	nd.data = content.dptr;
31481a3e762Slukem 	nd.size = content.dsize;
315275da9fcSlukem 	return ((db->put)(db, &nk, &nd,
31660aa689cSthorpej 	    (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0));
31760aa689cSthorpej }
318