[darwinbuild-changes] [491] trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Mar 20 15:19:50 PDT 2009


Revision: 491
          http://trac.macosforge.org/projects/darwinbuild/changeset/491
Author:   wsiegrist at apple.com
Date:     2009-03-20 15:19:50 -0700 (Fri, 20 Mar 2009)
Log Message:
-----------
Merging PR-6688645

Modified Paths:
--------------
    trunk/darwinup/Archive.cpp
    trunk/darwinup/Depot.cpp
    trunk/darwinup/Depot.h
    trunk/darwinup/File.cpp
    trunk/darwinup/File.h
    trunk/darwinup/Utils.cpp
    trunk/darwinup/Utils.h
    trunk/darwinup/main.cpp

Property Changed:
----------------
    trunk/
    trunk/darwinbuild/darwinbuild.in
    trunk/darwinbuild/darwinmaster.sh.in
    trunk/darwinbuild/installXcode.in
    trunk/darwinbuild/packageRoots.sh.in
    trunk/darwinbuild/thinPackages.sh.in


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
/trunk:432-434
   + /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-6688645:479-490
/trunk:432-434


Property changes on: trunk/darwinbuild/darwinbuild.in
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/PR-4841388/darwinbuild/darwinbuild:399-419
/branches/PR-6358021/darwinbuild/darwinbuild:442-443
/branches/PR-6392966/darwinbuild/darwinbuild:423-427
/branches/PR-6398060/darwinbuild/darwinbuild:433-434
/branches/PR-6493844/darwinbuild/darwinbuild.in:460-461
/branches/PR-6497694/darwinbuild/darwinbuild.in:466-468,471
/trunk/darwinbuild/darwinbuild:432-434
   + /branches/PR-4841388/darwinbuild/darwinbuild:399-419
/branches/PR-6358021/darwinbuild/darwinbuild:442-443
/branches/PR-6392966/darwinbuild/darwinbuild:423-427
/branches/PR-6398060/darwinbuild/darwinbuild:433-434
/branches/PR-6493844/darwinbuild/darwinbuild.in:460-461
/branches/PR-6497694/darwinbuild/darwinbuild.in:466-468,471
/branches/PR-6688645/darwinbuild/darwinbuild.in:479-490
/trunk/darwinbuild/darwinbuild:432-434


Property changes on: trunk/darwinbuild/darwinmaster.sh.in
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/PR-4841388/darwinbuild/darwinmaster.sh:399-419
/branches/PR-6358021/darwinbuild/darwinmaster.sh:442-443
/branches/PR-6392966/darwinbuild/darwinmaster.sh:423-427
/branches/PR-6398060/darwinbuild/darwinmaster.sh:433-434
/branches/PR-6493844/darwinbuild/darwinmaster.sh.in:460-461
/branches/PR-6497694/darwinbuild/darwinmaster.sh.in:466-468,471
/trunk/darwinbuild/darwinmaster.sh:432-434
   + /branches/PR-4841388/darwinbuild/darwinmaster.sh:399-419
/branches/PR-6358021/darwinbuild/darwinmaster.sh:442-443
/branches/PR-6392966/darwinbuild/darwinmaster.sh:423-427
/branches/PR-6398060/darwinbuild/darwinmaster.sh:433-434
/branches/PR-6493844/darwinbuild/darwinmaster.sh.in:460-461
/branches/PR-6497694/darwinbuild/darwinmaster.sh.in:466-468,471
/branches/PR-6688645/darwinbuild/darwinmaster.sh.in:479-490
/trunk/darwinbuild/darwinmaster.sh:432-434


Property changes on: trunk/darwinbuild/installXcode.in
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/PR-4841388/darwinbuild/installXcode:399-419
/branches/PR-6358021/darwinbuild/installXcode:442-443
/branches/PR-6392966/darwinbuild/installXcode:423-427
/branches/PR-6398060/darwinbuild/installXcode:433-434
/branches/PR-6493844/darwinbuild/installXcode.in:460-461
/branches/PR-6497694/darwinbuild/installXcode.in:466-468,471
/trunk/darwinbuild/installXcode:432-434
   + /branches/PR-4841388/darwinbuild/installXcode:399-419
/branches/PR-6358021/darwinbuild/installXcode:442-443
/branches/PR-6392966/darwinbuild/installXcode:423-427
/branches/PR-6398060/darwinbuild/installXcode:433-434
/branches/PR-6493844/darwinbuild/installXcode.in:460-461
/branches/PR-6497694/darwinbuild/installXcode.in:466-468,471
/branches/PR-6688645/darwinbuild/installXcode.in:479-490
/trunk/darwinbuild/installXcode:432-434


Property changes on: trunk/darwinbuild/packageRoots.sh.in
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/PR-4841388/darwinbuild/packageRoots.sh:399-419
/branches/PR-6358021/darwinbuild/packageRoots.sh:442-443
/branches/PR-6392966/darwinbuild/packageRoots.sh:423-427
/branches/PR-6398060/darwinbuild/packageRoots.sh:433-434
/branches/PR-6493844/darwinbuild/packageRoots.sh.in:460-461
/branches/PR-6497694/darwinbuild/packageRoots.sh.in:466-468,471
/trunk/darwinbuild/packageRoots.sh:432-434
   + /branches/PR-4841388/darwinbuild/packageRoots.sh:399-419
/branches/PR-6358021/darwinbuild/packageRoots.sh:442-443
/branches/PR-6392966/darwinbuild/packageRoots.sh:423-427
/branches/PR-6398060/darwinbuild/packageRoots.sh:433-434
/branches/PR-6493844/darwinbuild/packageRoots.sh.in:460-461
/branches/PR-6497694/darwinbuild/packageRoots.sh.in:466-468,471
/branches/PR-6688645/darwinbuild/packageRoots.sh.in:479-490
/trunk/darwinbuild/packageRoots.sh:432-434


Property changes on: trunk/darwinbuild/thinPackages.sh.in
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/PR-4841388/darwinbuild/thinPackages.sh:399-419
/branches/PR-6358021/darwinbuild/thinPackages.sh:442-443
/branches/PR-6392966/darwinbuild/thinPackages.sh:423-427
/branches/PR-6398060/darwinbuild/thinPackages.sh:433-434
/branches/PR-6493844/darwinbuild/thinPackages.sh.in:460-461
/branches/PR-6497694/darwinbuild/thinPackages.sh.in:466-468,471
/trunk/darwinbuild/thinPackages.sh:432-434
   + /branches/PR-4841388/darwinbuild/thinPackages.sh:399-419
/branches/PR-6358021/darwinbuild/thinPackages.sh:442-443
/branches/PR-6392966/darwinbuild/thinPackages.sh:423-427
/branches/PR-6398060/darwinbuild/thinPackages.sh:433-434
/branches/PR-6493844/darwinbuild/thinPackages.sh.in:460-461
/branches/PR-6497694/darwinbuild/thinPackages.sh.in:466-468,471
/branches/PR-6688645/darwinbuild/thinPackages.sh.in:479-490
/trunk/darwinbuild/thinPackages.sh:432-434

Modified: trunk/darwinup/Archive.cpp
===================================================================
--- trunk/darwinup/Archive.cpp	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/Archive.cpp	2009-03-20 22:19:50 UTC (rev 491)
@@ -80,6 +80,7 @@
 char* Archive::create_directory(const char* prefix) {
 	int res = 0;
 	char* path = this->directory_name(prefix);
+	IF_DEBUG("creating directory: %s\n", path);
 	if (path && res == 0) res = mkdir(path, 0777);
 	if (res != 0) {
 		fprintf(stderr, "%s:%d: could not create directory: %s: %s (%d)\n", __FILE__, __LINE__, path, strerror(errno), errno);
@@ -96,6 +97,7 @@
 	char uuidstr[37];
 	uuid_unparse_upper(m_uuid, uuidstr);
 	asprintf(&tarpath, "%s/%s.tar.bz2", prefix, uuidstr);
+	IF_DEBUG("compacting %s/%s to %s\n", prefix, uuidstr, tarpath);
 	if (tarpath) {
 		const char* args[] = {
 			"/usr/bin/tar",
@@ -119,6 +121,7 @@
 	char uuidstr[37];
 	uuid_unparse_upper(m_uuid, uuidstr);
 	asprintf(&tarpath, "%s/%s.tar.bz2", prefix, uuidstr);
+	IF_DEBUG("expanding %s to %s\n", tarpath, prefix);
 	if (tarpath) {
 		const char* args[] = {
 			"/usr/bin/tar",
@@ -223,4 +226,4 @@
 		fprintf(stderr, "Error: unknown archive type: %s\n", path);
 	}
 	return archive;
-}
\ No newline at end of file
+}

Modified: trunk/darwinup/Depot.cpp
===================================================================
--- trunk/darwinup/Depot.cpp	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/Depot.cpp	2009-03-20 22:19:50 UTC (rev 491)
@@ -42,28 +42,36 @@
 #include <sqlite3.h>
 
 Depot::Depot() {
+        m_prefix = NULL;
 	m_depot_path = NULL;
 	m_database_path = NULL;
 	m_archives_path = NULL;
 	m_db = NULL;
 	m_lock_fd = -1;
+	m_is_locked = 0;
 }
 
 Depot::Depot(const char* prefix) {
 	m_lock_fd = -1;
+	m_is_locked = 0;
+	asprintf(&m_prefix, "%s", prefix);
+	join_path(&m_depot_path, m_prefix, "/.DarwinDepot");
+	join_path(&m_database_path, m_depot_path, "/Database-V100");
+	join_path(&m_archives_path, m_depot_path, "/Archives");
 
-	asprintf(&m_depot_path,    "%s/.DarwinDepot",  prefix);
-	asprintf(&m_database_path, "%s/Database-V100", m_depot_path);
-	asprintf(&m_archives_path, "%s/Archives",      m_depot_path);
-
 	mkdir(m_depot_path,    m_depot_mode);
 	mkdir(m_archives_path, m_depot_mode);
 
-	(void)this->lock(LOCK_SH);
+	int res = 0;
 
+	res = this->lock(LOCK_SH);
+	if (res == 0) {
+	        m_is_locked = 1;
+	}
+
 	int exists = is_regular_file(m_database_path);
 
-	int res = sqlite3_open(m_database_path, &m_db);
+	res = sqlite3_open(m_database_path, &m_db);
 	if (res != 0) {
 		sqlite3_close(m_db);
 		m_db = NULL;
@@ -81,12 +89,14 @@
 Depot::~Depot() {
 	if (m_lock_fd != -1)	this->unlock();
 	if (m_db)		sqlite3_close(m_db);
+        if (m_prefix)           free(m_prefix);
 	if (m_depot_path)	free(m_depot_path);
 	if (m_database_path)	free(m_database_path);
 	if (m_archives_path)	free(m_archives_path);
 }
 
 const char*	Depot::archives_path()		{ return m_archives_path; }
+const char*     Depot::prefix()                 { return m_prefix; }
 
 // Unserialize an archive from the database.
 // Find the archive by UUID.
@@ -266,6 +276,8 @@
 
 	const char* path_argv[] = { path, NULL };
 	
+	IF_DEBUG("[analyze] analyzing path: %s\n", path);
+
 	FTS* fts = fts_open((char**)path_argv, FTS_PHYSICAL | FTS_COMFOLLOW | FTS_XDEV, fts_compare);
 	FTSENT* ent = fts_read(fts); // throw away the entry for path itself
 	while (res != -1 && (ent = fts_read(fts)) != NULL) {
@@ -279,7 +291,10 @@
 			// the file we last installed in this location (preceding),
 			// and the file that actually exists in this location (actual).
 		
-			File* actual = FileFactory(file->path());
+			char* actpath;
+			join_path(&actpath, this->prefix(), file->path());
+			File* actual = FileFactory(actpath);
+
 			File* preceding = this->file_preceded_by(file);
 			
 			if (actual == NULL) {
@@ -345,16 +360,28 @@
 				char path[PATH_MAX];
 				char* backup_dirpath;
 
-				size_t len = strlcpy(path, actual->path(), sizeof(path));
+				// we need the path minus our destination path for moving to the archive
+				char *relpath = strstr(actual->path(), m_prefix);
+				if (relpath) {
+				        // advance to just past the destination path
+				        relpath += strlen(m_prefix);
+				} 
+
+				size_t len = strlcpy(path, (relpath ? relpath : actual->path()), 
+						     sizeof(path));
 				assert(len <= sizeof(path));
 				
+
 				const char* dir = dirname(path);
 				assert(dir != NULL);
 				
+				char *uuidpath;
 				char uuidstr[37];
 				uuid_unparse_upper(rollback->uuid(), uuidstr);
 				
-				asprintf(&backup_dirpath, "%s/%s/%s", m_archives_path, uuidstr, dir);
+				asprintf(&uuidpath, "%s/%s", m_archives_path, uuidstr);
+				assert(uuidpath != NULL);
+				join_path(&backup_dirpath, uuidpath, dir);
 				assert(backup_dirpath != NULL);
 				
 				res = mkdir_p(backup_dirpath);
@@ -363,6 +390,8 @@
 				} else {
 					res = 0;
 				}
+				free(backup_dirpath);
+				free(uuidpath);
 			}
 			
 			
@@ -379,6 +408,7 @@
 			assert(res == 0);
 			if (preceding && preceding != actual) delete preceding;
 			if (actual) delete actual;
+			free(actpath);
 			delete file;
 		}
 	}
@@ -415,10 +445,18 @@
 	int res = 0;
 
 	if (INFO_TEST(file->info(), FILE_INFO_ROLLBACK_DATA)) {
-		char* dstpath;
+	        char *dstpath, *relpath, *uuidpath;
 		char uuidstr[37];
-		uuid_unparse_upper(context->archive->uuid(), uuidstr);
-		asprintf(&dstpath, "%s/%s/%s", context->depot->m_archives_path, uuidstr, file->path());
+		// we need the path minus our destination path for moving to the archive
+		relpath = strstr(file->path(), context->depot->m_prefix);
+		if (relpath) {
+		        // advance to just past the destination path
+		        relpath += strlen(context->depot->m_prefix);
+		} 
+		uuid_unparse_upper(context->archive->uuid(), uuidstr);		
+		asprintf(&uuidpath, "%s/%s", context->depot->m_archives_path, uuidstr);
+		assert(uuidpath != NULL);
+		join_path(&dstpath, uuidpath, (relpath ? relpath : file->path()));
 		assert(dstpath != NULL);
 
 		++context->files_modified;
@@ -440,21 +478,22 @@
 					  "/usr/lib/libgcc_s"};
 		size_t numfiles = sizeof(tarfiles)/sizeof(*tarfiles);
 		for (i = 0; i < numfiles; i++) {
-		  if (strncmp(tarfiles[i], file->path(), strlen(tarfiles[i])) == 0) {
-		    docopy = true;
-		    break;
-		  }
+		        if (strncmp(tarfiles[i], file->path(), strlen(tarfiles[i])) == 0) {
+			        docopy = true;
+				break;
+			}
 		}
 		if (docopy) {
-		  IF_DEBUG("[backup] copyfile(%s, %s)\n", file->path(), dstpath);
-		  res = copyfile(file->path(), dstpath, NULL, COPYFILE_ALL);
+		        IF_DEBUG("[backup] copyfile(%s, %s)\n", file->path(), dstpath);
+			res = copyfile(file->path(), dstpath, NULL, COPYFILE_ALL);
 		} else {
-		  IF_DEBUG("[backup] rename(%s, %s)\n", file->path(), dstpath);
-		  res = rename(file->path(), dstpath);
+		        IF_DEBUG("[backup] rename(%s, %s)\n", file->path(), dstpath);
+			res = rename(file->path(), dstpath);
 		}
 
 		if (res != 0) fprintf(stderr, "%s:%d: backup failed: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
 		free(dstpath);
+		free(uuidpath);
 	}
 	return res;
 }
@@ -467,9 +506,9 @@
 	if (INFO_TEST(file->info(), FILE_INFO_INSTALL_DATA)) {
 		++context->files_modified;
 
-		res = file->install(context->depot->m_archives_path);
+		res = file->install(context->depot->m_archives_path, context->depot->m_prefix);
 	} else {
-		res = file->install_info();
+		res = file->install_info(context->depot->m_prefix);
 	}
 	if (res != 0) fprintf(stderr, "%s:%d: install failed: %s: %s (%d)\n", __FILE__, __LINE__, file->path(), strerror(errno), errno);
 	return res;
@@ -485,8 +524,8 @@
 
 	// Check the consistency of the database before proceeding with the installation
 	// If this fails, abort the installation.
-//	res = this->check_consistency();
-//	if (res != 0) return res;
+	// res = this->check_consistency();
+	// if (res != 0) return res;
 
 	res = this->lock(LOCK_EX);
 	if (res != 0) return res;
@@ -626,7 +665,10 @@
 		return 0;
 	}
 	
-	File* actual = FileFactory(file->path());
+	char* actpath;
+	join_path(&actpath, context->depot->m_prefix, file->path());
+	IF_DEBUG("[uninstall] actual path is %s\n", actpath);
+	File* actual = FileFactory(actpath);
 	uint32_t flags = File::compare(file, actual);
 		
 	if (actual != NULL && flags != FILE_INFO_IDENTICAL) {
@@ -649,11 +691,11 @@
 				if (INFO_TEST(flags, FILE_INFO_DATA_DIFFERS)) {
 					state = 'U';
 					IF_DEBUG("[uninstall]    restoring\n");
-					if (res == 0) res = preceding->install(context->depot->m_archives_path);
+					if (res == 0) res = preceding->install(context->depot->m_archives_path, context->depot->m_prefix);
 				} else if (INFO_TEST(flags, FILE_INFO_MODE_DIFFERS) ||
 					   INFO_TEST(flags, FILE_INFO_GID_DIFFERS) ||
 					   INFO_TEST(flags, FILE_INFO_UID_DIFFERS)) {
-					if (res == 0) res = preceding->install_info();
+					if (res == 0) res = preceding->install_info(context->depot->m_prefix);
 				} else {
 					IF_DEBUG("[uninstall]    no changes; leaving in place\n");
 				}
@@ -673,6 +715,8 @@
 	fprintf(stderr, "%c %s\n", state, file->path());
 
 	if (res != 0) fprintf(stderr, "%s:%d: uninstall failed: %s\n", __FILE__, __LINE__, file->path());
+
+	free(actpath);
 	return res;
 }
 
@@ -963,6 +1007,8 @@
 	return this->SQL("COMMIT TRANSACTION");
 }
 
+int Depot::is_locked() { return m_is_locked; }
+
 int Depot::lock(int operation) {
 	int res = 0;
 	if (m_lock_fd == -1) {

Modified: trunk/darwinup/Depot.h
===================================================================
--- trunk/darwinup/Depot.h	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/Depot.h	2009-03-20 22:19:50 UTC (rev 491)
@@ -37,6 +37,7 @@
 	
 	virtual ~Depot();
 
+        const char*     prefix();
 	const char*	database_path();
 	const char*	archives_path();
 
@@ -70,6 +71,9 @@
 	int iterate_files(Archive* archive, FileIteratorFunc func, void* context);
 	int iterate_archives(ArchiveIteratorFunc func, void* context);
 
+        // test if the depot is currently locked 
+        int is_locked();
+
 	protected:
 
 	// Serialize access to the Depot via flock(2).
@@ -110,8 +114,10 @@
 
 	sqlite3*	m_db;
 	mode_t		m_depot_mode;
+        char*           m_prefix;
 	char*		m_depot_path;
 	char*		m_database_path;
 	char*		m_archives_path;
 	int		m_lock_fd;
+        int             m_is_locked;
 };

Modified: trunk/darwinup/File.cpp
===================================================================
--- trunk/darwinup/File.cpp	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/File.cpp	2009-03-20 22:19:50 UTC (rev 491)
@@ -132,20 +132,25 @@
 	free(dig);
 }
 
-int File::install(const char* prefix) {
+int File::install(const char* prefix, const char* dest) {
 	int res = 0;
 	Archive* archive = this->archive();
 	assert(archive != NULL);
 	char* dirpath = archive->directory_name(prefix);
+	IF_DEBUG("[install] dirpath is %s\n", dirpath);
 
 	char srcpath[PATH_MAX];
-	const char* dstpath = this->path();
+	const char* path = this->path();
+	char* dstpath;
+	join_path(&dstpath, dest, path);
+
 	if (dirpath) {
-		ssize_t len = snprintf(srcpath, sizeof(srcpath), "%s/%s", dirpath, dstpath);
+	        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, dstpath);
+			fprintf(stderr, "ERROR: [install] path too long: %s/%s\n", dirpath, path);
 			return -1;
 		}
+		IF_DEBUG("[install] about to rename %s to %s\n", srcpath, dstpath);
 		res = rename(srcpath, dstpath);
 		if (res == -1) {
 			if (errno == ENOENT) {
@@ -153,7 +158,7 @@
 				// expansion of the archive that contains it.
 				if (is_directory(dirpath) == 0) {
 					res = archive->expand_directory(prefix);
-					if (res == 0) res = this->install(prefix);
+					if (res == 0) res = this->install(prefix, dest);
 				} else {
 					// archive was already expanded, so
 					// the file is truly missing (worry).
@@ -176,6 +181,7 @@
 	} else {
 		res = -1;
 	}
+	free(dstpath);
 	return res;
 }
 
@@ -185,9 +191,10 @@
 	return -1;
 }
 
-int File::install_info() {
+int File::install_info(const char* dest) {
 	int res = 0;
-	const char* path = this->path();
+	char* path;
+	join_path(&path, dest, this->path());
 	uid_t uid = this->uid();
 	gid_t gid = this->gid();
 	mode_t mode = this->mode() & ALLPERMS;
@@ -197,6 +204,7 @@
 	IF_DEBUG("[install] chmod(%s, %04o)\n", path, mode);
 	if (res == 0) res = chmod(path, mode);
 
+	free(path);
 	return res;
 }
 
@@ -220,6 +228,7 @@
 	int res = 0;
 	const char* path = this->path();
 	res = unlink(path);
+	IF_DEBUG("[remove] unlink %s\n", path);
 	if (res == -1 && errno == ENOENT) {
 		// We can safely ignore this because we were going to
 		// remove the file anyway
@@ -244,6 +253,7 @@
 	int res = 0;
 	const char* path = this->path();
 	res = unlink(path);
+	IF_DEBUG("[remove] unlink %s", path);
 	if (res == -1 && errno == ENOENT) {
 		// We can safely ignore this because we were going to
 		// remove the file anyway
@@ -254,7 +264,7 @@
 	return res;
 }
 
-int Symlink::install_info() {
+int Symlink::install_info(const char* dest) {
 	int res = 0;
 	const char* path = this->path();
 	//mode_t mode = this->mode() & ALLPERMS;
@@ -271,13 +281,15 @@
 
 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) {
+int Directory::install(const char* prefix, const char* dest) {
 	// We create a new directory instead of renaming the
 	// existing one, since that would move the entire
 	// sub-tree, and lead to a lot of ENOENT errors.
 	int res = 0;
 	
-	const char* dstpath = this->path();
+	char* dstpath;
+	join_path(&dstpath, dest, this->path());
+	
 	mode_t mode = this->mode() & ALLPERMS;
 	uid_t uid = this->uid();
 	gid_t gid = this->gid();
@@ -287,6 +299,8 @@
 	if (res != 0) fprintf(stderr, "ERROR: %s:%d: %s: %s (%d)\n", __FILE__, __LINE__, dstpath, strerror(errno), errno);
 	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);
+
+	free(dstpath);
 	return res;
 }
 
@@ -294,12 +308,13 @@
 	int res = 0;
 	const char* path = this->path();
 	res = rmdir(path);
+	IF_DEBUG("[remove] rmdir %s\n", path);
 	if (res == -1 && errno == ENOENT) {
 		// We can safely ignore this because we were going to
 		// remove the directory anyway
 		res = 0;
 	} else if (res == -1 && errno == ENOTEMPTY) {
-		res = remove_directory(path);
+	        res = remove_directory(path);
 	} else if (res == -1) {
 		fprintf(stderr, "%s:%d: %s (%d)\n", __FILE__, __LINE__, strerror(errno), errno);
 	}

Modified: trunk/darwinup/File.h
===================================================================
--- trunk/darwinup/File.h	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/File.h	2009-03-20 22:19:50 UTC (rev 491)
@@ -130,17 +130,16 @@
 	//  Member functions
 	////
 
-	// Installs the file at the given prefix onto the
-	// root volume.  i.e., for regular files:
-	// rename(prefix + this->archive()->uuid() + this->path(), this->path());
-	virtual int install(const char* prefix);
+	// Installs the file from the archive into the prefix
+	// i.e., for regular files:
+	// rename(prefix + this->archive()->uuid() + this->path(), dest + this->path());
+        virtual int install(const char* prefix, const char* dest);
 	
-	// Sets the mode, uid, and gid of the file on the
-	// root volume.
+	// Sets the mode, uid, and gid of the file in the dest path
 	// XXX: rename as repair()?
-	virtual int install_info();
+	virtual int install_info(const char* dest);
 	
-	// Removes the file from the root volume.
+	// Removes the file
 	virtual int remove();
 
 	// Prints one line to the output stream indicating
@@ -192,7 +191,7 @@
 struct Symlink : File {
 	Symlink(Archive* archive, FTSENT* ent);
 	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);
-	virtual int install_info();
+	virtual int install_info(const char* dest);
 	virtual int remove();
 };
 
@@ -203,6 +202,6 @@
 struct Directory : File {
 	Directory(Archive* archive, FTSENT* ent);
 	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);
-	virtual int install(const char* prefix);
+	virtual int install(const char* prefix, const char* dest);
 	virtual int remove();
 };

Modified: trunk/darwinup/Utils.cpp
===================================================================
--- trunk/darwinup/Utils.cpp	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/Utils.cpp	2009-03-20 22:19:50 UTC (rev 491)
@@ -141,3 +141,38 @@
 	}
 	return res;
 }
+
+#define compact_slashes(buf, count) do { memmove(buf - count + 1, buf, strlen(buf) + 1); buf -= count; } while (0)
+
+/**
+ * join_path joins two paths and removes any extra slashes,
+ *  even internal ones in p1 or p2. It allocates memory
+ *  for the string and the caller is responsible for freeing.
+ */
+int join_path(char **out, const char *p1, const char *p2) {
+	asprintf(out, "%s/%s", p1, p2);
+	if (!out) {
+	        fprintf(stderr, "Error: join_path is out of memory!\n");
+		return -1;
+	}
+	
+	int slashes = 0;
+	char *cur = *out;
+	while (*cur != '\0') {
+	        if (*cur == '/') {
+		        slashes++;
+		} else {
+		        // we found the next non-slash
+		        if (slashes > 1) {
+			  compact_slashes(cur, slashes);
+			} 
+			slashes = 0;
+		}
+		cur++;
+	}
+	// see if we had extra slashes at the very end of p2
+	if (slashes > 1) {
+	        compact_slashes(cur, slashes);
+	} 
+	return 0;
+}

Modified: trunk/darwinup/Utils.h
===================================================================
--- trunk/darwinup/Utils.h	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/Utils.h	2009-03-20 22:19:50 UTC (rev 491)
@@ -42,6 +42,9 @@
 int has_suffix(const char* str, const char* sfx);
 int exec_with_args(const char** args);
 
+int join_path(char** out, const char* p1, const char* p2);
+int compact_slashes(char* orig, int slashes);
+
 inline int INFO_TEST(uint32_t word, uint32_t flag) { return ((word & flag) != 0); }
 inline int INFO_SET(uint32_t word, uint32_t flag) { return (word | flag); }
 inline int INFO_CLR(uint32_t word, uint32_t flag) { return (word & (~flag)); }

Modified: trunk/darwinup/main.cpp
===================================================================
--- trunk/darwinup/main.cpp	2009-03-20 21:17:31 UTC (rev 490)
+++ trunk/darwinup/main.cpp	2009-03-20 22:19:50 UTC (rev 491)
@@ -30,17 +30,21 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <limits.h>
 
 void usage(char* progname) {
-	char* pad = strdup(progname);
-	size_t i;
-	for (i = 0; i < strlen(pad); ++i) pad[i] = ' ';
-	
-	fprintf(stderr, "usage: %s install   <path>\n", progname);
-	fprintf(stderr, "       %s list\n", pad);
-	fprintf(stderr, "       %s files     <uuid>\n", pad);
-	fprintf(stderr, "       %s uninstall <uuid>\n", pad);
-	fprintf(stderr, "       %s verify    <uuid>\n", pad);
+	fprintf(stderr, "usage:    %s [-v] [-p DIR] [command] [args]          \n", progname);
+	fprintf(stderr, "                                                               \n");
+	fprintf(stderr, "options:                                                       \n");
+	fprintf(stderr, "          -p DIR     operate on roots under DIR (default: /)   \n");
+	fprintf(stderr, "          -v         verbose (use -vv for extra verbosity)     \n");
+	fprintf(stderr, "                                                               \n");
+	fprintf(stderr, "commands:                                                      \n");
+	fprintf(stderr, "          install    <path>                                    \n");
+	fprintf(stderr, "          list                                                 \n");
+	fprintf(stderr, "          files      <uuid>                                    \n");
+	fprintf(stderr, "          uninstall  <uuid>                                    \n");
+	fprintf(stderr, "          verify     <uuid>                                    \n");
 	exit(1);
 }
 
@@ -48,18 +52,26 @@
 uint32_t verbosity;
 
 int main(int argc, char* argv[]) {
-	int res = 0;
-	Depot* depot = new Depot("/");
-	
-	char* progname = strdup(basename(argv[0]));
-	
+	char* progname = strdup(basename(argv[0]));      
+
+	char* path;
+	int custom_path = 0;
+
 	int ch;
-	while ((ch = getopt(argc, argv, "v")) != -1) {
+	while ((ch = getopt(argc, argv, "p:v")) != -1) {
 		switch (ch) {
 		case 'v':
 			verbosity <<= 1;
 			verbosity |= VERBOSE;
 			break;
+		case 'p':
+		        if (strlen(optarg) > (PATH_MAX - 1)) {
+			        fprintf(stderr, "Error: -p option value is too long \n");
+				exit(3);
+			}
+			path = optarg;
+			custom_path = 1;
+			break;
 		case '?':
 		default:
 			usage(progname);
@@ -68,6 +80,20 @@
 	argc -= optind;
 	argv += optind;
 
+	int res = 0;
+
+	if (!custom_path) {
+		asprintf(&path, "/");
+	}
+	Depot* depot = new Depot(path);
+	if (!depot->is_locked()) {
+	        fprintf(stderr, 
+			"Error: unable to access and lock %s. " \
+			"The directory must exist and be writable.\n", depot->prefix());
+		exit(2);
+	}
+
+
 	if (argc == 2 && strcmp(argv[0], "install") == 0) {
 		char uuid[37];
 		Archive* archive = ArchiveFactory(argv[1]);
@@ -125,6 +151,9 @@
 	} else {
 		usage(progname);
 	}
+	if (!custom_path) {
+		free(path);
+	}
 	exit(res);
 	return res;
 }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20090320/9294f016/attachment-0001.html>


More information about the darwinbuild-changes mailing list