@matheusbsbs / matheus-bagliano / commits / ea9e98c3a5
Fork 0

Windows: Work around misbehaved rename().

Windows's rename() is based on the MoveFile() API, which fails if the destination exists. Here we work around the problem by using MoveFileEx(). Furthermore, the posixly correct error is returned if the destination is a directory. The implementation is still slightly incomplete, however, because of the missing error code translation: We assume that the failure is due to permissions. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>

Johannes Sixt committed Dec 7, 2007 at 22:19 UTC ea9e98c3a54d3b693367fbb8c87812b17ad95869
2 files changed +28
compat/mingw.c
+25
@@ -73,6 +73,31 @@ char *mingw_getcwd(char *pointer, int len)
73 return ret;
74 }
75
76 +#undef rename
77 +int mingw_rename(const char *pold, const char *pnew)
78 +{
79 + /*
80 + * Try native rename() first to get errno right.
81 + * It is based on MoveFile(), which cannot overwrite existing files.
82 + */
83 + if (!rename(pold, pnew))
84 + return 0;
85 + if (errno != EEXIST)
86 + return -1;
87 + if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
88 + return 0;
89 + /* TODO: translate more errors */
90 + if (GetLastError() == ERROR_ACCESS_DENIED) {
91 + DWORD attrs = GetFileAttributes(pnew);
92 + if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
93 + errno = EISDIR;
94 + return -1;
95 + }
96 + }
97 + errno = EACCES;
98 + return -1;
99 +}
100 +
101 struct passwd *getpwuid(int uid)
102 {
103 static char user_name[100];
compat/mingw.h
+3
@@ -151,6 +151,9 @@ int mingw_open (const char *filename, int oflags, ...);
151 char *mingw_getcwd(char *pointer, int len);
152 #define getcwd mingw_getcwd
153
154 +int mingw_rename(const char*, const char*);
155 +#define rename mingw_rename
156 +
157 /*
158 * git specific compatibility
159 */