diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-11-18 15:09:31 +0100 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-11-19 21:12:56 +0100 |
commit | 3497201ce66f35401bd02109c06c110671493ad8 (patch) | |
tree | 0f3e4fcdc99df02e4879c8154396d5ae89bc5758 /unpack | |
parent | 585997f4677db3707eb99b1012dad036ddecc0d0 (diff) |
Make rdsquashfs unpack work on Windows
AFAIK the only thing we can actually unpack on Windows is regular
files and directories, so only do that.
Furthermore, we have no way of setting Unix file attributes, so
skip that.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'unpack')
-rw-r--r-- | unpack/rdsquashfs.h | 4 | ||||
-rw-r--r-- | unpack/restore_fstree.c | 134 |
2 files changed, 98 insertions, 40 deletions
diff --git a/unpack/rdsquashfs.h b/unpack/rdsquashfs.h index a36d283..9e21050 100644 --- a/unpack/rdsquashfs.h +++ b/unpack/rdsquashfs.h @@ -12,6 +12,10 @@ #include "fstree.h" #include "util/util.h" +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif #ifdef HAVE_SYS_XATTR_H #include <sys/xattr.h> #endif diff --git a/unpack/restore_fstree.c b/unpack/restore_fstree.c index dac1a8c..dbcebfa 100644 --- a/unpack/restore_fstree.c +++ b/unpack/restore_fstree.c @@ -6,45 +6,64 @@ */ #include "rdsquashfs.h" -static int create_node(const sqfs_tree_node_t *n, int flags) +#ifdef _WIN32 +static int create_node(const sqfs_tree_node_t *n, const char *name) { - const sqfs_tree_node_t *c; - int fd, ret; - char *name; + WCHAR *wpath = NULL; + DWORD length; + HANDLE fh; - if (!is_filename_sane((const char *)n->name)) { - fprintf(stderr, "Found an entry named '%s', skipping.\n", - n->name); - return 0; - } + length = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) + 1; + if (length <= 0) + goto fail; - name = sqfs_tree_node_get_path(n); - if (name == NULL) { - fprintf(stderr, "Constructing full path for '%s': %s\n", - (const char *)n->name, strerror(errno)); + wpath = alloc_array(sizeof(wpath[0]), length); + if (wpath == NULL) { + perror(name); return -1; } - ret = canonicalize_name(name); - assert(ret == 0); + MultiByteToWideChar(CP_UTF8, 0, name, -1, wpath, length); + wpath[length - 1] = '\0'; - if (!(flags & UNPACK_QUIET)) - printf("creating %s\n", name); + switch (n->inode->base.mode & S_IFMT) { + case S_IFDIR: + if (!CreateDirectoryW(wpath, NULL)) + goto fail; + break; + case S_IFREG: + fh = CreateFileW(wpath, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, CREATE_NEW, 0, NULL); + + if (fh == INVALID_HANDLE_VALUE) + goto fail; + + CloseHandle(fh); + break; + default: + break; + } + + free(wpath); + return 0; +fail: + fprintf(stderr, "Creating %s: %ld\n", name, GetLastError()); + free(wpath); + return -1; +} +#else +static int create_node(const sqfs_tree_node_t *n, const char *name) +{ + sqfs_u32 devno; + int fd; switch (n->inode->base.mode & S_IFMT) { case S_IFDIR: if (mkdir(name, 0755) && errno != EEXIST) { fprintf(stderr, "mkdir %s: %s\n", name, strerror(errno)); - goto fail; - } - - free(name); - name = NULL; - - for (c = n->children; c != NULL; c = c->next) { - if (create_node(c, flags)) - goto fail; + return -1; } break; case S_IFLNK: @@ -52,7 +71,7 @@ static int create_node(const sqfs_tree_node_t *n, int flags) fprintf(stderr, "ln -s %s %s: %s\n", n->inode->slink_target, name, strerror(errno)); - goto fail; + return -1; } break; case S_IFSOCK: @@ -60,13 +79,11 @@ static int create_node(const sqfs_tree_node_t *n, int flags) if (mknod(name, (n->inode->base.mode & S_IFMT) | 0700, 0)) { fprintf(stderr, "creating %s: %s\n", name, strerror(errno)); - goto fail; + return -1; } break; case S_IFBLK: - case S_IFCHR: { - sqfs_u32 devno; - + case S_IFCHR: if (n->inode->base.type == SQFS_INODE_EXT_BDEV || n->inode->base.type == SQFS_INODE_EXT_CDEV) { devno = n->inode->data.dev_ext.devno; @@ -77,16 +94,16 @@ static int create_node(const sqfs_tree_node_t *n, int flags) if (mknod(name, n->inode->base.mode & S_IFMT, devno)) { fprintf(stderr, "creating device %s: %s\n", name, strerror(errno)); - goto fail; + return -1; } break; - } case S_IFREG: fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) { fprintf(stderr, "creating %s: %s\n", name, strerror(errno)); - goto fail; + return -1; } close(fd); @@ -95,11 +112,47 @@ static int create_node(const sqfs_tree_node_t *n, int flags) break; } - free(name); return 0; -fail: +} +#endif + +static int create_node_dfs(const sqfs_tree_node_t *n, int flags) +{ + const sqfs_tree_node_t *c; + char *name; + int ret; + + if (!is_filename_sane((const char *)n->name)) { + fprintf(stderr, "Found an entry named '%s', skipping.\n", + n->name); + return 0; + } + + name = sqfs_tree_node_get_path(n); + if (name == NULL) { + fprintf(stderr, "Constructing full path for '%s': %s\n", + (const char *)n->name, strerror(errno)); + return -1; + } + + ret = canonicalize_name(name); + assert(ret == 0); + + if (!(flags & UNPACK_QUIET)) + printf("creating %s\n", name); + + ret = create_node(n, name); free(name); - return -1; + if (ret) + return -1; + + if (S_ISDIR(n->inode->base.mode)) { + for (c = n->children; c != NULL; c = c->next) { + if (create_node_dfs(c, flags)) + return -1; + } + } + return 0; } #ifdef HAVE_SYS_XATTR_H @@ -191,6 +244,7 @@ static int set_attribs(sqfs_xattr_reader_t *xattr, } #endif +#ifndef _WIN32 if (flags & UNPACK_SET_TIMES) { struct timespec times[2]; @@ -222,7 +276,7 @@ static int set_attribs(sqfs_xattr_reader_t *xattr, goto fail; } } - +#endif free(path); return 0; fail: @@ -240,11 +294,11 @@ int restore_fstree(sqfs_tree_node_t *root, int flags) if (S_ISDIR(root->inode->base.mode)) { for (n = root->children; n != NULL; n = n->next) { - if (create_node(n, flags)) + if (create_node_dfs(n, flags)) return -1; } } else { - if (create_node(root, flags)) + if (create_node_dfs(root, flags)) return -1; } |