Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Oct 2010 06:49:44 GMT
From:      David Forsythe <dforsyth@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 184654 for review
Message-ID:  <201010130649.o9D6niT5012745@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-
+#include <assert.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/tree.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fts.h>
 #include <limits.h>
 
 /* 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) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010130649.o9D6niT5012745>