diff options
Diffstat (limited to 'Utilities/cmlibarchive/libarchive/filter_fork_windows.c')
-rw-r--r-- | Utilities/cmlibarchive/libarchive/filter_fork_windows.c | 143 |
1 files changed, 108 insertions, 35 deletions
diff --git a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c index 272e56c6b..fa59cc9e9 100644 --- a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c +++ b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,17 +26,100 @@ #include "archive_platform.h" #if defined(_WIN32) && !defined(__CYGWIN__) +#include "archive_cmdline_private.h" +#include "archive_string.h" #include "filter_fork.h" pid_t -__archive_create_child(const char *path, int *child_stdin, int *child_stdout) +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) { HANDLE childStdout[2], childStdin[2],childStderr; SECURITY_ATTRIBUTES secAtts; STARTUPINFO staInfo; PROCESS_INFORMATION childInfo; - char cmd[MAX_PATH]; + struct archive_string cmdline; + struct archive_string fullpath; + struct archive_cmdline *acmd; + char *arg0, *ext; + int i, l; + DWORD fl, fl_old; + + childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE; + childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE; + childStderr = INVALID_HANDLE_VALUE; + archive_string_init(&cmdline); + archive_string_init(&fullpath); + + acmd = __archive_cmdline_allocate(); + if (acmd == NULL) + goto fail; + if (__archive_cmdline_parse(acmd, cmd) != ARCHIVE_OK) + goto fail; + + /* + * Search the full path of 'path'. + * NOTE: This does not need if we give CreateProcessA 'path' as + * a part of the cmdline and give CreateProcessA NULL as first + * parameter, but I do not like that way. + */ + ext = strrchr(acmd->path, '.'); + if (ext == NULL || strlen(ext) > 4) + /* 'path' does not have a proper extension, so we have to + * give SearchPath() ".exe" as the extension. */ + ext = ".exe"; + else + ext = NULL;/* 'path' has an extension. */ + + fl = MAX_PATH; + do { + if (archive_string_ensure(&fullpath, fl) == NULL) + goto fail; + fl_old = fl; + fl = SearchPathA(NULL, acmd->path, ext, fl, fullpath.s, + &arg0); + } while (fl != 0 && fl > fl_old); + if (fl == 0) + goto fail; + + /* + * Make a command line. + */ + for (l = 0, i = 0; acmd->argv[i] != NULL; i++) { + if (i == 0) + continue; + l += (int)strlen(acmd->argv[i]) + 1; + } + if (archive_string_ensure(&cmdline, l + 1) == NULL) + goto fail; + for (i = 0; acmd->argv[i] != NULL; i++) { + if (i == 0) { + const char *p, *sp; + + if ((p = strchr(acmd->argv[i], '/')) != NULL || + (p = strchr(acmd->argv[i], '\\')) != NULL) + p++; + else + p = acmd->argv[i]; + if ((sp = strchr(p, ' ')) != NULL) + archive_strappend_char(&cmdline, '"'); + archive_strcat(&cmdline, p); + if (sp != NULL) + archive_strappend_char(&cmdline, '"'); + } else { + archive_strappend_char(&cmdline, ' '); + archive_strcat(&cmdline, acmd->argv[i]); + } + } + if (i <= 1) { + const char *sp; + + if ((sp = strchr(arg0, ' ')) != NULL) + archive_strappend_char(&cmdline, '"'); + archive_strcat(&cmdline, arg0); + if (sp != NULL) + archive_strappend_char(&cmdline, '"'); + } secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); secAtts.bInheritHandle = TRUE; @@ -44,33 +127,15 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0) goto fail; if (!SetHandleInformation(childStdout[0], HANDLE_FLAG_INHERIT, 0)) - { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); goto fail; - } - if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); + if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) goto fail; - } if (!SetHandleInformation(childStdin[1], HANDLE_FLAG_INHERIT, 0)) - { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); - CloseHandle(childStdin[0]); - CloseHandle(childStdin[1]); goto fail; - } if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), GetCurrentProcess(), &childStderr, 0, TRUE, - DUPLICATE_SAME_ACCESS) == 0) { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); - CloseHandle(childStdin[0]); - CloseHandle(childStdin[1]); + DUPLICATE_SAME_ACCESS) == 0) goto fail; - } memset(&staInfo, 0, sizeof(staInfo)); staInfo.cb = sizeof(staInfo); @@ -79,17 +144,9 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) staInfo.hStdInput = childStdin[0]; staInfo.wShowWindow = SW_HIDE; staInfo.dwFlags = 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(childStdout[0]); - CloseHandle(childStdout[1]); - CloseHandle(childStdin[0]); - CloseHandle(childStdin[1]); - CloseHandle(childStderr); + if (CreateProcessA(fullpath.s, cmdline.s, NULL, NULL, TRUE, 0, + NULL, NULL, &staInfo, &childInfo) == 0) goto fail; - } WaitForInputIdle(childInfo.hProcess, INFINITE); CloseHandle(childInfo.hProcess); CloseHandle(childInfo.hThread); @@ -100,17 +157,33 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) CloseHandle(childStdout[1]); CloseHandle(childStdin[0]); + archive_string_free(&cmdline); + archive_string_free(&fullpath); + __archive_cmdline_free(acmd); return (childInfo.dwProcessId); fail: + if (childStdout[0] != INVALID_HANDLE_VALUE) + CloseHandle(childStdout[0]); + if (childStdout[1] != INVALID_HANDLE_VALUE) + CloseHandle(childStdout[1]); + if (childStdin[0] != INVALID_HANDLE_VALUE) + CloseHandle(childStdin[0]); + if (childStdin[1] != INVALID_HANDLE_VALUE) + CloseHandle(childStdin[1]); + if (childStderr != INVALID_HANDLE_VALUE) + CloseHandle(childStderr); + archive_string_free(&cmdline); + archive_string_free(&fullpath); + __archive_cmdline_free(acmd); return (-1); } void __archive_check_child(int in, int out) { - (void)in; /* UNSED */ - (void)out; /* UNSED */ + (void)in; /* UNUSED */ + (void)out; /* UNUSED */ Sleep(100); } |