Exemplo n.º 1
0
//void do_install(opkg_conf* conf, char* pkg_name, char* install_root_name, char* link_root_name, char** version_criteria)
void do_install(opkg_conf* conf, string_map* pkgs, char* install_root_name, char* link_root_name, int is_upgrade, int overwrite_config, int overwrite_other_package_files, int force_reinstall, char* tmp_root)
{
	string_map* package_data = initialize_string_map(1);
	string_map* matching_packages = initialize_string_map(1);
	string_map* pkgs_from_file = initialize_string_map(1);
	unsigned long num_destroyed;


	char* install_root_path = (char*)get_string_map_element(conf->dest_names, install_root_name);
	char* overlay_path = NULL; // no special treatment of overlay, can be reenabled  by setting this variable here if we ever need it


	char* test_dir  = dynamic_strcat(2, (overlay_path != NULL ? overlay_path : install_root_path), "/usr/lib/opkg/info");
	if(!create_dir_and_test_writable(test_dir))
	{
		fprintf(stderr, "ERROR: Specified install destination is not writable, exiting\n");
		exit(1);
	}
	free(test_dir);

	



	if(install_root_path == NULL)
	{
		printf("ERROR: No destination %s found, cannot install\n\n", install_root_name);
		exit(1);
	}
	
	char* tmp_dir = (char*)malloc(1024);
	if(create_tmp_dir(tmp_root == NULL ? "/tmp" : tmp_root, &tmp_dir) != 0)
	{
		fprintf(stderr, "ERROR: Could not create tmp dir, exiting\n");
		exit(1);
	}


	/* Determine all packages to install by first loading all package names, status & dependencies (and no other variables) */
	load_all_package_data(conf, package_data, matching_packages, NULL, LOAD_MINIMAL_PKG_VARIABLES_FOR_ALL, install_root_name, 1, NULL );
	destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed);

		
	/* determine list of all packiages we are about to install, including dependencies */
	string_map* install_pkgs_map = initialize_string_map(1);
	char** install_pkg_list = NULL;	
	unsigned long install_pkg_list_len = 0;
	char* unsatisfied_dep_err = NULL;



	
	/* new string map var with all pkgs to install = pkgs, keys = version */
	unsigned long num_pkg_names;
	char** pkg_names = get_string_map_keys(pkgs, &num_pkg_names);
	int pkg_name_index;
	
	
	
	
	/* 
	 * Load data for any packages being installed via ipk and
	 * determine if any packages we are about to install 
	 * provide anything, and if so set package we are installing to preferred
	 */
	string_map* preferred_provides = initialize_string_map(1);
	for(pkg_name_index=0;pkg_name_index < num_pkg_names; pkg_name_index++)
	{
		char* pkg_name = pkg_names[pkg_name_index];
		char** version_criteria = get_string_map_element(pkgs, pkg_name);
		char* install_pkg_version = NULL;
		int install_pkg_is_current;

		
		/* deal with case where we're installing from file */
		if(path_exists(pkg_name))
		{
			//installing from file
			char* pkg_file = pkg_name;


			//extract control files
			int err = 0;
			char* tmp_control        = dynamic_strcat(2, tmp_dir, "/tmp_ctrl");
			char* tmp_control_prefix = dynamic_strcat(2, tmp_control, "/tmp.");
			char* tmp_control_name   = dynamic_strcat(2, tmp_control_prefix, "control");

			mkdir_p(tmp_control, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH );
			deb_extract(	pkg_file,
					stderr,
					extract_control_tar_gz | extract_all_to_fs| extract_preserve_date | extract_unconditional,
					tmp_control_prefix, 
					NULL, 
					&err);
			if(err != 0)
			{
				fprintf(stderr, "ERROR: %s is not a valid package file, cannot install\n", pkg_file);
				rm_r(tmp_dir);
				exit(1);
			}
			string_map* tmp_control_pkg_data = initialize_string_map(1);
			matching_packages = initialize_string_map(1);
		       	load_package_data(tmp_control_name, 0, tmp_control_pkg_data, matching_packages, NULL, LOAD_ALL_PKG_VARIABLES, NULL, NULL);
			unsigned long num_ctrl_names;
			char** ctrl_name_list = get_string_map_keys(tmp_control_pkg_data, &num_ctrl_names);
			destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed);
		

			err = 1; //set back to 0 when data successfully loaded
			if(num_ctrl_names > 0)
			{
				int ctrl_name_index;
				for(ctrl_name_index=0; ctrl_name_list[ctrl_name_index] != NULL; ctrl_name_index++)
				{
					if( strcmp(ctrl_name_list[ctrl_name_index], PROVIDES_STRING) != 0)
					{
						pkg_name = strdup(ctrl_name_list[ctrl_name_index]);
					}
				}



				char* version = NULL;
				int is_current;
				string_map* pkg_info = get_package_current_or_latest(tmp_control_pkg_data, pkg_name, &is_current, &version);
				if(pkg_info != NULL)
				{
					err = 0;
					set_string_map_element(pkg_info, "Install-File-Location", strdup(pkg_file));
					set_string_map_element(pkg_info, "Version", version); //we need to save this, since we are going to set a special version to make sure data doesn't get over-written later, also no need to free version now

					char* special_version = dynamic_strcat(2, version, "@@_FILE_INSTALL_VERSION_@@");
					char** new_version_criteria = malloc(3*sizeof(char*));
					new_version_criteria[0] = strdup("=");
					new_version_criteria[1] = special_version;
					new_version_criteria[2] = NULL;
					version_criteria = new_version_criteria;
					
					string_map* all_current_versions = get_string_map_element(package_data, pkg_name);
					if(all_current_versions == NULL)
					{
						all_current_versions=initialize_string_map(1);
						set_string_map_element(package_data, pkg_name, all_current_versions);
					}
					set_string_map_element(all_current_versions, special_version, pkg_info);
					set_string_map_element(all_current_versions, LATEST_VERSION_STRING, special_version);
				
					free(pkg_names[pkg_name_index]);
					pkg_names[pkg_name_index] = strdup(pkg_name);

				
					set_string_map_element(pkgs, pkg_name, copy_null_terminated_string_array(new_version_criteria));	
					set_string_map_element(pkgs_from_file, pkg_name, strdup("D"));
				}
			}
			free_null_terminated_string_array(ctrl_name_list);
			if(err != 0)
			{
				fprintf(stderr, "ERROR: %s is not a valid package file, cannot install\n", pkg_file);
				rm_r(tmp_dir);
				exit(1);
			}

			free_if_not_null(tmp_control);
			free_if_not_null(tmp_control_prefix);
			free_if_not_null(tmp_control_name);
			rm_r(tmp_control);
		}

		/* determine if package provides anything, and set this package to preferred if so*/
		string_map* install_pkg_data = get_package_current_or_latest_matching(package_data, pkg_name, version_criteria, &install_pkg_is_current, &install_pkg_version);
		if(install_pkg_data != NULL)
		{
			char* provides_str = get_string_map_element(install_pkg_data, "Provides");
			if(provides_str != NULL)
			{
				if(strlen(provides_str) > 0)
				{
					unsigned long num_provides;
					char package_separators[] = {' ', ',', ':', ';', '\'', '\"', '\t', '\r', '\n'};
					char** provides_list = split_on_separators(provides_str, package_separators, 9, -1, 0, &num_provides);
					int provides_index;
					char* provides_unique_key = dynamic_strcat(3, pkg_name, "@", install_pkg_version);
					for(provides_index=0; provides_index < num_provides; provides_index++)
					{
						char* provides_name = strdup(provides_list[provides_index]);
						char* eq = strchr(provides_name, '=');
						if(eq != NULL) { *eq = '\0' ; }
						if(strlen(provides_name) > 0)
						{
							set_string_map_element(preferred_provides, provides_name, strdup(provides_unique_key));
						}
					}
				}
			}
		}
	
	}


	/* reload with new preferred_provides */
	free_recursive_package_vars(package_data);
	matching_packages = initialize_string_map(1);
	load_all_package_data(conf, package_data, matching_packages, NULL, LOAD_MINIMAL_PKG_VARIABLES_FOR_ALL, install_root_name, 1, preferred_provides );
	destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed);
	
	
	/* load data and do sanity checks for packages we are about to install */
	for(pkg_name_index=0;pkg_name_index < num_pkg_names; pkg_name_index++)
	{
		char* pkg_name = pkg_names[pkg_name_index];
		char** version_criteria = get_string_map_element(pkgs, pkg_name);
		char* install_pkg_version = NULL;
		int install_pkg_is_current;

		

		load_recursive_package_data_variables(package_data, pkg_name, 1, 0, 0); // load required-depends for package of interest only 
		string_map* install_pkg_data = get_package_current_or_latest_matching(package_data, pkg_name, version_criteria, &install_pkg_is_current, &install_pkg_version);
		char* install_status = install_pkg_data == NULL ? NULL : get_string_map_element(install_pkg_data, "Status");

	
		if(install_status != NULL)
		{
			char** old_el = set_string_map_element(install_pkgs_map, pkg_name, copy_null_terminated_string_array(version_criteria) );
			if(old_el != NULL){ free_null_terminated_string_array(old_el); }

			string_map* install_pkg_depend_map = get_string_map_element(install_pkg_data, "Required-Depends");
			if(install_pkg_depend_map != NULL)
			{
				unsigned long num_keys;
				char** load_detail_pkgs = get_string_map_keys(install_pkg_depend_map, &num_keys);
				int ldp_index;
				for(ldp_index=0;ldp_index < num_keys && unsatisfied_dep_err == NULL; ldp_index++)
				{
					char* dep_name = load_detail_pkgs[ldp_index];
					char** dep_def= get_string_map_element(install_pkg_depend_map, dep_name);
					if(get_string_map_element(install_pkgs_map, dep_name) != NULL)
					{
						/* 
						 * We really should check here whether old dependency def can be reconciled with the new one, and report an error if it can't 
						 * Right now we just use the heuristic that top-level (user specified, not dependency) package defs get preference, followed
						 * by first dependency encountered.
						 *
						 * Since right now versioning features aren't really being used very much other than kernel dependencies in Gargoyle/OpenWrt
						 * I'm just leaving this comment here as a reminder that this should be addressed at some point rather than messing with it now
						 *
						 */

						dep_def = get_string_map_element(install_pkgs_map, dep_name);
					}
					else
					{
						set_string_map_element(install_pkgs_map, dep_name, copy_null_terminated_string_array(dep_def));
					}
	
					//error checking, check that dependency definition exists
					char* latest_version = NULL;
					int latest_is_current = 0;
					string_map* dep_info = get_package_current_or_latest_matching(package_data, dep_name, dep_def, &latest_is_current, &latest_version);
					
					
					//check if we have a version installed different than what is required
					int have_current;
					char* current_version = NULL;
					string_map* cur_info = get_package_current_or_latest(package_data, dep_name, &have_current, &current_version);
					if(have_current && (latest_is_current == 0 || dep_info == NULL))
					{
						//should only get here if dep_def[1] is not null (version mismatch doesn't make sense if no version is specified)
						char* cur_status = get_string_map_element(cur_info, "Status");
						if(strstr(cur_status, " hold ") != NULL)
						{
							unsatisfied_dep_err = dynamic_strcat(11, "ERROR: Dependency ", dep_name, " (", dep_def[0], " ", dep_def[1], ") of package ", pkg_name, " is installed,\n\t\tbut has incompatible version ", current_version, " and is marked as 'hold'");
						}
						else
						{
							unsatisfied_dep_err = dynamic_strcat(10, "ERROR: Dependency ", dep_name, " (", dep_def[0], " ", dep_def[1], ") of package ", pkg_name, " is installed,\n\t\tbut has incompatible version ", current_version);
						}
					}
					free_if_not_null(current_version);
					free_if_not_null(latest_version);
	
					// check that dependency definition exists
					if(unsatisfied_dep_err == NULL && dep_info == NULL)
					{
						if(dep_def[1] != NULL)
						{
							unsatisfied_dep_err = dynamic_strcat(9, "ERROR: Dependency ", dep_name, " (", dep_def[0], " ", dep_def[1], ") of package ", pkg_name, " cannot be found, try updating your package lists");
						}
						else
						{
							unsatisfied_dep_err = dynamic_strcat(5, "ERROR: Dependency ", dep_name, " of package ", pkg_name, " cannot be found, try updating your package lists");
						}
					}
									
				}
				free_null_terminated_string_array(load_detail_pkgs);
			}
	
		}
		install_status = install_pkg_data == NULL ? NULL : get_string_map_element(install_pkg_data, "Status");




		/* error checking before we start install */
		if(install_pkg_data == NULL || install_status == NULL)
		{
			fprintf(stderr, "ERROR: No package named %s found, try updating your package lists\n\n", pkg_name);
			rm_r(tmp_dir);
			exit(1);
		}
		if(strstr(install_status, " installed") != NULL)
		{
			if(force_reinstall)
			{
				fprintf(stderr, "WARNING: Package %s is already installed, forcing removal and reinstallation\n\n", pkg_name);
				free_package_data(package_data);
				string_map* rm_pkg = initialize_string_map(1);
				set_string_map_element(rm_pkg, pkg_name, alloc_depend_def(NULL));
				do_remove(conf, rm_pkg, (overwrite_config ? 0 : 1), 0, 1, 0, tmp_root);
				
				//restart install
				return do_install(conf, pkgs, install_root_name, link_root_name, is_upgrade, overwrite_config, overwrite_other_package_files, force_reinstall, tmp_root);
				
			}
			else
			{
				fprintf(stderr, "WARNING: Package %s is already installed, ignoring\n", pkg_name);
				fprintf(stderr, "         Use --force-reinstall to force reinstallation\n\n");
				char** old_el = remove_string_map_element(install_pkgs_map, pkg_name);
				if(old_el != NULL){ free_null_terminated_string_array(old_el); };
			}

		}

		if(unsatisfied_dep_err != NULL)
		{
			fprintf(stderr, "%s\n", unsatisfied_dep_err);
			rm_r(tmp_dir);
			exit(1);
		}
	}


	
	
	/* load more detailed data on packages we are about to install */
	free_recursive_package_vars(package_data); /* note: whacks install_pkg_depend_map */	
	string_map* parameters = initialize_string_map(1);
	matching_packages = initialize_string_map(1);
	set_string_map_element(parameters, "package-list", install_pkgs_map);
	
	load_all_package_data(conf, package_data, matching_packages, parameters, LOAD_MINIMAL_FOR_ALL_PKGS_ALL_FOR_MATCHING, install_root_name, 0, preferred_provides);
	
	unsigned long from_file_pkg_list_len;
	char** from_file_pkg_list = get_string_map_keys(pkgs_from_file, &from_file_pkg_list_len);
	int from_file_index;
	for(from_file_index=0; from_file_index < from_file_pkg_list_len; from_file_index++)
	{
		char* old = set_string_map_element(matching_packages, from_file_pkg_list[from_file_index], strdup("D"));
		free_if_not_null(old);
	}
	free_null_terminated_string_array(from_file_pkg_list);
	install_pkg_list = get_string_map_keys(matching_packages, &install_pkg_list_len);
	


	
	
	destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed);
	destroy_string_map(parameters, DESTROY_MODE_IGNORE_VALUES, &num_destroyed);
	

	char* all_pkg_list_str = join_strs(", ", install_pkg_list, install_pkg_list_len, 0, 0); 
	uint64_t combined_size = 0;
	int pkg_index;


	for(pkg_index=0; pkg_index < install_pkg_list_len; pkg_index++)
	{
		char** match_criteria = get_string_map_element(install_pkgs_map, install_pkg_list[pkg_index]);
		string_map* pkg = get_package_current_or_latest_matching(package_data, install_pkg_list[pkg_index], match_criteria, NULL, NULL);
		char* next_size_str = get_string_map_element(pkg, "Installed-Size");
		uint64_t next_size = 0;
		if(sscanf(next_size_str,  SCANFU64, &next_size) > 0)
		{
			combined_size = combined_size + next_size; 
		} 
	}
	uint64_t root_size = destination_bytes_free(conf, install_root_name);
	if(combined_size >= root_size )
	{
		fprintf(stderr, "ERROR: Not enough space in destination %s to install specified packages:\n\t%s\n\n", install_root_name, all_pkg_list_str);
		rm_r(tmp_dir);
		exit(1);
	}


	if(all_pkg_list_str != NULL)
	{
		printf("Preparing to install the following packages, which will require " SCANFU64 " bytes:\n\t%s\n\n", combined_size, all_pkg_list_str);
	}
	else
	{
		fprintf(stderr, "No packages to install.\n\n");
	}

	/* Set status of new required packages to half-installed, set user-installed on requested package, installed time on all */
	char* install_root_status_path = dynamic_strcat(2, install_root_path, "/usr/lib/opkg/status");
	string_map* install_root_status = initialize_string_map(1);
	matching_packages = initialize_string_map(1);
	if(path_exists(install_root_status_path))
	{
		load_package_data(install_root_status_path, 0, install_root_status, matching_packages, NULL, LOAD_ALL_PKG_VARIABLES, install_root_name, preferred_provides);
	}
	destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed);



	time_t now = time(NULL);
	char install_time[20];
	sprintf(install_time, "%lu", now);
	for(pkg_index=0; pkg_index < install_pkg_list_len; pkg_index++)
	{
		int is_installed;
		char* install_version = NULL;
		char** match_criteria = get_string_map_element(install_pkgs_map, install_pkg_list[pkg_index]);
		string_map* pkg = get_package_current_or_latest_matching(package_data, install_pkg_list[pkg_index], match_criteria, &is_installed, &install_version);


		if(is_installed == 0) /* should never be true, but check anyway */
		{
			char* old_status = remove_string_map_element(pkg, "Status");
			free(old_status);
			char* status_parts[3] = { "install", "ok", "half-installed" };
			status_parts[1] = get_string_map_element(pkgs, install_pkg_list[pkg_index]) != NULL ? "user" : status_parts[1];
			char* new_status = dynamic_strcat(5, status_parts[0], " ", status_parts[1], " ", status_parts[2]);
			set_string_map_element(pkg, "Status", new_status);

			set_string_map_element(pkg, "Installed-Time", strdup(install_time));
			set_string_map_element(pkg, "Install-Destination", strdup(install_root_name));
			if(link_root_name != NULL)
			{
				set_string_map_element(pkg, "Link-Destination", strdup(link_root_name));
			}

			add_package_data(install_root_status, &pkg, install_pkg_list[pkg_index], install_version, NULL); 
			/* Note: we just added pkg data structure from package_data to install_root_status, Be careful on cleanup! */
		}
	}
	save_package_data_as_status_file(install_root_status, install_root_status_path);




	

	string_map* install_called_pkgs = initialize_string_map(1);

	int err = 0;
	for(pkg_name_index=0;pkg_name_index < num_pkg_names; pkg_name_index++)
	{
		char* pkg_name = pkg_names[pkg_name_index];
		if(get_string_map_element(install_pkgs_map, pkg_name) != NULL && get_string_map_element(install_called_pkgs, pkg_name) == NULL)
		{
			int install_pkg_is_current;
			char* install_pkg_version = NULL;
			char** version_criteria = get_string_map_element(pkgs, pkg_name);
			get_package_current_or_latest_matching(package_data, pkg_name, version_criteria, &install_pkg_is_current, &install_pkg_version);
			err = recursively_install(pkg_name, install_pkg_version, install_root_name, link_root_name, overlay_path, is_upgrade, overwrite_config, overwrite_other_package_files, tmp_dir, conf, package_data, install_called_pkgs);
		
			free_if_not_null(install_pkg_version);
		}
	}
	

	if(err)
	{
		fprintf(stderr, "An error occurred during Installation, removing partially installed packages.\n");
		unsigned long num_install_called_pkgs;
		char** install_called_pkg_list = get_string_map_keys(install_called_pkgs, &num_install_called_pkgs);
		int pkg_index;
		for(pkg_index=0; pkg_index < num_install_called_pkgs; pkg_index++)
		{
			remove_individual_package(install_called_pkg_list[pkg_index], conf, package_data, tmp_dir, 0, 0);
		}
		free_null_terminated_string_array(install_called_pkg_list);
		//call remove function to do cleanup of partial install
		//DO NOT EXIT HERE, fixup status file below
	}
	//remove tmp dir -- need to do this whether or not there is an error
	rm_r(tmp_dir);
	free(tmp_dir);


	//set status of new packages to installed on success, and remove on failure
	for(pkg_index=0; pkg_index < install_pkg_list_len; pkg_index++)
	{	
		/* no need to check version, should only be one installed version at a time... */
		string_map* pkg = get_package_current_or_latest(install_root_status, install_pkg_list[pkg_index], NULL, NULL); 
		if(pkg != NULL)
		{
			if(!err)
			{
				char* status = get_string_map_element(pkg, "Status");
				if(strstr(status, " half-installed") != NULL)
				{
					char* status_parts[3] = { "install", "ok", "installed" };
					status_parts[1] = get_string_map_element(pkgs, install_pkg_list[pkg_index]) != NULL ? "user" : status_parts[1];
					char* new_status = dynamic_strcat(5, status_parts[0], " ", status_parts[1], " ", status_parts[2]);
					char* old_status = set_string_map_element(pkg, "Status", new_status);
					free_if_not_null(old_status);
				}
			}
			else
			{
				string_map* all_pkg_versions = remove_string_map_element(install_root_status, install_pkg_list[pkg_index]);
				free_all_package_versions(all_pkg_versions);
			}
		}
	}
	save_package_data_as_status_file(install_root_status, install_root_status_path);
	if(!err)
	{
		if(all_pkg_list_str != NULL)
		{
			printf("Installation of packages successful.\n\n");
		}
	}
	else
	{
		printf("Finished removing partially installed packages.\n\n");
	}
}
Exemplo n.º 2
0
ip_bw* load_usage_from_file(char* in_file_path, unsigned long* num_ips, time_t* last_backup)
{
	ip_bw* data = NULL;
	*num_ips = 0;
	*last_backup = 0;
	FILE* in_file = fopen(in_file_path, "r");
	if(in_file != NULL)
	{
		unsigned long num_data_parts = 0;
		char* file_data = read_entire_file(in_file, 4086, &num_data_parts);
		fclose(in_file);
		char whitespace[] =  {'\n', '\r', '\t', ' '};
		char** data_parts = split_on_separators(file_data, whitespace, 4, -1, 0, &num_data_parts);
		free(file_data);

		*num_ips = (num_data_parts/2) + 1;
       		data = (ip_bw*)malloc( (*num_ips) * sizeof(ip_bw) );
		*num_ips = 0;
		unsigned long data_index = 0;
		unsigned long data_part_index = 0;
		while(data_part_index < num_data_parts)
		{
			ip_bw next;
			struct in_addr ipaddr;
			int valid = inet_aton(data_parts[data_part_index], &ipaddr);
			if(!valid)
			{
				sscanf(data_parts[data_part_index], "%ld", last_backup);
				//printf("last_backup = %ld\n", *last_backup);
			}
			data_part_index++;

			if(valid && data_index < num_data_parts)
			{
				next.ip = ipaddr.s_addr;
				valid = sscanf(data_parts[data_part_index], "%lld", (long long int*)&(next.bw) );
				data_part_index++;
			}
			else
			{
				valid = 0;
			}

			if(valid)
			{
				//printf("next.bw = %lld\n", next.bw);
				//printf("next.ip = %d\n", next.ip);
				data[data_index] = next;
				data_index++;
				*num_ips = *num_ips + 1;
			}
		}
		
		/* cleanup by freeing data_parts */
		for(data_part_index = 0; data_part_index < num_data_parts; data_part_index++)
		{
			free(data_parts[data_part_index]);
		}
		
		free(data_parts);
	}
	return data;
}
Exemplo n.º 3
0
string_map* parse_parameters(int argc, char** argv)
{
    string_map* parameters = initialize_string_map(1);
    if(argc == 1)
    {
        print_usage();  //exits
    }
    char* run_type = argv[1];
    if(	strcmp(run_type, "list") != 0 &&
            strcmp(run_type, "list-installed") != 0 &&
            strcmp(run_type, "list_installed") != 0 &&
            strcmp(run_type, "dest-info") != 0 &&
            strcmp(run_type, "dest_info") != 0 &&
            strcmp(run_type, "info") != 0 &&
            strcmp(run_type, "update") != 0 &&
            strcmp(run_type, "install") != 0 &&
            strcmp(run_type, "remove") != 0 &&
            strcmp(run_type, "upgrade") != 0
      )
    {
        print_usage();  //exits
    }
    set_string_map_element(parameters, "run-type", run_type);


    static struct option long_options[] = {
        {"force-depends",           0, 0, 'p'},
        {"force_depends",           0, 0, 'p'},
        {"force-overwrite",         0, 0, 'w'},
        {"force_overwrite",         0, 0, 'w'},
        {"force-maintainer",        0, 0, 'm'},
        {"force_maintainer",        0, 0, 'm'},
        {"force-overwrite-configs", 0, 0, 'm'},
        {"force_overwrite-configs", 0, 0, 'm'},
        {"force-reinstall",         0, 0, 'e'},
        {"force_reinstall",         0, 0, 'e'},
        {"autoremove",              0, 0, 'a'},
        {"autoremove-same-dest",    0, 0, 's'},
        {"autoremove_same_dest",    0, 0, 's'},
        {"conf",                    1, 0, 'c'},
        {"dest",                    1, 0, 'd'},
        {"link-dest",               1, 0, 'l'},
        {"link_dest",               1, 0, 'l'},
        {"only-dest",               1, 0, 'n'},
        {"only_dest",               1, 0, 'n'},
        {"tmp-dir",                 1, 0, 't'},
        {"tmp_dir",                 1, 0, 't'},
        {"output-format",           1, 0, 'o'},
        {"output_format",           1, 0, 'o'},
        {"matching-regex",          0, 0, 'r'},
        {"matching_regex",          0, 0, 'r'},
        {"regex",                   0, 0, 'r'},
        {"package-variables",       1, 0, 'v'},
        {"package_variables",       1, 0, 'v'},
        {"help",                    0, 0, 'h'},
        {NULL, 0, NULL, 0}
    };

    int expect_regex =0;

    int option_index = 0;
    int c;
    while ((c = getopt_long(argc, argv, "pwmeasc:d:l:n:t:o:rv:h", long_options, &option_index)) != -1)
    {
        switch(c)
        {
        case 'p':
            set_string_map_element(parameters, "force-depends", strdup("D"));
            break;
        case 'w':
            set_string_map_element(parameters, "force-overwrite", strdup("D"));
            break;
        case 'm':
            set_string_map_element(parameters, "force-overwrite-configs", strdup("D"));
            break;
        case 'e':
            set_string_map_element(parameters, "force-reinstall", strdup("D"));
            break;
        case 'a':
            set_string_map_element(parameters, "autoremove", strdup("D"));
            break;
        case 's':
            set_string_map_element(parameters, "autoremove-same-destination", strdup("D"));
            break;
        case 'c':
            set_string_map_element(parameters, "conf", strdup(optarg));
            break;
        case 'd':
            set_string_map_element(parameters, "install-destination", strdup(optarg));
            break;
        case 'l':
            set_string_map_element(parameters, "link-destination", strdup(optarg));
            break;
        case 'n':
            set_string_map_element(parameters, "only-destination", strdup(optarg));
            break;
        case 't':
            set_string_map_element(parameters, "tmp-dir", strdup(optarg));
            break;
        case 'o':
            set_string_map_element(parameters, "output-format", strdup(optarg));
            break;
        case 'v':
            if(strlen(optarg) >0)
            {

                unsigned long num_pieces=0;
                char seps[] = {',', ';', ':', ' ', '\r', '\n', '\t' }; //include newlines to strip them off end of line
                char** split_line = split_on_separators(optarg, seps, 7, -1, 0, &num_pieces);
                if(num_pieces > 0)
                {
                    string_map* package_variables = initialize_string_map(1);
                    int piece_index;
                    for(piece_index=0; piece_index < num_pieces; piece_index++)
                    {
                        if(strlen(split_line[piece_index]) > 0)
                        {
                            set_string_map_element(package_variables, split_line[piece_index], strdup("D"));
                        }
                    }
                    if(package_variables->num_elements > 0)
                    {
                        set_string_map_element(parameters, "package-variables", package_variables);
                    }
                }
                free_null_terminated_string_array(split_line);
            }
            break;

        case 'r':
            //--matching-regex, or just --regex
            expect_regex = 1;
            break;
        case 'h':
        default:
            print_usage(); //exits
            break;
        }
    }

    if( expect_regex == 1 && strcmp(run_type, "info") != 0 && strcmp(run_type, "list") != 0 && strcmp(run_type, "list-installed") != 0 && strcmp(run_type, "list_installed") )
    {
        fprintf(stderr, "ERROR: package list can only specified with regular expression when using 'list', 'list-installed' or 'info' commands\n\n");
        exit(1);
    }



    string_map* pkg_list = initialize_string_map(1);
    set_string_map_element(parameters, "package-list", pkg_list);
    for(option_index=1; option_index < argc; option_index++)
    {
        int option_str_len = strlen(argv[option_index]);
        if(argv[option_index][0] == '-' && option_str_len > 1)
        {
            int has_arg=0;
            int test_index;
            const char* name;
            const char* test_name = argv[option_index] + 1;
            int is_long_opt=0;
            if(argv[option_index][1] == '-')
            {
                test_name = argv[option_index] + 2;
                is_long_opt = 1;
            }
            for(test_index=0; (name = (long_options[test_index]).name) != NULL ; test_index++)
            {
                if( (is_long_opt == 1 && strcmp(test_name, name) == 0) || (is_long_opt == 0 && test_name[0] == (long_options[test_index]).val) )
                {
                    has_arg = (long_options[test_index]).has_arg;
                }
            }
            if(has_arg)
            {
                option_index++;
            }
        }
        else if(strcmp(argv[option_index], run_type) != 0)
        {
            if(expect_regex)
            {
                regex_t* packages_matching_regex = (regex_t*)malloc(sizeof(regex_t));
                char* regex_str = strdup(argv[option_index]);
                int regex_len = strlen(regex_str);
                if(get_string_map_element(parameters, "package-regex") != NULL)
                {
                    fprintf(stderr, "ERROR: Only one regular expression can be specified at a time.\n\n");
                    exit(1);

                }
                if(regex_str[0] != '/' || regex_str[regex_len-1] != '/')
                {
                    free(regex_str);
                    regex_str=dynamic_strcat(3, "/", argv[option_index], "/");
                }
                if( convert_to_regex(regex_str, packages_matching_regex) )
                {
                    set_string_map_element(parameters, "package-regex", packages_matching_regex);
                }
                else
                {
                    fprintf(stderr, "ERROR: Invalid regular expression \"%s\"\n\n", regex_str);
                    exit(1);
                }
                free(regex_str);
            }
            else
            {
                set_string_map_element(pkg_list, argv[option_index], alloc_depend_def(NULL));
            }
        }
    }
    if(	strcmp(run_type, "install") == 0 ||
            strcmp(run_type, "remove")  == 0 ||
            strcmp(run_type, "upgrade") == 0
      )
    {
        if(pkg_list->num_elements == 0)
        {
            printf("ERROR: No packages specified to %s.\n\n", run_type);
            exit(1);
        }
    }


    return parameters;
}
Exemplo n.º 4
0
int main(int argc, char **argv)
{
	char *table = argv[1];
	char *delete_chain = argv[2];
	if(argc != 3)
	{
		printf("USAGE: %s [TABLE] [CHAIN TO DELETE]\n\n", argv[0]);
		return 0;
	}

	char *command = dynamic_strcat(3, "iptables -t ", table, " -L -n --line-numbers 2>/dev/null");
	unsigned long num_lines = 0;
	char** table_dump = get_shell_command_output_lines(command, &num_lines);
	free(command);
	

	unsigned long line_index;
	char* current_chain = NULL;
	list* delete_commands = initialize_list();


	for(line_index=0; line_index < num_lines; line_index++)
	{
		char* line = table_dump[line_index];
		unsigned long num_pieces = 0;
		char whitespace[] = { '\t', ' ', '\r', '\n' };
		char** line_pieces = split_on_separators(line, whitespace, 4, -1, 0, &num_pieces);
		if(strcmp(line_pieces[0], "Chain") == 0)
		{
			if(current_chain != NULL) { free(current_chain); }
			current_chain = strdup(line_pieces[1]);
		}
		else 
		{
			unsigned long line_num;
			int read = sscanf(line_pieces[0], "%ld", &line_num);

			if(read > 0 && current_chain != NULL && num_pieces >1)
			{
				if(strcmp(line_pieces[1], delete_chain) == 0)
				{
					char* delete_command = dynamic_strcat(7, "iptables -t ", table, " -D ", current_chain, " ", line_pieces[0], " 2>/dev/null");
					push_list(delete_commands, delete_command);
				}
			}
		}

		//free line_pieces
		free_null_terminated_string_array(line_pieces);
	}
	free_null_terminated_string_array(table_dump);
	
	/* final two commands to flush chain being deleted and whack it */
	unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -F ", delete_chain, " 2>/dev/null"));
	unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -X ", delete_chain, " 2>/dev/null"));

	/* run delete commands */
	while(delete_commands->length > 0)
	{
		char *next_command = (char*)pop_list(delete_commands);
		char **out = get_shell_command_output_lines(next_command, &num_lines);
		free_null_terminated_string_array(out);
	}

	return 0;
}
/* 
 * assumes 24hr time, not am/pm, in format:
 * (Day of week) hours:minutes:seconds
 * if day of week is present, returns seconds since midnight on Sunday
 * otherwise, seconds since midnight
 */
unsigned long parse_time(char* time_str)
{
	while((*time_str == ' ' || *time_str == '\t') && *time_str != '\0') { time_str++; }
	
	int weekday = -1;
	if(strlen(time_str) > 3)
	{
		char wday_test[4];
		memcpy(wday_test, time_str, 3);
		wday_test[3] = '\0';
		to_lowercase(wday_test);
		if(strcmp(wday_test, "sun") == 0)
		{
			weekday = 0;
		}
		else if(strcmp(wday_test, "mon") == 0)
		{
			weekday = 1;
		}
		else if(strcmp(wday_test, "tue") == 0)
		{
			weekday = 2;
		}
		else if(strcmp(wday_test, "wed") == 0)
		{
			weekday = 3;
		}
		else if(strcmp(wday_test, "thu") == 0)
		{
			weekday = 4;
		}
		else if(strcmp(wday_test, "fri") == 0)
		{
			weekday = 5;
		}
		else if(strcmp(wday_test, "sat") == 0)
		{
			weekday = 6;
		}
	}

	if(weekday >= 0)
	{
		time_str = time_str + 3;
		while( (*time_str < 48 || *time_str > 57) && *time_str != '\0') { time_str++; }
	}

	char** time_parts=split_on_separators(time_str, ":", 1, -1, 0);
	unsigned long seconds = weekday < 0 ? 0 : ( ((unsigned long)(weekday))*60*60*24 );
	unsigned long tmp;
	unsigned long multiple = 60*60;

	int tp_index = 0;
	for(tp_index=0; time_parts[tp_index] != NULL; tp_index++)
	{
		sscanf(time_parts[tp_index], "%ld", &tmp);
		seconds = seconds + (tmp*multiple);
		multiple = (unsigned long)(multiple/60);
		free(time_parts[tp_index]);
	}
	free(time_parts);

	return seconds;
}
/* is_weekly_range indicates whether we're parsing hours within a single day or a range over a whole week */
long* parse_time_ranges(char* time_ranges, unsigned char is_weekly_range)
{
	char** pieces = split_on_separators(time_ranges, ",", 1, -1, 0);
	int num_pieces = 0;
	for(num_pieces = 0; pieces[num_pieces] != NULL; num_pieces++) {};
	long *parsed = (long*)malloc( (1+(num_pieces*2)) * sizeof(long));


	
	int piece_index = 0;
	for(piece_index = 0; pieces[piece_index] != NULL; piece_index++)
	{
		trim_flanking_whitespace(pieces[piece_index]);
		char** times=split_on_separators(pieces[piece_index], "-", 1, 2, 0);
		int time_count = 0;
		for(time_count = 0; times[time_count] != 0 ; time_count++){}
		if( time_count == 2 )
		{
			unsigned long  start = parse_time(trim_flanking_whitespace(times[0]));
			unsigned long end = parse_time(trim_flanking_whitespace(times[1]));
			parsed[ piece_index*2 ] = (long)start;
			parsed[ (piece_index*2)+1 ] = (long)end;

			free( times[1] );
		}
		if( time_count > 0) { free(times[0]); }

		free(times);
		free(pieces[piece_index]);
	}
	free(pieces);
	parsed[ (num_pieces*2) ] = -1; // terminated with -1 


	// make sure there is no overlap -- this will invalidate ranges 
	int range_index = 0;
	char overlap_found = 0;
	for(range_index = 0; range_index < num_pieces; range_index++)
	{
		// now test for overlap 
		long start1 = parsed[ (range_index*2) ];
		long end1 = parsed[ (range_index*2)+1 ];
		end1= end1 < start1 ? end1 + (is_weekly_range ? 7*24*60*60 : 24*60*60) : end1;
		
		int range_index2 = 0;
		for(range_index2 = 0; range_index2 < num_pieces; range_index2++)
		{
			if(range_index2 != range_index)
			{
				long start2 = parsed[ (range_index2*2) ];
				long end2 = parsed[ (range_index2*2)+1 ];
				end2= end2 < start2 ? end2 + (is_weekly_range ? 7*24*60*60 : 24*60*60) : end2;
				overlap_found = overlap_found || (start1 < end2 && end1 > start2 );
			}
		}
	}

	if(!overlap_found)
	{
		// sort ranges 
		int sorted_index = 0;
		while(parsed[sorted_index] != -1)
		{
			int next_start=-1;
			int next_start_index=-1;
			int test_index;
			long tmp1;
			long tmp2;
			for(test_index=sorted_index; parsed[test_index] != -1; test_index=test_index+2)
			{
				next_start_index = next_start < 0 || next_start > parsed[test_index] ? test_index : next_start_index;
				next_start = next_start < 0 || next_start > parsed[test_index] ? parsed[test_index] : next_start;
			}
			tmp1 = parsed[next_start_index];
			tmp2 = parsed[next_start_index+1];
			parsed[next_start_index] = parsed[sorted_index];
			parsed[next_start_index+1] = parsed[sorted_index+1];
			parsed[sorted_index] = 	tmp1;
			parsed[sorted_index+1] = tmp2;
			sorted_index = sorted_index + 2;
		}
	}
	else
	{
		// de-allocate parsed, set to NULL 
		free(parsed);
		parsed = NULL;
	}

	// merge time ranges where end of first = start of second 
	merge_adjacent_time_ranges(parsed, is_weekly_range);


	// if always active, free & return NULL 
	int max_multiple = is_weekly_range ? 7 : 1;
	if(parsed[0] == 0 && parsed[1] == max_multiple*24*60*60)
	{
		free(parsed);
		parsed = NULL;
	}


	//adjust so any range that crosses end of range is split in two
	int num_range_indices=0;
	for(num_range_indices=0; parsed[num_range_indices] != -1; num_range_indices++){}

	long* adjusted_range = (long*)malloc((3+num_range_indices)*sizeof(long));
	int ar_index = 0;
	int old_index = 0;
	if(parsed[num_range_indices-1] < parsed[0])
	{
		adjusted_range[0] = 0;
		adjusted_range[1] = parsed[num_range_indices-1];
		ar_index = ar_index + 2;
		parsed[num_range_indices-1] = -1;
	}
	for(old_index=0; parsed[old_index] != -1; old_index++)
	{
		adjusted_range[ar_index] = parsed[old_index];
		ar_index++;
	}

	if(ar_index % 2 == 1 )
	{
		adjusted_range[ar_index] = is_weekly_range ? 7*24*60*60 : 24*60*60;
		ar_index++;
	}
	adjusted_range[ar_index] = -1;
	free(parsed);
	
	return adjusted_range;
}
/* takes a string of days e.g. "Monday, Tuesday, Friday", and turns into an array of 7 longs
 * each 0 or 1, one for each weekday starting with sunday, e.g. [0,1,1,0,0,1,0] for our example 
 */
long* parse_weekdays(char* wd_str)
{
	long* weekdays = (long*)malloc(7*sizeof(long));
	weekdays[0] = weekdays[1] = weekdays[2] = weekdays[3] = weekdays[4] = weekdays[5] = weekdays[6] = 0;

	char** days = split_on_separators(wd_str, ",", 1, -1, 0);
	int day_index;
	int found = 0;
	for(day_index=0; days[day_index] != NULL; day_index++)
	{
		char day[4];
		trim_flanking_whitespace(days[day_index]);
		memcpy(day, days[day_index], 3);
		free(days[day_index]);
		day[3] = '\0';
		to_lowercase(day);
		if(strcmp(day, "sun") == 0)
		{
			weekdays[0] = 1;
			found = 1;
		}
		else if(strcmp(day, "mon") ==0)
		{
			weekdays[1] = 1;
			found = 1;
		}
		else if(strcmp(day, "tue") ==0)
		{
			weekdays[2] = 1;
			found = 1;
		}
		else if(strcmp(day, "wed") ==0)
		{
			weekdays[3] = 1;
			found = 1;
		}	
		else if(strcmp(day, "thu") ==0)
		{
			weekdays[4] = 1;
			found = 1;
		}
		else if(strcmp(day, "fri") ==0)
		{
			weekdays[5] = 1;
			found = 1;
		}
		else if(strcmp(day, "sat") ==0)
		{
			weekdays[6] = 1;
			found = 1;
		}
		else if(strcmp(day, "all") ==0)
		{
			weekdays[0] = weekdays[1] = weekdays[2] = weekdays[3] = weekdays[4] = weekdays[5] = weekdays[6] = 1;
			found = 1;
		}
	}
	free(days);
	if(found == 0)
	{
		free(weekdays);
		weekdays = NULL;
	}
	return weekdays;	
}