⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dpkg.c

📁 手机嵌入式Linux下可用的busybox源码
💻 C
📖 第 1 页 / 共 3 页
字号:
					continue;				}				/* There is a conflict against the package name				 * check if version conflict as well */				if (test_version(package_hashtable[deb_file[i]->package]->version,						package_edge->version, package_edge->operator)) {					error_msg_and_die("Package %s conflict with %s",						name_hashtable[package_hashtable[deb_file[i]->package]->name],						name_hashtable[package_hashtable[status_package_num]->name]);				}			}		}	}	/* Check dependendcies */	i = 0;	while (deb_file[i] != NULL) {		const common_node_t *package_node = package_hashtable[deb_file[i]->package];		int status_num = 0;		for (j = 0; j < package_hashtable[deb_file[i]->package]->num_of_edges; j++) {			const edge_t *package_edge = package_node->edge[j];			const unsigned int package_num = search_package_hashtable(package_edge->name,				package_edge->version, package_edge->operator);			status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);			state_status = get_status(status_num, 3);			state_want = get_status(status_num, 1);			switch (package_edge->type) {				case(EDGE_PRE_DEPENDS):				case(EDGE_OR_PRE_DEPENDS):					/* It must be already installed */					/* NOTE: This is untested, nothing apropriate in my status file */					if ((package_hashtable[package_num] == NULL) || (state_status != search_name_hashtable("installed"))) {						error_msg_and_die("Package %s pre-depends on %s, but it is not installed",							name_hashtable[package_node->name],							name_hashtable[package_edge->name]);					}					break;				case(EDGE_DEPENDS):				case(EDGE_OR_DEPENDS):					/* It must be already installed, or to be installed */					if ((package_hashtable[package_num] == NULL) ||						((state_status != search_name_hashtable("installed")) &&						(state_want != search_name_hashtable("want_install")))) {						error_msg_and_die("Package %s depends on %s, but it is not installed, or flaged to be installed",							name_hashtable[package_node->name],							name_hashtable[package_edge->name]);					}					break;			}		}		i++;	}	free(conflicts);	return(TRUE);}char **create_list(const char *filename){	FILE *list_stream;	char **file_list = xmalloc(sizeof(char *));	char *line = NULL;	char *last_char;	int length = 0;	int count = 0;	/* dont use [xw]fopen here, handle error ourself */	list_stream = fopen(filename, "r");	if (list_stream == NULL) {		*file_list = NULL;		return(file_list);	}	while (getline(&line, &length, list_stream) != -1) {		file_list = xrealloc(file_list, sizeof(char *) * (length + 1));		last_char = last_char_is(line, '\n');		if (last_char) {			*last_char = '\0';		}		file_list[count] = xstrdup(line);		free(line);		count++;		length = 0;	}	fclose(list_stream);	if (count == 0) {		return(NULL);	} else {		file_list[count] = NULL;		return(file_list);	}}/* maybe i should try and hook this into remove_file.c somehow */int remove_file_array(char **remove_names, char **exclude_names){	struct stat path_stat;	int match_flag;	int remove_flag = FALSE;	int i,j;	if (remove_names == NULL) {		return(FALSE);	}	for (i = 0; remove_names[i] != NULL; i++) {		match_flag = FALSE;		if (exclude_names != NULL) {			for (j = 0; exclude_names[j] != 0; j++) {				if (strcmp(remove_names[i], exclude_names[j]) == 0) {					match_flag = TRUE;					break;				}			}		}		if (!match_flag) {			if (lstat(remove_names[i], &path_stat) < 0) {				continue;			}			if (S_ISDIR(path_stat.st_mode)) {				if (rmdir(remove_names[i]) != -1) {					remove_flag = TRUE;				}			} else {				if (unlink(remove_names[i]) != -1) {					remove_flag = TRUE;				}			}		}	}	return(remove_flag);}int run_package_script(const char *package_name, const char *script_type){	struct stat path_stat;	char *script_path;	script_path = xmalloc(strlen(package_name) + strlen(script_type) + 21);	sprintf(script_path, "/var/lib/dpkg/info/%s.%s", package_name, script_type);	/* If the file doesnt exist is isnt a fatal */	if (lstat(script_path, &path_stat) < 0) {		free(script_path);		return(EXIT_SUCCESS);	} else {		free(script_path);		return(system(script_path));	}}void all_control_list(char **remove_files, const char *package_name){	const char *all_extensions[11] = {"preinst", "postinst", "prerm", "postrm",		"list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL };	int i;	/* Create a list of all /var/lib/dpkg/info/<package> files */	for(i = 0; i < 10; i++) {		remove_files[i] = xmalloc(strlen(package_name) + strlen(all_extensions[i]) + 21);		sprintf(remove_files[i], "/var/lib/dpkg/info/%s.%s", package_name, all_extensions[i]);	}	remove_files[10] = NULL;}void remove_package(const unsigned int package_num){	const char *package_name = name_hashtable[package_hashtable[package_num]->name];	const unsigned int status_num = search_status_hashtable(package_name);	const int package_name_length = strlen(package_name);	char **remove_files;	char **exclude_files;	char list_name[package_name_length + 25];	char conffile_name[package_name_length + 30];	int return_value;	printf("Removing %s ...\n", package_name);	/* run prerm script */	return_value = run_package_script(package_name, "prerm");	if (return_value == -1) {		error_msg_and_die("script failed, prerm failure");	}	/* Create a list of files to remove, and a seperate list of those to keep */	sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);	remove_files = create_list(list_name);	sprintf(conffile_name, "/var/lib/dpkg/info/%s.conffiles", package_name);	exclude_files = create_list(conffile_name);	/* Some directories cant be removed straight away, so do multiple passes */	while (remove_file_array(remove_files, exclude_files) == TRUE);	/* Create a list of all /var/lib/dpkg/info/<package> files */	remove_files = xmalloc(11);	all_control_list(remove_files, package_name);	/* Create a list of files in /var/lib/dpkg/info/<package>.* to keep  */	exclude_files = xmalloc(sizeof(char*) * 3);	exclude_files[0] = xstrdup(conffile_name);	exclude_files[1] = xmalloc(package_name_length + 27);	sprintf(exclude_files[1], "/var/lib/dpkg/info/%s.postrm", package_name);	exclude_files[2] = NULL;	remove_file_array(remove_files, exclude_files);	/* rename <package>.conffile to <package>.list */	rename(conffile_name, list_name);	/* Change package status */	set_status(status_num, "deinstall", 1);	set_status(status_num, "config-files", 3);}void purge_package(const unsigned int package_num){	const char *package_name = name_hashtable[package_hashtable[package_num]->name];	const unsigned int status_num = search_status_hashtable(package_name);	char **remove_files;	char **exclude_files;	char list_name[strlen(package_name) + 25];	/* run prerm script */	if (run_package_script(package_name, "prerm") == -1) {		error_msg_and_die("script failed, prerm failure");	}	/* Create a list of files to remove */	sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);	remove_files = create_list(list_name);	exclude_files = xmalloc(1);	exclude_files[0] = NULL;	/* Some directories cant be removed straight away, so do multiple passes */	while (remove_file_array(remove_files, exclude_files) == TRUE);	/* Create a list of all /var/lib/dpkg/info/<package> files */	remove_files = xmalloc(11);	all_control_list(remove_files, package_name);	remove_file_array(remove_files, exclude_files);	/* run postrm script */	if (run_package_script(package_name, "postrm") == -1) {		error_msg_and_die("postrm fialure.. set status to what?");	}	/* Change package status */	set_status(status_num, "purge", 1);	set_status(status_num, "not-installed", 3);}void unpack_package(deb_file_t *deb_file){	const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];	const unsigned int status_num = search_status_hashtable(package_name);	const unsigned int status_package_num = status_hashtable[status_num]->status;	FILE *out_stream;	char *info_prefix;	/* If existing version, remove it first */	if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {		/* Package is already installed, remove old version first */		printf("Preparing to replace %s %s (using %s) ...\n", package_name,			name_hashtable[package_hashtable[status_package_num]->version],			deb_file->filename);		remove_package(status_package_num);	} else {		printf("Unpacking %s (from %s) ...\n", package_name, deb_file->filename);	}	/* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */	info_prefix = (char *) xmalloc(sizeof(package_name) + 20 + 4 + 1);	sprintf(info_prefix, "/var/lib/dpkg/info/%s.", package_name);	deb_extract(deb_file->filename, stdout, (extract_quiet | extract_control_tar_gz | extract_all_to_fs), info_prefix, NULL);	/* Extract data.tar.gz to the root directory */	deb_extract(deb_file->filename, stdout, (extract_quiet | extract_data_tar_gz | extract_all_to_fs), "/", NULL);	/* Create the list file */	strcat(info_prefix, "list");	out_stream = xfopen(info_prefix, "w");				deb_extract(deb_file->filename, out_stream, (extract_quiet | extract_data_tar_gz | extract_list), NULL, NULL);	fclose(out_stream);	/* change status */	set_status(status_num, "install", 1);	set_status(status_num, "unpacked", 3);	free(info_prefix);}void configure_package(deb_file_t *deb_file){	const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];	const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version];	const int status_num = search_status_hashtable(package_name);	int return_value;	printf("Setting up %s (%s)\n", package_name, package_version);	/* Run the preinst prior to extracting */	return_value = run_package_script(package_name, "postinst");	if (return_value == -1) {		/* TODO: handle failure gracefully */		error_msg_and_die("postrm failure.. set status to what?");	}	/* Change status to reflect success */	set_status(status_num, "install", 1);	set_status(status_num, "installed", 3);}extern int dpkg_main(int argc, char **argv){	deb_file_t **deb_file = NULL;	status_node_t *status_node;	int opt = 0;	int package_num;	int dpkg_opt = 0;	int deb_count = 0;	int state_status;	int status_num;	int i;	while ((opt = getopt(argc, argv, "CF:ilPru")) != -1) {		switch (opt) {			case 'C': // equivalent to --configure in official dpkg				dpkg_opt |= dpkg_opt_configure;				dpkg_opt |= dpkg_opt_package_name;				break;			case 'F': // equivalent to --force in official dpkg				if (strcmp(optarg, "depends") == 0) {					dpkg_opt |= dpkg_opt_force_ignore_depends;				}							case 'i':				dpkg_opt |= dpkg_opt_install;				dpkg_opt |= dpkg_opt_filename;				break;			case 'l':				dpkg_opt |= dpkg_opt_list_installed;			case 'P':				dpkg_opt |= dpkg_opt_purge;				dpkg_opt |= dpkg_opt_package_name;				break;			case 'r':				dpkg_opt |= dpkg_opt_remove;				dpkg_opt |= dpkg_opt_package_name;				break;			case 'u':	/* Equivalent to --unpack in official dpkg */				dpkg_opt |= dpkg_opt_unpack;				dpkg_opt |= dpkg_opt_filename;				break;			default:				show_usage();		}	}	if ((argc == optind) || (dpkg_opt == 0)) {		show_usage();	} 	puts("(Reading database ... xxxxx files and directories installed.)");	index_status_file("/var/lib/dpkg/status");	/* Read arguments and store relevant info in structs */	deb_file = xmalloc(sizeof(deb_file_t));	while (optind < argc) {		deb_file[deb_count] = (deb_file_t *) xmalloc(sizeof(deb_file_t));		if (dpkg_opt & dpkg_opt_filename) {			deb_file[deb_count]->filename = xstrdup(argv[optind]);			deb_file[deb_count]->control_file = deb_extract(argv[optind], stdout, (extract_control_tar_gz | extract_one_to_buffer), NULL, "./control");			if (deb_file[deb_count]->control_file == NULL) {				error_msg_and_die("Couldnt extract control file");			}			package_num = fill_package_struct(deb_file[deb_count]->control_file);			if (package_num == -1) {				error_msg("Invalid control file in %s", argv[optind]);				continue;			}			deb_file[deb_count]->package = (unsigned int) package_num;			/* Add the package to the status hashtable */			if ((dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) {				status_node = (status_node_t *) xmalloc(sizeof(status_node_t));				status_node->package = deb_file[deb_count]->package;				/* use reinstreq isnt changed to "ok" until the package control info				 * is written to the status file*/				status_node->status = search_name_hashtable("install reinstreq not-installed");				status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);				status_hashtable[status_num] = status_node;			}		}		else if (dpkg_opt & dpkg_opt_package_name) {			deb_file[deb_count]->filename = NULL;			deb_file[deb_count]->control_file = NULL;			deb_file[deb_count]->package = search_package_hashtable(				search_name_hashtable(argv[optind]),				search_name_hashtable("ANY"), VER_ANY);			if (package_hashtable[deb_file[deb_count]->package] == NULL) {				error_msg_and_die("Package %s is uninstalled or unknown\n", argv[optind]);			}			state_status = get_status(search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]), 3);			/* check package status is "installed" */			if (dpkg_opt & dpkg_opt_remove) {				if ((strcmp(name_hashtable[state_status], "not-installed") == 0) ||					(strcmp(name_hashtable[state_status], "config-files") == 0)) {					error_msg_and_die("%s is already removed.", name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);				}			}			else if (dpkg_opt & dpkg_opt_purge) {				/* if package status is "conf-files" then its ok */				if (strcmp(name_hashtable[state_status], "not-installed") == 0) {					error_msg_and_die("%s is already purged.", name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);				}			}		}		deb_count++;		optind++;	}	deb_file[deb_count] = NULL;	/* Check that the deb file arguments are installable */	/* TODO: check dependencies before removing */	if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) {		if (!check_deps(deb_file, 0, deb_count)) {			error_msg_and_die("Dependency check failed");		}	}	for (i = 0; i < deb_count; i++) {		/* Remove or purge packages */		if (dpkg_opt & dpkg_opt_remove) {			remove_package(deb_file[i]->package);		}		else if (dpkg_opt & dpkg_opt_purge) {			purge_package(deb_file[i]->package);		}		else if (dpkg_opt & dpkg_opt_unpack) {			unpack_package(deb_file[i]);		}		else if (dpkg_opt & dpkg_opt_install) {			unpack_package(deb_file[i]);			configure_package(deb_file[i]);		}		else if (dpkg_opt & dpkg_opt_configure) {			configure_package(deb_file[i]);		}	}	write_status_file(deb_file);	for (i = 0; i < deb_count; i++) {		free(deb_file[i]->control_file);		free(deb_file[i]->filename);		free(deb_file[i]);	}	free(deb_file);	for (i = 0; i < NAME_HASH_PRIME; i++) {		if (name_hashtable[i] != NULL) {			free(name_hashtable[i]);		}	}	for (i = 0; i < PACKAGE_HASH_PRIME; i++) {		free_package(package_hashtable[i]);	}	for (i = 0; i < STATUS_HASH_PRIME; i++) {		if (status_hashtable[i] != NULL) {			free(status_hashtable[i]);		}	}	return(EXIT_FAILURE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -