summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-11-18 15:09:31 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-11-19 21:12:56 +0100
commit3497201ce66f35401bd02109c06c110671493ad8 (patch)
tree0f3e4fcdc99df02e4879c8154396d5ae89bc5758
parent585997f4677db3707eb99b1012dad036ddecc0d0 (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>
-rw-r--r--unpack/rdsquashfs.h4
-rw-r--r--unpack/restore_fstree.c134
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;
}