/* $NetBSD: pkgdb.c,v 1.1.1.3 2007/08/23 15:19:15 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" #endif #include #if HAVE_SYS_CDEFS_H #include #endif #ifndef lint __RCSID("$NetBSD: pkgdb.c,v 1.1.1.3 2007/08/23 15:19:15 joerg Exp $"); #endif /* * Copyright (c) 1999 Hubert Feyrer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Hubert Feyrer for * the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if HAVE_DB_185_H #include #elif HAVE_DB1_DB_H #include #elif HAVE_DB_H #include #endif #if HAVE_ERR_H #include #endif #if HAVE_ERRNO_H #include #endif #if HAVE_FCNTL_H #include #endif #if HAVE_STDARG_H #include #endif #if HAVE_STDIO_H #include #endif #if HAVE_STRING_H #include #endif #if defined(HAVE_DBOPEN) || (defined(HAVE___DB185_OPEN) && defined(HAVE_DB_185_H)) #define HAVE_DBLIB 1 #else #define HAVE_DBLIB 0 #endif #include "lib.h" #define PKGDB_FILE "pkgdb.byfile.db" /* indexed by filename */ /* * Where we put logging information by default if PKG_DBDIR is unset. */ #ifndef DEF_LOG_DIR #define DEF_LOG_DIR "/var/db/pkg" #endif /* just in case we change the environment variable name */ #define PKG_DBDIR "PKG_DBDIR" #if HAVE_DBLIB static DB *pkgdbp; #endif static char *pkgdb_dir = NULL; static char pkgdb_cache[MaxPathSize]; #if HAVE_DBLIB /* * Open the pkg-database * Return value: * 1: everything ok * 0: error */ int pkgdb_open(int mode) { BTREEINFO info; char cachename[MaxPathSize]; /* try our btree format first */ info.flags = 0; info.cachesize = 2*1024*1024; info.maxkeypage = 0; info.minkeypage = 0; info.psize = 4096; info.compare = NULL; info.prefix = NULL; info.lorder = 0; pkgdbp = (DB *) dbopen(_pkgdb_getPKGDB_FILE(cachename, sizeof(cachename)), (mode == ReadOnly) ? O_RDONLY : O_RDWR | O_CREAT, 0644, DB_BTREE, (void *) &info); return (pkgdbp != NULL); } /* * Close the pkg database */ void pkgdb_close(void) { if (pkgdbp != NULL) { (void) (*pkgdbp->close) (pkgdbp); pkgdbp = NULL; } } /* * Store value "val" with key "key" in database * Return value is as from ypdb_store: * 0: ok * 1: key already present * -1: some other error, see errno */ int pkgdb_store(const char *key, const char *val) { DBT keyd, vald; if (pkgdbp == NULL) return -1; keyd.data = (void *) key; keyd.size = strlen(key) + 1; vald.data = (void *) val; vald.size = strlen(val) + 1; if (keyd.size > MaxPathSize || vald.size > MaxPathSize) return -1; return (*pkgdbp->put) (pkgdbp, &keyd, &vald, R_NOOVERWRITE); } /* * Recall value for given key * Return value: * NULL if some error occurred or value for key not found (check errno!) * String for "value" else */ char * pkgdb_retrieve(const char *key) { DBT keyd, vald; int status; if (pkgdbp == NULL) return NULL; keyd.data = (void *) key; keyd.size = strlen(key) + 1; errno = 0; /* to be sure it's 0 if the key doesn't match anything */ vald.data = (void *)NULL; vald.size = 0; status = (*pkgdbp->get) (pkgdbp, &keyd, &vald, 0); if (status) { vald.data = NULL; vald.size = 0; } return vald.data; } /* dump contents of the database to stdout */ int pkgdb_dump(void) { DBT key; DBT val; int type; if (pkgdb_open(ReadOnly)) { for (type = R_FIRST ; (*pkgdbp->seq)(pkgdbp, &key, &val, type) == 0 ; type = R_NEXT) { printf("file: %.*s pkg: %.*s\n", (int) key.size, (char *) key.data, (int) val.size, (char *) val.data); } pkgdb_close(); return 0; } else return -1; } /* * Remove data set from pkgdb * Return value as ypdb_delete: * 0: everything ok * 1: key not present * -1: some error occurred (see errno) */ int pkgdb_remove(const char *key) { DBT keyd; if (pkgdbp == NULL) return -1; keyd.data = (char *) key; keyd.size = strlen(key) + 1; if (keyd.size > MaxPathSize) return -1; return (*pkgdbp->del) (pkgdbp, &keyd, 0); } /* * Remove any entry from the cache which has a data field of `pkg'. * Return value: * 1: everything ok * 0: error */ int pkgdb_remove_pkg(const char *pkg) { DBT data; DBT key; int type; int ret; int cc; char cachename[MaxPathSize]; if (pkgdbp == NULL) { return 0; } (void) _pkgdb_getPKGDB_FILE(cachename, sizeof(cachename)); cc = strlen(pkg); for (ret = 1, type = R_FIRST; (*pkgdbp->seq)(pkgdbp, &key, &data, type) == 0 ; type = R_NEXT) { if ((cc + 1) == data.size && strncmp(data.data, pkg, cc) == 0) { if (Verbose) { printf("Removing file `%s' from %s\n", (char *)key.data, cachename); } switch ((*pkgdbp->del)(pkgdbp, &key, 0)) { case -1: warn("Error removing `%s' from %s", (char *)key.data, cachename); ret = 0; break; case 1: warn("Key `%s' not present in %s", (char *)key.data, cachename); ret = 0; break; } } } return ret; } #else /* !HAVE_DBLIB */ int pkgdb_open(int mode) { return 1; } void pkgdb_close(void) {} int pkgdb_store(const char *key, const char *val) { return 0; } char *pkgdb_retrieve(const char *key) { return NULL; } int pkgdb_dump(void) { return 0; } int pkgdb_remove(const char *key) { return 0; } int pkgdb_remove_pkg(const char *pkg) { return 1; } #endif /* HAVE_DBLIB */ /* * Return the location of the package reference counts database directory. */ char * pkgdb_refcount_dir(void) { static char buf[MaxPathSize]; char *tmp; if ((tmp = getenv(PKG_REFCOUNT_DBDIR_VNAME))) strlcpy(buf, tmp, sizeof(buf)); else snprintf(buf, sizeof(buf), "%s.refcount", _pkgdb_getPKGDB_DIR()); return buf; } /* * Return name of cache file in the buffer that was passed. */ char * _pkgdb_getPKGDB_FILE(char *buf, unsigned size) { (void) snprintf(buf, size, "%s/%s", _pkgdb_getPKGDB_DIR(), PKGDB_FILE); return buf; } /* * Return directory where pkgdb is stored */ const char * _pkgdb_getPKGDB_DIR(void) { char *tmp; if (pkgdb_dir == NULL) { if ((tmp = getenv(PKG_DBDIR))) _pkgdb_setPKGDB_DIR(tmp); else _pkgdb_setPKGDB_DIR(DEF_LOG_DIR); } return pkgdb_dir; } /* * Set the first place we look for where pkgdb is stored. */ void _pkgdb_setPKGDB_DIR(const char *dir) { (void) snprintf(pkgdb_cache, sizeof(pkgdb_cache), "%s", dir); pkgdb_dir = pkgdb_cache; } char * pkgdb_pkg_file(const char *pkg, const char *file) { char *buf; if (asprintf(&buf, "%s/%s/%s", _pkgdb_getPKGDB_DIR(), pkg, file) == -1) err(EXIT_FAILURE, "asprintf failed"); return buf; }