Ejemplo n.º 1
0
void fatal_update_error(int from_version, int to_version)
{
	struct list *version_list = NULL;

	version_list = list_prepend_data(version_list, (void *)((intptr_t)to_version));
	version_list = list_prepend_data(version_list, (void *)((intptr_t)from_version));
	efivar_bootloader_set_next_boot_to_repair(repair_update_failure,
						  version_list);
	list_free_list(version_list);
}
Ejemplo n.º 2
0
extern int timerlist_add_timer(t_connection * owner, time_t when, t_timer_cb cb, t_timer_data data)
{
    t_timer * timer;
    
    if (!owner)
    {
	eventlog(eventlog_level_error,"timerlist_add_timer","got NULL owner");
	return -1;
    }
    
    if (!(timer = malloc(sizeof(t_timer))))
    {
	eventlog(eventlog_level_error,"timerlist_add_timer","could not allocate memory for timer");
	return -1;
    }
    timer->owner = owner;
    timer->when  = when;
    timer->cb    = cb;
    timer->data  = data;
    
    if (list_prepend_data(timerlist_head,timer)<0)
    {
	free(timer);
	eventlog(eventlog_level_error,"timerlist_add_timer","could not prepend temp");
	return -1;
    }
    
    return 0;
}
Ejemplo n.º 3
0
void critical_verify_error(int version)
{
	struct list *version_list = NULL;

	version_list = list_prepend_data(version_list, (void *)((intptr_t)version));
	efivar_bootloader_set_next_boot_to_repair(repair_verify_failure,
						  version_list);
	list_free_list(version_list);
}
Ejemplo n.º 4
0
		int topiclist_add_topic(char const * channel_name, char const * topic_text, int do_save)
		{
			t_topic * topic;

			topic = (t_topic*)xmalloc(sizeof(t_topic));
			topic->channel_name = xstrdup(channel_name);
			topic->topic = xstrdup(topic_text);
			list_prepend_data(topiclist_head, topic);
			topic->save = do_save;
			return 0;
		}
Ejemplo n.º 5
0
/* try to insert the file into the hashmap download queue
 * returns 1 if no download is needed
 * returns 0 if download is needed
 * returns -1 if error */
static int swupd_curl_hashmap_insert(struct file *file)
{
	struct list *iter;
	struct file *tmp;
	char *tar_dotfile;
	char *targetfile;
	struct stat stat;
	int hashmap_index = file->hash[0];
	struct swupd_curl_hashbucket *bucket = &swupd_curl_hashmap[hashmap_index];

	pthread_mutex_lock(&bucket->mutex);

	iter = bucket->list;
	while (iter) {
		tmp = iter->data;
		if (hash_equal(tmp->hash, file->hash)) {
			// hash already in download queue
			pthread_mutex_unlock(&bucket->mutex);
			return 1;
		}
		iter = iter->next;
	}

	// if valid target file is already here, no need to download
	string_or_die(&targetfile, "%s/staged/%s", state_dir, file->hash);

	if (lstat(targetfile, &stat) == 0) {
		if (verify_file(file, targetfile)) {
			free(targetfile);
			pthread_mutex_unlock(&bucket->mutex);
			return 1;
		}
	}
	free(targetfile);

	// hash not in queue and not present in staged

	// clean up in case any prior download failed in a partial state
	string_or_die(&tar_dotfile, "%s/download/.%s.tar", state_dir, file->hash);
	unlink(tar_dotfile);
	free(tar_dotfile);

	// queue the hash for download
	iter = bucket->list;
	if ((iter = list_prepend_data(iter, file)) == NULL) {
		pthread_mutex_unlock(&bucket->mutex);
		return -1;
	}
	bucket->list = iter;

	pthread_mutex_unlock(&bucket->mutex);
	return 0;
}
Ejemplo n.º 6
0
/* deep clone a list of char * */
struct list *list_deep_clone_strs(struct list *list)
{
	struct list *clone = NULL;
	struct list *item;

	item = list_tail(list);
	while (item) {
		clone = list_prepend_data(clone, strdup(item->data));
		item = item->prev;
	}

	return clone;
}
Ejemplo n.º 7
0
struct list *list_clone(struct list *list)
{
	struct list *clone = NULL;
	struct list *item;

	item = list_tail(list);
	while (item) {
		clone = list_prepend_data(clone, item->data);
		item = item->prev;
	}

	return clone;
}
Ejemplo n.º 8
0
bool hashmap_put(struct hashmap *hashmap, void *data)
{
	struct list **items, *i;

	items = get_hashmap_list(hashmap, data);
	for (i = *items; i; i = i->next) {
		if (hashmap->equal(data, i->data)) {
			return false;
		}
	}
	*items = list_prepend_data(*items, data);

	return true;
}
Ejemplo n.º 9
0
/* Bundle install one ore more bundles passed in bundles
 * param as a null terminated array of strings
 */
int install_bundles_frontend(char **bundles)
{
	int lock_fd;
	int ret = 0;
	int current_version;
	struct list *bundles_list = NULL;
	struct manifest *mom;

	/* initialize swupd and get current version from OS */
	ret = swupd_init(&lock_fd);
	if (ret != 0) {
		printf("Failed updater initialization, exiting now.\n");
		return ret;
	}

	current_version = get_current_version(path_prefix);
	if (current_version < 0) {
		printf("Error: Unable to determine current OS version\n");
		ret = ECURRENT_VERSION;
		goto clean_and_exit;
	}

	swupd_curl_set_current_version(current_version);

	mom = load_mom(current_version);
	if (!mom) {
		printf("Cannot load official manifest MoM for version %i\n", current_version);
		ret = EMOM_NOTFOUND;
		goto clean_and_exit;
	}

	for (; *bundles; ++bundles) {
		bundles_list = list_prepend_data(bundles_list, *bundles);
	}

	ret = install_bundles(bundles_list, current_version, mom);
	list_free_list(bundles_list);

	free_manifest(mom);
clean_and_exit:
	swupd_deinit(lock_fd);

	return ret;
}
Ejemplo n.º 10
0
/* Bundle install one ore more bundles passed in bundles
 * param as a null terminated array of strings
 */
int install_bundles_frontend(char **bundles)
{
	int lock_fd;
	int ret = 0;
	int current_version;
	struct list *bundles_list = NULL;
	struct manifest *mom;

	/* initialize swupd and get current version from OS */
	ret = swupd_init(&lock_fd);
	if (ret != 0) {
		printf("Failed updater initialization, exiting now.\n");
		return ret;
	}

	current_version = read_version_from_subvol_file(path_prefix);
	swupd_curl_set_current_version(current_version);

	ret = load_manifests(current_version, current_version, "MoM", NULL, &mom);
	if (ret != 0) {
		printf("Cannot load official manifest MoM for version %i\n", current_version);
		ret = EMOM_NOTFOUND;
		goto clean_and_exit;
	}

	for (; *bundles; ++bundles) {
		bundles_list = list_prepend_data(bundles_list, *bundles);
	}

	ret = install_bundles(bundles_list, current_version, mom);
	list_free_list(bundles_list);

	free_manifest(mom);
clean_and_exit:
	swupd_curl_cleanup();
	v_lockfile(lock_fd);
	dump_file_descriptor_leaks();
	free_globals();

	return ret;
}
Ejemplo n.º 11
0
int add_included_manifests(struct manifest *mom)
{
	struct list *subbed = NULL;
	struct list *iter;
	int ret;

	iter = list_head(subs);
	while (iter) {
		subbed = list_prepend_data(subbed, ((struct sub *)iter->data)->component);
		iter = iter->next;
	}

	if (add_subscriptions(subbed, mom->version, mom) >= 0) {
		ret = 0;
	} else {
		ret = -1;
	}
	list_free_list(subbed);

	return ret;
}
static struct list *parse_version_list(char *csv_version_str)
{
	char *token;
	int version;
	struct list *list = NULL;

	if (!csv_version_str)
		return NULL;

	token = strtok(csv_version_str, ",");
	while (token != NULL) {
		if (sscanf(token, "%i", &version) != 1) {
			list_free_list(list);
			return NULL;
		}
		list = list_prepend_data(list, (void *)((intptr_t)version));
		token = strtok(NULL, ",");
	}

	return list;
}
Ejemplo n.º 13
0
static int perform_curl_io_and_complete(int *left)
{
	CURLMsg *msg;
	long ret;
	CURLMcode curlm_ret;
	CURLcode curl_ret;

	curlm_ret = curl_multi_perform(mcurl, left);
	if (curlm_ret != CURLM_OK) {
		return -1;
	}

	while (true) {
		CURL *handle;
		struct file *file;

		msg = curl_multi_info_read(mcurl, left);
		if (!msg) {
			break;
		}
		if (msg->msg != CURLMSG_DONE) {
			continue;
		}

		handle = msg->easy_handle;
		ret = 404;
		curl_ret = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &ret);
		if (curl_ret != CURLE_OK) {
			continue;
		}

		curl_ret = curl_easy_getinfo(handle, CURLINFO_PRIVATE, (char **)&file);
		if (curl_ret != CURLE_OK) {
			curl_easy_cleanup(handle);
			continue;
		}

		/* The easy handle may have an error set, even if the server returns
		 * HTTP 200, so retry the download for this case. */
		if (ret == 200 && msg->data.result != CURLE_OK) {
			printf("Error for %s download: %s\n", file->hash,
			       curl_easy_strerror(msg->data.result));
			failed = list_prepend_data(failed, file);
		} else if (ret == 200) {
			/* When both web server and CURL report success, only then
			 * proceed to uncompress. */
			if (untar_full_download(file)) {
				printf("Error for %s tarfile extraction, (check free space for %s?)\n",
				       file->hash, state_dir);
				failed = list_prepend_data(failed, file);
			}
		} else if (ret == 0) {
			/* When using the FILE:// protocol, 0 indicates success.
			 * Otherwise, it means the web server hasn't responded yet.
			 */
			if (local_download) {
				if (untar_full_download(file)) {
					printf("Error for %s tarfile extraction, (check free space for %s?)\n",
					       file->hash, state_dir);
					failed = list_prepend_data(failed, file);
				}
			} else {
				printf("Error for %s download: No response received\n",
				       file->hash);
				failed = list_prepend_data(failed, file);
			}
		} else {
			printf("Error for %s download: Received %ld response\n", file->hash, ret);
			failed = list_prepend_data(failed, file);

			unlink_all_staged_content(file);
		}
		if (file->staging) {
			free(file->staging);
			file->staging = NULL;
		}

		/* NOTE: Intentionally no removal of file from hashmap.  All
		 * needed files need determined and queued in one complete
		 * preparation phase.  Once all needed files are all present,
		 * they can be staged.  Otherwise a complex datastructure and
		 * retries are needed to insure only one download of a file
		 * happens fully to success AND a HASH.tar is uncompressed to
		 * and HASH and staged to the _multiple_ filenames with that
		 * hash. */

		curl_multi_remove_handle(mcurl, handle);
		curl_easy_cleanup(handle);
		file->curl = NULL;
	}

	curlm_ret = curl_multi_perform(mcurl, left);
	if (curlm_ret != CURLM_OK) {
		return -1;
	}

	return 0;
}
Ejemplo n.º 14
0
t_list * realmlist_load(char const * filename)
{
    FILE *          fp;
    unsigned int    line;
    unsigned int    pos;
    unsigned int    len;
    t_addr *        raddr;
    char *          temp, *temp2;
    char *          buff;
    char *          name;
    char *          desc;
    t_realm *       realm;
    t_list *        list_head = NULL;
    
    if (!filename)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");
        return NULL;
    }
    
    if (!(fp = fopen(filename,"r")))
    {
        eventlog(eventlog_level_error,__FUNCTION__,"could not open realm file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
        return NULL;
    }
    
    list_head = list_create();

    for (line=1; (buff = file_get_line(fp)); line++)
    {
        for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++);
        if (buff[pos]=='\0' || buff[pos]=='#')
        {
            continue;
        }
        if ((temp = strrchr(buff,'#')))
        {
	    unsigned int endpos;
	    
            *temp = '\0';
	    len = strlen(buff)+1;
            for (endpos=len-1;  buff[endpos]=='\t' || buff[endpos]==' '; endpos--);
            buff[endpos+1] = '\0';
        }
        
	/* skip any separators */
	for (temp = buff; *temp && (*temp == ' ' || *temp == '\t');temp++);
	if (*temp != '"') {
	    eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename);
	    continue;
	}
	
	temp2 = temp + 1;
	/* find the next " */
	for (temp = temp2; *temp && *temp != '"';temp++);
	if (*temp != '"' || temp == temp2) {
	    eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename);
	    continue;
	}
	
	/* save the realmname */
	*temp = '\0';
        name = xstrdup(temp2);
	
	/* eventlog(eventlog_level_trace, __FUNCTION__,"found realmname: %s",name); */

	/* skip any separators */
	for(temp = temp + 1; *temp && (*temp == '\t' || *temp == ' ');temp++);
	
	if (*temp == '"') { /* we have realm description */
	    temp2 = temp + 1;
	    /* find the next " */
	    for(temp = temp2;*temp && *temp != '"';temp++);
	    if (*temp != '"' || temp == temp2) {
		eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no valid description)",line,filename);
		xfree(name);
		continue;
	    }
	    
	    /* save the description */
	    *temp = '\0';
    	    desc = xstrdup(temp2);
	    
	    /* eventlog(eventlog_level_trace, __FUNCTION__,"found realm desc: %s",desc); */

	    /* skip any separators */
	    for(temp = temp + 1; *temp && (*temp == ' ' || *temp == '\t');temp++);
	} else desc = xstrdup("\0");

	temp2 = temp;
	/* find out where address ends */
	for(temp = temp2 + 1; *temp && *temp != ' ' && *temp != '\t';temp++);

	if (*temp) *temp++ = '\0'; /* if is not the end of the file, end addr and move forward */

	/* eventlog(eventlog_level_trace, __FUNCTION__,"found realm ip: %s",temp2); */

	if (!(raddr = addr_create_str(temp2,0,BNETD_REALM_PORT))) /* 0 means "this computer" */ {
	    eventlog(eventlog_level_error,__FUNCTION__,"invalid address value for field 3 on line %u in file \"%s\"",line,filename);
	    xfree(name);
	    xfree(desc);
	    continue;
	}
	
	if (!(realm = realm_create(name,desc,addr_get_ip(raddr),addr_get_port(raddr))))
	{
	    eventlog(eventlog_level_error,__FUNCTION__,"could not create realm");
	    addr_destroy(raddr);
	    xfree(name);
	    xfree(desc);
	    continue;
	}

	addr_destroy(raddr);
	xfree(name);
	xfree(desc);
	
	list_prepend_data(list_head,realm);
    }
    file_get_line(NULL); // clear file_get_line buffer
    if (fclose(fp)<0)
	eventlog(eventlog_level_error,__FUNCTION__,"could not close realm file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno));
    return list_head;
}
Ejemplo n.º 15
0
static struct manifest *manifest_from_file(int version, char *component, bool header_only, bool latest, bool is_mix)
{
	FILE *infile;
	char line[MANIFEST_LINE_MAXLEN], *c, *c2;
	int count = 0;
	int deleted = 0;
	struct manifest *manifest;
	struct list *includes = NULL;
	char *filename;
	char *basedir;
	uint64_t filecount = 0;
	uint64_t contentsize = 0;
	int manifest_hdr_version;
	int manifest_enc_version;

	if (!is_mix) {
		basedir = state_dir;
	} else {
		basedir = MIX_STATE_DIR;
	}
	string_or_die(&filename, "%s/%i/Manifest.%s", basedir, version, component);

	infile = fopen(filename, "rbm");
	if (infile == NULL) {
		free_string(&filename);
		return NULL;
	}
	free_string(&filename);

	/* line 1: MANIFEST\t<version> */
	line[0] = 0;
	if (fgets(line, MANIFEST_LINE_MAXLEN - 1, infile) == NULL) {
		goto err_close;
	}

	if (strncmp(line, "MANIFEST\t", 9) != 0) {
		goto err_close;
	}

	c = &line[9];
	manifest_enc_version = strtoull(c, NULL, 10);
	if (manifest_enc_version == 0) {
		goto err_close;
	}

	line[0] = 0;
	while (strcmp(line, "\n") != 0) {
		/* read the header */
		line[0] = 0;
		if (fgets(line, MANIFEST_LINE_MAXLEN - 1, infile) == NULL) {
			break;
		}
		c = strchr(line, '\n');
		if (c) {
			*c = 0;
		} else {
			goto err_close;
		}

		if (strlen(line) == 0) {
			break;
		}
		c = strchr(line, '\t');
		if (c) {
			c++;
		} else {
			goto err_close;
		}

		if (strncmp(line, "version:", 8) == 0) {
			manifest_hdr_version = strtoull(c, NULL, 10);
			if (manifest_hdr_version != version) {
				goto err_close;
			}
		}
		if (strncmp(line, "filecount:", 10) == 0) {
			filecount = strtoull(c, NULL, 10);
		}
		if (strncmp(line, "contentsize:", 12) == 0) {
			contentsize = strtoull(c, NULL, 10);
		}
		if (latest && strncmp(component, "MoM", 3) == 0) {
			if (strncmp(line, "actions:", 8) == 0) {
				post_update_actions = list_prepend_data(post_update_actions, strdup(c));
				if (!post_update_actions->data) {
					fprintf(stderr, "WARNING: Unable to read post update action from Manifest.MoM. \
							Another update or verify may be required.\n");
				}
			}
		}
Ejemplo n.º 16
0
/* This function is meant to be called while staging file to fix any missing/incorrect paths.
 * While staging a file, if its parent directory is missing, this would try to create the path
 * by breaking it into sub-paths and fixing them top down.
 * Here, target_MoM is the consolidated manifest for the version you are trying to update/verify.
 */
int verify_fix_path(char *targetpath, struct manifest *target_MoM)
{
	struct list *path_list = NULL; /* path_list contains the subparts in the path */
	char *path;
	char *tmp = NULL, *target = NULL;
	char *url = NULL;
	struct stat sb;
	int ret = 0;
	struct file *file;
	char *tar_dotfile = NULL;
	struct list *list1 = NULL;

	/* This shouldn't happen */
	if (strcmp(targetpath, "/") == 0) {
		return ret;
	}

	/* Removing trailing '/' from the path */
	path = strdup_or_die(targetpath);
	if (path[strlen(path) - 1] == '/') {
		path[strlen(path) - 1] = '\0';
	}

	/* Breaking down the path into parts.
	 * eg. Path /usr/bin/foo will be broken into /usr,/usr/bin and /usr/bin/foo
	 */
	while (strcmp(path, "/") != 0) {
		path_list = list_prepend_data(path_list, strdup_or_die(path));
		tmp = strdup_or_die(dirname(path));
		free_string(&path);
		path = tmp;
	}
	free_string(&path);

	list1 = list_head(path_list);
	while (list1) {
		path = list1->data;
		list1 = list1->next;

		free_string(&target);
		free_string(&tar_dotfile);
		free_string(&url);

		target = mk_full_filename(path_prefix, path);

		/* Search for the file in the manifest, to get the hash for the file */
		file = search_file_in_manifest(target_MoM, path);
		if (file == NULL) {
			fprintf(stderr, "Error: Path %s not found in any of the subscribed manifests"
					"in verify_fix_path for path_prefix %s\n",
				path, path_prefix);
			ret = -1;
			goto end;
		}

		if (file->is_deleted) {
			fprintf(stderr, "Error: Path %s found deleted in verify_fix_path\n", path);
			ret = -1;
			goto end;
		}

		ret = stat(target, &sb);
		if (ret == 0) {
			if (verify_file(file, target)) {
				continue;
			}
			fprintf(stderr, "Hash did not match for path : %s ... fixing\n", path);
		} else if (ret == -1 && errno == ENOENT) {
			fprintf(stderr, "Path %s is missing on the file system ... fixing\n", path);
		} else {
			goto end;
		}
		/* In some circumstances (Docker using layers between updates/bundle adds,
                 * corrupt staging content) we could have content which fails to stage.
		 * In order to avoid this causing failure in verify_fix_path, remove the
		 * staging content before proceeding. This also cleans up in case any prior
		 * download failed in a partial state.
		 */
		unlink_all_staged_content(file);

		string_or_die(&tar_dotfile, "%s/download/.%s.tar", state_dir, file->hash);

		string_or_die(&url, "%s/%i/files/%s.tar", content_url, file->last_change, file->hash);
		ret = swupd_curl_get_file(url, tar_dotfile);

		if (ret != 0) {
			fprintf(stderr, "Error: Failed to download file %s in verify_fix_path\n", file->filename);
			unlink(tar_dotfile);
			goto end;
		}
		if (untar_full_download(file) != 0) {
			fprintf(stderr, "Error: Failed to untar file %s\n", file->filename);
			ret = -1;
			goto end;
		}

		ret = do_staging(file, target_MoM);
		if (ret != 0) {
			fprintf(stderr, "Error: Path %s failed to stage in verify_fix_path\n", path);
			goto end;
		}
	}
end:
	free_string(&target);
	free_string(&tar_dotfile);
	free_string(&url);
	list_free_list_and_data(path_list, free_path_data);
	return ret;
}
Ejemplo n.º 17
0
/* This function is meant to be called while staging file to fix any missing/incorrect paths.
 * While staging a file, if its parent directory is missing, this would try to create the path
 * by breaking it into sub-paths and fixing them top down.
 * Here, target_MoM is the consolidated manifest for the version you are trying to update/verify.
 */
int verify_fix_path(char *targetpath, struct manifest *target_MoM)
{
	struct list *path_list = NULL; /* path_list contains the subparts in the path */
	char *path;
	char *tmp = NULL, *target = NULL;
	char *url = NULL;
	struct stat sb;
	int ret = 0;
	struct file *file;
	char *tar_dotfile = NULL;
	struct list *list1 = NULL;

	/* This shouldn't happen */
	if (strcmp(targetpath, "/") == 0) {
		return ret;
	}

	/* Removing trailing '/' from the path */
	path = strdup(targetpath);
	if (path[strlen(path) - 1] == '/') {
		path[strlen(path) - 1] = '\0';
	}

	/* Breaking down the path into parts.
	 * eg. Path /usr/bin/foo will be broken into /usr,/usr/bin and /usr/bin/foo
	 */
	while (strcmp(path, "/") != 0) {
		path_list = list_prepend_data(path_list, strdup(path));
		tmp = strdup(dirname(path));
		free(path);
		path = tmp;
	}
	free(path);

	list1 = list_head(path_list);
	while (list1) {
		path = list1->data;
		list1 = list1->next;

		target = mk_full_filename(path_prefix, path);

		/* Search for the file in the manifest, to get the hash for the file */
		file = search_file_in_manifest(target_MoM, path);
		if (file == NULL) {
			printf("Error: Path %s not found in any of the subscribed manifests"
			       "in verify_fix_path for path_prefix %s\n",
			       path, path_prefix);
			ret = -1;
			goto end;
		}

		if (file->is_deleted) {
			printf("Error: Path %s found deleted in verify_fix_path\n", path);
			ret = -1;
			goto end;
		}

		ret = stat(target, &sb);
		if (ret == 0) {
			if (verify_file(file, target)) {
				continue;
			}
			printf("Hash did not match for path : %s\n", path);
		} else if (ret == -1 && errno == ENOENT) {
			printf("Path %s is missing on the file system\n", path);
		} else {
			goto end;
		}

		string_or_die(&tar_dotfile, "%s/download/.%s.tar", state_dir, file->hash);

		// clean up in case any prior download failed in a partial state
		unlink(tar_dotfile);

		string_or_die(&url, "%s/%i/files/%s.tar", content_url, file->last_change, file->hash);
		ret = swupd_curl_get_file(url, tar_dotfile, NULL, NULL, false);

		if (ret != 0) {
			printf("Error: Failed to download file %s in verify_fix_path\n", file->filename);
			unlink(tar_dotfile);
			goto end;
		}
		if (untar_full_download(file) != 0) {
			printf("Error: Failed to untar file %s\n", file->filename);
			ret = -1;
			goto end;
		}

		ret = do_staging(file, target_MoM);
		if (ret != 0) {
			printf("Error: Path %s failed to stage in verify_fix_path\n", path);
			goto end;
		}
	}
end:
	if (target) {
		free(target);
	}
	if (tar_dotfile) {
		free(tar_dotfile);
	}
	if (url) {
		free(url);
	}
	list_free_list_and_data(path_list, free_path_data);
	return ret;
}
Ejemplo n.º 18
0
/* do_search()
 * Description: Perform a lookup of the specified search string in all Clear manifests
 * for the current os release.
 */
static void do_search(struct manifest *MoM, char search_type, char *search_term)
{
	struct list *list;
	struct list *sublist;
	struct file *file;
	struct file *subfile;
	struct list *bundle_info = NULL;
	struct manifest *subman = NULL;
	int i;
	bool done_with_bundle, done_with_search = false;
	bool hit = false;
	bool man_load_failures = false;
	long hit_count = 0;

	list = MoM->manifests;
	while (list && !done_with_search) {
		file = list->data;
		list = list->next;
		done_with_bundle = false;

		/* Load sub-manifest */
		subman = load_manifest(file->last_change, file, MoM, false);
		if (!subman) {
			fprintf(stderr, "Failed to load manifest %s\n", file->filename);
			man_load_failures = true;
			continue;
		}

		/* record contentsize and includes for install size calculation */
		struct bundle_result *bundle = NULL;
		bundle = calloc(sizeof(struct bundle_result), 1);
		ON_NULL_ABORT(bundle);
		/* copy relevant information over for future use */
		strncpy(bundle->bundle_name, subman->component, BUNDLE_NAME_MAXLEN - 1);
		bundle->topsize = subman->contentsize;
		/* do a deep copy of the includes list */
		bundle->includes = list_deep_clone_strs(subman->includes);
		bundle_info = list_prepend_data(bundle_info, bundle);

		if (display_files) {
			/* Display bundle name. Marked up for pattern matchability */
			fprintf(stderr, "--Bundle: %s--\n", file->filename);
		}

		/* Loop through sub-manifest, searching for files matching the desired pattern */
		sublist = subman->files;
		while (sublist && !done_with_bundle) {
			subfile = sublist->data;
			sublist = sublist->next;

			if ((!subfile->is_file) && (!subfile->is_link)) {
				continue;
			}

			if (display_files) {
				/* Just display filename */
				file_search(subfile->filename, NULL, NULL);
			} else if (search_type == '0') {
				/* Search for exact match, not path addition */
				if (file_search(subfile->filename, "", search_term)) {
					report_find(file->filename, subfile->filename, search_term);
					hit = true;
				}
			} else if (search_type == 'l') {
				/* Check each supported library path for a match */
				for (i = 0; lib_paths[i] != NULL; i++) {
					if (file_search(subfile->filename, lib_paths[i], search_term)) {
						report_find(file->filename, subfile->filename, search_term);
						hit = true;
					}
				}
			} else if (search_type == 'b') {
				/* Check each supported path for binaries */
				for (i = 0; bin_paths[i] != NULL; i++) {
					if (file_search(subfile->filename, bin_paths[i], search_term)) {
						report_find(file->filename, subfile->filename, search_term);
						hit = true;
					}
				}
			} else {
				fprintf(stderr, "Unrecognized search type. -b or -l supported\n");
				done_with_search = true;
				break;
			}

			/* Determine the level of completion we've reached */
			if (hit) {
				if (scope == 'b') {
					done_with_bundle = true;
				} else if (scope == 'o') {
					done_with_bundle = true;
					done_with_search = true;
				}

				hit_count++;
			}
			hit = false;
		}

		free_manifest(subman);
	}

	if (!hit_count) {
		fprintf(stderr, "Search term not found.\n");
	}

	bool display_size = (scope != 'o' && !man_load_failures);
	if (display_size) {
		apply_size_penalty(bundle_info);
	}
	list_free_list_and_data(bundle_info, free_bundle_result_data);

	if (num_results != INT_MAX) {
		sort_results();
	} else {
		results = list_sort(results, bundle_size_cmp);
	}

	if (csv_format) {
		print_csv_results();
	} else {
		print_final_results(display_size);
	}
	list_free_list_and_data(results, free_bundle_result_data);
}
Ejemplo n.º 19
0
int main(int argc, char **argv)
{
	struct list *list = NULL;
	struct list *list1, *list2;
	struct list *item, *item2, *item3, *head, *tail;
	unsigned int i;
	struct timeval tod;
	unsigned int seed;
	unsigned int len = TEST_LIST_LEN;
	clock_t t;
	unsigned int *data;

	/* List length must be greater than 3 for all tests to work */
	if (argc > 1) {
		len = atoi(argv[1]);
	}
	if (len < 4) {
		printf("List length must be at least 4 for tests.\n");
		return EXIT_FAILURE;
	}

	/* seed the random generator so that we get different lists each time */
	gettimeofday(&tod, NULL);
	seed = (unsigned int) tod.tv_sec;
	srand(seed);

	/* create a list with random data between 0 and len */
	for (i = 1; i <= len; i++) {
		data = malloc(sizeof(unsigned int));
		if (!data) {
			printf("data allocation failed\n");
			exit(-1);
		}
		*data = (unsigned int) rand() % len;
		list = list_append_data(list, data);
	}
	printf("List constructed, seed = %d, len = %d\n", seed, list_len(list));

	t = clock();
	list = list_sort(list, data_compare);
	t = clock() - t;

	/* check list elements are in right order */
	if (check_list_order(list, 1) != 0) {
		printf ("Sorted (1) List is in wrong order\n");
		return EXIT_FAILURE;
	}

	/* check sorted list has the expected len */
	if (list_len(list) != len) {
		printf("Wrong sorted (1) list len = %d instead of %d", i, len);
		return EXIT_FAILURE;
	}
	// dump_list(list);
	printf("List sorted in %f seconds\n", (float) t / CLOCKS_PER_SEC);

	/* sort again on sorted list to check special case */

	t = clock();
	list = list_sort(list, data_compare);
	t = clock() - t;

	if (check_list_order(list, 1) != 0) {
		printf ("Sorted (2) List is in wrong order\n");
		return EXIT_FAILURE;
	}
	if (list_len(list) != len) {
		printf("Wrong sorted (2) list len = %d instead of %d", i, len);
		return EXIT_FAILURE;
	}
	// dump_list(list);
	printf("Sorted list sorted again in %f seconds\n", (float) t / CLOCKS_PER_SEC);

	/* reverse sort from sorted state */

	t = clock();
	list = list_sort(list, data_compare_reverse);
	t = clock() - t;

	if (check_list_order(list, -1) != 0) {
		printf ("Sorted (3) List is in wrong order\n");
		return EXIT_FAILURE;
	}
	if (list_len(list) != len) {
		printf("Wrong sorted (3) list len = %d instead of %d", i, len);
		return EXIT_FAILURE;
	}
	// dump_list(list);
	printf("Sorted list sorted reverse in %f seconds\n", (float) t / CLOCKS_PER_SEC);

	/* Check freeing the head item.
	 * This must return the 2nd item, which must be the new head */
	head = list_head(list);
	item2 = head->next;
	list = list_free_item(head, free);
	if (list != item2) {
		printf("removing head item did not return 2nd item\n");
		return EXIT_FAILURE;
	}
	if (item2->prev) {
		printf("item returned after removing head is not new head\n");
		return EXIT_FAILURE;
	}
	if (list_len(item2) != len - 1) {
		printf("removing head item did not result in the right list len\n");
		return EXIT_FAILURE;
	}
	printf ("Removing head correctly returned 2nd item as new head\n");

	/* Check freeing middle item, must return previous item */
	head = list_head(list);
	item2 = head->next;
	item3 = item2->next;
	list = list_free_item(item2, free);
	if (list != head) {
		printf("removing 2nd item did not return head item\n");
		return EXIT_FAILURE;
	}
	if ((head != item3->prev) || (head->next != item3)) {
		printf("removing 2nd item did not link 3rd item to head\n");
		return EXIT_FAILURE;
	}

	if (list_len(list) != len - 2) {
		printf("removing 2nd item did not result in the right list len\n");
		return EXIT_FAILURE;
	}
	printf ("Removing middle item correctly returned previous item\n");

	/* Check freeing tail, must return new tail */
	tail = list_tail(list);
	item = tail->prev;
	list = list_free_item(tail, free);
	if (list != item) {
		printf("removing tail did not return prev item\n");
		return EXIT_FAILURE;
	}
	tail = list_tail(list);
	if (list != tail) {
		printf("removing tail did not return new tail\n");
		return EXIT_FAILURE;
	}
	if (list_len(list) != len - 3) {
		printf("removing tail did not result in the right list len\n");
		return EXIT_FAILURE;
	}
	printf ("Removing tail correctly returned previous item as new tail\n");

	list_free_list_and_data(list, free);
	list = NULL;

	/* Check list_concat */
	list1 = NULL;
	list2 = NULL;

	for (i = 3; i > 0; i--) {
		data = malloc(sizeof(unsigned int));
		if (!data) {
			printf("data allocation failed\n");
			exit(-1);
		}
		*data = (unsigned int) i;
		list1 = list_prepend_data(list1, data);
	}

	for (i = 6; i > 3; i--) {
		data = malloc(sizeof(unsigned int));
		if (!data) {
			printf("data allocation failed\n");
			exit(-1);
		}
		*data = (unsigned int) i;
		list2 = list_prepend_data(list2, data);
	}

	/* Check concat one list with empty list */
	list = list_concat(list1, NULL);
	if (list_len(list) != 3) {
		printf("concat(list1, NULL) did not result in a list len of 3\n");
		return EXIT_FAILURE;
	}
	if (list != list1) {
		printf("concat(list1, NULL) did not return list1\n");
		return EXIT_FAILURE;
	}
	if (list_head(list) != list) {
		printf("concat(list1, NULL) did not return list1 head\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->data)) != 1) {
		printf("concat(list1, NULL) head is wrong\n");
		return EXIT_FAILURE;
	}
	printf ("concat(list1, NULL) is OK\n");
	// dump_list(list);

	/* Check concat empty list with one list*/
	list = list_concat(NULL, list2);
	if (list_len(list) != 3) {
		printf("concat(NULL, list2) did not result in a list len of 3\n");
		return EXIT_FAILURE;
	}
	if (list != list2) {
		printf("concat(NULL, list2) did not return list2\n");
		return EXIT_FAILURE;
	}
	if (list_head(list) != list) {
		printf("concat(NULL, list2) did not return list2 head\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->data)) != 4) {
		printf("concat(NULL, list2) head is wrong\n");
		return EXIT_FAILURE;
	}
	printf ("concat(NULL, list2) is OK\n");
	// dump_list(list);

	/* Check concat two lists */
	list = list_concat(list1->next, list2->next->next);
	if (list_len(list) != 6) {
		printf("concat(list1, list2) did not result in a list len of 6\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->data)) != 1) {
		printf("concat(list1, list2) did not return list1 head\n");
		return EXIT_FAILURE;
	}
	if (*((unsigned int*)(list->next->next->next->data)) != 4) {
		printf("concat(list1, list2) 4th item is not 4\n");
		return EXIT_FAILURE;
	}
	printf ("concat(list1, list2) is OK\n");
	// dump_list(list);

	list_free_list_and_data(list, free);

	printf ("*** ALL LIST TESTS COMPLETED OK***\n");

    return EXIT_SUCCESS;
}
Ejemplo n.º 20
0
/* full_download() attempts to enqueue a file for later asynchronous download
   - NOTE: See swupd_curl_get_file() for single file synchronous downloads. */
void full_download(struct file *file)
{
	char *url = NULL;
	CURL *curl = NULL;
	int ret = -EFULLDOWNLOAD;
	char *filename = NULL;
	CURLMcode curlm_ret = CURLM_OK;
	CURLcode curl_ret = CURLE_OK;

	ret = swupd_curl_hashmap_insert(file);
	if (ret > 0) { /* no download needed */
		/* File already exists - report success */
		ret = 0;
		goto out_good;
	} else if (ret < 0) { /* error */
		goto out_bad;
	} /* else (ret == 0)	   download needed */

	curl = curl_easy_init();
	if (curl == NULL) {
		goto out_bad;
	}
	file->curl = curl;

	ret = poll_fewer_than(MAX_XFER, MAX_XFER_BOTTOM);
	if (ret) {
		clean_curl_multi_queue();
		goto out_bad;
	}

	string_or_die(&url, "%s/%i/files/%s.tar", content_url, file->last_change, file->hash);

	string_or_die(&filename, "%s/download/.%s.tar", state_dir, file->hash);
	file->staging = filename;

	curl_ret = curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
	if (curl_ret != CURLE_OK) {
		goto out_bad;
	}

	curl_ret = curl_easy_setopt(curl, CURLOPT_PRIVATE, (void *)file);
	if (curl_ret != CURLE_OK) {
		goto out_bad;
	}
	curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, swupd_download_file);
	if (curl_ret != CURLE_OK) {
		goto out_bad;
	}
	curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)file);
	if (curl_ret != CURLE_OK) {
		goto out_bad;
	}

	curl_ret = swupd_curl_set_basic_options(curl, url);
	if (curl_ret != CURLE_OK) {
		goto out_bad;
	}

	curlm_ret = curl_multi_add_handle(mcurl, curl);
	if (curlm_ret != CURLM_OK) {
		goto out_bad;
	}

	if (poll_fewer_than(MAX_XFER + 10, MAX_XFER) != 0) {
		clean_curl_multi_queue();
	}
	ret = 0;
	goto out_good;

out_bad:
	failed = list_prepend_data(failed, file);
	if (curl != NULL) {
		/* Must remove handle out of multi queue first!*/
		curl_multi_remove_handle(mcurl, curl);
		curl_easy_cleanup(curl);
	}
	free(filename);
out_good:
	free(url);
}
Ejemplo n.º 21
0
extern int realmlist_create(char const * filename)
{
    FILE *          fp;
    unsigned int    line;
    unsigned int    pos;
    unsigned int    len;
    t_addr *        raddr;
    char *          temp;
    char *          buff;
    char *          name;
    char *          desc;
    char *          addr;
    t_realm *       realm;

    if (!filename)
    {
        eventlog(eventlog_level_error,"realmlist_create","got NULL filename");
        return -1;
    }

    if (!(realmlist_head = list_create()))
    {
        eventlog(eventlog_level_error,"realmlist_create","could not create list");
        return -1;
    }

    if (!(fp = fopen(filename,"r")))
    {
        eventlog(eventlog_level_error,"realmlist_create","could not open realm file \"%s\" for reading (fopen: %s)",filename,strerror(errno));
	list_destroy(realmlist_head);
	realmlist_head = NULL;
        return -1;
    }

    for (line=1; (buff = file_get_line(fp)); line++)
    {
        for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++);
        if (buff[pos]=='\0' || buff[pos]=='#')
        {
            free(buff);
            continue;
        }
        if ((temp = strrchr(buff,'#')))
        {
	    unsigned int endpos;

            *temp = '\0';
	    len = strlen(buff)+1;
            for (endpos=len-1;  buff[endpos]=='\t' || buff[endpos]==' '; endpos--);
            buff[endpos+1] = '\0';
        }
        len = strlen(buff)+1;

        if (!(name = malloc(len)))
        {
            eventlog(eventlog_level_error,"realmlist_create","could not allocate memory for name");
            free(buff);
            continue;
        }
        if (!(desc = malloc(len)))
        {
            eventlog(eventlog_level_error,"realmlist_create","could not allocate memory for desc");
            free(name);
            free(buff);
            continue;
        }
        if (!(addr = malloc(len)))
        {
            eventlog(eventlog_level_error,"realmlist_create","could not allocate memory for desc");
            free(desc);
            free(name);
            free(buff);
            continue;
        }

	if (sscanf(buff," \"%[^\"]\" \"%[^\"]\" %s",name,desc,addr)!=3)
	{
	    if (sscanf(buff," \"%[^\"]\" \"\" %s",name,addr)==2)
		desc[0] = '\0';
	    else
	    {
		eventlog(eventlog_level_error,"realmlist_create","malformed line %u in file \"%s\"",line,filename);
		free(addr);
		free(desc);
         	free(name);
		free(buff);
		continue;
	    }
	}

	free(buff);

	if (!(raddr = addr_create_str(addr,0,BNETD_REALM_PORT))) /* 0 means "this computer" */
	{
	    eventlog(eventlog_level_error,"realmlist_create","invalid address value for field 3 on line %u in file \"%s\"",line,filename);
	    free(addr);
	    free(desc);
	    free(name);
	    continue;
	}

	free(addr);

	if (!(realm = realm_create(name,desc,addr_get_ip(raddr),addr_get_port(raddr))))
	{
	    eventlog(eventlog_level_error,"realmlist_create","could not create realm");
	    addr_destroy(raddr);
	    free(desc);
	    free(name);
	    continue;
	}

	addr_destroy(raddr);
        free(desc);
	free(name);

	if (list_prepend_data(realmlist_head,realm)<0)
	{
	    eventlog(eventlog_level_error,"realmlist_create","could not prepend realm");
	    realm_destroy(realm);
	    continue;
	}
    }
    if (fclose(fp)<0)
	eventlog(eventlog_level_error,"realmlist_create","could not close realm file \"%s\" after reading (fclose: %s)",filename,strerror(errno));
    return 0;
}
Ejemplo n.º 22
0
static struct manifest *manifest_from_file(int version, char *component, bool header_only, bool latest, bool is_mix)
{
	FILE *infile;
	char line[MANIFEST_LINE_MAXLEN], *c, *c2;
	int count = 0;
	int deleted = 0;
	struct manifest *manifest;
	struct list *includes = NULL;
	char *filename;
	char *basedir;
	uint64_t filecount = 0;
	uint64_t contentsize = 0;
	int manifest_hdr_version;
	int manifest_enc_version;

	if (!is_mix) {
		basedir = state_dir;
	} else {
		basedir = MIX_STATE_DIR;
	}
	string_or_die(&filename, "%s/%i/Manifest.%s", basedir, version, component);

	infile = fopen(filename, "rbm");
	if (infile == NULL) {
		free_string(&filename);
		return NULL;
	}
	free_string(&filename);

	/* line 1: MANIFEST\t<version> */
	line[0] = 0;
	if (fgets(line, MANIFEST_LINE_MAXLEN - 1, infile) == NULL) {
		goto err_close;
	}

	if (strncmp(line, "MANIFEST\t", 9) != 0) {
		goto err_close;
	}

	c = &line[9];
	manifest_enc_version = strtoull(c, NULL, 10);
	if (manifest_enc_version == 0) {
		goto err_close;
	}

	line[0] = 0;
	while (strcmp(line, "\n") != 0) {
		/* read the header */
		line[0] = 0;
		if (fgets(line, MANIFEST_LINE_MAXLEN - 1, infile) == NULL) {
			break;
		}
		c = strchr(line, '\n');
		if (c) {
			*c = 0;
		} else {
			goto err_close;
		}

		if (strlen(line) == 0) {
			break;
		}
		c = strchr(line, '\t');
		if (c) {
			c++;
		} else {
			goto err_close;
		}

		if (strncmp(line, "version:", 8) == 0) {
			manifest_hdr_version = strtoull(c, NULL, 10);
			if (manifest_hdr_version != version) {
				goto err_close;
			}
		}
		if (strncmp(line, "filecount:", 10) == 0) {
			filecount = strtoull(c, NULL, 10);
			if (filecount > 4000000) {
				/* Note on the number 4,000,000. We want this
				 * to be big enough to allow Manifest.Full to
				 * pass (currently about 450,000 March 18) but
				 * small enough that when multiplied by
				 * sizeof(struct file) it fits into
				 * size_t. For a system with size_t being a 32
				 * bit value, this constrains it to be less
				 * than about 6,000,000, but close to infinity
				 * for systems with 64 bit size_t.
				 */
				fprintf(stderr, "Error: preposterous (%" PRIu64 ") number of files in %s Manifest, more than 4 million skipping\n",
					filecount, component);
				goto err_close;
			}
		}
		if (strncmp(line, "contentsize:", 12) == 0) {
			contentsize = strtoull(c, NULL, 10);
			if (contentsize > 2000000000000UL) {
				fprintf(stderr, "Error: preposterous (%" PRIu64 ") size of files in %s Manifest, more than 2TB skipping\n",
					contentsize, component);
				goto err_close;
			}
		}
		if (latest && strncmp(component, "MoM", 3) == 0) {
			if (strncmp(line, "actions:", 8) == 0) {
				post_update_actions = list_prepend_data(post_update_actions, strdup_or_die(c));
				if (!post_update_actions->data) {
					fprintf(stderr, "WARNING: Unable to read post update action from Manifest.MoM. \
							Another update or verify may be required.\n");
				}
			}
		}