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