xref: /netbsd-src/external/bsd/pkg_install/dist/lib/pkgdb.c (revision f75f5aae154fcd0572e8889e4fea2a51d67bbf08)
1 /*	$NetBSD: pkgdb.c,v 1.1.1.5 2009/10/07 13:19:45 joerg Exp $	*/
2 
3 #if HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 #include <nbcompat.h>
7 #if HAVE_SYS_CDEFS_H
8 #include <sys/cdefs.h>
9 #endif
10 __RCSID("$NetBSD: pkgdb.c,v 1.1.1.5 2009/10/07 13:19:45 joerg Exp $");
11 
12 /*-
13  * Copyright (c) 1999-2008 The NetBSD Foundation, Inc.
14  * All rights reserved.
15  *
16  * This code is derived from software contributed to The NetBSD Foundation
17  * by Hubert Feyrer <hubert@feyrer.de>.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  * 1. Redistributions of source code must retain the above copyright
23  *    notice, this list of conditions and the following disclaimer.
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in the
26  *    documentation and/or other materials provided with the distribution.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 #ifdef NETBSD
42 #include <db.h>
43 #else
44 #include <nbcompat/db.h>
45 #endif
46 #if HAVE_ERR_H
47 #include <err.h>
48 #endif
49 #if HAVE_ERRNO_H
50 #include <errno.h>
51 #endif
52 #if HAVE_FCNTL_H
53 #include <fcntl.h>
54 #endif
55 #if HAVE_STDARG_H
56 #include <stdarg.h>
57 #endif
58 #if HAVE_STDIO_H
59 #include <stdio.h>
60 #endif
61 #if HAVE_STRING_H
62 #include <string.h>
63 #endif
64 
65 #include "lib.h"
66 
67 #define PKGDB_FILE	"pkgdb.byfile.db"	/* indexed by filename */
68 
69 /*
70  * Where we put logging information by default if PKG_DBDIR is unset.
71  */
72 #ifndef DEF_LOG_DIR
73 #define DEF_LOG_DIR		"/var/db/pkg"
74 #endif
75 
76 /* just in case we change the environment variable name */
77 #define PKG_DBDIR		"PKG_DBDIR"
78 
79 static DB   *pkgdbp;
80 static char *pkgdb_dir = NULL;
81 static char  pkgdb_cache[MaxPathSize];
82 
83 /*
84  *  Open the pkg-database
85  *  Return value:
86  *   1: everything ok
87  *   0: error
88  */
89 int
90 pkgdb_open(int mode)
91 {
92 	BTREEINFO info;
93 	char	cachename[MaxPathSize];
94 
95 	/* try our btree format first */
96 	info.flags = 0;
97 	info.cachesize = 2*1024*1024;
98 	info.maxkeypage = 0;
99 	info.minkeypage = 0;
100 	info.psize = 4096;
101 	info.compare = NULL;
102 	info.prefix = NULL;
103 	info.lorder = 0;
104 	pkgdbp = (DB *) dbopen(_pkgdb_getPKGDB_FILE(cachename, sizeof(cachename)),
105 	    (mode == ReadOnly) ? O_RDONLY : O_RDWR | O_CREAT,
106 	    0644, DB_BTREE, (void *) &info);
107 	return (pkgdbp != NULL);
108 }
109 
110 /*
111  * Close the pkg database
112  */
113 void
114 pkgdb_close(void)
115 {
116 	if (pkgdbp != NULL) {
117 		(void) (*pkgdbp->close) (pkgdbp);
118 		pkgdbp = NULL;
119 	}
120 }
121 
122 /*
123  * Store value "val" with key "key" in database
124  * Return value is as from ypdb_store:
125  *  0: ok
126  *  1: key already present
127  * -1: some other error, see errno
128  */
129 int
130 pkgdb_store(const char *key, const char *val)
131 {
132 	DBT     keyd, vald;
133 
134 	if (pkgdbp == NULL)
135 		return -1;
136 
137 	keyd.data = __UNCONST(key);
138 	keyd.size = strlen(key) + 1;
139 	vald.data = __UNCONST(val);
140 	vald.size = strlen(val) + 1;
141 
142 	if (keyd.size > MaxPathSize || vald.size > MaxPathSize)
143 		return -1;
144 
145 	return (*pkgdbp->put) (pkgdbp, &keyd, &vald, R_NOOVERWRITE);
146 }
147 
148 /*
149  * Recall value for given key
150  * Return value:
151  *  NULL if some error occurred or value for key not found (check errno!)
152  *  String for "value" else
153  */
154 char   *
155 pkgdb_retrieve(const char *key)
156 {
157 	DBT     keyd, vald;
158 	int     status;
159 
160 	if (pkgdbp == NULL)
161 		return NULL;
162 
163 	keyd.data = __UNCONST(key);
164 	keyd.size = strlen(key) + 1;
165 	errno = 0;		/* to be sure it's 0 if the key doesn't match anything */
166 
167 	vald.data = (void *)NULL;
168 	vald.size = 0;
169 	status = (*pkgdbp->get) (pkgdbp, &keyd, &vald, 0);
170 	if (status) {
171 		vald.data = NULL;
172 		vald.size = 0;
173 	}
174 
175 	return vald.data;
176 }
177 
178 /* dump contents of the database to stdout */
179 int
180 pkgdb_dump(void)
181 {
182 	DBT     key;
183 	DBT	val;
184 	int	type;
185 
186 	if (pkgdb_open(ReadOnly)) {
187 		for (type = R_FIRST ; (*pkgdbp->seq)(pkgdbp, &key, &val, type) == 0 ; type = R_NEXT) {
188 			printf("file: %.*s pkg: %.*s\n",
189 				(int) key.size, (char *) key.data,
190 				(int) val.size, (char *) val.data);
191 		}
192 		pkgdb_close();
193 		return 0;
194 	} else
195 		return -1;
196 }
197 
198 /*
199  *  Remove data set from pkgdb
200  *  Return value as ypdb_delete:
201  *   0: everything ok
202  *   1: key not present
203  *  -1: some error occurred (see errno)
204  */
205 int
206 pkgdb_remove(const char *key)
207 {
208 	DBT     keyd;
209 
210 	if (pkgdbp == NULL)
211 		return -1;
212 
213 	keyd.data = __UNCONST(key);
214 	keyd.size = strlen(key) + 1;
215 	if (keyd.size > MaxPathSize)
216 		return -1;
217 
218 	return (*pkgdbp->del) (pkgdbp, &keyd, 0);
219 }
220 
221 /*
222  *  Remove any entry from the cache which has a data field of `pkg'.
223  *  Return value:
224  *   1: everything ok
225  *   0: error
226  */
227 int
228 pkgdb_remove_pkg(const char *pkg)
229 {
230 	DBT     data;
231 	DBT     key;
232 	int	type;
233 	int	ret;
234 	size_t	cc;
235 	char	cachename[MaxPathSize];
236 
237 	if (pkgdbp == NULL) {
238 		return 0;
239 	}
240 	(void) _pkgdb_getPKGDB_FILE(cachename, sizeof(cachename));
241 	cc = strlen(pkg);
242 	for (ret = 1, type = R_FIRST; (*pkgdbp->seq)(pkgdbp, &key, &data, type) == 0 ; type = R_NEXT) {
243 		if ((cc + 1) == data.size && strncmp(data.data, pkg, cc) == 0) {
244 			if (Verbose) {
245 				printf("Removing file `%s' from %s\n", (char *)key.data, cachename);
246 			}
247 			switch ((*pkgdbp->del)(pkgdbp, &key, 0)) {
248 			case -1:
249 				warn("Error removing `%s' from %s", (char *)key.data, cachename);
250 				ret = 0;
251 				break;
252 			case 1:
253 				warn("Key `%s' not present in %s", (char *)key.data, cachename);
254 				ret = 0;
255 				break;
256 
257 			}
258 		}
259 	}
260 	return ret;
261 }
262 
263 /*
264  *  Return the location of the package reference counts database directory.
265  */
266 char *
267 pkgdb_refcount_dir(void)
268 {
269 	static char buf[MaxPathSize];
270 	char *tmp;
271 
272 	if ((tmp = getenv(PKG_REFCOUNT_DBDIR_VNAME)) != NULL)
273 		strlcpy(buf, tmp, sizeof(buf));
274 	else
275 		snprintf(buf, sizeof(buf), "%s.refcount", _pkgdb_getPKGDB_DIR());
276 	return buf;
277 }
278 
279 /*
280  *  Return name of cache file in the buffer that was passed.
281  */
282 char *
283 _pkgdb_getPKGDB_FILE(char *buf, unsigned size)
284 {
285 	(void) snprintf(buf, size, "%s/%s", _pkgdb_getPKGDB_DIR(), PKGDB_FILE);
286 	return buf;
287 }
288 
289 /*
290  *  Return directory where pkgdb is stored
291  */
292 const char *
293 _pkgdb_getPKGDB_DIR(void)
294 {
295 	char *tmp;
296 
297 	if (pkgdb_dir == NULL) {
298 		if ((tmp = getenv(PKG_DBDIR)) != NULL)
299 			_pkgdb_setPKGDB_DIR(tmp);
300 		else
301 			_pkgdb_setPKGDB_DIR(DEF_LOG_DIR);
302 	}
303 
304 	return pkgdb_dir;
305 }
306 
307 /*
308  *  Set the first place we look for where pkgdb is stored.
309  */
310 void
311 _pkgdb_setPKGDB_DIR(const char *dir)
312 {
313 	(void) snprintf(pkgdb_cache, sizeof(pkgdb_cache), "%s", dir);
314 	pkgdb_dir = pkgdb_cache;
315 }
316 
317 char *
318 pkgdb_pkg_file(const char *pkg, const char *file)
319 {
320 	return xasprintf("%s/%s/%s", _pkgdb_getPKGDB_DIR(), pkg, file);
321 }
322