PERFORCE change 82892 for review

soc-andrew soc-andrew at FreeBSD.org
Wed Aug 31 09:25:09 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=82892

Change 82892 by soc-andrew at soc-andrew_serv on 2005/08/31 09:24:19

	Mark and install package dependencies. Delete unselected packages

Affected files ...

.. //depot/projects/soc2005/bsdinstaller/src/usr.sbin/bsdinstaller/backend/fn_install_freebsd.c#9 edit

Differences ...

==== //depot/projects/soc2005/bsdinstaller/src/usr.sbin/bsdinstaller/backend/fn_install_freebsd.c#9 (text+ko) ====

@@ -47,6 +47,8 @@
 #include <sys/types.h>
 #include <sys/utsname.h>
 
+#include <archive.h>
+#include <archive_entry.h>
 #include <dirent.h>
 #include <limits.h>
 #include <string.h>
@@ -63,6 +65,7 @@
 
 #include <installer/commands.h>
 #include <installer/dist.h>
+#include <installer/package.h>
 #include <installer/uiutil.h>
 
 char *mtree_file[] = { "root", "var", "usr", "sendmail", NULL };
@@ -97,6 +100,10 @@
 static int post_install(struct i_fn_args *);
 void fn_install_os(struct i_fn_args *);
 void fn_select_packages(struct i_fn_args*, struct aura_dict*, char*);
+void fn_add_remove_packages(struct i_fn_args *, struct aura_dict *,
+                            struct dfui_response *);
+void fn_package_mark_dependencies(struct aura_dict *, char *);
+void fn_package_install_dependencies(struct i_fn_args *, struct aura_dict *installed, char *, struct commands *);
 
 static int
 pre_install(struct i_fn_args *a)
@@ -197,8 +204,8 @@
 	char base[PATH_MAX];
 	/* This should be big enough as the largest dist name is ~9 */
 	char dist_name[32];
-	void *rv, *rk;
-	size_t rv_len, rk_len;
+	void *rk;
+	size_t rk_len;
 	int i;
 	struct commands *cmds;
 	struct utsname name;
@@ -462,7 +469,6 @@
 void
 fn_install_packages(struct i_fn_args *a)
 {
-	struct dfui_field *fi;
 	struct dfui_form *f;
 	struct dfui_response *r;
 	DIR *d;
@@ -470,6 +476,38 @@
 	struct aura_dict *packages;
 	int done = 0;
 
+	packages = aura_dict_new(13, AURA_DICT_LIST);
+
+	/* Add all installed packages to the dictonary */
+
+	d = opendir("/mnt/var/db/pkg");
+	if (d != NULL) {
+		/* loop through all sub-directories to the package dir */
+		while ((de = readdir(d)) != NULL) {
+			/*
+			 * I tried to check if (de->d_type == DT_DIR) here
+			 * but d_type was always 0
+			 */
+			struct stat sb;
+			char file[PATH_MAX];
+
+			if (de->d_name[0] == '.')
+				continue;
+
+			snprintf(file, PATH_MAX, "/mnt/var/db/pkg/%s",
+			    de->d_name);
+			stat(file, &sb);
+
+			if (!S_ISDIR(sb.st_mode))
+				continue;
+
+			aura_dict_store(packages,
+			    de->d_name, strlen(de->d_name),
+			    de->d_name, strlen(de->d_name));
+		}
+		closedir(d);
+	}
+
 	f = dfui_form_create(
 	    "install_packages",
 	    _("Install Packages"),
@@ -517,8 +555,6 @@
 	dfui_form_action_add(f, "cancel",
 	    dfui_info_new(_("Cancel"), "", ""));
 
-	packages = aura_dict_new(13, AURA_DICT_LIST);
-
 	while (done == 0)
 	{
 		if (!dfui_be_present(a->c, f, &r))
@@ -528,33 +564,49 @@
 			done = 1;
 		} else if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
 			/* Install the packages */
-			char *key;
-			int key_len;
+			char *key, *data;
+			size_t key_len, data_len;
+			struct commands *cmds;
+			struct aura_dict *installed;
+
+			cmds = commands_new();
+			installed = aura_dict_new(13, AURA_DICT_LIST);
 
 			aura_dict_rewind(packages);
+
+			/* Install all selected packages */
 			while (!aura_dict_eof(packages)) {
-				struct commands *cmds;
 
 				/* Set dist_name */
 				aura_dict_get_current_key(packages, (void*)&key,
 				    &key_len);
-				key[key_len] = '\0';
 
-				cmds = commands_new();
+				aura_dict_fetch(packages, key, key_len,
+				    &data, &data_len);
 
-				command_add(cmds,
-				    "cp /usr/packages/All/%s.tbz /mnt/tmp",
-				    key);
-				command_add(cmds,
-				    "pkg_add -C /mnt /tmp/%s.tbz", key);
-				command_add(cmds, "rm /mnt/tmp/%s.tbz", key);
+				key[key_len] = '\0';
+				data[data_len] = '\0';
 
-				commands_execute(a, cmds);
-				commands_free(cmds);
-
+				/*
+				 * If the package is marked as to be deleted
+				 * and is installed then remove it.
+				 */
+				if (strncmp("deleted", data, 8) == 0) {
+					if (pkg_exists(a, key)) {
+						printf("Delete %s\n", key);
+						command_add(cmds, "chroot /mnt"
+						    " pkg_delete %s", key);
+					}
+				} else {
+					fn_package_install_dependencies(a, installed, key, cmds);
+				}
 				aura_dict_next(packages);
 			}
 
+			aura_dict_free(installed);
+			commands_execute(a, cmds);
+			commands_free(cmds);
+
 			done = 1;
 		} else {
 			/* move to the next level window */
@@ -572,7 +624,6 @@
 void
 fn_select_packages(struct i_fn_args *a, struct aura_dict *packages, char *dir)
 {
-	struct dfui_field *fi;
 	struct dfui_form *f;
 	struct dfui_response *r;
 	struct dfui_dataset *ds;
@@ -596,7 +647,7 @@
 	    "Install this Package", "",
 	    "p", "control", "checkbox",
 
-	    "f", "package", "Package name",
+	    "f", "package", "Package name                    ",
 	    "The name of the Package to install", "",
 	    "p", "editable", "false",
 
@@ -616,16 +667,22 @@
 		return;
 	}
 
+	/* loop through all sub-directories to the package dir */
 	while ((de = readdir(d)) != NULL) {
-		/* I tried to use de->d_type == DT_DIR but d_type was always 0 */
+		/*
+		 * I tried to check if (de->d_type == DT_DIR) here
+		 * but d_type was always 0
+		 */
 		struct stat sb;
 		char file[PATH_MAX];
-		char *extension;
+		char *extension, *data;
+		int data_len;
 
 		if (de->d_name[0] == '.')
 			continue;
 
-		snprintf(file, PATH_MAX, "/usr/packages/%s/%s", dir, de->d_name);
+		snprintf(file, PATH_MAX, "/usr/packages/%s/%s", dir,
+		    de->d_name);
 		stat(file, &sb);
 
 		if (!S_ISREG(sb.st_mode))
@@ -636,7 +693,16 @@
 			extension[0] = '\0';
 
 		ds = dfui_dataset_new();
-		dfui_dataset_celldata_add(ds, "install", "N");
+
+		aura_dict_fetch(packages, de->d_name, strlen(de->d_name),
+		    (void*)&data, &data_len);
+
+		/* If the package is in the dictonary and is not deleted, mark it */
+		if (aura_dict_exists(packages, de->d_name,
+		    strlen(de->d_name)) != 0 && strncmp("deleted", data, 8) != 0)
+			dfui_dataset_celldata_add(ds, "install", "Y");
+		else
+			dfui_dataset_celldata_add(ds, "install", "N");
 		dfui_dataset_celldata_add(ds, "package", de->d_name);
 		dfui_form_dataset_add(f, ds);
 	}
@@ -647,27 +713,186 @@
 		abort_backend();
 
 	if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
-		/* Add the packages and dependencies to the dictonary */
-		for (ds = dfui_response_dataset_get_first(r); ds != NULL;
-		     ds = dfui_dataset_get_next(ds)) {
-			char install[2];
+		fn_add_remove_packages(a, packages, r);
+	}
+
+	dfui_response_free(r);
+	dfui_form_free(f);
+}
+
+/*
+ * "removes" the packages from the disctonary that are unselected
+ * Then adds the selected ones and dependencies
+ */
+void
+fn_add_remove_packages(struct i_fn_args *a, struct aura_dict *packages,
+	struct dfui_response *r)
+{
+	struct dfui_dataset *ds;
+
+	/* Remove unselected packages dictonary */
+	for (ds = dfui_response_dataset_get_first(r); ds != NULL;
+	     ds = dfui_dataset_get_next(ds)) {
+		char install[2];
+		char *package;
+		int len;
 
-			/* Copy the value of the install field to install */
-			strncpy(install, dfui_dataset_get_value(ds, "install"), 2);
+		/* Copy the value of the install field to install */
+		strncpy(install, dfui_dataset_get_value(ds, "install"), 2);
 
-			if (strncasecmp(install, "Y", 2) == 0) {
-				/* Select this dist for installation */
-				char *package;
-				int len;
+		package = (char*)dfui_dataset_get_value
+		    (ds, "package");
+		len = strlen(package);
 
-				package = (char*)dfui_dataset_get_value(ds, "package");
-				len = strlen(package);
+		if (strncasecmp(install, "N", 2) == 0) {
+			/*
+			 * "remove" this package from the dictonary by
+			 * changing it's value to "deleted".
+			 */
+			if (aura_dict_exists(packages, package,
+			    strlen(package)) != 0) {
 				aura_dict_store(packages, package, len,
-				    package, len);
+				    "deleted", 8);
+				printf("Delete: %s\n", package);
 			}
 		}
 	}
 
-	dfui_response_free(r);
-	dfui_form_free(f);
+	/* Add selected packages and dependencies to the dictonary */
+	for (ds = dfui_response_dataset_get_first(r); ds != NULL;
+	     ds = dfui_dataset_get_next(ds)) {
+		char install[2];
+		char *package;
+		int len;
+
+		/* Copy the value of the install field to install */
+		strncpy(install, dfui_dataset_get_value(ds, "install"), 2);
+
+		package = (char*)dfui_dataset_get_value
+		    (ds, "package");
+		len = strlen(package);
+
+		if (strncasecmp(install, "Y", 2) == 0) {
+			/* Find all unmarked dependencies and mark them */
+			fn_package_mark_dependencies(packages, package);
+		}
+	}
+}
+
+void
+fn_package_mark_dependencies(struct aura_dict *packages, char *package)
+{
+	struct archive *a;
+	struct archive_entry *entry;
+	char *file;
+
+	/* If the package is in the dictonary don't check it's dependencies */
+	if (aura_dict_exists(packages, package, strlen(package)) != 0) {
+		char *data;
+		size_t data_len;
+		aura_dict_fetch(packages, package, strlen(package),
+		    (void*)&data, &data_len);
+		if (strncmp("deleted", data, 8) != 0)
+			return;
+	}
+
+	/* Add this package to be installed */
+	aura_dict_store(packages, package, strlen(package), package, strlen(package));
+
+	a = archive_read_new();
+	archive_read_support_compression_all(a);
+	archive_read_support_format_all(a);
+
+	asprintf(&file, "/usr/packages/All/%s.tbz", package);
+	archive_read_open_file(a, file, 10240);
+	free(file);
+
+	if (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
+		void *buffer;
+		char *b;
+		int64_t len = archive_entry_size(entry);
+
+		buffer = malloc(len + 1);
+		archive_read_data_into_buffer(a, buffer, len);
+		b = buffer;
+		b[len] = 0;
+
+		/* Find the dependencies from the buffer */
+		while ((b = strstr(b, "@pkgdep")) != NULL) {
+			char *eol = strchr(b, '\n');
+			eol[0] = '\0';
+			b+=8;
+			/* Recurse to the dependent package to install it */
+			fn_package_mark_dependencies(packages, b);
+			b = eol + 1;
+		}
+		free(buffer);
+	}
+
+	archive_read_finish(a);
+}
+
+/*
+ * Installs a package and it's dependencies
+ * XXX: This is a copy of the code above, it should be generalized
+ */
+void
+fn_package_install_dependencies(struct i_fn_args *ar, struct aura_dict *installed, char *package, struct commands *cmds)
+{
+	struct archive *a;
+	struct archive_entry *entry;
+	char *file;
+	size_t len = strlen(package);
+
+	/* If the package is installed return */
+	if (pkg_exists(ar, package))
+		return;
+
+	/* If the package is in the to-be-installed dictonary return */
+	if (aura_dict_exists(installed, package, len))
+		return;
+
+	aura_dict_store(installed, package, len, package, len);
+
+	a = archive_read_new();
+	archive_read_support_compression_all(a);
+	archive_read_support_format_all(a);
+
+	asprintf(&file, "/usr/packages/All/%s.tbz", package);
+	archive_read_open_file(a, file, 10240);
+	free(file);
+
+	/* Find the dependencies and install them */
+	if (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
+		void *buffer;
+		char *b;
+		int64_t len = archive_entry_size(entry);
+
+		buffer = malloc(len + 1);
+		archive_read_data_into_buffer(a, buffer, len);
+		b = buffer;
+		b[len] = 0;
+
+		/* Find the dependencies from the buffer */
+		while ((b = strstr(b, "@pkgdep")) != NULL) {
+			char *eol = strchr(b, '\n');
+			eol[0] = '\0';
+			b+=8;
+			/* Recurse to the dependent package to install it */
+			fn_package_install_dependencies(ar, installed, b, cmds);
+			b = eol + 1;
+		}
+		free(buffer);
+	}
+
+	printf("Install %s\n", package);
+	command_add(cmds,
+	    "cp /usr/packages/All/%s.tbz "
+	    "/mnt/tmp", package);
+	command_add(cmds,
+	    "pkg_add -C /mnt /tmp/%s.tbz", package);
+	command_add(cmds, "rm /mnt/tmp/%s.tbz", package);
+
+	archive_read_finish(a);
 }
+


More information about the p4-projects mailing list