From owner-p4-projects@FreeBSD.ORG Wed Oct 13 06:49:45 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E84901065673; Wed, 13 Oct 2010 06:49:44 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AA69E1065670 for ; Wed, 13 Oct 2010 06:49:44 +0000 (UTC) (envelope-from dforsyth@FreeBSD.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id 95B618FC14 for ; Wed, 13 Oct 2010 06:49:44 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id o9D6niI2012748 for ; Wed, 13 Oct 2010 06:49:44 GMT (envelope-from dforsyth@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id o9D6niT5012745 for perforce@freebsd.org; Wed, 13 Oct 2010 06:49:44 GMT (envelope-from dforsyth@FreeBSD.org) Date: Wed, 13 Oct 2010 06:49:44 GMT Message-Id: <201010130649.o9D6niT5012745@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to dforsyth@FreeBSD.org using -f From: David Forsythe To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 184654 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Oct 2010 06:49:45 -0000 http://p4web.freebsd.org/@@184654?ac=10 Change 184654 by dforsyth@skunk on 2010/10/13 06:49:39 Committing mainly for back up. Packages are now created by databases. Logging isnt in this change. Affected files ... .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/Makefile#4 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/database.c#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/database.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/database_internal.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/depend.c#1 add .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/depend.h#1 add .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/file.c#1 add .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/file.h#1 add .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/freebsd_database_directorydb.c#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/freebsd_database_directorydb.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/freebsd_plist.c#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/freebsd_plist.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/internal.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/pkg.c#4 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/pkg.h#4 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/pkg_freebsd.c#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/pkg_freebsd.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/pkg_internal.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/libpkg/pkg_pkg.h#3 edit .. //depot/projects/soc2010/dforsyth_libpkg/pkg_install/pkg_dump/pkg_dump.c#2 edit Differences ... ==== //depot/projects/soc2010/dforsyth_libpkg/libpkg/Makefile#4 (text+ko) ==== @@ -14,12 +14,13 @@ property.c \ database.c \ repository.c \ - pkg_freebsd.c \ freebsd_plist.c \ freebsd_database_directorydb.c \ freebsd_repository_ftp.c \ util.c \ - exec.c + exec.c \ + file.c \ + depend.c CFLAGS+= -std=c99 ==== //depot/projects/soc2010/dforsyth_libpkg/libpkg/database.c#3 (text+ko) ==== @@ -18,10 +18,24 @@ #define MAGIC 0x00000001 -struct pkg_database * -pkg_database_create(void) +#include "freebsd_database_directorydb.h" + +/* + * Verify the magic value in a package database. If there is a mismatch, crash + * the client application. + */ +void +_pkg_db_check_magic(struct pkg_db *db, const char *func) +{ + if (db->magic != MAGIC) { + PKG_CLIENT_CRASH(func, "database magic number mismatch."); + } +} + +struct pkg_db * +pkg_db_create(void) { - struct pkg_database *db; + struct pkg_db *db; db = calloc(1, sizeof(*db)); if (db == NULL) { @@ -29,168 +43,158 @@ } db->magic = MAGIC; + /* If NULL, closed. If not NULL, open. */ db->internal = NULL; - db->vtable = NULL; - db->status = CLOSED; + + /* TODO: NULL out callback pointers. */ + db->open = fbsd_directorydb_open; + db->all = fbsd_directorydb_all; + db->get = fbsd_directorydb_get; return (db); } -/* - * Verify the magic value in a package database. If there is a mismatch, crash - * the client application. - */ -void -_pkg_database_check_magic(struct pkg_database *db, const char *func) -{ - if (db->magic != MAGIC) { - PKG_CLIENT_CRASH(func, "database magic number mismatch."); - } -} - -/* Release a package database from memory. */ int -pkg_database_release(struct pkg_database *db) +pkg_db_finish(struct pkg_db *db) { - _pkg_database_check_magic(db, __func__); - - if (db->status != CLOSED) { - if (db->vtable->close(db) != PKG_OK) { - warnx("db->vtable->close() failed."); + if (db->internal != NULL) { + if (pkg_db_close(db) != PKG_OK) { + warnx("Could not close pkg_db (%s)\n", db->path); return (PKG_NOT_OK); } } + free(db); return (PKG_OK); } -void -_pkg_database_set_vtable(struct pkg_database *db, struct pkg_database_vtable *vt) -{ - db->vtable = vt; -} - -/* - * Do a check on the magic value, attributes, and vtable of a database, then - * call its open callback. +/* + * Open a database. */ int -pkg_database_open(struct pkg_database *db, const char *location, u_int f) +pkg_db_open(struct pkg_db *db, const char *path) { int r; - _pkg_database_check_magic(db, __func__); + _pkg_db_check_magic(db, __func__); + + r = PKG_NOT_OK; + if ((r = db->open(db, path)) == PKG_OK) { + strcpy(db->path, path); + } -#if 0 - debug_logger(LOG_LIBRARY, "Open pkg_database at \"%s\".", location); -#endif - - if ((r = db->vtable->open(db, location, f)) == PKG_OK) { - db->status = OPEN; - } - /* Need the return value incase we caught a fatal. */ return (r); } -int -pkg_database_close(struct pkg_database *db) +struct pkg_list * +pkg_db_all(struct pkg_db *db) { - int r; + return (db->all(db)); +} - if (db->status != OPEN) { +uid_t +pkg_db_owner(struct pkg_db *db) +{ + if (db->internal == NULL) { return (PKG_NOT_OK); } - if ((r = db->vtable->close(db)) == PKG_OK) { - db->status = CLOSED; + return (db->owner(db)); +} + +const char * +pkg_db_path(struct pkg_db *db) +{ + if (db->internal == NULL) { + return (NULL); } - return (r); + + return (db->path); } -/* Get the next package in a database. */ int -pkg_database_get_next_pkg(struct pkg_database *db, struct pkg *p, u_int f) +pkg_db_close(struct pkg_db *db) { int r; - _pkg_check_magic(p, __func__); - _pkg_database_check_magic(db, __func__); + if (db->internal != NULL) { + if (db->close) { + r = db->close(db); + } else { + r = PKG_OK; + } + } else { + /* kaboom? */ + return (PKG_NOT_OK); + } + + return (r); +} + +struct pkg * +pkg_db_add(struct pkg_db *db, const char *key) +{ + struct pkg *pkg; - if (db->status != OPEN) { - return (PKG_NOT_OK); + pkg = pkg_alloc(); + if (pkg == NULL) { + return (NULL); } - /* - * The database and package have both been validated. Clear the package - * and pass it to the _get_next_pkg function in the vtable. - */ - pkg_clear(p); - r = db->vtable->get_next_pkg(db, p, f); - if (r == PKG_FATAL) { - PKG_CLIENT_CRASH(__func__, "Got PKG_FATAL"); + /* Do the add and set up pkg. */ + if (db->add(db, pkg, key) != PKG_OK) { + pkg_free(pkg); + return (NULL); } - return (r); + return (pkg); } -#if 0 -int -pkg_database_get_pkg(struct pkg_database *db, struct pkg *, u_int f) +struct pkg * +pkg_db_get(struct pkg_db *db, const char *key) { - int r; + /* XXX: This function is a perfect example of why I need error + * properties. */ + struct pkg *pkg; + + pkg = pkg_alloc(); + if (pkg == NULL) { + return (NULL); + } - _pkg_check_magic(p, __func__); - _pkg_database_check_magic(db, __func__); - - if (db->status != OPEN) { - PKG_CLIENT_CRASH(__func__, "Database is not open"); + strcpy(pkg->key, key); + if (db->get(db, pkg, key) != PKG_OK) { + return (NULL); } - r = db->vtable->get_pkg(db, p, f); - - PKG_CLIENT_CRASH(__func__, "Not implemented."); - - return (r) + return (pkg); } -#endif -void -pkg_database_rewind(struct pkg_database *db) +int +pkg_db_delete(struct pkg_db *db, const char *key) { - _pkg_database_check_magic(db, __func__); - db->vtable->rewind(db); + /* Does a complete removal of all information pertaining to pkg key from + * the database. Any pkg objects for this package or now invalid/stale. + * */ + return (db->delete(db, key)); } int -pkg_database_add_pkg(struct pkg_database *db, struct pkg *p, u_int f) +pkg_db_destroy(struct pkg_db *db, struct pkg *p) { -#if 0 - int r; -#endif - (void)f; + (void)db; + (void)p; + return (PKG_OK); +} - _pkg_check_magic(p, __func__); - - if (db->status != OPEN) { - PKG_CLIENT_CRASH(__func__, "db->status != OPEN"); - } - /* Log this action. */ - /* - * This functions will put weird shit in your logs if you haven't set - * the key_name attribute. - */ -#if 0 - r = pkg_logging_log_database_add(p, db->vtable->add, db, p, f); - return (r); -#endif - PKG_CLIENT_CRASH(__func__, "Not implemented."); - return (PKG_NOT_OK); +int +pkg_db_revert(struct pkg_db *db) +{ + return (db->revert(db)); } int -pkg_database_remove_pkg(struct pkg_database *db, const char *name) +pkg_db_sync(struct pkg_db *db) { - _pkg_database_check_magic(db, __func__); - - return (db->vtable->remove_pkg(db, name)); + return (db->sync(db)); } ==== //depot/projects/soc2010/dforsyth_libpkg/libpkg/database.h#3 (text+ko) ==== @@ -10,34 +10,59 @@ #include "pkg.h" -/* XXX: Init's for database types. */ -void pkg_database_directorydb_init(struct pkg_database *); +/* Allocate a new pkg_db object. */ +struct pkg_db *pkg_db_create(void); + +/* Free a pkg_db object. Closes with no sync if open. */ +int pkg_db_finish(struct pkg_db *); + +/* Get the path of a pkg_db . */ +const char *pkg_db_path(struct pkg_db *); + +struct pkg_list *pkg_db_all(struct pkg_db *); + +/* XXX: Get allocates a package if the package is already in the db. Add + * allocates a package if the package is NOT already in the db. */ + +/* Create a pkg in a pkg_db. If the pkg already exists, returns NULL. */ +struct pkg *pkg_db_add(struct pkg_db *, const char *); + +/* Get a pkg from a pkg_db. If the package does not exist, returns NULL. */ +struct pkg *pkg_db_get(struct pkg_db *, const char *); -struct pkg_database *pkg_database_create(void); +// /* Get all pkgs from a pkg_db that match an expressions. */ +// struct pkg_list *pkg_db_get(struct pkg_db *, const char *); -int pkg_database_release(struct pkg_database *); +/* Deletes a pkg from a pkg_db. */ +int pkg_db_delete(struct pkg_db *, const char *); -uid_t pkg_database_owner(struct pkg_database *); +/* Destroy a pkg object that was created by pkg_db. */ +int pkg_db_destroy(struct pkg_db *, struct pkg *); -/* Get the next package in a database. */ -int pkg_database_get_next_pkg(struct pkg_database *, struct pkg *, u_int); +/* Returns the uid of the owner of a pkg_db. */ +uid_t pkg_db_owner(struct pkg_db *); -/* Get the current package (again). */ -int pkg_database_get_pkg(struct pkg_database *, struct pkg *, u_int); +void pkg_db_set_callbacks(struct pkg_db *, + int (*close) (struct pkg_db *), + struct pkg *(*add) (struct pkg_db *, const char *), + int (*delete) (struct pkg_db *, const char *), + int (*open) (struct pkg_db *, const char *), + uid_t (*owner) (struct pkg_db *), + struct pkg *(*get) (struct pkg_db *, const char *, + uint32_t), + int (*revert) (struct pkg_db *), + int (*sync) (struct pkg_db *)); -/* Reset the cursor in a database. */ -void pkg_database_rewind(struct pkg_database *); +/* Undo all changes to a pkg_db. */ +int pkg_db_revert(struct pkg_db *); /* Open a database for interaction. */ -int pkg_database_open(struct pkg_database *, const char *, u_int); +int pkg_db_open(struct pkg_db *, const char *); /* Close a database. */ -int pkg_database_close(struct pkg_database *); +int pkg_db_close(struct pkg_db *); -/* Add a package to a database. */ -int pkg_database_add_pkg(struct pkg_database *, struct pkg *, u_int); - -/* Remove a package (by key) from a database. */ -int pkg_database_remove_pkg(struct pkg_database *, const char *); +/* Sync changes to a pkg_db to disk. */ +int pkg_db_sync(struct pkg_db *); #endif ==== //depot/projects/soc2010/dforsyth_libpkg/libpkg/database_internal.h#3 (text+ko) ==== @@ -8,29 +8,27 @@ #include "database.h" -struct pkg_database_vtable { - int (*add_pkg) (struct pkg_database *, struct pkg *, u_int); - int (*close) (struct pkg_database *); - int (*remove_pkg) (struct pkg_database *, const char *); - int (*get_next_pkg) (struct pkg_database *, struct pkg *, u_int); - int (*get_pkg) (struct pkg_database *, struct pkg *, u_int); - int (*rewind) (struct pkg_database *); - int (*open) (struct pkg_database *, const char *, u_int); - uid_t (*owner) (struct pkg_database *); -}; - /* Define the package database type. */ -struct pkg_database { +struct pkg_db { unsigned int magic; /* init */ + char path[PATH_MAX]; /* Internal db pointer for whatever backend is in use. */ void *internal; - status_t status; - struct pkg_database_vtable *vtable; + + int (*add) (struct pkg_db *, struct pkg *, const char *); + int (*close) (struct pkg_db *); + int (*contains) (struct pkg_db *, const char *); + int (*get) (struct pkg_db *, struct pkg *, + const char *); + struct pkg_list *(*all) (struct pkg_db *); + int (*open) (struct pkg_db *, const char *); + uid_t (*owner) (struct pkg_db *); + int (*delete) (struct pkg_db *, const char *); + int (*revert) (struct pkg_db *); + int (*sync) (struct pkg_db *); }; /* Check the magic value in a database. */ -void _pkg_database_check_magic(struct pkg_database *, const char *); +void _pkg_db_check_magic(struct pkg_db *, const char *); -void _pkg_database_set_vtable(struct pkg_database *, - struct pkg_database_vtable *); #endif ==== //depot/projects/soc2010/dforsyth_libpkg/libpkg/freebsd_database_directorydb.c#3 (text+ko) ==== @@ -6,333 +6,596 @@ #include #include #include - +#include +#include +#include +#include #include #include -#include #include /* Cool kids club. */ #include "internal.h" #include "freebsd_database_directorydb.h" +#include "freebsd_plist.h" + +#include "file.h" + +struct _read_plist { + struct pkg_property *plist; + char key[PATH_MAX]; + uint32_t parsed; + RB_ENTRY(_read_plist) entry; +}; + struct _directorydb { - char *location[2]; - FTS *ftsp; + /* Location of the database. */ + char path[PATH_MAX]; + + /* Journal handle. */ + int journal; + char journal_path[PATH_MAX]; + char journal_dir_path[PATH_MAX]; + + /* A NULL terminated list of keys the db currently has. */ + char **keylist; + + /* + * The time of our last access. If this has changed, another + * directorydb instance has changes something, so we need to refresh. + */ + time_t last; + + RB_HEAD(plist_head, _read_plist) plist_head; }; -static int _fts_entry_compare(const FTSENT * const *, const FTSENT * const *); -static int _read_pkg(struct pkg_database *, FTSENT *, struct pkg *, u_int); -static int _write_pkg(struct pkg_database *, struct pkg *, u_int); -static int _pkg_database_directorydb_open(struct pkg_database *, const char *, - u_int); -static uid_t _pkg_database_directorydb_owner(struct pkg_database *); -static int _pkg_database_directorydb_rewind(struct pkg_database *); -static int _pkg_database_directorydb_close(struct pkg_database *); -static int _pkg_database_directorydb_add_pkg(struct pkg_database *, - struct pkg *, u_int); -static int _pkg_database_directorydb_remove_pkg(struct pkg_database *, - const char *); -static int _pkg_database_directorydb_get_next_pkg(struct pkg_database *, - struct pkg *, u_int); +#define CONTENTS 0x00000001 +#define DESCRIPTION 0x00000002 +#define COMMENT 0x00000004 +#define DISPLAY 0x00000008 -static struct pkg_database_vtable _vt = { - .open = _pkg_database_directorydb_open, - .close = _pkg_database_directorydb_close, - .add_pkg = _pkg_database_directorydb_add_pkg, - .remove_pkg = _pkg_database_directorydb_remove_pkg, - .rewind = _pkg_database_directorydb_rewind, - .get_next_pkg = _pkg_database_directorydb_get_next_pkg, - .owner = _pkg_database_directorydb_owner +static struct pkg_info { + uint32_t info_mask; + const char *info_name; + const char *file_name; +} pkg_entries [] = { + { CONTENTS, FBSD_METANAME_CONTENTS, "+CONTENTS" }, + { DESCRIPTION, FBSD_METANAME_DESCRIPTION, "+DESC" }, + { COMMENT, FBSD_METANAME_COMMENT, "+COMMENT" }, + { DISPLAY, FBSD_METANAME_DISPLAY, "+DISPLAY" }, + { 0, NULL, NULL }, }; +static const char *fbsd_directorydb_pkg_origin(struct pkg *); +static const char *fbsd_directorydb_pkg_name(struct pkg *); +static const char *fbsd_directorydb_pkg_comment(struct pkg *); +static const char *fbsd_directorydb_pkg_description(struct pkg *); +static const char *fbsd_directorydb_get_string_property( + struct _directorydb *, const char *, + const char *, uint32_t); +static struct pkg_property *fbsd_directorydb_get_plist( + struct _directorydb *, const char *); +static int fbsd_directorydb_read_pkg( + struct _directorydb *, const char *, + struct pkg_property *, uint32_t); +static char *read_file(const char *); +static int _read_plist_cmp(struct _read_plist *, + struct _read_plist *); +static int dselect(const struct dirent *ent); +static void fbsd_pkg_setup(struct pkg_db *, + struct pkg *pkg, const char *key); +static int fbsd_directorydb_property_to_file( + struct pkg_property *, struct pkg_file *file); + +RB_GENERATE_STATIC(plist_head, _read_plist, entry, _read_plist_cmp); + +#define PKG_DIRDB_MAGIC 0x11111111 +#define DB_DIRDB_MAGIC 0x11111111 + +/* The journal file. */ +#define JOURNAL ".journal" +/* Where the journaler can store files for changes before a sync. */ +#define JOURNAL_DIR ".journal_sav" + +#define journal_open(path) open(path, O_CREAT | O_APPEND | O_EXLOCK) -/* Initialize and return a static vtable for directorydb ops. */ -struct pkg_database_vtable * -pkg_database_directorydb_vtable(void) +#define _pkg_check_magic(p) assert(p->magic == PKG_DIRDB_MAGIC) +#define _db_check_magic(db) assert(db->magic == DB_DIRDB_MAGIC) + +static int +_read_plist_cmp(struct _read_plist *a, struct _read_plist *b) { -#if 0 - static struct pkg_database_vtable vt; - - vt.open = _pkg_database_directorydb_open; - vt.close = _pkg_database_directorydb_close; - vt.add_pkg = _pkg_database_directorydb_add_pkg; - vt.remove_pkg = _pkg_database_directorydb_remove_pkg; - vt.rewind = _pkg_database_directorydb_rewind; - vt.get_next_pkg = _pkg_database_directorydb_get_next_pkg; -#endif - return (&_vt); + return (strcmp(a->key, b->key)); } -void -pkg_database_directorydb_init(struct pkg_database *db) +static int +dselect(const struct dirent *ent) { - _pkg_database_set_vtable(db, &_vt); + return (ent->d_name[0] != '.' && ent->d_type == DT_DIR); } -const char * -pkg_database_directorydb_type_name(void) +/* Close a "connection" to a directorydb. */ +int +fbsd_directorydb_close(struct pkg_db *db) { - return ("directorydb"); + struct _directorydb *d = db->internal; + close(d->journal); + return (0); } -static uid_t -_pkg_database_directorydb_owner(struct pkg_database *db) +/* Open a "connection" to a directorydb. */ +int +fbsd_directorydb_open(struct pkg_db *db, const char *path) { struct _directorydb *d; struct stat sb; - - d = db->internal; - if (d == NULL || lstat(d->location[0], &sb) < 0) { - return (-1); - } + int jfd; - return (sb.st_uid); -} + printf("ddb open\n"); -static int -_pkg_database_directorydb_open(struct pkg_database *db, const char *path, - u_int flags) -{ - struct _directorydb *d; - (void)flags; - d = calloc(1, sizeof(*d)); if (d == NULL) { return (PKG_NOT_OK); } - /* Initialize everything. */ - d->location[0] = strdup(path); - d->location[1] = NULL; + strcpy(d->path, path); + printf("path: %s\n", d->path); + + db->magic = DB_DIRDB_MAGIC; + RB_INIT(&d->plist_head); + + (void)jfd; + (void)sb; +#if 0 + + /* Open the journal. */ + + strcpy(d->journal_path, d->path); + strcat(d->journal_path, JOURNAL); + + /* Grab the lock on the journal file, creating it if it doesn't exist. + * */ + if ((jfd = journal_open(d->journal_path)) < 0) { + return (PKG_NOT_OK); + } + + /* Make sure that the journal dir exists (create it if it doesn't). */ + strcpy(d->journal_dir_path, d->path); + strcpy(d->journal_dir_path, "/"); + strcpy(d->journal_dir_path, JOURNAL_DIR); - /* Use fts here so we can get ordering and a quick refresh. */ - d->ftsp = fts_open(d->location, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, - _fts_entry_compare); + if (stat(d->journal_dir_path, &sb) < 0) { + /* not there. */ + mkdir(d->journal_dir_path, 0755); + } else if (!S_ISDIR(sb.st_mode)) { + close(jfd); + return (PKG_NOT_OK); /* This could probably be FATAL */ + } - if (d->ftsp == NULL) { - PKG_CLIENT_CRASH(__func__, "Failed to open database."); + /* Let the journal file go. */ + if (close(jfd) < 0) { + return (PKG_FATAL); } +#endif + /* Annnnd... go. */ db->internal = d; return (PKG_OK); } -static int -_pkg_database_directorydb_rewind(struct pkg_database *db) +static void +fbsd_pkg_setup(struct pkg_db *db, struct pkg *pkg, const char *key) +{ + if (pkg == NULL) { + return; + } + + pkg->magic = PKG_DIRDB_MAGIC; + pkg->source = db; + strcpy(pkg->key, key); + + pkg->name = fbsd_directorydb_pkg_name; + pkg->origin = fbsd_directorydb_pkg_origin; + pkg->comment = fbsd_directorydb_pkg_comment; + pkg->description = fbsd_directorydb_pkg_description; + + pkg->files = fbsd_directorydb_files; +} + +struct pkg_list * +fbsd_directorydb_all(struct pkg_db *db) +{ + int c; + struct _directorydb *d; + struct dirent **ents; + struct pkg *pkg; + struct pkg_list *list; + + d = db->internal; + + c = scandir(d->path, &ents, dselect, alphasort); + if (c < 0) { + return (NULL); + } + + list = malloc(sizeof(*list)); + TAILQ_INIT(list); + for (int i = 0; i < c; ++i) { + pkg = pkg_alloc(); + fbsd_pkg_setup(db, pkg, ents[i]->d_name); + TAILQ_INSERT_TAIL(list, pkg, next); + free(ents[i]); + } + free(ents); + + return (list); +} + +#define fbsd_directorydb_list(fn_name, list_type, type, list_name, data_loc, converter) \ +struct list_type * \ +fn_name(struct pkg *pkg) \ +{ \ + struct type *a; \ + struct pkg_property *plist; \ + struct pkg_property *property_list; \ + struct pkg_property *property_node; \ + struct list_type *list; \ + struct _directorydb *d; \ + struct pkg_db *db; \ + const char *key; \ + list = malloc(sizeof(*list)); \ + if (list == NULL) return (NULL); \ + TAILQ_INIT(list); \ + db = pkg->source; \ + d = db->internal; \ + key = pkg->key; \ + plist = fbsd_directorydb_get_plist(d, key); \ + if (plist == NULL) return (NULL); \ + property_list = pkg_property_dict_get_property(plist, list_name); \ + if (property_list == NULL) { \ + fbsd_directorydb_read_pkg(d, key, plist, data_loc); \ + property_list = pkg_property_dict_get_property(plist, \ + list_name); \ + } \ + if (property_list == NULL) return (NULL); \ + property_node = NULL; \ + while ((property_node = pkg_property_list_get_next_property( \ + property_list, property_node)) != NULL) { \ + a = malloc(sizeof(*a)); \ + converter(property_node, a); \ + TAILQ_INSERT_TAIL(list, a, next); \ + } \ + return (list); \ +} + +fbsd_directorydb_list(fbsd_directorydb_files, pkg_file_list, pkg_file, FBSD_FILES, + CONTENTS, fbsd_directorydb_property_to_file); + +#if 0 +struct pkg_file_list * +fbsd_directorydb_files(struct pkg *pkg) { + struct pkg_file *file; + struct pkg_property *plist; + struct pkg_property *file_list; + struct pkg_property *file_node; + struct pkg_file_list *list; struct _directorydb *d; + struct pkg_db *db; + const char *key; + list = malloc(sizeof(*list)); + if (list == NULL) return (NULL); + TAILQ_INIT(list); + + db = pkg->source; d = db->internal; + key = pkg->key; + + plist = fbsd_directorydb_get_plist(d, key); + if (plist == NULL) { + return (NULL); + } + + + file_list = pkg_property_dict_get_property(plist, FBSD_FILES); + if (file_list == NULL) { + fbsd_directorydb_read_pkg(d, key, plist, CONTENTS); + file_list = pkg_property_dict_get_property(plist, FBSD_FILES); + } + if (file_list == NULL) { + return (NULL); + } - fts_close(d->ftsp); - d->ftsp = fts_open(d->location, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, - _fts_entry_compare); - if (d->ftsp == NULL) { - PKG_CLIENT_CRASH(__func__, "Failed ot open database"); + file_node = NULL; + while ((file_node = pkg_property_list_get_next_property(file_list, + file_node)) != NULL) { + file = pkg_file_alloc(); + fbsd_directorydb_property_to_file(file_node, file); + TAILQ_INSERT_TAIL(list, file, next); } + return (list); +} +#endif + +static int +fbsd_directorydb_property_to_file(struct pkg_property *node, + struct pkg_file *file) +{ + struct pkg_property *string; + + /* Should probably assert that node is a dict... */ + + string = pkg_property_dict_get_property(node, FBSD_PATHNAME); + strcpy(file->pathname, pkg_property_string_get_string(string)); + string = pkg_property_dict_get_property(node, FBSD_PREFIX); + strcpy(file->prefix, pkg_property_string_get_string(string)); + return (PKG_OK); } -static int -_pkg_database_directorydb_close(struct pkg_database *db) +int +fbsd_directorydb_contains(struct pkg_db *db, const char *key) { struct _directorydb *d; + struct stat sb; + char path[PATH_MAX]; d = db->internal; - fts_close(d->ftsp); - free(d->location[0]); - free(d); - return (PKG_OK); + + strcpy(path, d->path); + strcat(path, "/"); + strcat(path, key); + + if (stat(path, &sb) < 0) { + return (0); + } + + return (S_ISDIR(sb.st_mode)); } -static int -_pkg_database_directorydb_get_next_pkg(struct pkg_database *db, struct pkg *p, - u_int flags) +int +fbsd_directorydb_add(struct pkg_db *db, struct pkg *pkg, const char *name) { struct _directorydb *d; - FTSENT *f; + char path[PATH_MAX]; + int r; d = db->internal; - while ((f = fts_read(d->ftsp)) != NULL) { - /* make sure this is a directory. And that we're at the right - * level. This is basically just skipping the database basedir. - */ - if (f->fts_info != FTS_D || f->fts_level != 1) { - continue; - } + strcpy(path, d->path); + strcat(path, "/"); + strcat(path, name); + + r = mkdir(path, 0700); + + pkg->magic = PKG_DIRDB_MAGIC; + pkg->source = db; + pkg->plist = NULL; + + pkg->origin = fbsd_directorydb_pkg_origin; + pkg->name = fbsd_directorydb_pkg_name; + + return (r == 0 ? PKG_OK : PKG_NOT_OK); +} + +int +fbsd_directorydb_get(struct pkg_db *db, struct pkg *pkg, const char *name) +{ + struct _directorydb *d; + char path[PATH_MAX]; + struct stat sb; + + d = db->internal; - fts_set(d->ftsp, f, FTS_SKIP); /* We don't want the children. */ - /* Jump into _read_pkg and hope for the best. */ - return (_read_pkg(db, f, p, flags)); + strcpy(path, d->path); + strcat(path, "/"); + strcat(path, name); + + if (stat(path, &sb) < 0) { + printf("no stat %s\n", name); + return (PKG_NOT_OK); } + + pkg->magic = PKG_DIRDB_MAGIC; + pkg->source = db; + pkg->plist = NULL; - /* 'Cursor' is at the end. */ - return (PKG_NOT_OK); + pkg->origin = fbsd_directorydb_pkg_origin; + pkg->name = fbsd_directorydb_pkg_name; + + return (PKG_OK); } -static int -_pkg_database_directorydb_add_pkg(struct pkg_database *db, struct pkg *p, - u_int flags) +static const char * +fbsd_directorydb_pkg_origin(struct pkg *pkg) { - _write_pkg(db, p, flags); - _pkg_database_directorydb_rewind(db); + struct pkg_db *db; + struct _directorydb *d; + + _pkg_check_magic(pkg); + + db = pkg->source; + _db_check_magic(db); + d = db->internal; >>> TRUNCATED FOR MAIL (1000 lines) <<<