예제 #1
0
파일: write.c 프로젝트: kamilWLca/brix
/*
 * Write a single entry to the archive.
 */
static void
write_entry(struct bsdtar *bsdtar, struct archive *a,
    struct archive_entry *entry)
{
	int fd = -1;
	int e;
	size_t align = 4096;

	if (archive_entry_size(entry) > 0) {
		const char *pathname = archive_entry_sourcepath(entry);
		/* TODO: Use O_DIRECT here and set 'align' to the
		 * actual filesystem block size.  As of July 2010, new
		 * directory-traversal code is going in that will make
		 * it much easier to track filesystem properties like
		 * this during the traversal. */
		fd = open(pathname, O_RDONLY | O_BINARY);
		align = 4096;
		if (fd == -1) {
			if (!bsdtar->verbose)
				lafe_warnc(errno,
				    "%s: could not open file", pathname);
			else
				fprintf(stderr, ": %s", strerror(errno));
			return;
		}
	}

	e = archive_write_header(a, entry);
	if (e != ARCHIVE_OK) {
		if (!bsdtar->verbose)
			lafe_warnc(0, "%s: %s",
			    archive_entry_pathname(entry),
			    archive_error_string(a));
		else
			fprintf(stderr, ": %s", archive_error_string(a));
	}

	if (e == ARCHIVE_FATAL)
		exit(1);

	/*
	 * If we opened a file earlier, write it out now.  Note that
	 * the format handler might have reset the size field to zero
	 * to inform us that the archive body won't get stored.  In
	 * that case, just skip the write.
	 */
	if (e >= ARCHIVE_WARN && fd >= 0 && archive_entry_size(entry) > 0) {
		if (write_file_data(bsdtar, a, entry, fd, align))
			exit(1);
	}

	/*
	 * If we opened a file, close it now even if there was an error
	 * which made us decide not to write the archive body.
	 */
	if (fd >= 0)
		close(fd);
}
예제 #2
0
파일: write.c 프로젝트: marccodes/lfl
/*
 * Backend for write_entry.
 */
static void
write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
    struct archive_entry *entry)
{
	int fd = -1;
	int e;

	if (archive_entry_size(entry) > 0) {
		const char *pathname = archive_entry_sourcepath(entry);
		fd = open(pathname, O_RDONLY);
		if (fd == -1) {
			if (!bsdtar->verbose)
				bsdtar_warnc(bsdtar, errno,
				    "%s: could not open file", pathname);
			else
				fprintf(stderr, ": %s", strerror(errno));
			return;
		}
	}

	e = archive_write_header(a, entry);
	if (e != ARCHIVE_OK) {
		if (!bsdtar->verbose)
			bsdtar_warnc(bsdtar, 0, "%s: %s",
			    archive_entry_pathname(entry),
			    archive_error_string(a));
		else
			fprintf(stderr, ": %s", archive_error_string(a));
	}

	if (e == ARCHIVE_FATAL)
		exit(1);

	/*
	 * If we opened a file earlier, write it out now.  Note that
	 * the format handler might have reset the size field to zero
	 * to inform us that the archive body won't get stored.  In
	 * that case, just skip the write.
	 */
	if (e >= ARCHIVE_WARN && fd >= 0 && archive_entry_size(entry) > 0) {
		if (write_file_data(bsdtar, a, entry, fd))
			exit(1);
	}

	/*
	 * If we opened a file, close it now even if there was an error
	 * which made us decide not to write the archive body.
	 */
	if (fd >= 0)
		close(fd);
}
예제 #3
0
파일: fs.c 프로젝트: sjrct/Frosk64
static void write_fs_h(node * n, FILE * f, int add)
{
	unsigned zero = 0;
	int i = 0;

	seek_to_node(f, n->node_ptr);	
	fseek(f, add, SEEK_CUR);

	fputc(n->type, f);

	switch (n->type)
	{
	case NT_FILE:
		fputc(n->u.file.perm, f);
		fwrite((char*)(&zero), 1, 2, f);
		fwrite((char*)(&n->u.file.owner), sizeof(int), 1, f);

		if (n->u.file.name == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.file.name->node_ptr), sizeof(int), 1, f);

		if (n->u.file.first_data == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.file.first_data->node_ptr), sizeof(int), 1, f);

		if (n->u.file.next == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.file.next->node_ptr), sizeof(int), 1, f);

		if (n->u.file.parent == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.file.parent->node_ptr), sizeof(int), 1, f);

		if (n->u.file.name != NULL) write_fs_h(n->u.file.name, f, add);
		if (n->u.file.first_data != NULL) write_fs_h(n->u.file.first_data, f, add);
		if (n->u.file.next != NULL) write_fs_h(n->u.file.next, f, add);

		if (add == 0) write_file_data(n, f);
		break;
		
	case NT_DIR:
		fputc(n->u.dir.perm, f);
		fwrite((char*)(&zero), 1, 2, f);
		fwrite((char*)(&n->u.dir.owner), sizeof(int), 1, f);

		if (n->u.dir.name == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.dir.name->node_ptr), sizeof(int), 1, f);

		if (n->u.dir.first_file == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.dir.first_file->node_ptr), sizeof(int), 1, f);

		if (n->u.dir.next == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.dir.next->node_ptr), sizeof(int), 1, f);

		if (n->u.dir.parent == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.dir.parent->node_ptr), sizeof(int), 1, f);

		if (n->u.dir.name != NULL) write_fs_h(n->u.dir.name, f, add);
		if (n->u.dir.first_file != NULL) write_fs_h(n->u.dir.first_file, f, add);
		if (n->u.dir.next != NULL) write_fs_h(n->u.dir.next, f, add);
		break;

	case NT_INDIRECT:
		fputc(n->u.indirect.perm, f);
		fwrite((char*)(&zero), 1, 2, f);
		fwrite((char*)(&n->u.indirect.owner), sizeof(int), 1, f);

		if (n->u.indirect.name == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.indirect.name->node_ptr), sizeof(int), 1, f);

		if (n->u.indirect.dest == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.indirect.dest->node_ptr), sizeof(int), 1, f);

		if (n->u.indirect.next == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.indirect.next->node_ptr), sizeof(int), 1, f);

		if (n->u.indirect.parent == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.indirect.parent->node_ptr), sizeof(int), 1, f);

		if (n->u.indirect.name != NULL) write_fs_h(n->u.indirect.name, f, add);
		if (n->u.indirect.dest != NULL) write_fs_h(n->u.indirect.dest, f, add);
		if (n->u.indirect.next != NULL) write_fs_h(n->u.indirect.next, f, add);
		break;
		
	case NT_DATA:
		fwrite((char*)(&zero), 1, 3, f);
		fwrite((char*)(&n->u.data.block_count), sizeof(int), 1, f);
		fwrite((char*)(&n->u.data.lba), sizeof(long long), 1, f);
		
		if (n->u.data.next == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.data.next), sizeof(int), 1, f);
		
		fwrite((char*)(&n->u.data.bytes_in_last_block), sizeof(int), 1, f);

		if (n->u.data.next != NULL) write_fs_h(n->u.data.next, f, add);
		break;
	
	case NT_STRING:
		fputc(n->u.string.size, f);
		for (i = 0; i < STR_CHARS_PER_NODE; i++) fputc(n->u.string.str[i], f);
				
		if (n->u.string.next == NULL) fwrite((char*)(&zero), sizeof(int), 1, f);
		else fwrite((char*)(&n->u.string.next), sizeof(int), 1, f);

		if (n->u.string.next != NULL) write_fs_h(n->u.string.next, f, add);
		
		break;
		
	case NT_FREE:
		fseek(f, 23, SEEK_CUR);
		break;
	}

	if (add == 0) {
		write_fs_h(n, f, 0x1000);
	}
}
예제 #4
0
파일: write.c 프로젝트: zeha/tarsnap-deb
/*
 * Backend for write_entry.
 */
static void
write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
    struct archive_entry *entry, const struct stat *st, const char *rpath)
{
	off_t			 skiplen;
	CCACHE_ENTRY		*cce = NULL;
	int			 filecached = 0;
	int fd = -1;
	int e;

	/*
	 * If this archive entry needs data, we have a canonical path to the
	 * relevant file, and the chunkification cache isn't disabled, ask
	 * the chunkification cache to find the entry for the file (if one
	 * already exists) and tell us if it can provide the entire file.
	 */
	if ((st != NULL) && S_ISREG(st->st_mode) && (rpath != NULL) &&
	    (archive_entry_size(entry) > 0) && (bsdtar->cachecrunch < 2) &&
	    (bsdtar->chunk_cache != NULL)) {
		cce = ccache_entry_lookup(bsdtar->chunk_cache, rpath, st,
		    bsdtar->write_cookie, &filecached);
	}

	/*
	 * Open the file if we need to write archive entry data and the
	 * chunkification cache can't provide all of it.
	 */
	if ((archive_entry_size(entry) > 0) && (filecached == 0)) {
		const char *pathname = archive_entry_sourcepath(entry);
		fd = open(pathname, O_RDONLY);
		if (fd == -1) {
			if (!bsdtar->verbose)
				bsdtar_warnc(bsdtar, errno,
				    "%s: could not open file", pathname);
			else
				fprintf(stderr, ": %s", strerror(errno));
			return;
		}
	}

	/* Write the archive header. */
	if (MODE_HEADER(bsdtar, a)) {
		bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
		exit(1);
	}
	e = archive_write_header(a, entry);
	if (e != ARCHIVE_OK) {
		if (!bsdtar->verbose)
			bsdtar_warnc(bsdtar, 0, "%s: %s",
			    archive_entry_pathname(entry),
			    archive_error_string(a));
		else
			fprintf(stderr, ": %s", archive_error_string(a));
	}

	if (e == ARCHIVE_FATAL)
		exit(1);

	/*
	 * If we opened a file earlier, write it out now.  Note that
	 * the format handler might have reset the size field to zero
	 * to inform us that the archive body won't get stored.  In
	 * that case, just skip the write.
	 */

	/* If the cache can provide the entire archive entry, do it. */
	if (e >= ARCHIVE_WARN && filecached &&
	    archive_entry_size(entry) > 0) {
		if (MODE_DATA(bsdtar, a)) {
			bsdtar_warnc(bsdtar, 0, "%s",
			    archive_error_string(a));
			exit(1);
		}
		skiplen = ccache_entry_write(cce, bsdtar->write_cookie);
		if (skiplen < st->st_size) {
			bsdtar_warnc(bsdtar, 0,
			    "Error writing cached archive entry");
			exit(1);
		}
		if (archive_write_skip(a, skiplen)) {
			bsdtar_warnc(bsdtar, 0, "%s",
			    archive_error_string(a));
			exit(1);
		}
	}

	/*
	 * We don't need to write anything now if the file was cached
	 * and the cache wrote it out earlier.
	 */
	if (e >= ARCHIVE_WARN && fd >= 0 && archive_entry_size(entry) > 0 &&
	    filecached == 0) {
		/* Switch into data mode. */
		if (MODE_DATA(bsdtar, a)) {
			bsdtar_warnc(bsdtar, 0, "%s",
			    archive_error_string(a));
			exit(1);
		}

		if (cce != NULL) {
			/* Ask the cache to write as much as possible. */
			skiplen = ccache_entry_writefile(cce,
			    bsdtar->write_cookie, bsdtar->cachecrunch, fd);
			if (skiplen < 0) {
				bsdtar_warnc(bsdtar, 0,
				    "Error writing archive");
				exit(1);
			}

			/* Skip forward in the file. */
			if (lseek(fd, skiplen, SEEK_SET) == -1) {
				bsdtar_warnc(bsdtar, errno, "lseek(%s)",
				    archive_entry_pathname(entry));
				exit(1);
			}

			/* Tell the archive layer that we've skipped. */
			if (archive_write_skip(a, skiplen)) {
				bsdtar_warnc(bsdtar, 0, "%s",
				    archive_error_string(a));
				exit(1);
			}
		}

		if (write_file_data(bsdtar, a, entry, fd))
			exit(1);
	}

	/* This entry is done. */
	if (!truncate_archive(bsdtar) && MODE_DONE(bsdtar, a)) {
		bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
		exit(1);
	}

	/* Tell the cache that we're done. */
	if (cce != NULL) {
		if (ccache_entry_end(bsdtar->chunk_cache, cce,
		    bsdtar->write_cookie, rpath, bsdtar->snaptime))
			exit(1);
		cce = NULL;
	}

	/*
	 * If we opened a file, close it now even if there was an error
	 * which made us decide not to write the archive body.
	 */
	if (fd >= 0)
		close(fd);
}
예제 #5
0
static bool update_remote_files(void *param, obs_data_t *remote_file)
{
	struct update_info *info = param;

	struct file_update_data data = {
		.name = obs_data_get_string(remote_file, "name"),
		.version = (int)obs_data_get_int(remote_file, "version")
	};

	enum_files(info->cache_package, newer_than_cache, &data);
	if (!data.newer && data.found)
		return true;

	if (!do_relative_http_request(info, info->remote_url, data.name))
		return true;

	if (info->callback) {
		struct file_download_data download_data;
		bool confirm;

		download_data.name = data.name;
		download_data.version = data.version;
		download_data.buffer.da = info->file_data.da;

		confirm = info->callback(info->param, &download_data);

		info->file_data.da = download_data.buffer.da;

		if (!confirm) {
			info("Update file '%s' (version %d) rejected",
					data.name, data.version);
			return true;
		}
	}

	write_file_data(info, info->temp, data.name);
	replace_file(info->temp, info->cache, data.name);

	info("Successfully updated file '%s' (version %d)",
			data.name, data.version);
	return true;
}

static void update_save_metadata(struct update_info *info)
{
	struct dstr path = { 0 };

	if (!info->etag_remote)
		return;

	dstr_copy(&path, info->cache);
	dstr_cat(&path, "meta.json");

	obs_data_t *data;
	data = obs_data_create();
	obs_data_set_string(data, "etag", info->etag_remote);
	obs_data_save_json(data, path.array);
	obs_data_release(data);
}

static void update_remote_version(struct update_info *info, int cur_version)
{
	int remote_version;
	long response_code;

	if (!do_http_request(info, info->url, &response_code))
		return;

	if (response_code == 304)
		return;

	if (!info->file_data.array || info->file_data.array[0] != '{') {
		warn("Remote package does not exist or is not valid json");
		return;
	}

	update_save_metadata(info);

	info->remote_package = obs_data_create_from_json(
			(char*)info->file_data.array);
	if (!info->remote_package) {
		warn("Failed to initialize remote package json");
		return;
	}

	remote_version = (int)obs_data_get_int(info->remote_package, "version");
	if (remote_version <= cur_version)
		return;

	write_file_data(info, info->temp, "package.json");

	info->remote_url = obs_data_get_string(info->remote_package, "url");
	if (!info->remote_url) {
		warn("No remote url in package file");
		return;
	}

	/* download new files */
	enum_files(info->remote_package, update_remote_files, info);

	replace_file(info->temp, info->cache, "package.json");

	info("Successfully updated package (version %d)", remote_version);
	return;
}