1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996,2008 Oracle.  All rights reserved.
5 */
6/*
7 * Copyright (c) 1990, 1993
8 *	Margo Seltzer.  All rights reserved.
9 */
10/*
11 * Copyright (c) 1990, 1993
12 *	The Regents of the University of California.  All rights reserved.
13 *
14 * This code is derived from software contributed to Berkeley by
15 * Margo Seltzer.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors
26 *    may be used to endorse or promote products derived from this software
27 *    without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * $Id: hsearch.c,v 12.11 2008/01/11 20:50:00 bostic Exp $
42 */
43
44#define	DB_DBM_HSEARCH	1
45#include "db_config.h"
46
47#include "db_int.h"
48
49static DB	*dbp;
50static ENTRY	 retval;
51
52/*
53 * Translate HSEARCH calls into DB calls so that DB doesn't step on the
54 * application's name space.
55 *
56 * EXTERN: #if DB_DBM_HSEARCH != 0
57 *
58 * EXTERN: int __db_hcreate __P((size_t));
59 * EXTERN: ENTRY *__db_hsearch __P((ENTRY, ACTION));
60 * EXTERN: void __db_hdestroy __P((void));
61 *
62 * EXTERN: #endif
63 */
64int
65__db_hcreate(nel)
66	size_t nel;
67{
68	int ret;
69
70	if ((ret = db_create(&dbp, NULL, 0)) != 0) {
71		__os_set_errno(ret);
72		return (1);
73	}
74
75	if ((ret = dbp->set_pagesize(dbp, 512)) != 0 ||
76	    (ret = dbp->set_h_ffactor(dbp, 16)) != 0 ||
77	    (ret = dbp->set_h_nelem(dbp, (u_int32_t)nel)) != 0 ||
78	    (ret = dbp->open(dbp, NULL,
79	    NULL, NULL, DB_HASH, DB_CREATE, DB_MODE_600)) != 0)
80		__os_set_errno(ret);
81
82	/*
83	 * !!!
84	 * Hsearch returns 0 on error, not 1.
85	 */
86	return (ret == 0 ? 1 : 0);
87}
88
89ENTRY *
90__db_hsearch(item, action)
91	ENTRY item;
92	ACTION action;
93{
94	DBT key, val;
95	int ret;
96
97	if (dbp == NULL) {
98		__os_set_errno(EINVAL);
99		return (NULL);
100	}
101	DB_INIT_DBT(key, item.key, strlen(item.key) + 1);
102	memset(&val, 0, sizeof(val));
103
104	switch (action) {
105	case ENTER:
106		DB_SET_DBT(val, item.data, strlen(item.data) + 1);
107
108		/*
109		 * Try and add the key to the database.  If we fail because
110		 * the key already exists, return the existing key.
111		 */
112		if ((ret =
113		    dbp->put(dbp, NULL, &key, &val, DB_NOOVERWRITE)) == 0)
114			break;
115		if (ret == DB_KEYEXIST &&
116		    (ret = dbp->get(dbp, NULL, &key, &val, 0)) == 0)
117			break;
118		/*
119		 * The only possible DB error is DB_NOTFOUND, and it can't
120		 * happen.  Check for a DB error, and lie if we find one.
121		 */
122		__os_set_errno(ret > 0 ? ret : EINVAL);
123		return (NULL);
124	case FIND:
125		if ((ret = dbp->get(dbp, NULL, &key, &val, 0)) != 0) {
126			if (ret != DB_NOTFOUND)
127				__os_set_errno(ret);
128			return (NULL);
129		}
130		item.data = (char *)val.data;
131		break;
132	default:
133		__os_set_errno(EINVAL);
134		return (NULL);
135	}
136	retval.key = item.key;
137	retval.data = item.data;
138	return (&retval);
139}
140
141void
142__db_hdestroy()
143{
144	if (dbp != NULL) {
145		(void)dbp->close(dbp, 0);
146		dbp = NULL;
147	}
148}
149