Merge branch 'sg/maint-gitdir-in-subdir'
[gitweb.git] / compat / mingw.c
index 09858f6c593d9a8301c857c81e09bfa24b955eac..3dbe6a77ffa4675b19e7183fd49e11212cb2cda0 100644 (file)
@@ -536,12 +536,16 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
                 * would normally create a console window. But
                 * since we'll be redirecting std streams, we do
                 * not need the console.
+                * It is necessary to use DETACHED_PROCESS
+                * instead of CREATE_NO_WINDOW to make ssh
+                * recognize that it has no console.
                 */
-               flags = CREATE_NO_WINDOW;
+               flags = DETACHED_PROCESS;
        } else {
                /* There is already a console. If we specified
-                * CREATE_NO_WINDOW here, too, Windows would
+                * DETACHED_PROCESS here, too, Windows would
                 * disassociate the child from the console.
+                * The same is true for CREATE_NO_WINDOW.
                 * Go figure!
                 */
                flags = 0;
@@ -815,6 +819,8 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
 #undef rename
 int mingw_rename(const char *pold, const char *pnew)
 {
+       DWORD attrs;
+
        /*
         * Try native rename() first to get errno right.
         * It is based on MoveFile(), which cannot overwrite existing files.
@@ -826,12 +832,19 @@ int mingw_rename(const char *pold, const char *pnew)
        if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
                return 0;
        /* TODO: translate more errors */
-       if (GetLastError() == ERROR_ACCESS_DENIED) {
-               DWORD attrs = GetFileAttributes(pnew);
-               if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
+       if (GetLastError() == ERROR_ACCESS_DENIED &&
+           (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
+               if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
                        errno = EISDIR;
                        return -1;
                }
+               if ((attrs & FILE_ATTRIBUTE_READONLY) &&
+                   SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
+                       if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
+                               return 0;
+                       /* revert file attributes on failure */
+                       SetFileAttributes(pnew, attrs);
+               }
        }
        errno = EACCES;
        return -1;