aboutsummaryrefslogtreecommitdiff
path: root/lib/io/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/io/src')
-rw-r--r--lib/io/src/unix/dir_iterator.c26
-rw-r--r--lib/io/src/win32/dir_iterator.c62
2 files changed, 83 insertions, 5 deletions
diff --git a/lib/io/src/unix/dir_iterator.c b/lib/io/src/unix/dir_iterator.c
index 12e2ac1..d2ae011 100644
--- a/lib/io/src/unix/dir_iterator.c
+++ b/lib/io/src/unix/dir_iterator.c
@@ -8,6 +8,7 @@
#include "io/dir_iterator.h"
#include "util/util.h"
#include "sqfs/error.h"
+#include "sqfs/io.h"
#include <sys/stat.h>
#include <stdlib.h>
@@ -126,11 +127,30 @@ static void dir_ignore_subdir(dir_iterator_t *it)
(void)it;
}
-static int dir_open_file_ro(dir_iterator_t *it, sqfs_istream_t **out)
+static int dir_open_file_ro(dir_iterator_t *base, sqfs_istream_t **out)
{
- (void)it;
+ unix_dir_iterator_t *it = (unix_dir_iterator_t *)base;
+ int fd, ret;
+
*out = NULL;
- return SQFS_ERROR_UNSUPPORTED;
+ if (it->state < 0)
+ return it->state;
+
+ if (it->state > 0 || it->ent == NULL)
+ return SQFS_ERROR_NO_ENTRY;
+
+ fd = openat(dirfd(it->dir), it->ent->d_name, O_RDONLY);
+ if (fd < 0)
+ return SQFS_ERROR_IO;
+
+ ret = sqfs_istream_open_handle(out, it->ent->d_name,
+ fd, SQFS_FILE_OPEN_READ_ONLY);
+ if (ret != 0) {
+ int err = errno;
+ close(fd);
+ errno = err;
+ }
+ return ret;
}
static int dir_read_xattr(dir_iterator_t *it, sqfs_xattr_t **out)
diff --git a/lib/io/src/win32/dir_iterator.c b/lib/io/src/win32/dir_iterator.c
index d9e5b7c..f66e323 100644
--- a/lib/io/src/win32/dir_iterator.c
+++ b/lib/io/src/win32/dir_iterator.c
@@ -8,6 +8,7 @@
#include "io/dir_iterator.h"
#include "util/util.h"
#include "sqfs/error.h"
+#include "sqfs/io.h"
#include <windows.h>
#include <stdlib.h>
@@ -121,9 +122,66 @@ static void dir_iterator_ignore_subdir(dir_iterator_t *it)
static int dir_iterator_open_file_ro(dir_iterator_t *it, sqfs_istream_t **out)
{
- (void)it;
+ dir_iterator_win32_t *dir = (dir_iterator_win32_t *)it;
+ size_t plen, slen;
+ os_error_t err;
+ WCHAR *str16;
+ DWORD length;
+ HANDLE hnd;
+ char *str8;
+ int ret;
+
*out = NULL;
- return SQFS_ERROR_UNSUPPORTED;
+
+ if (dir->state != 0)
+ return (dir->state > 0) ? SQFS_ERROR_NO_ENTRY : dir->state;
+
+ plen = wcslen(dir->path) - 1;
+ slen = wcslen(dir->ent.cFileName);
+
+ str16 = calloc(plen + slen + 1, sizeof(WCHAR));
+ if (str16 == NULL)
+ return SQFS_ERROR_ALLOC;
+
+ memcpy(str16, dir->path, plen * sizeof(WCHAR));
+ memcpy(str16 + plen, dir->ent.cFileName, slen * sizeof(WCHAR));
+
+ hnd = CreateFileW(str16, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ err = get_os_error_state();
+ free(str16);
+ set_os_error_state(err);
+
+ if (hnd == INVALID_HANDLE_VALUE)
+ return SQFS_ERROR_IO;
+
+ length = WideCharToMultiByte(CP_UTF8, 0, dir->ent.cFileName,
+ -1, NULL, 0, NULL, NULL);
+ if (length <= 0) {
+ CloseHandle(hnd);
+ return SQFS_ERROR_ALLOC;
+ }
+
+ str8 = calloc(1, length + 1);
+ if (str8 == NULL) {
+ CloseHandle(hnd);
+ return SQFS_ERROR_ALLOC;
+ }
+
+ WideCharToMultiByte(CP_UTF8, 0, dir->ent.cFileName, -1, str8,
+ length + 1, NULL, NULL);
+
+ ret = sqfs_istream_open_handle(out, str8, hnd,
+ SQFS_FILE_OPEN_READ_ONLY);
+ err = get_os_error_state();
+ free(str8);
+ if (ret != 0)
+ CloseHandle(hnd);
+ set_os_error_state(err);
+
+ return ret;
}
static int dir_iterator_read_xattr(dir_iterator_t *it, sqfs_xattr_t **out)