예제 #1
0
void prepare_delta_dir(struct manifest *manifest)
{
	char *path;
	char *conf;

	printf("Preparing delta directory \n");

	conf = config_output_dir();

	string_or_die(&path, "%s/%i", conf, manifest->version);
	if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
		if (errno != EEXIST) {
			LOG(NULL, "Failed to create directory ", "%s", path);
			return;
		}
	}
	free(path);
	string_or_die(&path, "%s/%i/delta/", conf, manifest->version);
	if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
		if (errno != EEXIST) {
			LOG(NULL, "Failed to create directory ", "%s", path);
			return;
		}
	}

	free(path);
	free(conf);
}
예제 #2
0
static double query_total_download_size(struct list *list)
{
	double ret;
	double size_sum = 0;
	struct file *file = NULL;
	char *untard_file = NULL;
	char *url = NULL;

	while (list) {
		file = list->data;
		list = list->next;

		string_or_die(&untard_file, "%s/%i/Manifest.%s", state_dir, file->last_change,
			      file->filename);

		if (access(untard_file, F_OK) == -1) {
			/* Does not exist client-side. Must download */
			string_or_die(&url, "%s/%i/Manifest.%s.tar", content_url,
				      file->last_change, file->filename);

			ret = swupd_query_url_content_size(url);
			if (ret != -1) {
				/* Convert file size from bytes to MB */
				ret = ret / 1000000;
				size_sum += ret;
			} else {
				return ret;
			}
		}
	}

	free(untard_file);
	return size_sum;
}
예제 #3
0
void unlink_all_staged_content(struct file *file)
{
	char *filename;

	/* downloaded tar file */
	string_or_die(&filename, "%s/download/%s.tar", state_dir, file->hash);
	unlink(filename);
	free(filename);
	string_or_die(&filename, "%s/download/.%s.tar", state_dir, file->hash);
	unlink(filename);
	free(filename);

	/* downloaded and un-tar'd file */
	string_or_die(&filename, "%s/staged/%s", state_dir, file->hash);
	if (file->is_dir) {
		rmdir(filename);
	} else {
		unlink(filename);
	}
	free(filename);

	/* delta file */
	if (file->peer) {
		string_or_die(&filename, "%s/delta/%i-%i-%s", state_dir,
			      file->peer->last_change, file->last_change, file->hash);
		unlink(filename);
		free(filename);
	}
}
예제 #4
0
/* Returns 0 == success, -1 == failure */
static int write_manifest_tar(struct manifest *manifest)
{
	char *conf = config_output_dir();
	char *tarcmd = NULL;
	int ret = -1;

	if (conf == NULL) {
		assert(0);
	}

	/* now, tar the thing up for efficient full file download */
	/* and put the signature of the plain manifest into the archive, too */
	if (enable_signing) {
		string_or_die(&tarcmd, TAR_COMMAND " --directory=%s/%i " TAR_PERM_ATTR_ARGS " -Jcf "
						   "%s/%i/Manifest.%s.tar Manifest.%s Manifest.%s.signed",
			      conf, manifest->version, conf, manifest->version, manifest->component,
			      manifest->component, manifest->component);
	} else {
		string_or_die(&tarcmd, TAR_COMMAND " --directory=%s/%i " TAR_PERM_ATTR_ARGS " -Jcf "
						   "%s/%i/Manifest.%s.tar Manifest.%s",
			      conf, manifest->version, conf, manifest->version, manifest->component,
			      manifest->component);
	}

	if (system(tarcmd) != 0) {
		fprintf(stderr, "Creation of Manifest.tar failed\n");
		goto exit;
	}
	ret = 0;
exit:
	free(tarcmd);
	free(conf);
	return ret;
}
예제 #5
0
// prepends prefix to an path (eg: the global path_prefix to a
// file->filename or some other path prefix and path), insuring there
// is no duplicate '/' at the strings' junction and no trailing '/'
char *mk_full_filename(const char *prefix, const char *path)
{
	char *fname = NULL;
	size_t len = 0;

	if (!path) {
		return NULL;
	}

	if (prefix) {
		len = strlen(prefix);
	}
	//Remove trailing '/' at the end of prefix
	while (len && prefix[len - 1] == '/') {
		len--;
	}

	//make sure a '/' will always be added between prefix and path
	if (path[0] == '/') {
		string_or_die(&fname, "%.*s%s", len, prefix, path);
	} else {
		string_or_die(&fname, "%.*s/%s", len, prefix, path);
	}
	return fname;
}
예제 #6
0
static int download_pack(int oldversion, int newversion, char *module)
{
	FILE *tarfile = NULL;
	char *tar = NULL;
	char *url = NULL;
	int err = -1;
	char *filename;
	struct stat stat;

	string_or_die(&filename, "%s/pack-%s-from-%i-to-%i.tar", STATE_DIR, module, oldversion, newversion);

	err = lstat(filename, &stat);
	if (err == 0 && stat.st_size == 0) {
		free(filename);
		return 0;
	}

	printf("Downloading %s pack for version %i\n", module, newversion);

	string_or_die(&url, "%s/%i/pack-%s-from-%i.tar", preferred_content_url, newversion, module, oldversion);

	err = swupd_curl_get_file(url, filename, NULL, NULL, true);
	if (err) {
		free(url);
		if ((lstat(filename, &stat) == 0) && (stat.st_size == 0)) {
			unlink(filename);
		}
		free(filename);
		return err;
	}

	if (!signature_download_and_verify(url, filename)) {
		free(url);
		unlink(filename);
		free(filename);
		return -1;
	}

	free(url);

	printf("Extracting pack.\n");
	string_or_die(&tar, "tar -C %s " TAR_PERM_ATTR_ARGS " -xf %s/pack-%s-from-%i-to-%i.tar 2> /dev/null",
		      STATE_DIR, STATE_DIR, module, oldversion, newversion);

	err = system(tar);
	if (WIFEXITED(err)) {
		err = WEXITSTATUS(err);
	}
	free(tar);
	unlink(filename);
	/* make a zero sized file to prevent redownload */
	tarfile = fopen(filename, "w");
	free(filename);
	if (tarfile) {
		fclose(tarfile);
	}

	return err;
}
예제 #7
0
static int download_pack(int oldversion, int newversion, char *module)
{
	FILE *tarfile = NULL;
	char *tar = NULL;
	char *url = NULL;
	int err = -1;
	char *filename;
	struct stat stat;

	string_or_die(&filename, "%s/pack-%s-from-%i-to-%i.tar", state_dir, module, oldversion, newversion);

	err = lstat(filename, &stat);
	if (err == 0 && stat.st_size == 0) {
		free(filename);
		return 0;
	}

	printf("Downloading %s pack for version %i\n", module, newversion);

	string_or_die(&url, "%s/%i/pack-%s-from-%i.tar", content_url, newversion, module, oldversion);

	err = swupd_curl_get_file(url, filename, NULL, NULL, true);
	if (err) {
		free(url);
		if ((lstat(filename, &stat) == 0) && (stat.st_size == 0)) {
			unlink(filename);
		}
		free(filename);
		return err;
	}

	free(url);

	printf("Extracting pack.\n");
	string_or_die(&tar, TAR_COMMAND " -C %s " TAR_PERM_ATTR_ARGS " -xf %s/pack-%s-from-%i-to-%i.tar 2> /dev/null",
		      state_dir, state_dir, module, oldversion, newversion);

	err = system(tar);
	if (WIFEXITED(err)) {
		err = WEXITSTATUS(err);
	}
	free(tar);
	unlink(filename);
	/* make a zero sized file to prevent redownload */
	tarfile = fopen(filename, "w");
	free(filename);
	if (tarfile) {
		fclose(tarfile);
	}

	// Only negative return values should indicate errors
	if (err > 0) {
		return -err;
	} else {
		return err;
	}
}
예제 #8
0
static void download_file(struct swupd_curl_parallel_handle *download_handle, struct file *file)
{
	char *url, *filename;

	string_or_die(&filename, "%s/download/.%s.tar", state_dir, file->hash);
	string_or_die(&url, "%s/%i/files/%s.tar", content_url, file->last_change, file->hash);
	swupd_curl_parallel_download_enqueue(download_handle, url, filename, file->hash, file);
	free_string(&url);
	free_string(&filename);
}
예제 #9
0
static int create_required_dirs(void)
{
	int ret = 0;
	int i;
	char *dir;
#define STATE_DIR_COUNT 3
	const char *dirs[] = { "delta", "staged", "download" };
	struct stat buf;
	bool missing = false;

	// check for existance
	ret = stat(state_dir, &buf);
	if (ret && (errno == ENOENT)) {
		missing = true;
	}
	for (i = 0; i < STATE_DIR_COUNT; i++) {
		string_or_die(&dir, "%s/%s", state_dir, dirs[i]);
		ret = stat(dir, &buf);
		if (ret) {
			missing = true;
		}
		free(dir);
	}

	if (missing) { // (re)create dirs
		char *cmd;

		for (i = 0; i < STATE_DIR_COUNT; i++) {
			string_or_die(&cmd, "mkdir -p %s/%s", state_dir, dirs[i]);
			ret = system(cmd);
			if (ret) {
				printf("Error: failed to create %s/%s\n", state_dir, dirs[i]);
				return -1;
			}
			free(cmd);

			string_or_die(&dir, "%s/%s", state_dir, dirs[i]);
			ret = chmod(dir, S_IRWXU);
			if (ret) {
				printf("Error: failed to set mode for %s/%s\n", state_dir, dirs[i]);
				return -1;
			}
			free(dir);
		}

		// chmod 700
		ret = chmod(state_dir, S_IRWXU);
		if (ret) {
			printf("Error: failed to set mode for state dir (%s)\n", state_dir);
			return -1;
		}
	}

	return 0;
}
예제 #10
0
/**
 * store a colon separated list of current mountpoint into
 * variable mounted_dirs, this function do not return a value.
 *
 * e.g: :/proc:/mnt/acct:
 */
static void get_mounted_directories(void)
{
	FILE *file;
	char *line = NULL;
	char *mnt;
	char *tmp;
	ssize_t ret;
	char *c;
	size_t n;

	file = fopen("/proc/self/mountinfo", "r");
	if (!file) {
		return;
	}

	while (!feof(file)) {
		ret = getline(&line, &n, file);
		if ((ret < 0) || (line == NULL)) {
			break;
		}

		c = strchr(line, '\n');
		if (c) {
			*c = 0;
		}

		n = 0;
		mnt = strtok(line, " ");
		while (mnt != NULL) {
			if (n == 4) {
				/* The "4" assumes today's mountinfo form of:
				* 16 36 0:3 / /proc rw,relatime master:7 - proc proc rw
				* where the fifth field is the mountpoint. */
				if (strcmp(mnt, "/") == 0) {
					break;
				}

				if (mounted_dirs == NULL) {
					string_or_die(&mounted_dirs, "%s", ":");
				}
				tmp = mounted_dirs;
				string_or_die(&mounted_dirs, "%s%s:", tmp, mnt);
				free(tmp);
				break;
			}
			n++;
			mnt = strtok(NULL, " ");
		}
		free(line);
		line = NULL;
	}
	free(line);
	fclose(file);
}
예제 #11
0
int get_current_version(char *path_prefix)
{
	char line[LINE_MAX];
	FILE *file;
	int v = -1;
	int err;
	char *buildstamp;
	char *src, *dest;

	string_or_die(&buildstamp, "%s/usr/lib/os-release", path_prefix);
	file = fopen(buildstamp, "rm");
	if (!file) {
		free_string(&buildstamp);
		string_or_die(&buildstamp, "%s/etc/os-release", path_prefix);
		file = fopen(buildstamp, "rm");
		if (!file) {
			free_string(&buildstamp);
			return v;
		}
	}

	while (!feof(file)) {
		line[0] = 0;
		if (fgets(line, LINE_MAX, file) == NULL) {
			break;
		}
		if (strncmp(line, "VERSION_ID=", 11) == 0) {
			src = &line[11];
			/* Drop quotes and newline in value */
			dest = src;
			while (*src) {
				if (*src == '\'' || *src == '"' || *src == '\n') {
					++src;
				} else {
					*dest = *src;
					++dest;
					++src;
				}
			}
			*dest = 0;

			err = strtoi_err(&line[11], &v);
			if (err != 0) {
				v = -1;
			}
			break;
		}
	}

	free_string(&buildstamp);
	fclose(file);
	return v;
}
예제 #12
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;
}
예제 #13
0
int create_required_dirs(void)
{
	int ret = 0;
	int i;
	char *dir;
#define STATE_DIR_COUNT 3
	const char *dirs[] = { "delta", "staged", "download" };
	struct stat buf;
	bool missing = false;

	// check for existance
	ret = stat(STATE_DIR, &buf);
	if (ret && (errno == ENOENT)) {
		missing = true;
	}
	for (i = 0; i < STATE_DIR_COUNT; i++) {
		string_or_die(&dir, "%s/%s", STATE_DIR, dirs[i]);
		ret = stat(dir, &buf);
		if (ret) {
			missing = true;
		}
		free(dir);
	}

	if (missing) { // (re)create dirs
		char *cmd;

		// laziness here for want of a simple "mkdir -p"
		string_or_die(&cmd, "mkdir -p %s/{delta,staged,download}", STATE_DIR);
		ret = system(cmd);
		if (ret) {
			return -1;
		}
		free(cmd);

		// chmod 700
		ret = chmod(STATE_DIR, S_IRWXU);
		if (ret) {
			return -1;
		}
		for (i = 0; i < STATE_DIR_COUNT; i++) {
			string_or_die(&dir, "%s/%s", STATE_DIR, dirs[i]);
			ret = chmod(dir, S_IRWXU);
			if (ret) {
				return -1;
			}
			free(dir);
		}
	}

	return 0;
}
예제 #14
0
/* Remove the contents of a staging directory (eg: /mnt/swupd/update/780 or
 * /mnt/swupd/update/delta) which are not supposed to contain
 * subdirectories containing files, ie: no need for true recursive removal.
 * Just the relative path (et: "780" or "delta" is passed as a parameter).
 *
 * return: 0 on success, non-zero on error
 */
int rm_staging_dir_contents(const char *rel_path)
{
	DIR *dir;
	struct dirent *entry;
	char *filename;
	char *abs_path;
	int ret = 0;

	string_or_die(&abs_path, "%s/%s", state_dir, rel_path);

	dir = opendir(abs_path);
	if (dir == NULL) {
		free_string(&abs_path);
		return -1;
	}

	while (true) {
		errno = 0;
		entry = readdir(dir);
		if (!entry) {
			/* readdir returns NULL on the end of a directory stream, we only
			 * want to set ret if errno is also set, indicating a failure */
			if (errno) {
				ret = errno;
			}
			break;
		}

		if (!strcmp(entry->d_name, ".") ||
		    !strcmp(entry->d_name, "..")) {
			continue;
		}

		string_or_die(&filename, "%s/%s", abs_path, entry->d_name);

		ret = remove(filename);
		if (ret != 0) {
			free_string(&filename);
			break;
		}
		free_string(&filename);
	}

	free_string(&abs_path);
	closedir(dir);

	return ret;
}
예제 #15
0
/* Compares the hash for BUNDLE with that listed in the Manifest.MoM.  If the
 * hash check fails, for now, we print a warning and return success, but
 * eventually will switch to being a fatal error and exit early.
 */
int verify_bundle_hash(struct manifest *manifest, struct file *bundle)
{
	struct list *iter = list_head(manifest->manifests);
	struct file *current;
	char *local = NULL;
	int ret = 0;

	while (iter) {
		current = iter->data;
		iter = iter->next;

		if (strcmp(current->filename, bundle->filename) != 0) {
			continue;
		}

		string_or_die(&local, "%s/%i/Manifest.%s", state_dir,
			      current->last_change, current->filename);

		if (!verify_file(bundle, local)) {
			printf("Warning: hash check failed for Manifest.%s for version %i\n",
			       current->filename, manifest->version);
			ret = 0;
		}
		break;
	}

	free(local);
	return ret;
}
예제 #16
0
/* clean_statedir will clean the state directory used by swupd (default to
 * /var/lib/swupd). It will remove all files except relevant manifests unless
 * all is set to true. Setting dry_run to true will print the files that would
 * be removed but will not actually remove them. */
enum swupd_code clean_statedir(bool dry_run, bool all)
{

	char *staged_dir = NULL;
	string_or_die(&staged_dir, "%s/staged", state_dir);
	int ret = remove_if(staged_dir, dry_run, is_fullfile);
	free_string(&staged_dir);
	if (ret != 0) {
		return ret;
	}

	/* Pack presence indicator files. */
	ret = remove_if(state_dir, dry_run, is_pack_indicator);
	if (ret != 0) {
		return ret;
	}

	/* Manifest delta files. */
	ret = remove_if(state_dir, dry_run, is_manifest_delta);
	if (ret != 0) {
		return ret;
	}

	/* NOTE: do not clean the state_dir/bundles directory */

	return clean_staged_manifests(state_dir, dry_run, all);
}
예제 #17
0
void ensure_version_image_exists(int version)
{
	char *conf;
	char *path = NULL;
	struct stat buf;
	int ret;

	conf = config_image_base();

	string_or_die(&path, "%s/%i", conf, version);

	free(conf);

	ret = stat(path, &buf);
	if (ret < 0) {
		fprintf(stderr, "Failed to stat image directory %s (%s).. exiting\n", path, strerror(errno));
		exit(EXIT_FAILURE);
	}

	if (!S_ISDIR(buf.st_mode)) {
		fprintf(stderr, "Assumed image directory %s is not a directory.. exiting\n", path);
		exit(EXIT_FAILURE);
	}

	free(path);
}
예제 #18
0
void write_new_version(char *filename, int version)
{
	FILE *file;
	char *fullfile = NULL;
	char *conf;

	conf = config_image_base();

	string_or_die(&fullfile, "%s/%s", conf, filename);

	file = fopen(fullfile, "w");

	free(conf);

	if (!file) {
		fprintf(stderr, "Cannot write new version, failed to open %s (%s)\n", fullfile, strerror(errno));
		free(fullfile);
		return;
	}

	fprintf(file, "%i\n", version);

	fclose(file);
	free(fullfile);
}
예제 #19
0
void read_current_version(char *filename)
{
	FILE *file;
	int v = 0;
	char *fullfile = NULL;
	char *conf;

	conf = config_image_base();

	string_or_die(&fullfile, "%s/%s", conf, filename);

	file = fopen(fullfile, "rm");

	free(conf);

	if (!file) {
		fprintf(stderr, "Cannot read current version, failed to open %s (%s)\n", fullfile, strerror(errno));
		free(fullfile);
		return;
	}

	if (fscanf(file, "%i", &v) < 0) {
		/* not even a single int there --> make sure to return 0 */
		fprintf(stderr, "Version file %s does not have a number in it. Setting version to 0\n", fullfile);
	}

	fclose(file);
	free(fullfile);

	current_version = v;
}
예제 #20
0
static int create_required_dirs(void)
{
	int ret = 0;
	unsigned int i;
	char *dir;
#define STATE_DIR_COUNT (sizeof(state_dirs) / sizeof(state_dirs[0]))
	const char *state_dirs[] = { "delta", "staged", "download", "telemetry" };

	// check for existence
	if (ensure_root_owned_dir(state_dir)) {
		//state dir doesn't exist
		if (mkdir_p(state_dir) != 0 || chmod(state_dir, S_IRWXU) != 0) {
			fprintf(stderr, "Error: failed to create %s\n", state_dir);
			return -1;
		}
	}

	for (i = 0; i < STATE_DIR_COUNT; i++) {
		string_or_die(&dir, "%s/%s", state_dir, state_dirs[i]);
		ret = ensure_root_owned_dir(dir);
		if (ret) {
			ret = mkdir(dir, S_IRWXU);
			if (ret) {
				fprintf(stderr, "Error: failed to create %s\n", dir);
				return -1;
			}
		}
		free_string(&dir);
	}
	/* Do a final check to make sure that the top level dir wasn't
	 * tampered with whilst we were creating the dirs */
	return ensure_root_owned_dir(state_dir);
}
예제 #21
0
int rm_bundle_file(const char *bundle)
{
	char *filename = NULL;
	int ret = 0;
	struct stat statb;

	string_or_die(&filename, "%s/%s/%s", path_prefix, BUNDLES_DIR, bundle);

	if (stat(filename, &statb) == -1) {
		goto out;
	}

	if (S_ISREG(statb.st_mode)) {
		if (unlink(filename) != 0) {
			ret = -1;
			goto out;
		}
	} else {
		ret = -1;
		goto out;
	}

out:
	free(filename);
	return ret;
}
예제 #22
0
static int swupd_rm_dir(const char *path)
{
	DIR *dir;
	struct dirent *entry;
	char *filename = NULL;
	int ret = 0;
	int err;

	dir = opendir(path);
	if (dir == NULL) {
		if (errno == ENOENT) {
			ret = 0;
			goto exit;
		} else {
			ret = -1;
			goto exit;
		}
	}

	while (true) {
		errno = 0;
		entry = readdir(dir);
		if (!entry) {
			if (!errno) {
				ret = errno;
			}
			break;
		}

		if (!strcmp(entry->d_name, ".") ||
		    !strcmp(entry->d_name, "..")) {
			continue;
		}

		free_string(&filename);
		string_or_die(&filename, "%s/%s", path, entry->d_name);

		err = swupd_rm(filename);
		if (err) {
			ret = -1;
			goto exit;
		}
	}

	/* Delete directory once it's empty */
	err = rmdir(path);
	if (err) {
		if (errno == ENOENT) {
		} else {
			ret = -1;
			goto exit;
		}
	}

exit:
	closedir(dir);
	free_string(&filename);
	return ret;
}
예제 #23
0
int mkdir_p(const char *dir)
{
	char *cmd;
	string_or_die(&cmd, "mkdir -p %s", dir);
	int ret = system(cmd);
	free_string(&cmd);
	return ret;
}
예제 #24
0
static void unlink_all_staged_content(struct file *file)
{
	char *filename;

	/* downloaded tar file */
	string_or_die(&filename, "%s/download/%s.tar", state_dir, file->hash);
	unlink(filename);
	free_string(&filename);
	string_or_die(&filename, "%s/download/.%s.tar", state_dir, file->hash);
	unlink(filename);
	free_string(&filename);

	/* downloaded and un-tar'd file */
	string_or_die(&filename, "%s/staged/%s", state_dir, file->hash);
	(void)remove(filename);
	free_string(&filename);
}
예제 #25
0
void check_mix_versions(int *current_version, int *server_version, char *path_prefix)
{
	*current_version = read_mix_version_file("/usr/share/clear/version", path_prefix);
	char *format_file;
	string_or_die(&format_file, MIX_STATE_DIR "version/format%s/latest", format_string);
	*server_version = read_mix_version_file(format_file, path_prefix);
	free_string(&format_file);
}
예제 #26
0
static void download_mix_file(struct file *file)
{
	char *url, *filename;

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

	/* Mix content is local, so don't queue files up for curl downloads */
	if (link_or_rename(url, filename) == 0) {
		untar_full_download(file);
	} else {
		warn("Failed to copy local mix file: %s\n", file->staging);
	}

	free_string(&url);
	free_string(&filename);
}
예제 #27
0
int copy_all(const char *src, const char *dst)
{
	char *cmd;
	string_or_die(&cmd, "cp -a %s %s 2> /dev/null", src, dst);
	int ret = system(cmd);
	free_string(&cmd);
	return ret;
}
예제 #28
0
// expects filename w/o path_prefix prepended
bool is_under_mounted_directory(const char *filename)
{
	bool ret = false;
	int err;
	char *token;
	char *mountpoint;
	char *dir;
	char *fname;
	char *tmp;

	if (mounted_dirs == NULL) {
		return false;
	}

	dir = strdup(mounted_dirs);
	if (dir == NULL) {
		abort();
	}

	token = strtok(dir + 1, ":");
	while (token != NULL) {
		string_or_die(&mountpoint, "%s/", token);

		tmp = mk_full_filename(path_prefix, filename);
		string_or_die(&fname, ":%s:", tmp);
		free(tmp);

		err = strncmp(fname, mountpoint, strlen(mountpoint));
		free(fname);
		if (err == 0) {
			free(mountpoint);
			ret = true;
			break;
		}

		token = strtok(NULL, ":");

		free(mountpoint);
	}

	free(dir);

	return ret;
}
예제 #29
0
void create_fullfiles(struct manifest *manifest)
{
	GList *deduped_file_list;
	char *path;
	char *conf, *empty;

	empty = config_empty_dir();

	char *const rmcmd[] = { "rm", "-rf", empty, NULL };
	if (system_argv(rmcmd) != 0) {
		assert(0);
	}
	g_mkdir_with_parents(empty, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
	free(empty);

	conf = config_output_dir();

	string_or_die(&path, "%s/%i", conf, manifest->version);
	if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
		if (errno != EEXIST) {
			LOG(NULL, "Failed to create directory ", "%s", path);
			return;
		}
	}
	free(path);
	string_or_die(&path, "%s/%i/files/", conf, manifest->version);
	if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
		if (errno != EEXIST) {
			LOG(NULL, "Failed to create directory ", "%s", path);
			return;
		}
	}
	free(path);
	free(conf);

	/* De-duplicate the list of fullfiles needing created to avoid races */
	deduped_file_list = get_deduplicated_fullfile_list(manifest);

	/* Submit tasks to create full files */
	submit_fullfile_tasks(deduped_file_list);

	g_list_free(deduped_file_list);
}
예제 #30
0
/* Remove the contents of a staging directory (eg: /mnt/swupd/update/780 or
 * /mnt/swupd/update/delta) which are not supposed to contain
 * subdirectories containing files, ie: no need for true recursive removal.
 * Just the relative path (et: "780" or "delta" is passed as a parameter).
 *
 * return: 0 on success, non-zero on error
 */
int rm_staging_dir_contents(const char *rel_path)
{
	DIR *dir;
	struct dirent entry;
	struct dirent *result;
	char *filename;
	char *abs_path;
	int ret;

	string_or_die(&abs_path, "%s/%s", state_dir, rel_path);

	dir = opendir(abs_path);
	if (dir == NULL) {
		free(abs_path);
		return -1;
	}

	while ((ret = readdir_r(dir, &entry, &result)) == 0) {
		if (result == NULL) {
			break;
		}

		if (!strcmp(entry.d_name, ".") ||
		    !strcmp(entry.d_name, "..")) {
			continue;
		}

		string_or_die(&filename, "%s/%s", abs_path, entry.d_name);

		ret = remove(filename);
		if (ret != 0) {
			free(filename);
			break;
		}
		free(filename);
	}

	free(abs_path);
	closedir(dir);

	sync();
	return ret;
}