diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-01-31 11:21:30 +0100 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-01-31 13:51:49 +0100 | 
| commit | cdccc69c62579b0c13b35fad0728079652b8f3c9 (patch) | |
| tree | 9fa54c710f73c5e08a9c8466e7a712eb63ee07ac /lib/io/src/unix | |
| parent | 2182129c8f359c4fa1390eaba7a65b595ccd4182 (diff) | |
Move library source into src sub-directory
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/io/src/unix')
| -rw-r--r-- | lib/io/src/unix/istream.c | 123 | ||||
| -rw-r--r-- | lib/io/src/unix/ostream.c | 173 | 
2 files changed, 296 insertions, 0 deletions
diff --git a/lib/io/src/unix/istream.c b/lib/io/src/unix/istream.c new file mode 100644 index 0000000..f8cffad --- /dev/null +++ b/lib/io/src/unix/istream.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * istream.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "../internal.h" + +typedef struct { +	istream_t base; +	char *path; +	int fd; + +	sqfs_u8 buffer[BUFSZ]; +} file_istream_t; + +static int file_precache(istream_t *strm) +{ +	file_istream_t *file = (file_istream_t *)strm; +	ssize_t ret; +	size_t diff; + +	while (strm->buffer_used < sizeof(file->buffer)) { +		diff = sizeof(file->buffer) - strm->buffer_used; + +		ret = read(file->fd, strm->buffer + strm->buffer_used, diff); + +		if (ret == 0) { +			strm->eof = true; +			break; +		} + +		if (ret < 0) { +			if (errno == EINTR) +				continue; + +			perror(file->path); +			return -1; +		} + +		strm->buffer_used += ret; +	} + +	return 0; +} + +static const char *file_get_filename(istream_t *strm) +{ +	file_istream_t *file = (file_istream_t *)strm; + +	return file->path; +} + +static void file_destroy(sqfs_object_t *obj) +{ +	file_istream_t *file = (file_istream_t *)obj; + +	if (file->fd != STDIN_FILENO) +		close(file->fd); + +	free(file->path); +	free(file); +} + +istream_t *istream_open_file(const char *path) +{ +	file_istream_t *file = calloc(1, sizeof(*file)); +	istream_t *strm = (istream_t *)file; + +	if (file == NULL) { +		perror(path); +		return NULL; +	} + +	sqfs_object_init(file, file_destroy, NULL); + +	file->path = strdup(path); +	if (file->path == NULL) { +		perror(path); +		goto fail_free; +	} + +	file->fd = open(path, O_RDONLY); +	if (file->fd < 0) { +		perror(path); +		goto fail_path; +	} + +	strm->buffer = file->buffer; +	strm->precache = file_precache; +	strm->get_filename = file_get_filename; +	return strm; +fail_path: +	free(file->path); +fail_free: +	free(file); +	return NULL; +} + +istream_t *istream_open_stdin(void) +{ +	file_istream_t *file = calloc(1, sizeof(*file)); +	istream_t *strm = (istream_t *)file; + +	if (file == NULL) +		goto fail; + +	sqfs_object_init(file, file_destroy, NULL); + +	file->path = strdup("stdin"); +	if (file->path == NULL) +		goto fail; + +	file->fd = STDIN_FILENO; +	strm->buffer = file->buffer; +	strm->precache = file_precache; +	strm->get_filename = file_get_filename; +	return strm; +fail: +	perror("creating file wrapper for stdin"); +	free(file); +	return NULL; +} diff --git a/lib/io/src/unix/ostream.c b/lib/io/src/unix/ostream.c new file mode 100644 index 0000000..5ef2af2 --- /dev/null +++ b/lib/io/src/unix/ostream.c @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * ostream.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "../internal.h" + +typedef struct { +	ostream_t base; +	char *path; +	int fd; + +	off_t sparse_count; +	off_t size; +} file_ostream_t; + +static int file_append(ostream_t *strm, const void *data, size_t size) +{ +	file_ostream_t *file = (file_ostream_t *)strm; +	ssize_t ret; + +	if (size == 0) +		return 0; + +	if (file->sparse_count > 0) { +		if (lseek(file->fd, file->sparse_count, SEEK_CUR) == (off_t)-1) +			goto fail_errno; + +		file->sparse_count = 0; +	} + +	while (size > 0) { +		ret = write(file->fd, data, size); + +		if (ret == 0) { +			fprintf(stderr, "%s: truncated data write.\n", +				file->path); +			return -1; +		} + +		if (ret < 0) { +			if (errno == EINTR) +				continue; +			goto fail_errno; +		} + +		file->size += ret; +		size -= ret; +		data = (const char *)data + ret; +	} + +	return 0; +fail_errno: +	perror(file->path); +	return -1; +} + +static int file_append_sparse(ostream_t *strm, size_t size) +{ +	file_ostream_t *file = (file_ostream_t *)strm; + +	file->sparse_count += size; +	file->size += size; +	return 0; +} + +static int file_flush(ostream_t *strm) +{ +	file_ostream_t *file = (file_ostream_t *)strm; + +	if (file->sparse_count > 0) { +		if (ftruncate(file->fd, file->size) != 0) +			goto fail; +	} + +	if (fsync(file->fd) != 0) { +		if (errno == EINVAL) +			return 0; +		goto fail; +	} + +	return 0; +fail: +	perror(file->path); +	return -1; +} + +static void file_destroy(sqfs_object_t *obj) +{ +	file_ostream_t *file = (file_ostream_t *)obj; + +	if (file->fd != STDOUT_FILENO) +		close(file->fd); + +	free(file->path); +	free(file); +} + +static const char *file_get_filename(ostream_t *strm) +{ +	file_ostream_t *file = (file_ostream_t *)strm; + +	return file->path; +} + +ostream_t *ostream_open_file(const char *path, int flags) +{ +	file_ostream_t *file = calloc(1, sizeof(*file)); +	ostream_t *strm = (ostream_t *)file; + +	if (file == NULL) { +		perror(path); +		return NULL; +	} + +	sqfs_object_init(file, file_destroy, NULL); + +	file->path = strdup(path); +	if (file->path == NULL) { +		perror(path); +		goto fail_free; +	} + +	if (flags & OSTREAM_OPEN_OVERWRITE) { +		file->fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); +	} else { +		file->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644); +	} + +	if (file->fd < 0) { +		perror(path); +		goto fail_path; +	} + +	if (flags & OSTREAM_OPEN_SPARSE) +		strm->append_sparse = file_append_sparse; + +	strm->append = file_append; +	strm->flush = file_flush; +	strm->get_filename = file_get_filename; +	return strm; +fail_path: +	free(file->path); +fail_free: +	free(file); +	return NULL; +} + +ostream_t *ostream_open_stdout(void) +{ +	file_ostream_t *file = calloc(1, sizeof(*file)); +	ostream_t *strm = (ostream_t *)file; + +	if (file == NULL) +		goto fail; + +	file->path = strdup("stdout"); +	if (file->path == NULL) +		goto fail; + +	file->fd = STDOUT_FILENO; +	strm->append = file_append; +	strm->flush = file_flush; +	strm->get_filename = file_get_filename; + +	sqfs_object_init(file, file_destroy, NULL); +	return strm; +fail: +	perror("creating file wrapper for stdout"); +	free(file); +	return NULL; +}  | 
