[Midnightbsd-cvs] src: lib/libmport: Latest developement version.

ctriv at midnightbsd.org ctriv at midnightbsd.org
Thu Nov 22 03:00:32 EST 2007


Log Message:
-----------
Latest developement version.  Nearing completion of package installation.

Modified Files:
--------------
    src/lib/libmport:
        Makefile (r1.2 -> r1.3)
        create_pkg.c (r1.6 -> r1.7)
        db_schema.c (r1.3 -> r1.4)
        error.c (r1.4 -> r1.5)
        mport.h (r1.4 -> r1.5)
        util.c (r1.6 -> r1.7)

Added Files:
-----------
    src/lib/libmport:
        db_stub.c (r1.1)
        db_util.c (r1.1)
        inst_init.c (r1.1)
        install_pkg.c (r1.1)

-------------- next part --------------
--- /dev/null
+++ lib/libmport/db_stub.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 2007 Chris Reinhardt
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $MidnightBSD: src/lib/libmport/db_stub.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $
+ */
+
+
+
+#include <sqlite3.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mport.h"
+
+__MBSDID("$MidnightBSD: src/lib/libmport/db_stub.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $");
+
+int mport_attach_stub_db(sqlite3 *db, const char *dir)
+{
+  char *file;
+  asprintf(&file, "%s/%s", dir, MPORT_STUB_DB_FILE);
+  
+  if (mport_db_do(db, "ATTACH %s AS stub", file) != MPORT_OK) { 
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  }
+  
+  free(file);
+  
+  return MPORT_OK;
+}
+
+int mport_get_meta_from_db(sqlite3 *db, mportPackageMeta **ref)
+{
+  mportPackageMeta *pack = *ref;
+  sqlite3_stmt *stmt;
+  const char *tmp = 0;
+  
+  pack = mport_new_packagemeta();
+  
+  if (pack == NULL) 
+    return MPORT_ERR_NO_MEM;
+    
+  if (sqlite3_prepare_v2(db, "SELECT (pkg, version, origin, lang, prefix) FROM stub.package", -1, &stmt, &tmp) != SQLITE_OK)
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+    
+  if (sqlite3_step(stmt) != SQLITE_DONE) 
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  
+  /* Copy pkg to pack->name */
+  if ((tmp = sqlite3_column_text(stmt, 0)) == NULL) 
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  
+  if ((pack->name = strdup(tmp)) == NULL)
+    return MPORT_ERR_NO_MEM;
+  
+  /* Copy version to pack->version */
+  if ((tmp = sqlite3_column_text(stmt, 1)) == NULL) 
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  
+  if ((pack->version = strdup(tmp)) == NULL)
+    return MPORT_ERR_NO_MEM;
+  
+  /* Copy origin to pack->origin */
+  if ((tmp = sqlite3_column_text(stmt, 2)) == NULL) 
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  
+  if ((pack->origin = strdup(tmp)) == NULL)
+    return MPORT_ERR_NO_MEM;
+
+  /* Copy lang to pack->lang */
+  if ((tmp = sqlite3_column_text(stmt, 4)) == NULL) 
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  
+  if ((pack->lang = strdup(tmp)) == NULL)
+    return MPORT_ERR_NO_MEM;
+
+  /* Copy prefix to pack->prefix */
+  if ((tmp = sqlite3_column_text(stmt, 5)) == NULL) 
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  
+  if ((pack->prefix = strdup(tmp)) == NULL)
+    return MPORT_ERR_NO_MEM;
+
+  sqlite3_finalize(stmt);
+  
+  return MPORT_OK;
+}
+
--- /dev/null
+++ lib/libmport/inst_init.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2007 Chris Reinhardt
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $MidnightBSD: src/lib/libmport/inst_init.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <sqlite3.h>
+#include "mport.h"
+
+__MBSDID("$MidnightBSD: src/lib/libmport/inst_init.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $");
+
+
+static int create_master_db(sqlite3 **);
+
+/* set up the master database, and related instance infrastructure. */
+int mport_inst_init(sqlite3 **db)
+{
+  if (mkdir(MPORT_INST_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) {
+    if (errno != EEXIST) 
+      RETURN_ERROR(MPORT_ERR_SYSCALL_FAILED, strerror(errno));
+  }
+  
+  return create_master_db(db);
+}
+  
+  
+static int create_master_db(sqlite3 **db) 
+{
+  if (sqlite3_open(MPORT_MASTER_DB_FILE, db) != 0) {
+    sqlite3_close(*db);
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(*db));
+  }
+  
+  /* create tables */
+  return mport_generate_master_schema(*db);
+}
Index: util.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/util.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -L lib/libmport/util.c -L lib/libmport/util.c -u -r1.6 -r1.7
--- lib/libmport/util.c
+++ lib/libmport/util.c
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <libgen.h>
 #include "mport.h"
 
 __MBSDID("$MidnightBSD$");
@@ -96,7 +97,7 @@
   
   return (lstat(file, &st) == 0);
 }
-  
+
 
 /* mport_xsystem(char *fmt, ...)
  * 
@@ -175,4 +176,73 @@
   *vec = NULL;
 }
 
+/*
+ * mport_run_plist_exec(fmt, cwd, last_file)
+ * 
+ * handles a @exec or a @unexec directive in a plist.  This function
+ * does the substitions and then runs the command.
+ *
+ * Substitutions:
+ * %F	The last filename extracted (last_file argument)
+ * %D	The current working directory (cwd)
+ * %B	Return the directory part ("dirname") of %D/%F
+ * %f	Return the filename part of ("basename") %D/%F
+ */
+int mport_run_plist_exec(const char *fmt, const char *cwd, const char *last_file) 
+{
+  size_t l;
+  size_t max = FILENAME_MAX * 2;
+  char cmnd[max];
+  char *pos = cmnd;
+  char *name;
+  
+  while (*fmt && max > 0) {
+    if (*fmt == '%') {
+      fmt++;
+      switch (*fmt) {
+        case 'F':
+          strlcpy(pos, last_file, max);
+          l = strlen(last_file);
+          pos += l;
+          max -= l;
+          break;
+        case 'D':
+          strlcpy(pos, cwd, max);
+          l = strlen(cwd);
+          pos += l;
+          max -= l;
+          break;
+        case 'B':
+          name = dirname(last_file);
+          strlcpy(pos, name, max);
+          l = strlen(name);
+          pos += l;
+          max -= l;
+          break;
+        case 'f':
+          name = basename(last_file);
+          strlcpy(pos, name, max);
+          l = strlen(name);
+          pos += l;
+          pos -= l;
+          break;
+        default:
+          *pos = *fmt;
+          max--;
+          pos++;
+      }
+      fmt++;
+    } else {
+      *pos = *fmt;
+      pos++;
+      fmt++;
+      max--;
+    }
+  }
+  
+  *pos = '\0';
+  
+  /* cmnd now hold the expaded command, now execute it*/
+  return mport_xsystem(cmnd);
+}          
 
Index: error.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/error.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L lib/libmport/error.c -L lib/libmport/error.c -u -r1.4 -r1.5
--- lib/libmport/error.c
+++ lib/libmport/error.c
@@ -45,6 +45,8 @@
   "Malformed packing list.",
   "SQLite error.",
   "File not found."
+  "System call failed.",
+  "libarchive error."
 };
   
 
Index: create_pkg.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/create_pkg.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -L lib/libmport/create_pkg.c -L lib/libmport/create_pkg.c -u -r1.6 -r1.7
--- lib/libmport/create_pkg.c
+++ lib/libmport/create_pkg.c
@@ -43,11 +43,10 @@
 #include <md5.h>
 #include <archive.h>
 #include <archive_entry.h>
-#include <mport.h>
+#include "mport.h"
 
 __MBSDID("$MidnightBSD$");
 
-#define PACKAGE_DB_FILENAME "+CONTENTS.db"
 
 static int create_package_db(sqlite3 **);
 static int create_plist(sqlite3 *, mportPlist *, mportPackageMeta *);
@@ -58,15 +57,16 @@
 static int archive_files(mportPlist *, mportPackageMeta *);
 static int clean_up(const char *);
 
+
 int mport_create_pkg(mportPlist *plist, mportPackageMeta *pack)
 {
-  /* create a temp dir to hold our meta files. */
-  char dirtmpl[] = "/tmp/mport.XXXXXXXX"; 
-  char *tmpdir   = mkdtemp(dirtmpl);
   
   int ret;
   sqlite3 *db;
-  
+
+  char dirtmpl[] = "/tmp/mport.XXXXXXXX"; 
+  char *tmpdir = mkdtemp(dirtmpl);
+
   if (tmpdir == NULL) {
     SET_ERROR(MPORT_ERR_FILEIO, strerror(errno));
     goto CLEANUP;
@@ -104,7 +104,7 @@
 
 static int create_package_db(sqlite3 **db) 
 {
-  if (sqlite3_open(PACKAGE_DB_FILENAME, db) != 0) {
+  if (sqlite3_open(MPORT_STUB_DB_FILE, db) != SQLITE_OK) {
     sqlite3_close(*db);
     RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(*db));
   }
@@ -337,7 +337,7 @@
  */ 
 #define COPY_PKG_METAFILE(field, tofile) \
   if (pack->field != NULL && mport_file_exists(pack->field)) { \
-    if ((ret = mport_copy_file(pack->field, #tofile)) != MPORT_OK) { \
+    if ((ret = mport_copy_file(pack->field, tofile)) != MPORT_OK) { \
       return ret; \
     } \
   } \
@@ -346,11 +346,11 @@
 static int copy_metafiles(mportPackageMeta *pack) 
 {
   int ret;
-  
-  COPY_PKG_METAFILE(mtree, +MTREE);
-  COPY_PKG_METAFILE(pkginstall, +INSTALL);
-  COPY_PKG_METAFILE(pkgdeinstall, +DEINSTALL);
-  COPY_PKG_METAFILE(pkgmessage, +MESSAGE);
+
+  COPY_PKG_METAFILE(mtree, MPORT_MTREE_FILE);
+  COPY_PKG_METAFILE(pkginstall, MPORT_INSTALL_FILE);
+  COPY_PKG_METAFILE(pkgdeinstall, MPORT_DEINSTALL_FILE);
+  COPY_PKG_METAFILE(pkgmessage, MPORT_MESSAGE_FILE);
   
   return ret;
 }
--- /dev/null
+++ lib/libmport/db_util.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2007 Chris Reinhardt
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $MidnightBSD: src/lib/libmport/db_util.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "mport.h"
+
+__MBSDID("$MidnightBSD: src/lib/libmport/db_util.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $");
+
+/* mport_db_do(sqlite3 *db, const char *sql, ...)
+ * 
+ * A wrapper for doing executing a single sql query.  Takes a sqlite3 struct
+ * pointer, a format string and a list of args.  See the documentation for 
+ * sqlite3_vmprintf() for format information.
+ */
+int mport_db_do(sqlite3 *db, const char *fmt, ...) 
+{
+  va_list args;
+  char *sql;
+  
+  va_start(args, fmt);
+  
+  if ((sql = sqlite3_vmprintf(fmt, args)) == NULL) {
+    return MPORT_ERR_NO_MEM;
+  }
+  
+  if (sqlite3_exec(db, sql, 0, 0, 0) != SQLITE_OK) {
+    sqlite3_free(sql);
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+  }
+  
+  sqlite3_free(sql);
+  
+  return MPORT_OK;
+}
+  
+
+
+
Index: db_schema.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/db_schema.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L lib/libmport/db_schema.c -L lib/libmport/db_schema.c -u -r1.3 -r1.4
--- lib/libmport/db_schema.c
+++ lib/libmport/db_schema.c
@@ -36,20 +36,36 @@
 
 static int run_sql(sqlite3 *db, const char *sql);
 
+#define RUN_SQL(db, sql) \
+  if (run_sql(db, sql) != SQLITE_OK) \
+    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db))
+
+
 int mport_generate_stub_schema(sqlite3 *db) 
 {
-  if (run_sql(db, "CREATE TABLE assets (pkg text not NULL, type int NOT NULL, data text, checksum text)") != SQLITE_OK)
-    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
-  if (run_sql(db, "CREATE TABLE package  (pkg text NOT NULL, version text NOT NULL, origin text NOT NULL, lang text, options text, date int NOT NULL, prefix text NOT NULL)") != SQLITE_OK)
-    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
-  if (run_sql(db, "CREATE TABLE conflicts (pkg text NOT NULL, conflict_pkg text NOT NULL, conflict_version text NOT NULL)") != SQLITE_OK)
-    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
-  if (run_sql(db, "CREATE TABLE depends   (pkg text NOT NULL, depend_pkgname text NOT NULL, depend_pkgversion text NOT NULL, depend_port text NOT NULL)") != SQLITE_OK)
-    RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));    
+  RUN_SQL(db, "CREATE TABLE assets    (pkg text not NULL, type int NOT NULL, data text, checksum text)");
+  RUN_SQL(db, "CREATE TABLE package   (pkg text NOT NULL, version text NOT NULL, origin text NOT NULL, lang text, options text, date int NOT NULL, prefix text NOT NULL)");
+  RUN_SQL(db, "CREATE TABLE conflicts (pkg text NOT NULL, conflict_pkg text NOT NULL, conflict_version text NOT NULL)");
+  RUN_SQL(db, "CREATE TABLE depends   (pkg text NOT NULL, depend_pkgname text NOT NULL, depend_pkgversion text NOT NULL, depend_port text NOT NULL)");
     
   return MPORT_OK;  
 }
 
+int mport_generate_master_schema(sqlite3 *db) 
+{
+  RUN_SQL(db, "CREATE TABLE IF NOT EXISTS packages (pkg text NOT NULL, version text NOT NULL, origin text NOT NULL, prefix text NOT NULL, lang text, options text, date int)");
+  RUN_SQL(db, "CREATE UNIQUE INDEX IF NOT EXISTS packages_pkg ON packages (pkg)");
+  RUN_SQL(db, "CREATE INDEX IF NOT EXISTS packages_origin ON packages (origin)");
+  RUN_SQL(db, "CREATE TABLE IF NOT EXISTS depends (pkg text NOT NULL, depend_pkgname text NOT NULL, depend_pkgversion text NOT NULL, depend_port text NOT NULL)");
+  RUN_SQL(db, "CREATE INDEX IF NOT EXISTS depends_pkg ON depends (pkg)");
+  RUN_SQL(db, "CREATE INDEX IF NOT EXISTS depends_dependpkgname ON depends (depend_pkgname)");
+  RUN_SQL(db, "CREATE TABLE IF NOT EXISTS assets (pkg text NOT NULL, type int NOT NULL, data text, checksum text)");
+  RUN_SQL(db, "CREATE INDEX IF NOT EXISTS assets_pkg ON assets (pkg)");
+  RUN_SQL(db, "CREATE INDEX IF NOT EXISTS assets_data ON assets (data)");
+  
+  return MPORT_OK;
+}
+
 static int run_sql(sqlite3 *db, const char *sql)
 {
   char *error = 0;
--- /dev/null
+++ lib/libmport/install_pkg.c
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2007 Chris Reinhardt
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $MidnightBSD: src/lib/libmport/install_pkg.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $
+ */
+
+
+
+#include "mport.h"
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <archive.h>
+#include <archive_entry.h>
+
+__MBSDID("$MidnightBSD: src/lib/libmport/install_pkg.c,v 1.1 2007/11/22 08:00:32 ctriv Exp $");
+
+static int do_pre_install(sqlite3 *, mportPackageMeta *, const char *);
+static int do_actual_install(struct archive *, struct archive_entry *, sqlite3 *, mportPackageMeta *, const char *);
+static int do_post_install(sqlite3 *, mportPackageMeta *, const char *);
+static int run_pkg_install(const char *, mportPackageMeta *, const char *);
+static int run_mtree(const char *, mportPackageMeta *);
+static int clean_up(const char *);
+static int rollback(void);
+
+int mport_install_pkg(const char *filename, const char *prefix) 
+{
+  /* 
+   * The general strategy here is to extract the meta-files into a tempdir, but
+   * extract the real files inplace.  There's huge IO overhead with having a stagging
+   * area. 
+   */
+  struct archive *a = archive_read_new();
+  struct archive_entry *entry;
+  char filepath[FILENAME_MAX];
+  const char *file;
+  sqlite3 *db;
+  mportPackageMeta *pack;
+  int ret = MPORT_OK;
+  
+  /* initialize our local mport instance */
+  if ((ret = mport_inst_init(&db)) != MPORT_OK) 
+    return ret;
+
+  /* extract the meta-files into the a temp dir */  
+  char dirtmpl[] = "/tmp/mport.XXXXXXXX"; 
+  char *tmpdir = mkdtemp(dirtmpl);
+
+  if (tmpdir == NULL)
+    RETURN_ERROR(MPORT_ERR_FILEIO, strerror(errno));
+    
+  archive_read_support_compression_bzip2(a);
+  archive_read_support_format_tar(a);
+
+  if (archive_read_open_filename(a, filename, 10240) != ARCHIVE_OK)
+    RETURN_ERROR(MPORT_ERR_ARCHIVE, archive_error_string(a));
+    
+  while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
+    file = archive_entry_pathname(entry);
+    
+    if (*file == '+') {
+      snprintf(filepath, FILENAME_MAX, "%s/%s", tmpdir, file);
+      archive_entry_set_pathname(entry, filepath);
+      archive_read_extract(a, entry, ARCHIVE_EXTRACT_OWNER|ARCHIVE_EXTRACT_PERM);
+    } else {
+      break;
+    }
+  }
+  
+  /* Attach the stub db */
+  if ((ret = mport_attach_stub_db(db, tmpdir)) != MPORT_OK) 
+    return ret;
+
+  /* get the meta object from the stub database */  
+  if ((ret = mport_get_meta_from_db(db, &pack)) != MPORT_OK)
+    return ret;
+  
+  if (prefix != NULL)
+    pack->prefix = (char *)prefix;
+    
+  /* check if this is installed already, depends, and conflicts */
+//  if ((ret = mport_check_preconditions(db, pack)) != MPORT_OK)
+//    return ret;
+ 
+  /* Run mtree.  Run pkg-install. Etc... */
+  if ((ret = do_pre_install(db, pack, tmpdir)) != MPORT_OK)
+    return ret;
+
+  if ((ret = do_actual_install(a, entry, db, pack, tmpdir)) != MPORT_OK)
+    return ret;
+  
+  archive_read_finish(a);
+  
+  if ((ret = do_post_install(db, pack, tmpdir)) != MPORT_OK)
+    return ret;
+ 
+  if ((ret = clean_up(tmpdir)) != MPORT_OK)
+    return ret;
+  
+  return ret;
+}
+
+/* This does everything that has to happen before we start installing files.
+ * We run mtree, pkg-install PRE-INSTALL, etc... 
+ */
+static int do_pre_install(sqlite3 *db, mportPackageMeta *pack, const char *tmpdir)
+{
+  int ret = MPORT_OK;
+  
+  /* run mtree */
+  if ((ret = run_mtree(tmpdir, pack)) != MPORT_OK)
+    return ret;
+  
+  /* run pkg-install PRE-INSTALL */
+  if ((ret = run_pkg_install(tmpdir, pack, "PRE-INSTALL")) != MPORT_OK)
+    return ret;
+
+  return ret;    
+}
+
+
+static int do_actual_install(
+      struct archive *a, 
+      struct archive_entry *entry,
+      sqlite3 *db, 
+      mportPackageMeta *pack, 
+      const char *tmpdir
+    )
+{
+  const char *err;
+  int ret;
+  mportPlistEntryType type;
+  char *data, *cwd;
+  char file[FILENAME_MAX];
+  sqlite3_stmt *assets;
+  
+  if (mport_db_do(db, "START TRANSACTION") != MPORT_OK) 
+    goto ERROR;
+
+  /* Insert the package meta row into the packages table  - XXX Does not honor pack->prefix! */  
+  if (mport_db_do(db, "INSERT INTO packages (pkg, version, origin, prefix, lang, options) SELECT (pkg, version, origin, prefix, lang, options) FROM stub.package") != MPORT_OK)
+    goto ERROR;
+  /* Insert the assets into the master table */
+  if (mport_db_do(db, "INSERT INTO assets (pkg, type, data, checksum) SELECT (pkg,type,data,checksum) FROM stub.assets") != MPORT_OK)
+    goto ERROR;  
+  /* Insert the depends into the master table */
+  if (mport_db_do(db, "INSERT INTO depends (pkg, depend_pkgname, depend_pkgversion, depend_port) SELECT (pkg, depend_pkgname, depend_pkgversion, depend_port) FROM stub.depends") != MPORT_OK) 
+    goto ERROR;
+  
+  if ((ret = sqlite3_prepare_v2(db, "SELECT type,data FROM stub.assets", -1, &assets, &err)) != SQLITE_OK) {
+    mport_set_err(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+    goto ERROR;
+  }
+
+  cwd = pack->prefix;
+
+  while ((ret = sqlite3_step(assets)) == SQLITE_ROW) {
+    type = (mportPlistEntryType)sqlite3_column_int(assets, 0);
+    data = (char *)sqlite3_column_text(assets, 1);
+      
+    switch (type) {
+      case PLIST_CWD:      
+        if (data == NULL) {
+          cwd = pack->prefix;
+        } else {
+          cwd = data;
+        }
+        break;
+      case PLIST_EXEC:
+        if ((ret = mport_run_plist_exec(data, cwd, file)) != MPORT_OK)
+          goto ERROR;
+        break;
+      case PLIST_FILE:
+        /* Our logic here is a bit backwards, because the first real file
+         * in the archive was read in the loop in mport_install_pkg.  we
+         * use the current entry and then update it. */
+        if (entry == NULL) {
+          mport_set_err(MPORT_ERR_INTERNAL, "Plist to arhive mismatch!");
+          goto ERROR; 
+        } 
+        snprintf(file, FILENAME_MAX, "%s/%s", cwd, data);
+        archive_entry_set_pathname(entry, file);
+        if ((ret = archive_read_extract(a, entry, ARCHIVE_EXTRACT_OWNER|ARCHIVE_EXTRACT_PERM)) != ARCHIVE_OK) {
+          mport_set_err(MPORT_ERR_ARCHIVE, archive_error_string(a));
+          goto ERROR;
+        }
+        /* we only look for fatal, because EOF is only an error if we come
+        back around. */
+        if (archive_read_next_header(a, &entry) == ARCHIVE_FATAL) {
+          mport_set_err(MPORT_ERR_ARCHIVE, archive_error_string(a));
+          goto ERROR;
+        }
+        break;
+      default:
+        /* do nothing */
+        break;
+    }
+  }
+  
+  sqlite3_finalize(assets);
+  
+  if (mport_db_do(db, "COMMIT TRANSACTION") != MPORT_OK) 
+    goto ERROR;
+  
+  return MPORT_OK;
+  
+  ERROR:
+    rollback();
+    return ret;
+}           
+
+static int do_post_install(sqlite3 *db, mportPackageMeta *pack, const char *tmpdir)
+{
+  return run_pkg_install(tmpdir, pack, "POST-INSTALL");
+}
+
+      
+static int run_mtree(const char *tmpdir, mportPackageMeta *pack)
+{
+  char file[FILENAME_MAX];
+  int ret;
+  
+  snprintf(file, FILENAME_MAX, "%s/%s", tmpdir, MPORT_MTREE_FILE);
+  
+  if (mport_file_exists(file)) {
+    if ((ret = mport_xsystem("%s -U -f %s -d -e -p %s >/dev/null", MPORT_MTREE_BIN, file, pack->prefix)) != 0) 
+      return mport_set_errx(MPORT_ERR_SYSCALL_FAILED, "%s returned non-zero: %i", MPORT_MTREE_BIN, ret);
+  }
+  
+  return MPORT_OK;
+}
+
+static int run_pkg_install(const char *tmpdir, mportPackageMeta *pack, const char *mode)
+{
+  char file[FILENAME_MAX];
+  int ret;
+  
+  snprintf(file, FILENAME_MAX, "%s/%s", tmpdir, MPORT_INSTALL_FILE);    
+  if (mport_file_exists(file)) {
+    if ((ret = mport_xsystem("PKG_PREFIX=%s %s %s %s", pack->prefix, MPORT_SH_BIN, file, mode)) != 0)
+      return mport_set_errx(MPORT_ERR_SYSCALL_FAILED, "%s %s returned non-zero: %i" MPORT_INSTALL_FILE, mode, ret);
+  }
+  
+  return MPORT_OK;
+}
+
+
+static int clean_up(const char *tmpdir) 
+{
+  // return mport_rmtree(tmpdir);
+  return MPORT_OK;
+}
+
+
+static int rollback()
+{
+  fprintf(stderr, "Rollback called!\n");
+  return 0;
+}
+
Index: mport.h
===================================================================
RCS file: /home/cvs/src/lib/libmport/mport.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -L lib/libmport/mport.h -L lib/libmport/mport.h -u -r1.4 -r1.5
--- lib/libmport/mport.h
+++ lib/libmport/mport.h
@@ -91,17 +91,32 @@
 mportPackageMeta * mport_new_packagemeta(void);
 void mport_free_packagemeta(mportPackageMeta *);
 
+
 /* Package creation */
 int mport_create_pkg(mportPlist *, mportPackageMeta *);
 
+
+/* Package installation */
+int mport_install_pkg(const char *, const char *);
+
+
 #include <sqlite3.h>
 
 /* schema */
-int mport_generate_plist_schema(sqlite3 *);
+int mport_generate_master_schema(sqlite3 *);
 int mport_generate_stub_schema(sqlite3 *);
 
-/* Errors */
+/* Various database convience functions */
+int mport_attach_stub_db(sqlite3 *, const char *);
+int mport_get_meta_from_db(sqlite3 *, mportPackageMeta **);
+int mport_db_do(sqlite3 *, const char *, ...);
+
+
+/* instance init */
+int mport_inst_init(sqlite3 **);
+
 
+/* Errors */
 int mport_err_code(void);
 char * mport_err_string(void);
 
@@ -116,16 +131,34 @@
 #define MPORT_ERR_FILE_NOT_FOUND	5
 #define MPORT_ERR_SYSCALL_FAILED	6
 #define MPORT_ERR_ARCHIVE		7
+#define MPORT_ERR_INTERNAL		8
 
 #define RETURN_ERROR(code, msg) return mport_set_errx((code), "Error at %s:(%d): %s", __FILE__, __LINE__, (msg))
 #define SET_ERROR(code,msg) mport_set_errx((code), "Error at %s:(%d): %s", __FILE__, __LINE__, (msg))
 
-/* Utils */
 
+/* Utils */
 int mport_copy_file(const char *, const char *);
 int mport_rmtree(const char *);
 int mport_file_exists(const char *);
 int mport_xsystem(const char *, ...);
 void mport_parselist(char *, char ***);
+int mport_run_plist_exec(const char *, const char *, const char *);
+
+/* Meta files */
+#define MPORT_STUB_DB_FILE 	"+CONTENTS.db"
+#define MPORT_MTREE_FILE   	"+MTREE"
+#define MPORT_INSTALL_FILE 	"+INSTALL"
+#define MPORT_DEINSTALL_FILE	"+DEINSTALL"
+#define MPORT_MESSAGE_FILE	"+MESSAGE"
+
+
+/* Instance files */
+#define MPORT_INST_DIR 		"/var/db/mport"
+#define MPORT_MASTER_DB_FILE	"/var/db/mport/master.db"
+
+/* Binaries we use */
+#define MPORT_MTREE_BIN		"/usr/sbin/mtree"
+#define MPORT_SH_BIN		"/bin/sh"
 
-#endif
+#endif /* ! defined _MPORT_H */
Index: Makefile
===================================================================
RCS file: /home/cvs/src/lib/libmport/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -L lib/libmport/Makefile -L lib/libmport/Makefile -u -r1.2 -r1.3
--- lib/libmport/Makefile
+++ lib/libmport/Makefile
@@ -1,7 +1,7 @@
-# $FreeBSD: src/usr.sbin/pkg_install/lib/Makefile,v 1.18 2004/10/24 15:33:07 ru Exp $
+# $MidnightBSD$
 
 LIB=		mport
-SRCS=		plist.c	create_pkg.c db_schema.c util.c error.c
+SRCS=		plist.c	create_pkg.c db_schema.c db_stub.c db_util.c util.c error.c install_pkg.c inst_init.c
 
 INCS=		mport.h
 


More information about the Midnightbsd-cvs mailing list