]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Get a full path of a command name for CreateProcess().
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sat, 6 Oct 2012 04:20:45 +0000 (13:20 +0900)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sat, 6 Oct 2012 04:20:45 +0000 (13:20 +0900)
libarchive/filter_fork_windows.c

index c18ddff344f55bb5cb90416a349b017305943617..7052ac72ab5fb38313800a01f444a9393fc4eb83 100644 (file)
 #include "filter_fork.h"
 
 pid_t
-__archive_create_child(const char *path, char * const argv[], int *child_stdin,
+__archive_create_child(const char *cmd, char * const argv[], int *child_stdin,
     int *child_stdout)
 {
        HANDLE childStdout[2], childStdin[2],childStderr;
        SECURITY_ATTRIBUTES secAtts;
        STARTUPINFO staInfo;
        PROCESS_INFORMATION childInfo;
-       struct archive_string appname;
        struct archive_string cmdline;
+       struct archive_string fullpath;
+       char *ext;
        int i, l;
+       DWORD fl, fl_old;
 
-       archive_string_init(&appname);
+       childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE;
+       childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE;
+       childStderr = INVALID_HANDLE_VALUE;
        archive_string_init(&cmdline);
-       if (archive_string_ensure(&appname, strlen(path) + 1) == NULL)
+       archive_string_init(&fullpath);
+
+       /*
+        * Search the full path of 'cmd'.
+        * NOTE: This does not need if we give CreateProcessA 'cmd' as a part
+        * of the cmdline and give CreateProcessA NULL as first parameter,
+        * but I do not like that way.
+        */
+       ext = strrchr(cmd, '.');
+       if (ext == NULL || strlen(ext) > 4)
+               /* 'cmd' does not have a proper extension, so we have to
+                * give SearchPath() ".exe" as the extension. */
+               ext = ".exe";
+       else
+               ext = NULL;/* 'cmd' has an extension. */
+
+       fl = MAX_PATH;
+       do {
+               if (archive_string_ensure(&fullpath, fl) == NULL)
+                       goto fail;
+               fl_old = fl;
+               fl = SearchPath(NULL, cmd, ext, fl, fullpath.s, NULL);
+       } while (fl != 0 && fl > fl_old);
+       if (fl == 0)
                goto fail;
-       archive_strcpy(&appname, path);
+
+       /*
+        * Make a command line.
+        */
        for (l = 0, i = 0;  argv[i] != NULL; i++) {
                if (i == 0)
                        continue;
@@ -55,12 +85,12 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin,
        if (archive_string_ensure(&cmdline, l + 1) == NULL)
                goto fail;
        for (i = 0;  argv[i] != NULL; i++) {
-               if (i == 0)
-                       continue;
-               if (i > 1)
+               if (i > 0)
                        archive_strappend_char(&cmdline, ' ');
                archive_strcat(&cmdline, argv[i]);
        }
+       if (i <= 1)
+               cmdline.s[0] = 0;
 
        secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
        secAtts.bInheritHandle = TRUE;
@@ -68,33 +98,15 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin,
        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);
@@ -103,15 +115,9 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin,
        staInfo.hStdInput = childStdin[0];
        staInfo.wShowWindow = SW_HIDE;
        staInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-       if (CreateProcessA(appname.s, cmdline.s, 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);
@@ -122,13 +128,23 @@ __archive_create_child(const char *path, char * const argv[], int *child_stdin,
        CloseHandle(childStdout[1]);
        CloseHandle(childStdin[0]);
 
-       archive_string_free(&appname);
        archive_string_free(&cmdline);
+       archive_string_free(&fullpath);
        return (childInfo.dwProcessId);
 
 fail:
-       archive_string_free(&appname);
+       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);
        return (-1);
 }