diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-06-16 01:41:06 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-06-16 03:51:11 +0200 |
commit | c81e80bf35874696d9735f70e5c8327f92b5aca4 (patch) | |
tree | 5ef99ab43bde73674391d02ccc65d357874a34c1 /lib/sqfs/src/io/unix.c | |
parent | 8bff2715bfdfd2e6ce0c707f1310b169d4e454d0 (diff) |
libsquashfs: merge windows & unix file I/O primitives
By adding additional close/duplicate primitives, the remaining, mostly
identical istream/ostream/file code is mostly identical between Windows
and Unix and be merged, mostly without stitches.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/src/io/unix.c')
-rw-r--r-- | lib/sqfs/src/io/unix.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/sqfs/src/io/unix.c b/lib/sqfs/src/io/unix.c new file mode 100644 index 0000000..45af2ce --- /dev/null +++ b/lib/sqfs/src/io/unix.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * unix.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#define SQFS_BUILDING_DLL +#include "config.h" + +#include "sqfs/io.h" +#include "sqfs/error.h" + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +int sqfs_open_native_file(sqfs_file_handle_t *out, const char *filename, + sqfs_u32 flags) +{ + int open_mode; + + *out = -1; + + if (flags & ~SQFS_FILE_OPEN_ALL_FLAGS) + return SQFS_ERROR_UNSUPPORTED; + + 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; + } + } + + *out = open(filename, open_mode, 0644); + + return (*out < 0) ? SQFS_ERROR_IO : 0; +} + +void sqfs_close_native_file(sqfs_file_handle_t fd) +{ + while (close(fd) != 0 && errno == EINTR) + ; +} + +int sqfs_duplicate_native_file(sqfs_file_handle_t in, sqfs_file_handle_t *out) +{ + *out = dup(in); + return (*out < 0) ? SQFS_ERROR_IO : 0; +} + +int sqfs_seek_native_file(sqfs_file_handle_t fd, + sqfs_s64 offset, sqfs_u32 flags) +{ + int whence; + off_t off; + + switch (flags & SQFS_FILE_SEEK_TYPE_MASK) { + case SQFS_FILE_SEEK_START: whence = SEEK_SET; break; + case SQFS_FILE_SEEK_CURRENT: whence = SEEK_CUR; break; + case SQFS_FILE_SEEK_END: whence = SEEK_END; break; + default: return SQFS_ERROR_UNSUPPORTED; + } + + if (flags & ~(SQFS_FILE_SEEK_FLAG_MASK | SQFS_FILE_SEEK_TYPE_MASK)) + return SQFS_ERROR_UNSUPPORTED; + + off = lseek(fd, offset, whence); + if (off == ((off_t)-1)) { + if (errno == ESPIPE) + return SQFS_ERROR_UNSUPPORTED; + return SQFS_ERROR_IO; + } + + if (flags & SQFS_FILE_SEEK_TRUNCATE) { + while (ftruncate(fd, off) != 0) { + if (errno != EINTR) + return SQFS_ERROR_IO; + } + } + + return 0; +} |