diff options
-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; } |