[Midnightbsd-cvs] src: lib/libmport: Next developement snapshot.
ctriv at midnightbsd.org
ctriv at midnightbsd.org
Sat Apr 26 13:59:26 EDT 2008
Log Message:
-----------
Next developement snapshot.
Many bug fixes: hardlinks work correctly, exec/unxec parsing, etc...
Packages now have a status, on install it starts as 'dirty', and is set to
'clean' if the install succeeds. Similar logic is used in package deletion,
which now tries harder to keep going after errors.
Modified Files:
--------------
src/lib/libmport:
bundle.c (r1.1 -> r1.2)
check_preconditions.c (r1.1 -> r1.2)
create_primative.c (r1.1 -> r1.2)
db.c (r1.3 -> r1.4)
default_cbs.c (r1.1 -> r1.2)
delete_primative.c (r1.1 -> r1.2)
error.c (r1.6 -> r1.7)
install_primative.c (r1.1 -> r1.2)
instance.c (r1.1 -> r1.2)
mport.h (r1.9 -> r1.10)
util.c (r1.9 -> r1.10)
version_cmp.c (r1.2 -> r1.3)
-------------- next part --------------
Index: instance.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/instance.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L lib/libmport/instance.c -L lib/libmport/instance.c -u -r1.1 -r1.2
--- lib/libmport/instance.c
+++ lib/libmport/instance.c
@@ -33,10 +33,9 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
+#include <stdarg.h>
#include "mport.h"
-__MBSDID("$MidnightBSD$");
-
/* allocate mem for a mportInstance */
mportInstance * mport_instance_new()
@@ -74,6 +73,11 @@
}
+ if (sqlite3_create_function(mport->db, "mport_version_cmp", 2, SQLITE_ANY, NULL, &mport_version_cmp_sqlite, NULL, NULL) != SQLITE_OK) {
+ sqlite3_close(mport->db);
+ RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(mport->db));
+ }
+
/* set the default UI callbacks */
mport->msg_cb = &mport_default_msg_cb;
mport->progress_init_cb = &mport_default_progress_init_cb;
@@ -81,6 +85,7 @@
mport->progress_free_cb = &mport_default_progress_free_cb;
mport->confirm_cb = &mport_default_confirm_cb;
+
/* create tables */
return mport_generate_master_schema(mport->db);
@@ -115,6 +120,25 @@
}
+/* callers for the callbacks (only for msg at the moment) */
+void mport_call_msg_cb(mportInstance *mport, const char *fmt, ...)
+{
+ va_list args;
+ char *msg;
+
+ va_start(args, fmt);
+ (void)vasprintf(&msg, fmt, args);
+ va_end(args);
+
+ if (msg == NULL)
+ return; /* No message for you! */
+
+ (mport->msg_cb)(msg);
+
+ free(msg);
+}
+
+
int mport_instance_free(mportInstance *mport)
{
if (sqlite3_close(mport->db) != SQLITE_OK) {
Index: version_cmp.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/version_cmp.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L lib/libmport/version_cmp.c -L lib/libmport/version_cmp.c -u -r1.2 -r1.3
--- lib/libmport/version_cmp.c
+++ lib/libmport/version_cmp.c
@@ -29,10 +29,9 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
+#include <assert.h>
#include "mport.h"
-__MBSDID("$MidnightBSD$");
-
struct version {
char *version;
int revision;
@@ -66,6 +65,24 @@
return result;
}
+void mport_version_cmp_sqlite(sqlite3_context *context, int argc, sqlite3_value **argv)
+{
+ char *a, *b;
+
+ assert(argc == 2);
+
+ a = strdup(sqlite3_value_text(argv[0]));
+ b = strdup(sqlite3_value_text(argv[1]));
+
+ assert(a != NULL);
+ assert(b != NULL);
+
+ sqlite3_result_int(context, mport_version_cmp(a, b));
+
+ free(a);
+ free(b);
+}
+
static void parse_version(const char *in, struct version *v)
{
char *s = strdup(in);
Index: util.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/util.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -L lib/libmport/util.c -L lib/libmport/util.c -u -r1.9 -r1.10
--- lib/libmport/util.c
+++ lib/libmport/util.c
@@ -80,6 +80,31 @@
free(vec);
}
+/* a wrapper around chdir, to work with our error system */
+int mport_chdir(mportInstance *mport, const char *dir)
+{
+ if (mport != NULL) {
+ char *finaldir;
+
+ asprintf(&finaldir, "%s%s", mport->root, dir);
+
+ if (finaldir == NULL)
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't building root'ed dir");
+
+ if (chdir(finaldir) != 0) {
+ free(finaldir);
+ RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "Couldn't chdir to %s: %s", finaldir, strerror(errno));
+ }
+
+ free(finaldir);
+ } else {
+ if (chdir(dir) != 0)
+ RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "Couldn't chdir to %s: %s", dir, strerror(errno));
+ }
+
+ return MPORT_OK;
+}
+
/* deletes the entire directory tree at name.
* think rm -r filename
@@ -109,7 +134,7 @@
{
if (mkdir(dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) {
if (errno != EEXIST)
- RETURN_ERROR(MPORT_ERR_SYSCALL_FAILED, strerror(errno));
+ RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "Couldn't mkdir %s: %s", dir, strerror(errno));
}
return MPORT_OK;
@@ -129,12 +154,14 @@
if (ignore_nonempty && (errno == ENOTEMPTY || errno == ENOENT)) {
return MPORT_OK;
} else {
- RETURN_ERROR(MPORT_ERR_SYSCALL_FAILED, strerror(errno));
+ RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "Couldn't rmdir %s: %s", dir, strerror(errno));
}
}
return MPORT_OK;
}
+
+
/*
* Quick test to see if a file exists.
*/
@@ -164,13 +191,15 @@
if (vasprintf(&cmnd, fmt, args) == -1) {
/* XXX How will the caller know this is no mem, and not a failed exec? */
- return MPORT_ERR_NO_MEM;
+ va_end(args);
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't allocate xsystem cmnd string.");
}
-
+ va_end(args);
+
if (mport != NULL && *(mport->root) != '\0') {
char *chroot_cmd;
if (asprintf(&chroot_cmd, "%s %s %s", MPORT_CHROOT_BIN, mport->root, cmnd) == -1)
- return MPORT_ERR_NO_MEM;
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't allocate xsystem chroot string.");
free(cmnd);
cmnd = chroot_cmd;
@@ -179,7 +208,6 @@
ret = system(cmnd);
free(cmnd);
- va_end(args);
return ret;
}
@@ -240,7 +268,8 @@
* 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.
+ * does the substitions and then runs the command. last_file is
+ * absolute path.
*
* Substitutions:
* %F The last filename extracted (last_file argument)
@@ -253,17 +282,17 @@
size_t l;
size_t max = FILENAME_MAX * 2;
char cmnd[max];
- char fqfile[FILENAME_MAX];
char *pos = cmnd;
char *name;
-
+
while (*fmt && max > 0) {
if (*fmt == '%') {
fmt++;
switch (*fmt) {
case 'F':
- (void)strlcpy(pos, last_file, max);
- l = strlen(last_file);
+ /* last_file is absolute, so we skip the cwd at the begining */
+ (void)strlcpy(pos, last_file + strlen(cwd) + 1, max);
+ l = strlen(last_file + strlen(cwd) + 1);
pos += l;
max -= l;
break;
@@ -274,8 +303,7 @@
max -= l;
break;
case 'B':
- (void)snprintf(fqfile, sizeof(fqfile), "%s/%s", cwd, last_file);
- name = dirname(fqfile);
+ name = dirname(last_file);
(void)strlcpy(pos, name, max);
l = strlen(name);
pos += l;
@@ -303,7 +331,7 @@
}
*pos = '\0';
-
+
/* cmnd now hold the expaded command, now execute it*/
return mport_xsystem(mport, cmnd);
}
Index: delete_primative.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/delete_primative.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L lib/libmport/delete_primative.c -L lib/libmport/delete_primative.c -u -r1.1 -r1.2
--- lib/libmport/delete_primative.c
+++ lib/libmport/delete_primative.c
@@ -37,7 +37,6 @@
#include <stdlib.h>
#include "mport.h"
-__MBSDID("$MidnightBSD$");
@@ -49,17 +48,38 @@
int mport_delete_primative(mportInstance *mport, mportPackageMeta *pack, int force)
{
sqlite3_stmt *stmt;
- int ret;
+ int ret, current, total;
mportPlistEntryType type;
char *data, *checksum, *cwd;
struct stat st;
- char md5[33], file[FILENAME_MAX];
+ char md5[33];
if (force == 0) {
if (check_for_upwards_depends(mport, pack) != MPORT_OK)
RETURN_CURRENT_ERROR;
}
+ /* get the file count for the progress meter */
+ if (mport_db_prepare(mport->db, &stmt, "SELECT COUNT(*) FROM assets WHERE type=%i AND pkg=%Q", PLIST_FILE, pack->name) != MPORT_OK)
+ RETURN_CURRENT_ERROR;
+
+ switch (sqlite3_step(stmt)) {
+ case SQLITE_ROW:
+ total = sqlite3_column_int(stmt, 0) + 2;
+ current = 0;
+ sqlite3_finalize(stmt);
+ break;
+ default:
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(mport->db));
+ sqlite3_finalize(stmt);
+ RETURN_CURRENT_ERROR;
+ }
+
+ (mport->progress_init_cb)();
+
+ if (mport_db_do(mport->db, "UPDATE packages SET status='dirty' WHERE pkg=%Q", pack->name) != MPORT_OK)
+ RETURN_CURRENT_ERROR;
+
if (run_pkg_deinstall(mport, pack, "DEINSTALL") != MPORT_OK)
RETURN_CURRENT_ERROR;
@@ -84,56 +104,48 @@
type = (mportPlistEntryType)sqlite3_column_int(stmt, 0);
data = (char *)sqlite3_column_text(stmt, 1);
checksum = (char *)sqlite3_column_text(stmt, 2);
+
+ char file[FILENAME_MAX];
+ /* XXX TMP */
+ if (*data == '/') {
+ snprintf(file, sizeof(file), "%s%s", mport->root, data);
+ } else {
+ snprintf(file, sizeof(file), "%s%s/%s", mport->root, pack->prefix, data);
+ }
+
switch (type) {
- case PLIST_CWD:
- cwd = data == NULL ? pack->prefix : data;
- break;
case PLIST_FILE:
- (void)snprintf(file, FILENAME_MAX, "%s%s/%s", mport->root, cwd, data);
+ (mport->progress_step_cb)(++current, total, file);
+
if (lstat(file, &st) != 0) {
- char *msg;
- (void)asprintf(&msg, "Can't stat %s: %s", file, strerror(errno));
- (mport->msg_cb)(msg);
- free(msg);
+ mport_call_msg_cb(mport, "Can't stat %s: %s", file, strerror(errno));
break; /* next asset */
}
if (S_ISREG(st.st_mode)) {
- if (MD5File(file, md5) == NULL) {
- sqlite3_finalize(stmt);
- RETURN_ERRORX(MPORT_ERR_FILE_NOT_FOUND, "File not found: %s", file);
- }
+ if (MD5File(file, md5) == NULL)
+ mport_call_msg_cb(mport, "Can't md5 %s: %s", file, strerror(errno));
- if (strcmp(md5, checksum) != 0) {
- char *msg;
- (void)asprintf(&msg, "Checksum mismatch: %s", file);
- (mport->msg_cb)(msg);
- free(msg);
- }
+ if (strcmp(md5, checksum) != 0)
+ mport_call_msg_cb(mport, "Checksum mismatch: %s", file);
}
- if (unlink(file) != 0) {
- sqlite3_finalize(stmt);
- RETURN_ERROR(MPORT_ERR_SYSCALL_FAILED, strerror(errno));
- }
+ if (unlink(file) != 0)
+ mport_call_msg_cb(mport, "Could not unlink %s: %s", file, strerror(errno));
break;
case PLIST_UNEXEC:
if (mport_run_plist_exec(mport, data, cwd, file) != MPORT_OK) {
- sqlite3_finalize(stmt);
- RETURN_CURRENT_ERROR;
+ mport_call_msg_cb(mport, "Could not execute %s: %s", data, mport_err_string());
}
break;
case PLIST_DIRRM:
case PLIST_DIRRMTRY:
- (void)snprintf(file, FILENAME_MAX, "%s%s/%s", mport->root, cwd, data);
-
if (mport_rmdir(file, type == PLIST_DIRRMTRY ? 1 : 0) != MPORT_OK) {
- sqlite3_finalize(stmt);
- RETURN_CURRENT_ERROR;
+ mport_call_msg_cb(mport, "Could not remove directory '%s': %s", file, mport_err_string());
}
break;
@@ -147,6 +159,9 @@
if (run_pkg_deinstall(mport, pack, "POST-DEINSTALL") != MPORT_OK)
RETURN_CURRENT_ERROR;
+
+ if (mport_db_do(mport->db, "BEGIN TRANSACTION") != MPORT_OK)
+ RETURN_CURRENT_ERROR;
if (mport_db_do(mport->db, "DELETE FROM assets WHERE pkg=%Q", pack->name) != MPORT_OK)
RETURN_CURRENT_ERROR;
@@ -159,9 +174,23 @@
if (delete_pkg_infra(mport, pack) != MPORT_OK)
RETURN_CURRENT_ERROR;
+
+ if (mport_db_do(mport->db, "COMMIT TRANSACTION") != MPORT_OK)
+ RETURN_CURRENT_ERROR;
- return MPORT_OK;
-
+ (mport->progress_step_cb)(++current, total, "DB Updated");
+
+
+ /* clean up the master database file, we don't want to frag it */
+ if (mport_db_do(mport->db, "VACUUM") != MPORT_OK)
+ RETURN_CURRENT_ERROR;
+
+ (mport->progress_step_cb)(++current, total, "DB Defragged");
+
+
+ (mport->progress_free_cb)();
+
+ return MPORT_OK;
}
@@ -173,7 +202,10 @@
(void)snprintf(file, FILENAME_MAX, "%s/%s-%s/%s", MPORT_INST_INFRA_DIR, pack->name, pack->version, MPORT_DEINSTALL_FILE);
if (mport_file_exists(file)) {
- if ((ret = mport_xsystem(mport, "PKG_PREFIX=%s %s %s %s %s", pack->prefix, MPORT_SH_BIN, file, pack->name, mode)) != 0)
+ if (chmod(file, 755) != 0)
+ RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "chmod(%s, 755): %s", file, strerror(errno));
+
+ if ((ret = mport_xsystem(mport, "PKG_PREFIX=%s %s %s %s", pack->prefix, file, pack->name, mode)) != 0)
RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "%s %s returned non-zero: %i", MPORT_INSTALL_FILE, mode, ret);
}
Index: create_primative.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/create_primative.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L lib/libmport/create_primative.c -L lib/libmport/create_primative.c -u -r1.1 -r1.2
--- lib/libmport/create_primative.c
+++ lib/libmport/create_primative.c
@@ -42,8 +42,6 @@
#include <archive_entry.h>
#include "mport.h"
-__MBSDID("$MidnightBSD$");
-
static int create_stub_db(sqlite3 **);
static int insert_plist(sqlite3 *, mportPlist *, mportPackageMeta *);
@@ -73,16 +71,16 @@
ret = SET_ERROR(MPORT_ERR_FILEIO, strerror(errno));
goto CLEANUP;
}
-
+
if ((ret = create_stub_db(&db)) != MPORT_OK)
goto CLEANUP;
-
+
if ((ret = insert_plist(db, plist, pack)) != MPORT_OK)
goto CLEANUP;
-
+
if ((ret = insert_meta(db, pack)) != MPORT_OK)
goto CLEANUP;
-
+
if (sqlite3_close(db) != SQLITE_OK) {
ret = SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
goto CLEANUP;
@@ -222,9 +220,10 @@
/* insert depends and conflicts */
if ((ret = insert_depends(db, pack)) != MPORT_OK)
return ret;
+
if ((ret = insert_conflicts(db, pack)) != MPORT_OK)
return ret;
-
+
return MPORT_OK;
}
@@ -245,8 +244,6 @@
/* we have a conflict like apache-1.4. We want to do a m/(.*)-(.*)/ */
while (*conflict != NULL) {
version = rindex(*conflict, '-');
- *version = '\0';
- version++;
if (sqlite3_bind_text(stmnt, 1, pack->name, -1, SQLITE_STATIC) != SQLITE_OK) {
RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
@@ -254,8 +251,16 @@
if (sqlite3_bind_text(stmnt, 2, *conflict, -1, SQLITE_STATIC) != SQLITE_OK) {
RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
}
- if (sqlite3_bind_text(stmnt, 3, version, -1, SQLITE_STATIC) != SQLITE_OK) {
- RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ if (version != NULL) {
+ *version = '\0';
+ version++;
+ if (sqlite3_bind_text(stmnt, 3, version, -1, SQLITE_STATIC) != SQLITE_OK) {
+ RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ }
+ } else {
+ if (sqlite3_bind_text(stmnt, 3, "*", -1, SQLITE_STATIC) != SQLITE_OK) {
+ RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ }
}
if (sqlite3_step(stmnt) != SQLITE_DONE) {
RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
@@ -286,35 +291,41 @@
RETURN_CURRENT_ERROR;
/* depends look like this. break'em up into port, pkgversion and pkgname
- * perl-5.8.8_1:lang/perl5.8
+ * perl:lang/perl5.8:>=5.8.3
*/
while (*depend != NULL) {
- port = rindex(*depend, ':');
+ port = index(*depend, ':');
*port = '\0';
port++;
if (*port == 0)
RETURN_ERRORX(MPORT_ERR_MALFORMED_DEPEND, "Maformed depend: %s", *depend);
-
- pkgversion = rindex(*depend, '-');
- *pkgversion = '\0';
- pkgversion++;
-
- if (*pkgversion == 0)
- RETURN_ERRORX(MPORT_ERR_MALFORMED_DEPEND, "Maformed depend: %s", *depend);
-
+
if (sqlite3_bind_text(stmnt, 1, pack->name, -1, SQLITE_STATIC) != SQLITE_OK) {
RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
}
if (sqlite3_bind_text(stmnt, 2, *depend, -1, SQLITE_STATIC) != SQLITE_OK) {
RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
}
- if (sqlite3_bind_text(stmnt, 3, pkgversion, -1, SQLITE_STATIC) != SQLITE_OK) {
- RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+
+ pkgversion = index(port, ':');
+
+ if (pkgversion != NULL) {
+ *pkgversion = '\0';
+ pkgversion++;
+ if (sqlite3_bind_text(stmnt, 3, pkgversion, -1, SQLITE_STATIC) != SQLITE_OK) {
+ RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ }
+ } else {
+ if (sqlite3_bind_null(stmnt, 3) != SQLITE_OK) {
+ RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ }
}
+
if (sqlite3_bind_text(stmnt, 4, port, -1, SQLITE_STATIC) != SQLITE_OK) {
RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
}
+
if (sqlite3_step(stmnt) != SQLITE_DONE) {
RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
}
@@ -323,6 +334,9 @@
}
sqlite3_finalize(stmnt);
+
+ if (mport_db_do(db, "INSERT INTO exdepends SELECT * FROM depends") != MPORT_OK)
+ RETURN_CURRENT_ERROR;
return MPORT_OK;
}
Index: error.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/error.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -L lib/libmport/error.c -L lib/libmport/error.c -u -r1.6 -r1.7
--- lib/libmport/error.c
+++ lib/libmport/error.c
@@ -32,7 +32,6 @@
#include <string.h>
#include <stdarg.h>
-__MBSDID("$MidnightBSD$");
static int err;
static char err_msg[256];
@@ -63,19 +62,9 @@
return err;
}
-char * mport_err_string()
+const char * mport_err_string()
{
- size_t len = strlen(err_msg);
- char *copy = (char *)malloc(len + 1);
-
- if (copy == NULL) {
- fprintf(stderr, "Fatal error: unable to allocate memory for error string: %s\n", err_msg);
- exit(255);
- }
-
- strlcpy(copy, err_msg, len + 1);
-
- return copy;
+ return err_msg;
}
int mport_set_err(int code, const char *msg)
Index: install_primative.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/install_primative.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L lib/libmport/install_primative.c -L lib/libmport/install_primative.c -u -r1.1 -r1.2
--- lib/libmport/install_primative.c
+++ lib/libmport/install_primative.c
@@ -157,17 +157,19 @@
const char *tmpdir
)
{
- int ret, file_total;
+ int file_total, ret;
int file_count = 0;
mportPlistEntryType type;
- char *data;
- char file[FILENAME_MAX], last[FILENAME_MAX], cwd[FILENAME_MAX];
- sqlite3_stmt *assets, *count;
+ char *data, *checksum, *orig_cwd;
+ char file[FILENAME_MAX], cwd[FILENAME_MAX], dir[FILENAME_MAX];
+ sqlite3_stmt *assets, *count, *insert;
sqlite3 *db;
-
db = mport->db;
+ /* sadly, we can't just use abs pathnames, because it will break hardlinks */
+ orig_cwd = getcwd(NULL, 0);
+
/* get the file count for the progress meter */
if (mport_db_prepare(db, &count, "SELECT COUNT(*) FROM stub.assets WHERE type=%i", PLIST_FILE) != MPORT_OK)
RETURN_CURRENT_ERROR;
@@ -185,34 +187,52 @@
(mport->progress_init_cb)();
- if (mport_db_do(db, "BEGIN TRANSACTION") != MPORT_OK)
- goto ERROR;
- /* Insert the package meta row into the packages table (We use pack here because things might have been twiddled) */
- if ((ret = mport_db_do(db, "INSERT INTO packages (pkg, version, origin, prefix, lang, options) VALUES (%Q,%Q,%Q,%Q,%Q,%Q)", pack->name, pack->version, pack->origin, pack->prefix, pack->lang, pack->options)) != MPORT_OK)
+ /* Insert the package meta row into the packages table (We use pack here because things might have been twiddled) */
+ /* Note that this will be marked as dirty by default */
+ if (mport_db_do(db, "INSERT INTO packages (pkg, version, origin, prefix, lang, options) VALUES (%Q,%Q,%Q,%Q,%Q,%Q)", pack->name, pack->version, pack->origin, pack->prefix, pack->lang, pack->options) != MPORT_OK)
goto ERROR;
- /* Insert the assets into the master table */
- if ((ret = mport_db_do(db, "INSERT INTO assets (pkg, type, data, checksum) SELECT pkg,type,data,checksum FROM stub.assets WHERE pkg=%Q", pack->name)) != MPORT_OK)
+
+ /* Insert the assets into the master table (We do this one by one because we want to insert file
+ * assets as absolute paths. */
+ if (mport_db_prepare(db, &insert, "INSERT INTO assets (pkg, type, data, checksum) values (%Q,?,?,?)", pack->name) != MPORT_OK)
goto ERROR;
/* Insert the depends into the master table */
- if ((ret = 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 WHERE pkg=%Q", pack->name)) != MPORT_OK)
+ 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 WHERE pkg=%Q", pack->name) != MPORT_OK)
goto ERROR;
- if ((ret = mport_db_prepare(db, &assets, "SELECT type,data FROM stub.assets WHERE pkg=%Q", pack->name)) != MPORT_OK)
+ if (mport_db_prepare(db, &assets, "SELECT type,data,checksum FROM stub.assets WHERE pkg=%Q", pack->name) != MPORT_OK)
goto ERROR;
(void)strlcpy(cwd, pack->prefix, sizeof(cwd));
+
+ if (mport_chdir(mport, cwd) != MPORT_OK)
+ goto ERROR;
- while ((ret = sqlite3_step(assets)) == SQLITE_ROW) {
- type = (mportPlistEntryType)sqlite3_column_int(assets, 0);
- data = (char *)sqlite3_column_text(assets, 1);
-
+ while (1) {
+ ret = sqlite3_step(assets);
+
+ if (ret == SQLITE_DONE)
+ break;
+
+ if (ret != SQLITE_ROW) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+
+ type = (mportPlistEntryType)sqlite3_column_int(assets, 0);
+ data = (char *)sqlite3_column_text(assets, 1);
+ checksum = (char *)sqlite3_column_text(assets, 2);
+
switch (type) {
case PLIST_CWD:
(void)strlcpy(cwd, data == NULL ? pack->prefix : data, sizeof(cwd));
+ if (mport_chdir(mport, cwd) != MPORT_OK)
+ goto ERROR;
+
break;
case PLIST_EXEC:
- if ((ret = mport_run_plist_exec(mport, data, cwd, last)) != MPORT_OK)
+ if (mport_run_plist_exec(mport, data, cwd, file) != MPORT_OK)
goto ERROR;
break;
case PLIST_FILE:
@@ -220,17 +240,16 @@
* in the archive was read in the loop in mport_install_pkg. we
* use the current entry and then update it. */
if (entry == NULL) {
- ret = SET_ERROR(MPORT_ERR_INTERNAL, "Plist to arhive mismatch!");
+ SET_ERROR(MPORT_ERR_INTERNAL, "Plist to arhive mismatch!");
goto ERROR;
}
- (void)strlcpy(last, data, sizeof(last));
(void)snprintf(file, FILENAME_MAX, "%s%s/%s", mport->root, cwd, data);
archive_entry_set_pathname(entry, file);
- if ((ret = archive_read_extract(a, entry, ARCHIVE_EXTRACT_OWNER|ARCHIVE_EXTRACT_PERM|ARCHIVE_EXTRACT_TIME|ARCHIVE_EXTRACT_ACL|ARCHIVE_EXTRACT_FFLAGS)) != ARCHIVE_OK) {
- ret = SET_ERROR(MPORT_ERR_ARCHIVE, archive_error_string(a));
+ if (archive_read_extract(a, entry, ARCHIVE_EXTRACT_OWNER|ARCHIVE_EXTRACT_PERM|ARCHIVE_EXTRACT_TIME|ARCHIVE_EXTRACT_ACL|ARCHIVE_EXTRACT_FFLAGS) != ARCHIVE_OK) {
+ SET_ERRORX(MPORT_ERR_ARCHIVE, "Error extracting %s", archive_error_string(a));
goto ERROR;
}
@@ -239,7 +258,7 @@
/* 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) {
- ret = SET_ERROR(MPORT_ERR_ARCHIVE, archive_error_string(a));
+ SET_ERROR(MPORT_ERR_ARCHIVE, archive_error_string(a));
goto ERROR;
}
break;
@@ -247,21 +266,64 @@
/* do nothing */
break;
}
+
+ /* insert this assest into the master database */
+ if (sqlite3_bind_int(insert, 1, (int)type) != SQLITE_OK) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+ if (type == PLIST_FILE) {
+ /* don't put the root in the database! */
+ if (sqlite3_bind_text(insert, 2, file + strlen(mport->root), -1, SQLITE_STATIC) != SQLITE_OK) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+ if (sqlite3_bind_text(insert, 3, checksum, -1, SQLITE_STATIC) != SQLITE_OK) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+ } else if (type == PLIST_DIRRM || type == PLIST_DIRRMTRY) {
+ (void)snprintf(dir, FILENAME_MAX, "%s/%s", cwd, data);
+ if (sqlite3_bind_text(insert, 2, dir, -1, SQLITE_STATIC) != SQLITE_OK) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+ } else {
+ if (sqlite3_bind_text(insert, 2, data, -1, SQLITE_STATIC) != SQLITE_OK) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+
+ if (sqlite3_bind_null(insert, 3) != SQLITE_OK) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+ }
+
+ if (sqlite3_step(insert) != SQLITE_DONE) {
+ SET_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db));
+ goto ERROR;
+ }
+
+ sqlite3_reset(insert);
}
- sqlite3_finalize(assets);
+ sqlite3_finalize(assets);
+ sqlite3_finalize(insert);
- if (mport_db_do(db, "COMMIT TRANSACTION") != MPORT_OK)
+ if (mport_db_do(db, "UPDATE packages SET status='clean' WHERE pkg=%Q", pack->name) != MPORT_OK)
goto ERROR;
(mport->progress_free_cb)();
-
+ (void)mport_chdir(NULL, orig_cwd);
+ free(orig_cwd);
return MPORT_OK;
ERROR:
(mport->progress_free_cb)();
+ free(orig_cwd);
rollback();
- return ret;
+ RETURN_CURRENT_ERROR;
}
static int do_post_install(mportInstance *mport, mportPackageMeta *pack, const char *tmpdir)
@@ -312,8 +374,11 @@
(void)snprintf(file, FILENAME_MAX, "%s/%s/%s-%s/%s", tmpdir, MPORT_STUB_INFRA_DIR, pack->name, pack->version, MPORT_INSTALL_FILE);
if (mport_file_exists(file)) {
- if ((ret = mport_xsystem(mport, "PKG_PREFIX=%s %s %s %s %s", pack->prefix, MPORT_SH_BIN, file, pack->name, mode)) != 0)
- RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "%s %s returned non-zero: %i", MPORT_INSTALL_FILE, mode, ret);
+ if (chmod(file, 755) != 0)
+ RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "chmod(%s, 755): %s", file, strerror(errno));
+
+ if ((ret = mport_xsystem(mport, "PKG_PREFIX=%s %s %s %s", pack->prefix, file, pack->name, mode)) != 0)
+ RETURN_ERRORX(MPORT_ERR_SYSCALL_FAILED, "%s %s returned non-zero: %i", MPORT_INSTALL_FILE, mode, ret);
}
return MPORT_OK;
@@ -337,7 +402,7 @@
if ((file = fopen(filename, "r")) == NULL)
RETURN_ERRORX(MPORT_ERR_FILEIO, "Couldn't open %s: %s", filename, strerror(errno));
- if ((buf = (char *)malloc(st.st_size * sizeof(char))) == NULL)
+ if ((buf = (char *)malloc((st.st_size + 1) * sizeof(char))) == NULL)
return MPORT_ERR_NO_MEM;
@@ -346,7 +411,9 @@
RETURN_ERRORX(MPORT_ERR_FILEIO, "Read error: %s", strerror(errno));
}
- (mport->msg_cb)(buf);
+ buf[st.st_size] = 0;
+
+ mport_call_msg_cb(mport, buf);
free(buf);
Index: bundle.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/bundle.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L lib/libmport/bundle.c -L lib/libmport/bundle.c -u -r1.1 -r1.2
--- lib/libmport/bundle.c
+++ lib/libmport/bundle.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2007 Chris Reinhardt
+ * Copyright (c) 2007,2008 Chris Reinhardt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,13 @@
* $MidnightBSD$
*/
-
+/* Portions of this code (the hardlink handling) were inspired by and/or copied
+ * from write.c in bsdtar by Tim Kientzle. Copyright (c) 2003-2007 Tim Kientzle.
+ *
+ * The code referenced above was released under the same 2-clause BSD license as
+ * libmport.
+ */
+
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
@@ -38,6 +44,26 @@
#include <archive_entry.h>
#include "mport.h"
+#define LINK_TABLE_SIZE 512
+
+struct links_table {
+ size_t nbuckets;
+ size_t nentries;
+ struct link_node **buckets;
+};
+
+struct link_node {
+ int links;
+ dev_t dev;
+ ino_t ino;
+ struct link_node *next;
+ struct link_node *previous;
+ char *name;
+};
+
+
+static int lookup_hardlink(mportBundle *, struct archive_entry *, const struct stat *);
+static void free_linktable(struct links_table *);
/*
* mport_new_bundle()
@@ -64,7 +90,9 @@
bundle->archive = archive_write_new();
archive_write_set_compression_bzip2(bundle->archive);
archive_write_set_format_pax(bundle->archive);
-
+
+ bundle->links = NULL;
+
if (archive_write_open_filename(bundle->archive, bundle->filename) != ARCHIVE_OK) {
RETURN_ERROR(MPORT_ERR_ARCHIVE, archive_error_string(bundle->archive));
}
@@ -82,9 +110,10 @@
{
int ret = MPORT_OK;
- if (archive_write_finish(bundle->archive) != MPORT_OK)
+ if (archive_write_finish(bundle->archive) != ARCHIVE_OK)
ret = SET_ERROR(MPORT_ERR_ARCHIVE, archive_error_string(bundle->archive));
-
+
+ free_linktable(bundle->links);
free(bundle->filename);
free(bundle);
@@ -104,7 +133,7 @@
struct stat st;
int fd, len;
char buff[1024*64];
-
+
if (lstat(filename, &st) != 0) {
RETURN_ERROR(MPORT_ERR_SYSCALL_FAILED, strerror(errno));
}
@@ -112,23 +141,25 @@
entry = archive_entry_new();
archive_entry_set_pathname(entry, path);
+ if (!S_ISDIR(st.st_mode) && (st.st_nlink > 1))
+ if (lookup_hardlink(bundle, entry, &st) != MPORT_OK)
+ RETURN_CURRENT_ERROR;
if (S_ISLNK(st.st_mode)) {
/* we have us a symlink */
int linklen;
- char linkdata[PATH_MAX];
+ char linkdata[PATH_MAX + 1];
linklen = readlink(filename, linkdata, PATH_MAX);
if (linklen < 0)
RETURN_ERROR(MPORT_ERR_SYSCALL_FAILED, strerror(errno));
- linkdata[linklen] = 0;
+ linkdata[linklen] = '\0';
archive_entry_set_symlink(entry, linkdata);
}
-
-
+
if (st.st_flags != 0)
archive_entry_set_fflags(entry, st.st_flags, 0);
@@ -163,3 +194,137 @@
return MPORT_OK;
}
+static int lookup_hardlink(mportBundle *bundle, struct archive_entry *entry, const struct stat *st)
+{
+ struct links_table *links = bundle->links;
+ struct link_node *node, **new_buckets;
+ int hash;
+ size_t i, new_size;
+
+ if (links == NULL) {
+ if ((bundle->links = calloc(1, sizeof(struct links_table))) == NULL)
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't allocate links table");
+
+ links = bundle->links;
+ links->nbuckets = LINK_TABLE_SIZE;
+ links->nentries = 0;
+ links->buckets = calloc(links->nbuckets, sizeof(links->buckets[0]));
+
+ if (links->buckets == NULL) {
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't allocate links table mapping");
+ }
+ }
+
+ if (links->buckets == NULL) {
+ return MPORT_OK; /* just to be safe */
+ }
+
+ /* if the number of entires is twice the number of buckets, increase the table size */
+ if (links->nentries > (links->nbuckets * 2)) {
+ new_size = links->nbuckets * 2;
+ new_buckets = (struct link_node **)calloc(new_size, sizeof(struct link_node *));
+
+ if (new_buckets != NULL) {
+ for (i=0; i < links->nbuckets; i++) {
+ while (links->buckets[i] != NULL) {
+ /* remove old from bucket */
+ node = links->buckets[i];
+ links->buckets[i] = node;
+
+ hash = (node->dev ^ node->ino) % new_size;
+ if (new_buckets[hash] != NULL)
+ new_buckets[hash]->previous = node;
+
+ node->next = new_buckets[hash];
+ node->previous = NULL;
+ new_buckets[hash] = node;
+ }
+ }
+ free(links->buckets);
+ links->buckets = new_buckets;
+ links->nbuckets = new_size;
+ } else {
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't expand hard links hash table.");
+ }
+ }
+
+
+ /* ok, we're done with maintence of the hash table, we can now go on to trying
+ to find the location of this entry */
+ hash = (st->st_dev ^ st->st_ino) % links->nbuckets;
+
+ for (node = links->buckets[hash]; node != NULL; node = node->next) {
+ if (node->dev == st->st_dev && node->ino == st->st_ino) {
+ /* we found it! we're out of here */
+ archive_entry_copy_hardlink(entry, node->name);
+
+ node->links--;
+
+ /* no reason to keep this in the table, we've archived all the links */
+ if (node->links <= 0) {
+ if (node->previous != NULL)
+ node->previous->next = node->next;
+ if (node->next != NULL)
+ node->next->previous = node->previous;
+ if (links->buckets[hash] == node)
+ links->buckets[hash] = node->next;
+ if (node->name != NULL)
+ free(node->name);
+ links->nentries--;
+ free(node);
+ }
+
+ return MPORT_OK;
+ }
+ }
+
+ /* we didn't find any match to this file, so this is the first time we've seen
+ it. Put it in the table */
+ node = calloc(1, sizeof(struct link_node));
+ if (node != NULL)
+ node->name = strdup(archive_entry_pathname(entry));
+ if ((node == NULL) || (node->name == NULL))
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't add file to the links hashtable.");
+
+ if (links->buckets[hash] != NULL)
+ links->buckets[hash]->previous = node;
+
+ links->nentries++;
+ node->next = links->buckets[hash];
+ node->previous = NULL;
+ node->dev = st->st_dev;
+ node->ino = st->st_ino;
+ node->links = st->st_nlink - 1;
+
+ links->buckets[hash] = node;
+
+ return MPORT_OK;
+}
+
+
+static void free_linktable(struct links_table *links)
+{
+ size_t i;
+ struct link_node *node;
+
+ if ((links == NULL) || (links->buckets == NULL))
+ return;
+
+ for (i = 0; i < links->nbuckets; i++) {
+ while (links->buckets[i] != NULL) {
+ node = links->buckets[i];
+ links->buckets[i] = node->next;
+
+ free(node->name);
+
+ if (node->name != NULL)
+ free(node->name);
+
+ free(node);
+ }
+ }
+
+ free(links->buckets);
+ links->buckets = NULL;
+}
+
Index: db.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/db.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L lib/libmport/db.c -L lib/libmport/db.c -u -r1.3 -r1.4
--- lib/libmport/db.c
+++ lib/libmport/db.c
@@ -35,8 +35,6 @@
#include <string.h>
#include "mport.h"
-__MBSDID("$MidnightBSD$");
-
static int populate_meta_from_stmt(mportPackageMeta *, sqlite3 *, sqlite3_stmt *);
static int populate_vec_from_stmt(mportPackageMeta ***, int, sqlite3 *, sqlite3_stmt *);
@@ -54,9 +52,13 @@
va_start(args, fmt);
- if ((sql = sqlite3_vmprintf(fmt, args)) == NULL) {
- return MPORT_ERR_NO_MEM;
- }
+ sql = sqlite3_vmprintf(fmt, args);
+
+ va_end(args);
+
+ if (sql == NULL)
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't allocate memory for sql statement");
+
if (sqlite3_exec(db, sql, 0, 0, 0) != SQLITE_OK) {
sqlite3_free(sql);
@@ -82,10 +84,11 @@
char *sql;
va_start(args, fmt);
+ sql = sqlite3_vmprintf(fmt, args);
+ va_end(args);
- if ((sql = sqlite3_vmprintf(fmt, args)) == NULL) {
- return MPORT_ERR_NO_MEM;
- }
+ if (sql == NULL)
+ RETURN_ERROR(MPORT_ERR_NO_MEM, "Couldn't allocate memory for sql statement");
if (sqlite3_prepare_v2(db, sql, -1, stmt, NULL) != SQLITE_OK) {
SET_ERRORX(MPORT_ERR_SQLITE, "sql error preparing '%s': %s", sql, sqlite3_errmsg(db));
@@ -202,10 +205,12 @@
sqlite3 *db = mport->db;
va_start(args, fmt);
-
- if ((where = sqlite3_vmprintf(fmt, args)) == NULL) {
+ where = sqlite3_vmprintf(fmt, args);
+ va_end(args);
+
+ if (where == NULL)
RETURN_ERROR(MPORT_ERR_NO_MEM, "Could not build where clause");
- }
+
if (mport_db_prepare(db, &stmt, "SELECT count(*) FROM packages WHERE %s", where) != MPORT_OK)
RETURN_CURRENT_ERROR;
@@ -318,7 +323,7 @@
#define RUN_SQL(db, sql) \
if (mport_db_do(db, sql) != MPORT_OK) \
- RETURN_ERROR(MPORT_ERR_SQLITE, sqlite3_errmsg(db))
+ RETURN_CURRENT_ERROR
int mport_generate_stub_schema(sqlite3 *db)
@@ -326,19 +331,22 @@
RUN_SQL(db, "CREATE TABLE assets (pkg text not NULL, type int NOT NULL, data text, checksum text)");
RUN_SQL(db, "CREATE TABLE packages (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)");
-
+ RUN_SQL(db, "CREATE TABLE depends (pkg text NOT NULL, depend_pkgname text NOT NULL, depend_pkgversion text, depend_port text NOT NULL)");
+ RUN_SQL(db, "CREATE TABLE exdepends (pkg text NOT NULL, depend_pkgname text NOT NULL, depend_pkgversion text, 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 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, status text default 'dirty')");
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 TABLE IF NOT EXISTS depends (pkg text NOT NULL, depend_pkgname text NOT NULL, depend_pkgversion text, 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)");
Index: default_cbs.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/default_cbs.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L lib/libmport/default_cbs.c -L lib/libmport/default_cbs.c -u -r1.1 -r1.2
--- lib/libmport/default_cbs.c
+++ lib/libmport/default_cbs.c
@@ -87,6 +87,9 @@
double percent;
char *bar;
+ if (current > total)
+ current = total;
+
if ((tcgetattr(STDIN_FILENO, &term) < 0) || (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) < 0)) {
/* not a terminal or couldn't get terminal width*/
(void)printf("%s\n", msg);
Index: check_preconditions.c
===================================================================
RCS file: /home/cvs/src/lib/libmport/check_preconditions.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L lib/libmport/check_preconditions.c -L lib/libmport/check_preconditions.c -u -r1.1 -r1.2
--- lib/libmport/check_preconditions.c
+++ lib/libmport/check_preconditions.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2007 Chris Reinhardt
+ * Copyright (c) 2007,2008 Chris Reinhardt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,6 @@
#include "mport.h"
-__MBSDID("$MidnightBSD$");
static int check_if_installed(sqlite3 *, mportPackageMeta *);
@@ -112,7 +111,7 @@
int ret;
const char *inst_name, *inst_version;
- if (mport_db_prepare(db, &stmt, "SELECT packages.pkg, packages.version FROM stub.conflicts LEFT JOIN packages ON packages.pkg GLOB stub.conflicts.conflict_pkg AND packages.version GLOB stub.conflicts.conflict_version WHERE packages.pkg IS NOT NULL") != MPORT_OK)
+ if (mport_db_prepare(db, &stmt, "SELECT packages.pkg, packages.version FROM stub.conflicts LEFT JOIN packages ON packages.pkg GLOB stub.conflicts.conflict_pkg AND packages.version GLOB stub.conflicts.conflict_version WHERE sub.conflicts.pkg=%Q AND packages.pkg IS NOT NULL", pack->name) != MPORT_OK)
RETURN_CURRENT_ERROR;
while (1) {
@@ -147,10 +146,10 @@
int ret;
/* check for depends */
- if (mport_db_prepare(db, &stmt, "SELECT depend_pkgname, depend_pkgversion FROM stub.depends") != MPORT_OK)
+ if (mport_db_prepare(db, &stmt, "SELECT depend_pkgname, depend_pkgversion FROM stub.depends WHERE pkg=%Q", pack->name) != MPORT_OK)
RETURN_CURRENT_ERROR;
- if (mport_db_prepare(db, &lookup, "SELECT version FROM packages WHERE pkg=?") != MPORT_OK) {
+ if (mport_db_prepare(db, &lookup, "SELECT version FROM packages WHERE pkg=? AND status='clean'") != MPORT_OK) {
sqlite3_finalize(stmt);
RETURN_CURRENT_ERROR;
}
@@ -171,12 +170,40 @@
switch (sqlite3_step(lookup)) {
case SQLITE_ROW:
inst_version = sqlite3_column_text(lookup, 0);
-
- if (mport_version_cmp(inst_version, depend_version) < 0) {
+ int ok;
+
+ if (depend_version == NULL)
+ /* no minimum version */
+ break;
+
+ /* break out the compare op at the front of the version string */
+ if (depend_version[0] == '<') {
+ if (depend_version[1] == '=') {
+ depend_version += 2;
+ ok = (mport_version_cmp(inst_version, depend_version) <= 0);
+ } else {
+ depend_version++;
+ ok = (mport_version_cmp(inst_version, depend_version) < 0);
+ }
+ } else if (depend_version[0] == '>') {
+ if (depend_version[1] == '=') {
+ depend_version += 2;
+ ok = (mport_version_cmp(inst_version, depend_version) >= 0);
+ } else {
+ depend_version++;
+ ok = (mport_version_cmp(inst_version, depend_version) > 0);
+ }
+ } else {
+ sqlite3_finalize(lookup); sqlite3_finalize(stmt);
+ RETURN_ERRORX(MPORT_ERR_MALFORMED_DEPEND, "Maformed depend version for %s: %s", depend_pkg, depend_version);
+ }
+
+ if (!ok) {
SET_ERRORX(MPORT_ERR_MISSING_DEPEND, "%s depends on %s version %s. Version %s is installed.", pack->name, depend_pkg, depend_version, inst_version);
sqlite3_finalize(lookup); sqlite3_finalize(stmt);
RETURN_CURRENT_ERROR;
}
+
break;
case SQLITE_DONE:
/* this depend isn't installed. */
Index: mport.h
===================================================================
RCS file: /home/cvs/src/lib/libmport/mport.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -L lib/libmport/mport.h -L lib/libmport/mport.h -u -r1.9 -r1.10
--- lib/libmport/mport.h
+++ lib/libmport/mport.h
@@ -66,6 +66,8 @@
void mport_set_progress_free_cb(mportInstance *, mport_progress_free_cb);
void mport_set_confirm_cb(mportInstance *, mport_confirm_cb);
+void mport_call_msg_cb(mportInstance *, const char *, ...);
+
void mport_default_msg_cb(const char *);
int mport_default_confirm_cb(const char *, const char *, const char *, int);
void mport_default_progress_init_cb(void);
@@ -73,10 +75,12 @@
void mport_default_progress_free_cb(void);
+
/* Mport Bundle (a file containing packages) */
typedef struct {
struct archive *archive;
char *filename;
+ struct links_table *links;
} mportBundle;
mportBundle* mport_bundle_new(void);
@@ -165,11 +169,11 @@
/* version comparing */
int mport_version_cmp(const char *, const char *);
-
+void mport_version_cmp_sqlite(sqlite3_context *, int, sqlite3_value **);
/* Errors */
int mport_err_code(void);
-char * mport_err_string(void);
+const char * mport_err_string(void);
int mport_set_err(int, const char *);
int mport_set_errx(int , const char *, ...);
@@ -204,6 +208,7 @@
int mport_rmtree(const char *);
int mport_mkdir(const char *);
int mport_rmdir(const char *, int);
+int mport_chdir(mportInstance *, const char *);
int mport_file_exists(const char *);
int mport_xsystem(mportInstance *mport, const char *, ...);
void mport_parselist(char *, char ***);
More information about the Midnightbsd-cvs
mailing list