From 8ee3ee9c71418dbdb73d4350c17056024fb7ec41 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sun, 15 Sep 2019 17:56:07 +0200 Subject: Replace file descriptor IO in data_writer with sqfs_file_t First, this commit moves the create-blocks-from-fd function over to libsquashfs and ports it to work on an sqfs_file_t instead. Second, the function in the data_writer that reads from a file descriptor is adjusted to use an sqfs_file_t instead. Finally, the tools that use it have to be adjusted accordingly. Signed-off-by: David Oberhollenzer --- lib/sqfs/Makemodule.am | 4 +- lib/sqfs/io.c | 146 +++++------------------------------------ lib/sqfs/io_file.c | 151 +++++++++++++++++++++++++++++++++++++++++++ lib/sqfshelper/data_writer.c | 44 ++++--------- 4 files changed, 182 insertions(+), 163 deletions(-) create mode 100644 lib/sqfs/io_file.c (limited to 'lib') diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am index b58a28b..7d228a4 100644 --- a/lib/sqfs/Makemodule.am +++ b/lib/sqfs/Makemodule.am @@ -7,14 +7,14 @@ LIBSQFS_HEARDS = include/sqfs/data.h include/sqfs/meta_writer.h \ include/sqfs/error.h include/sqfs/io.h libsquashfs_la_SOURCES = $(LIBSQFS_HEARDS) lib/sqfs/id_table.c lib/sqfs/super.c -libsquashfs_la_SOURCES += lib/sqfs/readdir.c lib/sqfs/io.c lib/sqfs/xattr.c +libsquashfs_la_SOURCES += lib/sqfs/readdir.c lib/sqfs/io_file.c lib/sqfs/xattr.c libsquashfs_la_SOURCES += lib/sqfs/write_table.c lib/sqfs/meta_writer.c libsquashfs_la_SOURCES += lib/sqfs/read_super.c lib/sqfs/meta_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_inode.c lib/sqfs/write_inode.c libsquashfs_la_SOURCES += lib/sqfs/dir_writer.c lib/sqfs/xattr_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_table.c lib/sqfs/comp/compressor.c libsquashfs_la_SOURCES += lib/sqfs/io_stdin.c lib/sqfs/comp/internal.h -libsquashfs_la_SOURCES += lib/sqfs/blk_proc/process_block.c +libsquashfs_la_SOURCES += lib/sqfs/blk_proc/process_block.c lib/sqfs/io.c libsquashfs_la_SOURCES += lib/sqfs/blk_proc/internal.h libsquashfs_la_CPPFLAGS = $(AM_CPPFLAGS) libsquashfs_la_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) diff --git a/lib/sqfs/io.c b/lib/sqfs/io.c index f8773d0..4afb489 100644 --- a/lib/sqfs/io.c +++ b/lib/sqfs/io.c @@ -9,143 +9,31 @@ #include "sqfs/io.h" #include "sqfs/error.h" +#include "sqfs/block_processor.h" +#include "util.h" #include -#include -#include -#include - -typedef struct { - sqfs_file_t base; - - uint64_t size; - int fd; -} sqfs_file_stdio_t; - - -static void stdio_destroy(sqfs_file_t *base) -{ - sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; - - close(file->fd); - free(file); -} - -static int stdio_read_at(sqfs_file_t *base, uint64_t offset, - void *buffer, size_t size) -{ - sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; - ssize_t ret; - - while (size > 0) { - ret = pread(file->fd, buffer, size, offset); - - if (ret < 0) { - if (errno == EINTR) - continue; - return SQFS_ERROR_IO; - } - - if (ret == 0) - return SQFS_ERROR_OUT_OF_BOUNDS; - - buffer = (char *)buffer + ret; - size -= ret; - offset += ret; - } - - return 0; -} - -static int stdio_write_at(sqfs_file_t *base, uint64_t offset, - const void *buffer, size_t size) +int sqfs_file_create_block(sqfs_file_t *file, uint64_t offset, + size_t size, void *user, uint32_t flags, + sqfs_block_t **out) { - sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; - ssize_t ret; - - while (size > 0) { - ret = pwrite(file->fd, buffer, size, offset); - - if (ret < 0) { - if (errno == EINTR) - continue; - return SQFS_ERROR_IO; - } + sqfs_block_t *blk = alloc_flex(sizeof(*blk), 1, size); + int err; - if (ret == 0) - return SQFS_ERROR_OUT_OF_BOUNDS; + if (blk == NULL) + return SQFS_ERROR_ALLOC; - buffer = (const char *)buffer + ret; - size -= ret; - offset += ret; + err = file->read_at(file, offset, blk->data, size); + if (err) { + free(blk); + return err; } - if (offset >= file->size) - file->size = offset; + blk->user = user; + blk->size = size; + blk->flags = flags; + *out = blk; return 0; } - -static uint64_t stdio_get_size(const sqfs_file_t *base) -{ - const sqfs_file_stdio_t *file = (const sqfs_file_stdio_t *)base; - - return file->size; -} - -static int stdio_truncate(sqfs_file_t *base, uint64_t size) -{ - sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; - - if (ftruncate(file->fd, size)) - return SQFS_ERROR_IO; - - file->size = size; - return 0; -} - - -sqfs_file_t *sqfs_open_file(const char *filename, int flags) -{ - sqfs_file_stdio_t *file; - int open_mode, temp; - sqfs_file_t *base; - - if (flags & ~SQFS_FILE_OPEN_ALL_FLAGS) { - errno = EINVAL; - return NULL; - } - - file = calloc(1, sizeof(*file)); - base = (sqfs_file_t *)file; - if (file == NULL) - return NULL; - - if (flags & SQFS_FILE_OPEN_READ_ONLY) { - open_mode = O_RDONLY; - } else { - open_mode = O_CREAT | O_RDWR; - - if (flags & SQFS_FILE_OPEN_OVERWRITE) { - open_mode |= O_TRUNC; - } else { - open_mode |= O_EXCL; - } - } - - file->fd = open(filename, open_mode, 0600); - if (file->fd < 0) { - temp = errno; - free(file); - errno = temp; - return NULL; - } - - base->destroy = stdio_destroy; - base->read_at = stdio_read_at; - base->write_at = stdio_write_at; - base->get_size = stdio_get_size; - base->truncate = stdio_truncate; - return base; -} diff --git a/lib/sqfs/io_file.c b/lib/sqfs/io_file.c new file mode 100644 index 0000000..b57eddd --- /dev/null +++ b/lib/sqfs/io_file.c @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * io_file.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#define SQFS_BUILDING_DLL +#include "config.h" + +#include "sqfs/io.h" +#include "sqfs/error.h" + +#include +#include +#include +#include + + +typedef struct { + sqfs_file_t base; + + uint64_t size; + int fd; +} sqfs_file_stdio_t; + + +static void stdio_destroy(sqfs_file_t *base) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + + close(file->fd); + free(file); +} + +static int stdio_read_at(sqfs_file_t *base, uint64_t offset, + void *buffer, size_t size) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + ssize_t ret; + + while (size > 0) { + ret = pread(file->fd, buffer, size, offset); + + if (ret < 0) { + if (errno == EINTR) + continue; + return SQFS_ERROR_IO; + } + + if (ret == 0) + return SQFS_ERROR_OUT_OF_BOUNDS; + + buffer = (char *)buffer + ret; + size -= ret; + offset += ret; + } + + return 0; +} + +static int stdio_write_at(sqfs_file_t *base, uint64_t offset, + const void *buffer, size_t size) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + ssize_t ret; + + while (size > 0) { + ret = pwrite(file->fd, buffer, size, offset); + + if (ret < 0) { + if (errno == EINTR) + continue; + return SQFS_ERROR_IO; + } + + if (ret == 0) + return SQFS_ERROR_OUT_OF_BOUNDS; + + buffer = (const char *)buffer + ret; + size -= ret; + offset += ret; + } + + if (offset >= file->size) + file->size = offset; + + return 0; +} + +static uint64_t stdio_get_size(const sqfs_file_t *base) +{ + const sqfs_file_stdio_t *file = (const sqfs_file_stdio_t *)base; + + return file->size; +} + +static int stdio_truncate(sqfs_file_t *base, uint64_t size) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + + if (ftruncate(file->fd, size)) + return SQFS_ERROR_IO; + + file->size = size; + return 0; +} + + +sqfs_file_t *sqfs_open_file(const char *filename, int flags) +{ + sqfs_file_stdio_t *file; + int open_mode, temp; + sqfs_file_t *base; + + if (flags & ~SQFS_FILE_OPEN_ALL_FLAGS) { + errno = EINVAL; + return NULL; + } + + file = calloc(1, sizeof(*file)); + base = (sqfs_file_t *)file; + if (file == NULL) + return NULL; + + if (flags & SQFS_FILE_OPEN_READ_ONLY) { + open_mode = O_RDONLY; + } else { + open_mode = O_CREAT | O_RDWR; + + if (flags & SQFS_FILE_OPEN_OVERWRITE) { + open_mode |= O_TRUNC; + } else { + open_mode |= O_EXCL; + } + } + + file->fd = open(filename, open_mode, 0600); + if (file->fd < 0) { + temp = errno; + free(file); + errno = temp; + return NULL; + } + + base->destroy = stdio_destroy; + base->read_at = stdio_read_at; + base->write_at = stdio_write_at; + base->get_size = stdio_get_size; + base->truncate = stdio_truncate; + return base; +} diff --git a/lib/sqfshelper/data_writer.c b/lib/sqfshelper/data_writer.c index 43d5851..edd1770 100644 --- a/lib/sqfshelper/data_writer.c +++ b/lib/sqfshelper/data_writer.c @@ -319,34 +319,11 @@ static int add_sentinel_block(data_writer_t *data, file_info_t *fi, return sqfs_block_processor_enqueue(data->proc, blk); } -static sqfs_block_t *create_block(file_info_t *fi, int fd, size_t size, - uint32_t flags) -{ - sqfs_block_t *blk = alloc_flex(sizeof(*blk), 1, size); - - if (blk == NULL) { - perror(fi->input_file); - return NULL; - } - - if (fd >= 0) { - if (read_data(fi->input_file, fd, blk->data, size)) { - free(blk); - return NULL; - } - } - - blk->size = size; - blk->user = fi; - blk->flags = flags; - return blk; -} - -int write_data_from_fd(data_writer_t *data, file_info_t *fi, - int infd, int flags) +int write_data_from_file(data_writer_t *data, file_info_t *fi, + sqfs_file_t *file, int flags) { uint32_t blk_flags = BLK_FIRST_BLOCK; - uint64_t file_size = fi->size; + uint64_t offset, file_size; size_t diff, i = 0; sqfs_block_t *blk; @@ -356,16 +333,19 @@ int write_data_from_fd(data_writer_t *data, file_info_t *fi, if (flags & DW_ALLIGN_DEVBLK) blk_flags |= BLK_ALLIGN; - for (; file_size > 0; file_size -= diff) { - if (file_size > data->super->block_size) { + file_size = file->get_size(file); + + for (offset = 0; offset < file_size; offset += diff) { + if (file_size - offset > data->super->block_size) { diff = data->super->block_size; } else { - diff = file_size; + diff = file_size - offset; } - blk = create_block(fi, infd, diff, blk_flags); - if (blk == NULL) + if (sqfs_file_create_block(file, offset, diff, fi, + blk_flags, &blk)) { return -1; + } blk->index = i++; @@ -405,7 +385,7 @@ int write_data_from_fd(data_writer_t *data, file_info_t *fi, return -1; } - data->stats.bytes_read += fi->size; + data->stats.bytes_read += file_size; data->stats.file_count += 1; return 0; } -- cgit v1.2.3