]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
On Windows, libarchive/bsdtar can deal with an external program.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Thu, 19 Feb 2009 06:15:21 +0000 (01:15 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Thu, 19 Feb 2009 06:15:21 +0000 (01:15 -0500)
SVN-Revision: 674

CMakeLists.txt
libarchive/archive_read_support_compression_program.c
libarchive/archive_windows.c
libarchive/archive_windows.h
libarchive/archive_write_set_compression_program.c
libarchive/filter_fork_windows.c [new file with mode: 0644]

index 55a9312862d2cd0228df68d064aad9fdc69e1c78..6ff1d30e5807e9b93cda8678316b4295b10cd947 100644 (file)
@@ -622,6 +622,7 @@ SET(libarchive_MANS
 IF(WIN32)
   LIST(APPEND libarchive_SOURCES libarchive/archive_windows.c)
   LIST(APPEND libarchive_SOURCES libarchive/archive_windows.h)
+  LIST(APPEND libarchive_SOURCES libarchive/filter_fork_windows.c)
 ENDIF(WIN32)
 
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libarchive)
index 31adaeb366d0b7d5211687a1ecec78edd7a5e964..f26bfcca16f0564a71604cfb1374c9753ef884c9 100644 (file)
@@ -60,8 +60,8 @@ archive_read_support_compression_program(struct archive *a, const char *cmd)
 
 
 /* This capability is only available on POSIX systems. */
-#if !defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
-    !(defined(HAVE_FORK) || defined(HAVE_VFORK))
+#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
+    !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && !defined(_WIN32)
 
 /*
  * On non-Posix systems, allow the program to build, but choke if
index 9be562e3e5127b9b776702b6e76a6edbd265a16d..779e5c4a324cb6391594d555cb04ae57596a9d59 100644 (file)
@@ -533,6 +533,27 @@ la_chmod(const char *path, mode_t mode)
        return (r);
 }
 
+/*
+ * This fcntl is limited implemention.
+ */
+int
+la_fcntl(int fd, int cmd, int val)
+{
+       HANDLE handle;
+
+       handle = (HANDLE)_get_osfhandle(fd);
+       if (GetFileType(handle) == FILE_TYPE_PIPE) {
+               if (cmd == F_SETFL && val == 0) {
+                       DWORD mode = PIPE_WAIT;
+                       if (SetNamedPipeHandleState(
+                           handle, &mode, NULL, NULL) != 0)
+                               return (0);
+               }
+       }
+       errno = EINVAL;
+       return (-1);
+}
+
 __int64
 la_lseek(int fd, __int64 offset, int whence)
 {
@@ -658,6 +679,7 @@ la_open(const char *path, int flags, ...)
 ssize_t
 la_read(int fd, void *buf, size_t nbytes)
 {
+       HANDLE handle;
        DWORD bytes_read, lasterr;
        int r;
 
@@ -669,10 +691,31 @@ la_read(int fd, void *buf, size_t nbytes)
                errno = EBADF;
                return (-1);
        }
-       r = ReadFile((HANDLE)_get_osfhandle(fd), buf, (uint32_t)nbytes,
+       handle = (HANDLE)_get_osfhandle(fd);
+       if (GetFileType(handle) == FILE_TYPE_PIPE) {
+               DWORD sta;
+               if (GetNamedPipeHandleState(
+                   handle, &sta, NULL, NULL, NULL, NULL, 0) != 0 &&
+                   (sta & PIPE_NOWAIT) == 0) {
+                       DWORD avail = -1;
+                       int cnt = 3;
+
+                       while (PeekNamedPipe(
+                           handle, NULL, 0, NULL, &avail, NULL) != 0 &&
+                           avail == 0 && --cnt)
+                               Sleep(100);
+                       if (avail == 0)
+                               return (0);
+               }
+       }
+       r = ReadFile(handle, buf, (uint32_t)nbytes,
            &bytes_read, NULL);
        if (r == 0) {
                lasterr = GetLastError();
+               if (lasterr == ERROR_NO_DATA) {
+                       errno = EAGAIN;
+                       return (-1);
+               }
                if (lasterr == ERROR_BROKEN_PIPE)
                        return (0);
                if (lasterr == ERROR_ACCESS_DENIED)
@@ -921,6 +964,36 @@ la_unlink(const char *path)
        return (r);
 }
 
+/*
+ * This waitpid is limited implemention.
+ */
+pid_t
+la_waitpid(pid_t wpid, int *status, int option)
+{
+       HANDLE child;
+       DWORD cs, ret;
+
+       (void)option;/* UNUSED */
+       child = OpenProcess(PROCESS_ALL_ACCESS, FALSE, wpid);
+       if (child == NULL)
+               return (-1);
+       ret = WaitForSingleObject(child, INFINITE);
+       if (ret == WAIT_FAILED) {
+               CloseHandle(child);
+               return (-1);
+       }
+       if (GetExitCodeProcess(child, &cs) == 0) {
+               CloseHandle(child);
+               return (-1);
+       }
+       if (cs == STILL_ACTIVE)
+               *status = 0x100;
+       else
+               *status = (int)(cs & 0xff);
+       CloseHandle(child);
+       return (wpid);
+}
+
 ssize_t
 la_write(int fd, const void *buf, size_t nbytes)
 {
index 0b060a9eac694c1b06e2fa59b1749be7b7709b1b..7c326a99a3734ad8a7cfa3fe88ba5b2bfa7e0b13 100644 (file)
@@ -85,6 +85,7 @@
 #define        chdir           la_chdir
 #define        chmod           la_chmod
 #define        close           _close
+#define        fcntl           la_fcntl
 #define        fileno          _fileno
 #define        fstat           la_fstat
 #define        getcwd          _getcwd
 #define        tzset           _tzset
 #define        umask           _umask
 #define        unlink          la_unlink
+#define        waitpid         la_waitpid
 #define        write           la_write
 
 #define        O_RDONLY        _O_RDONLY
@@ -256,6 +258,8 @@ struct _timeval64i32 {
 #define __timeval _timeval64i32
 #endif
 
+typedef int pid_t;
+
 #define SYSTEM_PATH_CHAR       '\\'
 
 /* Message digest define */
@@ -311,6 +315,7 @@ extern int   utimes(const char *name, const struct __timeval *times);
 /* Replacement POSIX function */
 extern int      la_chdir(const char *path);
 extern int      la_chmod(const char *path, mode_t mode);
+extern int      la_fcntl(int fd, int cmd, int val);
 extern int      la_fstat(int fd, struct stat *st);
 extern __int64  la_lseek(int fd, __int64 offset, int whence);
 extern int      la_mkdir(const char *path, mode_t mode);
@@ -320,6 +325,7 @@ extern ssize_t       la_read(int fd, void *buf, size_t nbytes);
 extern int      la_rmdir(const char *path);
 extern int      la_stat(const char *path, struct stat *st);
 extern int      la_unlink(const char *path);
+extern pid_t    la_waitpid(pid_t wpid, int *status, int option);
 extern ssize_t  la_write(int fd, const void *buf, size_t nbytes);
 
 #define _stat64i32(path, st)   la_stat(path, st)
index 69c5d4286332b768fa83e2db508a7ac7dde1570f..a27c64793e981a700ac9c1100963f078f8cd2fb7 100644 (file)
@@ -28,8 +28,8 @@
 __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_program.c,v 1.3 2008/06/15 10:45:57 kientzle Exp $");
 
 /* This capability is only available on POSIX systems. */
-#if !defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
-    !(defined(HAVE_FORK) || defined(HAVE_VFORK))
+#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
+    !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && !defined(_WIN32)
 #include "archive.h"
 
 /*
diff --git a/libarchive/filter_fork_windows.c b/libarchive/filter_fork_windows.c
new file mode 100644 (file)
index 0000000..8380053
--- /dev/null
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2009 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+#ifdef _WIN32
+
+#include "filter_fork.h"
+
+pid_t
+__archive_create_child(const char *path, int *child_stdin, int *child_stdout)
+{
+       HANDLE childStdout[2], childStdin[2], childStdinWr, childStdoutRd;
+       SECURITY_ATTRIBUTES secAtts;
+       STARTUPINFO staInfo;
+       PROCESS_INFORMATION childInfo;
+       char cmd[MAX_PATH];
+       DWORD mode;
+
+       secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
+       secAtts.bInheritHandle = TRUE;
+       secAtts.lpSecurityDescriptor = NULL;
+       if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0)
+               goto fail;
+       if (DuplicateHandle(GetCurrentProcess(), childStdout[0],
+           GetCurrentProcess(), &childStdoutRd, 0, FALSE,
+           DUPLICATE_SAME_ACCESS) == 0) {
+               CloseHandle(childStdout[0]);
+               CloseHandle(childStdout[1]);
+               goto fail;
+       }
+       CloseHandle(childStdout[0]);
+
+       if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) {
+               CloseHandle(childStdoutRd);
+               CloseHandle(childStdout[1]);
+               goto fail;
+       }
+
+       if (DuplicateHandle(GetCurrentProcess(), childStdin[1],
+           GetCurrentProcess(), &childStdinWr, 0, FALSE,
+           DUPLICATE_SAME_ACCESS) == 0) {
+               CloseHandle(childStdoutRd);
+               CloseHandle(childStdout[1]);
+               CloseHandle(childStdin[0]);
+               CloseHandle(childStdin[1]);
+               goto fail;
+       }
+       CloseHandle(childStdin[1]);
+
+       memset(&staInfo, 0, sizeof(staInfo));
+       staInfo.cb = sizeof(staInfo);
+       staInfo.hStdOutput = childStdout[1];
+       staInfo.hStdInput = childStdin[0];
+       staInfo.wShowWindow = SW_HIDE;
+       staInfo.dwFlags = STARTF_USEFILLATTRIBUTE | STARTF_USECOUNTCHARS |
+           STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+       strncpy(cmd, path, sizeof(cmd)-1);
+       cmd[sizeof(cmd)-1] = '\0';
+       if (CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL,
+           &staInfo, &childInfo) == 0) {
+               CloseHandle(childStdoutRd);
+               CloseHandle(childStdout[1]);
+               CloseHandle(childStdin[0]);
+               CloseHandle(childStdinWr);
+               goto fail;
+       }
+       WaitForInputIdle(childInfo.hProcess, INFINITE);
+       CloseHandle(childInfo.hProcess);
+       CloseHandle(childInfo.hThread);
+
+       mode = PIPE_NOWAIT;
+       SetNamedPipeHandleState(childStdoutRd, &mode, NULL, NULL);
+       *child_stdout = _open_osfhandle((intptr_t)childStdoutRd, _O_RDONLY);
+       *child_stdin = _open_osfhandle((intptr_t)childStdinWr, _O_WRONLY);
+
+       return (childInfo.dwProcessId);
+
+fail:
+       return (-1);
+}
+
+void
+__archive_check_child(int in, int out)
+{
+       Sleep(100);
+}
+
+#endif /* _WIN32 */