Windows: Work around misbehaved rename().
[gitweb.git] / compat / mingw.c
index 0e1ddbe4dff977c4141df925940c90bbbe7f7e24..c6a5c1b2184643a84ac2fc9dde619f89f245386a 100644 (file)
@@ -73,6 +73,31 @@ char *mingw_getcwd(char *pointer, int len)
        return ret;
 }
 
+#undef rename
+int mingw_rename(const char *pold, const char *pnew)
+{
+       /*
+        * Try native rename() first to get errno right.
+        * It is based on MoveFile(), which cannot overwrite existing files.
+        */
+       if (!rename(pold, pnew))
+               return 0;
+       if (errno != EEXIST)
+               return -1;
+       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)) {
+                       errno = EISDIR;
+                       return -1;
+               }
+       }
+       errno = EACCES;
+       return -1;
+}
+
 struct passwd *getpwuid(int uid)
 {
        static char user_name[100];