PERFORCE change 184654 for review
David Forsythe
dforsyth at FreeBSD.org
Wed Oct 13 06:49:45 UTC 2010
http://p4web.freebsd.org/@@184654?ac=10
Change 184654 by dforsyth at 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) <<<
More information about the p4-projects
mailing list