[darwinbuild-changes] [881] trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Sep 17 17:28:32 PDT 2010


Revision: 881
          http://trac.macosforge.org/projects/darwinbuild/changeset/881
Author:   wsiegrist at apple.com
Date:     2010-09-17 17:28:31 -0700 (Fri, 17 Sep 2010)
Log Message:
-----------
Merge PR-8416637

Modified Paths:
--------------
    trunk/darwinup/Depot.cpp
    trunk/darwinup/Depot.h
    trunk/darwinup/File.cpp
    trunk/darwinup/File.h
    trunk/darwinup/Utils.cpp
    trunk/darwinup/main.cpp
    trunk/testing/darwinup/dest.tar.gz
    trunk/testing/darwinup/run-tests.sh

Added Paths:
-----------
    trunk/testing/darwinup/rep_dir_file.tar.gz
    trunk/testing/darwinup/rep_dir_link.tar.gz
    trunk/testing/darwinup/rep_file_dir.tar.gz
    trunk/testing/darwinup/rep_file_link.tar.gz
    trunk/testing/darwinup/rep_flink_dir.tar.gz
    trunk/testing/darwinup/rep_flink_file.tar.gz
    trunk/testing/darwinup/rep_link_dir.tar.gz
    trunk/testing/darwinup/rep_link_file.tar.gz

Removed Paths:
-------------
    trunk/testing/darwinup/root4.tar.gz

Property Changed:
----------------
    trunk/


Property changes on: trunk
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/PR-4841388:399-419
/branches/PR-6358021:442-443
/branches/PR-6392966:423-427
/branches/PR-6398060:433-434
/branches/PR-6493844:460-461
/branches/PR-6497694:466-468,471
/branches/PR-6634286:632-650
/branches/PR-6688645:479-490
/branches/PR-6722857:495-499
/branches/PR-6729491:655-664
/branches/PR-6973110:804-813
/branches/PR-7250612:635-650
/branches/PR-7341154:682-694
/branches/PR-7431723:660-664
/branches/PR-7461534:650-664
/branches/PR-7482850:670-671
/branches/PR-7489777:676-731
/branches/PR-7529688:692-694
/branches/PR-7593824:739-772
/branches/PR-7598640:703-731
/branches/PR-7748469:777-785
/branches/PR-7765119:790-791
/branches/PR-7798586:796-799
/branches/PR-7872907:830-840
/branches/PR-7935095:819-821
/branches/PR-8116613:849
/branches/PR-8279204:854-862
   + /branches/PR-4841388:399-419
/branches/PR-6358021:442-443
/branches/PR-6392966:423-427
/branches/PR-6398060:433-434
/branches/PR-6493844:460-461
/branches/PR-6497694:466-468,471
/branches/PR-6634286:632-650
/branches/PR-6688645:479-490
/branches/PR-6722857:495-499
/branches/PR-6729491:655-664
/branches/PR-6973110:804-813
/branches/PR-7250612:635-650
/branches/PR-7341154:682-694
/branches/PR-7431723:660-664
/branches/PR-7461534:650-664
/branches/PR-7482850:670-671
/branches/PR-7489777:676-731
/branches/PR-7529688:692-694
/branches/PR-7593824:739-772
/branches/PR-7598640:703-731
/branches/PR-7748469:777-785
/branches/PR-7765119:790-791
/branches/PR-7798586:796-799
/branches/PR-7872907:830-840
/branches/PR-7935095:819-821
/branches/PR-8116613:849
/branches/PR-8279204:854-862
/branches/PR-8416637:870-880

Modified: trunk/darwinup/Depot.cpp
===================================================================
--- trunk/darwinup/Depot.cpp	2010-09-16 22:51:34 UTC (rev 880)
+++ trunk/darwinup/Depot.cpp	2010-09-18 00:28:31 UTC (rev 881)
@@ -103,9 +103,9 @@
 	m_db = new DarwinupDatabase(m_database_path);
 	if (!m_db || !m_db->is_connected()) {
 		fprintf(stderr, "Error: unable to connect to database.\n");
-		return 1;
+		return DB_ERROR;
 	}
-	return 0;
+	return DB_OK;
 }
 
 int Depot::create_storage() {
@@ -138,7 +138,7 @@
 		perror(m_downloads_path);
 		return res;
 	}
-	return 0;
+	return DEPOT_OK;
 }
 
 // Initialize the depot
@@ -148,7 +148,7 @@
 	// initialization requires all these paths to be set
 	if (!(m_prefix && m_depot_path && m_database_path && 
 		  m_archives_path && m_downloads_path)) {
-		return -1;
+		return DEPOT_ERROR;
 	}
 	
 	if (writable) {
@@ -172,11 +172,11 @@
 	res = stat(m_database_path, &sb);
 	if (!writable && res == -1 && (errno == ENOENT || errno == ENOTDIR)) {
 		// depot does not exist
-		return -2; 
+		return DEPOT_NOT_EXIST; 
 	}
 	if (!writable && res == -1 && errno == EACCES) {
 		// permission denied
-		return -3;
+		return DEPOT_PERM_DENIED;
 	}
 
 	// take an exclusive lock
@@ -402,9 +402,9 @@
 	return res;
 }
 
-
 int Depot::analyze_stage(const char* path, Archive* archive, Archive* rollback,
 						 int* rollback_files) {
+	extern uint32_t force;
 	extern uint32_t dryrun;
 	int res = 0;
 	assert(archive != NULL);
@@ -475,9 +475,22 @@
 				if (INFO_TEST(actual->info(), FILE_INFO_NO_ENTRY)) {
 					state = 'A';
 				} else {
+					if (INFO_TEST(actual_flags, FILE_INFO_TYPE_DIFFERS) && !force) {
+						// the existing file on disk is a different type than what
+						// we are trying to install, so require the force option,
+						// otherwise print an error and bail
+						mode_t file_type = file->mode() & S_IFMT;
+						mode_t actual_type = actual->mode() & S_IFMT;
+						fprintf(stderr, FILE_OBJ_CHANGE_ERROR, actual->path(), 
+								FILE_TYPE_STRING(file_type),
+								FILE_TYPE_STRING(actual_type));
+						return DEPOT_OBJ_CHANGE;
+					}
 					state = 'U';
 				}
 				
+				
+				
 				if (INFO_TEST(actual_flags, FILE_INFO_TYPE_DIFFERS) ||
 				    INFO_TEST(actual_flags, FILE_INFO_DATA_DIFFERS)) {
 					IF_DEBUG("[analyze]    needs installation\n");
@@ -674,20 +687,25 @@
 			uuid_unparse_upper(archive->uuid(), uuid);
 			fprintf(stdout, "%s\n", uuid);
 		} else {
-			fprintf(stderr, "Error: Install failed. Rolling back installation.\n");
-			res = this->uninstall(archive);
-			if (res) {
-				fprintf(stderr, "Error: Unable to rollback installation. "
-						"Your system is in an inconsistent state! File a bug!\n");
-			} else {
-				fprintf(stdout, "Rollback successful.\n");
+			fprintf(stderr, "Error: Install failed.\n");				
+			if (res != DEPOT_OBJ_CHANGE) {
+				// object change errors come from analyze stage,
+				// so there is no installation to roll back
+				fprintf(stderr, "Rolling back installation.\n");
+				res = this->uninstall(archive);
+				if (res) {
+					fprintf(stderr, "Error: Unable to rollback installation. "
+							"Your system is in an inconsistent state! File a bug!\n");
+				} else {
+					fprintf(stdout, "Rollback successful.\n");
+				}
 			}
-			res = 1;
+			res = DEPOT_ERROR;
 		}
 	} else {
-		fprintf(stdout, "Error: unable to load \"%s\". Either the path is invalid or"
+		fprintf(stdout, "Error: unable to load \"%s\". Either the path is missing, invalid or"
 				         " the file is in an unknown format.\n", path);
-		return -1;
+		return DEPOT_ERROR;
 	}
 
 	return res;
@@ -739,8 +757,8 @@
 	int rollback_files = 0;
 	if (res == 0) res = this->analyze_stage(archive_path, archive, rollback, &rollback_files);
 	
-	// we can stop now if this is a dry run
-	if (dryrun) {
+	// we can stop now if analyze failed or this is a dry run
+	if (res || dryrun) {
 		remove_directory(archive_path);
 		remove_directory(rollback_path);
 		free(rollback_path);
@@ -855,7 +873,7 @@
 	// We never uninstall a file that was part of the base system
 	if (INFO_TEST(file->info(), FILE_INFO_BASE_SYSTEM)) {
 		IF_DEBUG("[uninstall]    base system; skipping\n");
-		return 0;
+		return DEPOT_OK;
 	}
 	
 	char* actpath;
@@ -941,10 +959,10 @@
 		// if in debug mode, get_all_archives returns rollbacks too, so just ignore
 		if (verbosity & VERBOSE_DEBUG) {
 			fprintf(stderr, "[uninstall] skipping uninstall since archive is a rollback.\n");
-			return 0;
+			return DEPOT_OK;
 		}
 		fprintf(stderr, "%s:%d: cannot uninstall a rollback archive.\n", __FILE__, __LINE__);
-		return -1;
+		return DEPOT_ERROR;
 	}
 
 	/** 
@@ -968,7 +986,7 @@
 				"happen.\n"
 				"-------------------------------------------------------------------------------\n",
 				archive->name(), archive->build(), m_build);
-		return 9999;
+		return DEPOT_BUILD_MISMATCH;
 	}
 
 	if (res != 0) return res;
@@ -1027,7 +1045,7 @@
 		fprintf(stdout, "R ");
 	}
 	file->print(stdout);
-	return 0;
+	return DEPOT_OK;
 }
 
 void Depot::archive_header() {
@@ -1063,7 +1081,7 @@
 	fprintf((FILE*)context, "%-6llu %-36s  %-12s  %-7s  %s\n", 
 			serial, uuid, date, (archive->build()?archive->build():""), archive->name());
 	
-	return 0;
+	return DEPOT_OK;
 }
 
 int Depot::list() {
@@ -1110,7 +1128,7 @@
 	extern uint32_t verbosity;
 	if (verbosity & VERBOSE_DEBUG) fprintf((FILE*)context, "%04x ", file->info());
 	file->print((FILE*)context);
-	return 0;
+	return DEPOT_OK;
 }
 
 int Depot::files(Archive* archive) {
@@ -1322,7 +1340,7 @@
 	}
 
 	free(path);
-	return 0;
+	return DEPOT_OK;
 }
 
 int Depot::has_file(Archive* archive, File* file) {
@@ -1401,7 +1419,7 @@
 	for (size_t i = 0; i < count; i++) {
 		if (!list[i]) {
 			fprintf(stdout, "Archive not found: %s\n", archspec);
-			return -1;
+			return DEPOT_ERROR;
 		}
 		if (verbosity & VERBOSE_DEBUG) {
 			char uuid[37];
@@ -1423,13 +1441,13 @@
 		(strncasecmp(archspec, "superseded", 10) == 0 && strlen(archspec) == 10)) {
 		fprintf(stderr, "Error: keywords 'all' and 'superseded' cannot be used with the"
 				" rename command.\n");
-		return -2;
+		return DEPOT_USAGE_ERROR;
 	}
 	
 	Archive* archive = this->get_archive(archspec);
 	if (!archive) {
 		fprintf(stdout, "Archive not found: %s\n", archspec);
-		return -1;
+		return DEPOT_NOT_EXIST;
 	}
 	
 	char uuid[37];
@@ -1440,7 +1458,7 @@
 
 	if (!name || strlen(name) == 0) {
 		fprintf(stderr, "Error: invalid name: '%s'\n", name);
-		return -3;
+		return DEPOT_ERROR;
 	}
 	
 	free(archive->m_name);

Modified: trunk/darwinup/Depot.h
===================================================================
--- trunk/darwinup/Depot.h	2010-09-16 22:51:34 UTC (rev 880)
+++ trunk/darwinup/Depot.h	2010-09-18 00:28:31 UTC (rev 881)
@@ -39,6 +39,15 @@
 #include "DB.h"
 #include "Archive.h"
 
+#define DEPOT_OK              0
+#define DEPOT_ERROR          -1
+#define DEPOT_NOT_EXIST      -2
+#define DEPOT_PERM_DENIED    -3
+#define DEPOT_OBJ_CHANGE     -4
+#define DEPOT_BUILD_MISMATCH -5
+#define DEPOT_USAGE_ERROR    -6
+
+
 struct Archive;
 struct File;
 struct DarwinupDatabase;

Modified: trunk/darwinup/File.cpp
===================================================================
--- trunk/darwinup/File.cpp	2010-09-16 22:51:34 UTC (rev 880)
+++ trunk/darwinup/File.cpp	2010-09-18 00:28:31 UTC (rev 881)
@@ -82,7 +82,8 @@
 	m_digest = NULL;
 }
 
-File::File(uint64_t serial, Archive* archive, uint32_t info, const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) {
+File::File(uint64_t serial, Archive* archive, uint32_t info, const char* path, 
+		   mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) {
 	m_serial = serial;
 	m_archive = archive;
 	m_info = info;
@@ -116,17 +117,21 @@
 
 uint32_t File::compare(File* a, File* b) {
 	if (a == b) return FILE_INFO_IDENTICAL; // identity
-	if (a == NULL) return 0xFFFFFFFF; // existent and nonexistent file are infinitely different
-	if (b == NULL) return 0xFFFFFFFF; // existent and nonexistent file are infinitely different
+	// existent and nonexistent file are infinitely different
+	if (a == NULL) return 0xFFFFFFFF; 
+	if (b == NULL) return 0xFFFFFFFF;
 	
 	uint32_t result = FILE_INFO_IDENTICAL;
 	if (a->m_uid != b->m_uid) result |= FILE_INFO_UID_DIFFERS;
 	if (a->m_gid != b->m_gid) result |= FILE_INFO_GID_DIFFERS;
 	if (a->m_mode != b->m_mode) result |= FILE_INFO_MODE_DIFFERS;
-	if ((a->m_mode & S_IFMT) != (b->m_mode & S_IFMT)) result |= FILE_INFO_TYPE_DIFFERS;
-	if ((a->m_mode & ALLPERMS) != (b->m_mode & ALLPERMS)) result |= FILE_INFO_PERM_DIFFERS;
+	if ((a->m_mode & S_IFMT) != (b->m_mode & S_IFMT)) 
+		result |= FILE_INFO_TYPE_DIFFERS;
+	if ((a->m_mode & ALLPERMS) != (b->m_mode & ALLPERMS)) 
+		result |= FILE_INFO_PERM_DIFFERS;
 	//if (a->m_size != b->m_size) result |= FILE_INFO_SIZE_DIFFERS;
-	if (Digest::equal(a->m_digest, b->m_digest) == 0) result |= FILE_INFO_DATA_DIFFERS;
+	if (Digest::equal(a->m_digest, b->m_digest) == 0) 
+		result |= FILE_INFO_DATA_DIFFERS;
 	return result;
 }
 
@@ -158,7 +163,8 @@
 	if (dirpath) {
 		ssize_t len = snprintf(srcpath, sizeof(srcpath), "%s/%s", dirpath, path);
 		if ((size_t)len > sizeof(srcpath)) {
-			fprintf(stderr, "ERROR: [install] path too long: %s/%s\n", dirpath, path);
+			fprintf(stderr, "ERROR: [install] path too long: %s/%s\n", 
+					dirpath, path);
 			return -1;
 		}
 		IF_DEBUG("[install] rename(%s, %s)\n", srcpath, dstpath);
@@ -168,20 +174,22 @@
 				// the file wasn't found, try to do on-demand
 				// expansion of the archive that contains it.
 				if (is_directory(dirpath) == 0) {
-					IF_DEBUG("[install] File::install on-demand archive expansion \n");
+					IF_DEBUG("[install] File::install on-demand archive expansion\n");
 					res = archive->expand_directory(prefix);
 					if (res == 0) res = this->install(prefix, dest);
 				} else {
 					// archive was already expanded, so
 					// the file is truly missing (worry).
 					IF_DEBUG("[install] File::install missing file in archive \n");
-					fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, srcpath, strerror(errno), errno);
+					fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+							__FILE__, __LINE__, srcpath, strerror(errno), errno);
 				}
 			} else if (force && errno == ENOTDIR) {
 				// a) some part of destination path does not exist
 				// b) from is a directory, but to is not
 				IF_DEBUG("[install] File::install ENOTDIR\n");
-				fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+				fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+						__FILE__, __LINE__, dstpath, strerror(errno), errno);
 			} else if (force && errno == EISDIR) {
 				// to is a directory, but from is not
 				IF_DEBUG("[install] replacing directory with a file\n");
@@ -190,28 +198,24 @@
 				rmstate = removefile_state_alloc();
 				res = removefile(dstpath, rmstate, REMOVEFILE_RECURSIVE);
 				removefile_state_free(rmstate);
-				if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+				if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n",
+									   __FILE__, __LINE__, dstpath, strerror(errno), 
+									   errno);
 				IF_DEBUG("[install] rename(%s, %s)\n", srcpath, dstpath);
 				res = rename(srcpath, dstpath);
-				if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+				if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n",
+									   __FILE__, __LINE__, dstpath, strerror(errno), 
+									   errno);
 			} else if (force && errno == ENOTEMPTY) {
 				// to is a directory and is not empty
 				IF_DEBUG("[install] File::install ENOTEMPTY\n");
-				fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+				fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+						__FILE__, __LINE__, dstpath, strerror(errno), errno);
 			} else {
-				if (!force) {
-					fprintf(stderr,
-							"-------------------------------------------------------------------------------\n"
-							"darwinup has encountered a potentially unsafe mismatch between the root and    \n"
-							"destination. For example, you may be trying to install a file where a directory\n" 
-							"currently exists. darwinup will not install this root by default since it could\n"
-							"cause damage to your system. You can use the force (-f) option to allow        \n"
-							"darwinup to attempt the install anyway.                                        \n"
-							"-------------------------------------------------------------------------------\n"
-							);
-				}
-				fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
-				fprintf(stderr, "ERROR: fatal error during File::install. Cannot continue.\n");
+				fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+						__FILE__, __LINE__, dstpath, strerror(errno), errno);
+				fprintf(stderr, "ERROR: fatal error during File::install. " \
+						"Cannot continue.\n");
 			}
 		} else {
 			IF_DEBUG("[install] rename(%s, %s)\n", srcpath, dstpath);
@@ -226,7 +230,8 @@
 
 int File::remove() {
 	// not implemented
-	fprintf(stderr, "%s:%d: call to abstract function File::remove\n", __FILE__, __LINE__);
+	fprintf(stderr, "%s:%d: call to abstract function File::remove\n", 
+			__FILE__, __LINE__);
 	return -1;
 }
 
@@ -251,13 +256,17 @@
 	m_info = INFO_SET(m_info, FILE_INFO_NO_ENTRY);
 }
 
-NoEntry::NoEntry(uint64_t serial, Archive* archive, uint32_t info, const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) : File(serial, archive, info, path, mode, uid, gid, size, digest) {}
+NoEntry::NoEntry(uint64_t serial, Archive* archive, uint32_t info, const char* path, 
+				 mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) 
+: File(serial, archive, info, path, mode, uid, gid, size, digest) {}
 
 Regular::Regular(Archive* archive, FTSENT* ent) : File(archive, ent) {
 	m_digest = new SHA1DigestMachO(ent->fts_accpath);
 }
 
-Regular::Regular(uint64_t serial, Archive* archive, uint32_t info, const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) : File(serial, archive, info, path, mode, uid, gid, size, digest) {
+Regular::Regular(uint64_t serial, Archive* archive, uint32_t info, const char* path, 
+				 mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) 
+: File(serial, archive, info, path, mode, uid, gid, size, digest) {
 	if (digest == NULL || serial == 0) {
 		m_digest = new SHA1DigestMachO(path);
 	}
@@ -273,7 +282,8 @@
 		// remove the file anyway
 		res = 0;
 	} else if (res != 0) {
-		fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, m_path, strerror(errno), errno);
+		fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+				__FILE__, __LINE__, m_path, strerror(errno), errno);
 	}
 	return res;
 }
@@ -282,7 +292,9 @@
 	m_digest = new SHA1DigestSymlink(ent->fts_accpath);
 }
 
-Symlink::Symlink(uint64_t serial, Archive* archive, uint32_t info, const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) : File(serial, archive, info, path, mode, uid, gid, size, digest) {
+Symlink::Symlink(uint64_t serial, Archive* archive, uint32_t info, const char* path,
+				 mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) 
+: File(serial, archive, info, path, mode, uid, gid, size, digest) {
 	if (digest == NULL || serial == 0) {
 		m_digest = new SHA1DigestSymlink(path);
 	}
@@ -298,7 +310,8 @@
 		// remove the file anyway
 		res = 0;
 	} else if (res == -1) {
-		fprintf(stderr, "%s:%d: %s (%d)\n", __FILE__, __LINE__, strerror(errno), errno);
+		fprintf(stderr, "%s:%d: %s (%d)\n", 
+				__FILE__, __LINE__, strerror(errno), errno);
 	}
 	return res;
 }
@@ -312,7 +325,8 @@
 	gid_t gid = this->gid();
 	IF_DEBUG("[install] lchown(%d, %d)\n", uid, gid);
 	if (res == 0) res = lchown(path, uid, gid);
-	if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, path, strerror(errno), errno);
+	if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+						   __FILE__, __LINE__, path, strerror(errno), errno);
 	//IF_DEBUG("[install] lchmod(%o)\n", mode);
 	//if (res == 0) res = lchmod(path, mode);
 	free(path);
@@ -321,7 +335,10 @@
 
 Directory::Directory(Archive* archive, FTSENT* ent) : File(archive, ent) {}
 
-Directory::Directory(uint64_t serial, Archive* archive, uint32_t info, const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) : File(serial, archive, info, path, mode, uid, gid, size, digest) {};
+Directory::Directory(uint64_t serial, Archive* archive, uint32_t info, 
+					 const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size,
+					 Digest* digest) 
+: File(serial, archive, info, path, mode, uid, gid, size, digest) {};
 
 int Directory::install(const char* prefix, const char* dest) {
 	// We create a new directory instead of renaming the
@@ -346,28 +363,35 @@
 			// this is expected in normal cases, so no need to force
 			IF_DEBUG("[install] directory already exists, setting mode \n");
 			res = chmod(dstpath, mode);
-			if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+			if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+								   __FILE__, __LINE__, dstpath, strerror(errno), 
+								   errno);
 		} else if (force) {
 			// this could be bad, so require the force option
-			IF_DEBUG("[install] original node is a file, we need to replace with a directory \n");
+			IF_DEBUG("[install] original node is a file, we need to replace " \
+					 "with a directory \n");
 			IF_DEBUG("[install] unlink(%s)\n", dstpath);
 			res = unlink(dstpath);
 			IF_DEBUG("[install] mkdir(%s, %04o)\n", dstpath, mode);
 			res = mkdir(dstpath, mode);
-			if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+			if (res == -1) fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+								   __FILE__, __LINE__, dstpath, strerror(errno), 
+								   errno);
 		}
 	} else if (force && res == -1 && errno == ENOTDIR) {
 		// some part of destination path is not a directory
 		IF_DEBUG("[install] Directory::install ENOTDIR \n");
 	} else if (res == -1) {
-		fprintf(stderr, "ERROR: %s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+		fprintf(stderr, "ERROR: %s:%d: %s: %s (%d)\n", 
+				__FILE__, __LINE__, dstpath, strerror(errno), errno);
 		fprintf(stderr, "ERROR: unable to create %s \n", dstpath);
 	}
 	
 	if (res == 0) {
 		res = chown(dstpath, uid, gid);
 		if (res != 0) {
-			fprintf(stderr, "ERROR: %s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
+			fprintf(stderr, "ERROR: %s:%d: %s: %s (%d)\n", 
+					__FILE__, __LINE__, dstpath, strerror(errno), errno);
 			fprintf(stderr, "ERROR: unable to change ownership of %s \n", dstpath);
 		}
 	}
@@ -388,31 +412,38 @@
 	} else if (res == -1 && errno == ENOTEMPTY) {
 	        res = remove_directory(path);
 	} else if (res == -1) {
-		fprintf(stderr, "%s:%d: %s (%d)\n", __FILE__, __LINE__, strerror(errno), errno);
+		fprintf(stderr, "%s:%d: %s (%d)\n", 
+				__FILE__, __LINE__, strerror(errno), errno);
 	}
 	return res;
 }
 
 
-File* FileFactory(uint64_t serial, Archive* archive, uint32_t info, const char* path, mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) {
+File* FileFactory(uint64_t serial, Archive* archive, uint32_t info, const char* path, 
+				  mode_t mode, uid_t uid, gid_t gid, off_t size, Digest* digest) {
 	File* file = NULL;
 	switch (mode & S_IFMT) {
 		case S_IFDIR:
-			file = new Directory(serial, archive, info, path, mode, uid, gid, size, digest);
+			file = new Directory(serial, archive, info, path, mode, uid, gid, size, 
+								 digest);
 			break;
 		case S_IFREG:
-			file = new Regular(serial, archive, info, path, mode, uid, gid, size, digest);
+			file = new Regular(serial, archive, info, path, mode, uid, gid, size, 
+							   digest);
 			break;
 		case S_IFLNK:
-			file = new Symlink(serial, archive, info, path, mode, uid, gid, size, digest);
+			file = new Symlink(serial, archive, info, path, mode, uid, gid, size, 
+							   digest);
 			break;
 		case 0:
 			if (INFO_TEST(info, FILE_INFO_NO_ENTRY)) {
-				file = new NoEntry(serial, archive, info, path, mode, uid, gid, size, digest);
+				file = new NoEntry(serial, archive, info, path, mode, uid, gid, size, 
+								   digest);
 				break;
 			}
 		default:
-			fprintf(stderr, "%s:%d: unexpected file type %o\n", __FILE__, __LINE__, mode & S_IFMT);
+			fprintf(stderr, "%s:%d: unexpected file type %o\n", 
+					__FILE__, __LINE__, mode & S_IFMT);
 			break;
 	}
 	return file;
@@ -435,10 +466,12 @@
 			break;
 		case FTS_DEFAULT:
 		case FTS_DNR:
-			fprintf(stderr, "%s:%d: could not read directory.  Run as root.\n", __FILE__, __LINE__);
+			fprintf(stderr, "%s:%d: could not read directory.  Run as root.\n",
+					__FILE__, __LINE__);
 			break;
 		default:
-			fprintf(stderr, "%s:%d: unexpected fts_info type %d\n", __FILE__, __LINE__, ent->fts_info);
+			fprintf(stderr, "%s:%d: unexpected fts_info type %d\n", 
+					__FILE__, __LINE__, ent->fts_info);
 			break;
 	}
 	return file;
@@ -462,11 +495,13 @@
 		return NULL;
 	}	
 	if (res == -1) {
-		fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, path, strerror(errno), errno);
+		fprintf(stderr, "%s:%d: %s: %s (%d)\n", 
+				__FILE__, __LINE__, path, strerror(errno), errno);
 		fprintf(stderr, "ERROR: unable to stat %s \n", path);
 		return NULL;
 	}
 	
-	file = FileFactory(0, NULL, FILE_INFO_NONE, path, sb.st_mode, sb.st_uid, sb.st_gid, sb.st_size, NULL);
+	file = FileFactory(0, NULL, FILE_INFO_NONE, path, sb.st_mode, sb.st_uid, 
+					   sb.st_gid, sb.st_size, NULL);
 	return file;
 }

Modified: trunk/darwinup/File.h
===================================================================
--- trunk/darwinup/File.h	2010-09-16 22:51:34 UTC (rev 880)
+++ trunk/darwinup/File.h	2010-09-18 00:28:31 UTC (rev 881)
@@ -39,6 +39,28 @@
 #include <sys/stat.h>
 #include <fts.h>
 
+#define FILE_OBJ_CHANGE_ERROR \
+"-----------------------------------------------------------------------------\n" \
+"Potentially unsafe mismatch between the root and destination:  \n\n" \
+"%s\n\n" \
+"You seem to be trying to install a %s over a %s.                             \n" \
+"Darwinup will not install this root by default since it could cause damage   \n" \
+"to your system. You can use the force (-f) option to allow darwinup to       \n" \
+"attempt the install anyway.                                                  \n" \
+"-----------------------------------------------------------------------------\n"
+
+#define FILE_TYPE_STRING(type) \
+(type == S_IFIFO ? "named pipe" : \
+(type == S_IFCHR ? "character special" : \
+(type == S_IFDIR ? "directory" : \
+(type == S_IFBLK ? "block special" : \
+(type == S_IFREG ? "file" : \
+(type == S_IFLNK ? "symbolic link" : \
+(type == S_IFSOCK ? "socket" : \
+(type == S_IFWHT ? "whiteout" : \
+"unknown"))))))))
+
+
 enum file_starseded_t {
 	FILE_SUPERSEDED,
 	FILE_PRECEDED

Modified: trunk/darwinup/Utils.cpp
===================================================================
--- trunk/darwinup/Utils.cpp	2010-09-16 22:51:34 UTC (rev 880)
+++ trunk/darwinup/Utils.cpp	2010-09-18 00:28:31 UTC (rev 881)
@@ -104,7 +104,7 @@
 
 int is_directory(const char* path) {
 	struct stat sb;
-	int res = stat(path, &sb);
+	int res = lstat(path, &sb);
 	return (res == 0 && S_ISDIR(sb.st_mode));
 }
 

Modified: trunk/darwinup/main.cpp
===================================================================
--- trunk/darwinup/main.cpp	2010-09-16 22:51:34 UTC (rev 880)
+++ trunk/darwinup/main.cpp	2010-09-18 00:28:31 UTC (rev 881)
@@ -183,14 +183,14 @@
 	// list handles args optional and in special ways
 	if (strcmp(argv[0], "list") == 0) {
 		res = depot->initialize(false);
-		if (res == -2) {
+		if (res == DEPOT_NOT_EXIST) {
 			// we are not asking to write, 
 			// but no depot exists yet either,
 			// so print an empty list
 			depot->archive_header();
 			exit(0);
 		}
-		if (res == -3) {
+		if (res == DEPOT_PERM_DENIED) {
 			// permission denied when trying to read
 			// the depot
 			fprintf(stderr, "Permission denied when trying to read the database.\n");
@@ -229,6 +229,10 @@
 				res = depot->process_archive(argv[0], argv[i]);
 			} else if (strcmp(argv[0], "uninstall") == 0) {
 				if (i==1 && depot->initialize(true)) exit(15);
+				// uninstall is always in force mode so it can
+				// uninstall archives that were installed under
+				// force mode
+				force = 1;
 				res = depot->process_archive(argv[0], argv[i]);
 			} else if (strcmp(argv[0], "verify") == 0) {
 				if (i==1 && depot->initialize(true)) exit(16);

Modified: trunk/testing/darwinup/dest.tar.gz
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_dir_file.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_dir_file.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_dir_link.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_dir_link.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_file_dir.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_file_dir.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_file_link.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_file_link.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_flink_dir.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_flink_dir.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_flink_file.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_flink_file.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_link_dir.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_link_dir.tar.gz)
===================================================================
(Binary files differ)

Copied: trunk/testing/darwinup/rep_link_file.tar.gz (from rev 880, branches/PR-8416637/testing/darwinup/rep_link_file.tar.gz)
===================================================================
(Binary files differ)

Deleted: trunk/testing/darwinup/root4.tar.gz
===================================================================
(Binary files differ)

Modified: trunk/testing/darwinup/run-tests.sh
===================================================================
--- trunk/testing/darwinup/run-tests.sh	2010-09-16 22:51:34 UTC (rev 880)
+++ trunk/testing/darwinup/run-tests.sh	2010-09-18 00:28:31 UTC (rev 881)
@@ -20,6 +20,20 @@
 
 ROOTS="root root2 root3"
 
+
+function is_file {
+	test -f $1 -a ! -L $1
+}
+
+function is_dir {
+	test -d $1 -a ! -L $1
+}
+
+function is_link {
+	test -L $1;
+}
+
+
 echo "INFO: Cleaning up testing area ..."
 rm -rf $PREFIX
 mkdir -p $PREFIX
@@ -32,11 +46,17 @@
 	tar zxvf $R.tar.gz -C $PREFIX
 done;
 
-for R in root4 root5 root6 root7 symlinks symlink_update;
+for R in root5 root6 root7 symlinks symlink_update;
 do
 	tar zxvf $R.tar.gz -C $PREFIX
 done;
 
+for R in rep_dir_file rep_dir_link rep_file_dir rep_file_link \
+		 rep_link_dir rep_link_file rep_flink_dir rep_flink_file;
+do
+	tar zxvf $R.tar.gz -C $PREFIX
+done;
+
 for R in 300dirs.tbz2 300files.tbz2 deep-rollback.cpgz deep-rollback-2.xar extension.tar.bz2;
 do
 	cp $R $PREFIX/
@@ -277,24 +297,24 @@
 $DARWINUP install $PREFIX/root
 $DARWINUP install $PREFIX/root6
 $DARWINUP rename root "RENAME1"
-C=$($DARWINUP list | grep "RENAME1" | wc -l | xargs)
+C=$($DARWINUP list | grep "RENAME1" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "1" 
 $DARWINUP rename oldest "RENAME2"
-C=$($DARWINUP list | grep "RENAME2" | wc -l | xargs)
+C=$($DARWINUP list | grep "RENAME2" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "1" 
 $DARWINUP uninstall "RENAME1"
-C=$($DARWINUP list | grep "RENAME1" | wc -l | xargs)
+C=$($DARWINUP list | grep "RENAME1" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "0" 
-C=$($DARWINUP files "RENAME2" | wc -l | xargs)
+C=$($DARWINUP files "RENAME2" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "17" 
-C=$($DARWINUP verify "RENAME2" | wc -l | xargs)
+C=$($DARWINUP verify "RENAME2" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "17"
 $DARWINUP rename root6 RENAME3 RENAME3 RENAME4 RENAME4 RENAME5 RENAME5 RENAME6
-C=$($DARWINUP list | grep "root6" | wc -l | xargs)
+C=$($DARWINUP list | grep "root6" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "0" 
-C=$($DARWINUP list | grep "RENAME6" | wc -l | xargs)
+C=$($DARWINUP list | grep "RENAME6" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "1" 
-C=$($DARWINUP files "RENAME6" | wc -l | xargs)
+C=$($DARWINUP files "RENAME6" | grep -Ev '^Found' | wc -l | xargs)
 test "$C" == "8"
 $DARWINUP uninstall all
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
@@ -313,16 +333,142 @@
 $DIFF $ORIG $DEST 2>&1
 
 
+echo "========== TEST: Forcing object change: file to directory ==========" 
+is_file $DEST/rep_file
+$DARWINUP -f install $PREFIX/rep_file_dir
+is_dir $DEST/rep_file
+$DARWINUP uninstall newest
+is_file $DEST/rep_file
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+echo "========== TEST: Forcing object change: file to symlink ==========" 
+is_file $DEST/rep_file
+$DARWINUP -f install $PREFIX/rep_file_link
+is_link $DEST/rep_file
+$DARWINUP uninstall newest
+is_file $DEST/rep_file
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+echo "========== TEST: Forcing object change: directory to file ==========" 
+is_dir $DEST/rep_dir
+$DARWINUP -f install $PREFIX/rep_dir_file
+is_file $DEST/rep_dir
+$DARWINUP uninstall newest
+is_dir $DEST/rep_dir
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+echo "========== TEST: Forcing object change: directory to symlink ==========" 
+is_dir $DEST/rep_dir
+$DARWINUP -f install $PREFIX/rep_dir_link
+is_link $DEST/rep_dir
+$DARWINUP uninstall newest
+is_dir $DEST/rep_dir
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+echo "========== TEST: Forcing object change: symlink->dir to file ==========" 
+is_link $DEST/rep_link
+$DARWINUP -f install $PREFIX/rep_link_file
+is_file $DEST/rep_link
+$DARWINUP uninstall newest
+is_link $DEST/rep_link
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+echo "========== TEST: Forcing object change: symlink->dir to directory ==========" 
+is_link $DEST/rep_link
+$DARWINUP -f install $PREFIX/rep_link_dir
+is_dir $DEST/rep_link
+$DARWINUP uninstall newest
+is_link $DEST/rep_link
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+echo "========== TEST: Forcing object change: symlink->file to file ==========" 
+is_link $DEST/rep_flink
+$DARWINUP -f install $PREFIX/rep_flink_file
+is_file $DEST/rep_flink
+$DARWINUP uninstall newest
+is_link $DEST/rep_flink
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+echo "========== TEST: Forcing object change: symlink->file to directory ==========" 
+is_link $DEST/rep_flink
+$DARWINUP -f install $PREFIX/rep_flink_dir
+is_dir $DEST/rep_flink
+$DARWINUP uninstall newest
+is_link $DEST/rep_flink
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+
+
+
 #
 # The following are expected failures
 #
+echo "========== Expected Failures =========="
 set +e
-echo "========== TEST: Trying a root that will fail due to object change =========="
-$DARWINUP install $PREFIX/root4
-if [ $? -ne 1 ]; then exit 1; fi
+
+echo "========== TEST: Try replacing File with Directory =========="
+$DARWINUP install $PREFIX/rep_file_dir
+if [ $? -ne 255 ]; then exit 1; fi
 echo "DIFF: diffing original test files to dest (should be no diffs) ..."
 $DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
 
+echo "========== TEST: Try replacing File with Symlink =========="
+$DARWINUP install $PREFIX/rep_file_link
+if [ $? -ne 255 ]; then exit 1; fi
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
+
+echo "========== TEST: Try replacing Directory with Symlink =========="
+$DARWINUP install $PREFIX/rep_dir_link
+if [ $? -ne 255 ]; then exit 1; fi
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
+
+echo "========== TEST: Try replacing Directory with File =========="
+$DARWINUP install $PREFIX/rep_dir_file
+if [ $? -ne 255 ]; then exit 1; fi
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
+
+echo "========== TEST: Try replacing Symlink to directory with Directory =========="
+$DARWINUP install $PREFIX/rep_link_dir
+if [ $? -ne 255 ]; then exit 1; fi
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
+
+echo "========== TEST: Try replacing Symlink to directory with File =========="
+$DARWINUP install $PREFIX/rep_link_file
+if [ $? -ne 255 ]; then exit 1; fi
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
+
+echo "========== TEST: Try replacing Symlink to file with Directory =========="
+$DARWINUP install $PREFIX/rep_flink_dir
+if [ $? -ne 255 ]; then exit 1; fi
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
+
+echo "========== TEST: Try replacing Symlink to file with File =========="
+$DARWINUP install $PREFIX/rep_flink_file
+if [ $? -ne 255 ]; then exit 1; fi
+echo "DIFF: diffing original test files to dest (should be no diffs) ..."
+$DIFF $ORIG $DEST 2>&1
+if [ $? -ne 0 ]; then exit 1; fi
+
 popd >> /dev/null
 echo "INFO: Done testing!"
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20100917/cfbc5c17/attachment-0001.html>


More information about the darwinbuild-changes mailing list