#include "../git-compat-util.h"
+#include "win32.h"
#include "../strbuf.h"
unsigned int _CRT_fmode = _O_BINARY;
return (time_t)winTime;
}
-extern int _getdrive( void );
/* We keep the do_lstat code in a separate function to avoid recursion.
* When a path ends with a slash, the stat will fail with ENOENT. In
* this case, we strip the trailing slashes and stat again.
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
- if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
- int fMode = S_IREAD;
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- fMode |= S_IFDIR;
- else
- fMode |= S_IFREG;
- if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
- fMode |= S_IWRITE;
-
+ if (!(errno = get_file_attr(file_name, &fdata))) {
buf->st_ino = 0;
buf->st_gid = 0;
buf->st_uid = 0;
buf->st_nlink = 1;
- buf->st_mode = fMode;
+ buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
- buf->st_dev = buf->st_rdev = (_getdrive() - 1);
+ buf->st_dev = buf->st_rdev = 0; /* not used by Git */
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
- errno = 0;
return 0;
}
-
- switch (GetLastError()) {
- case ERROR_ACCESS_DENIED:
- case ERROR_SHARING_VIOLATION:
- case ERROR_LOCK_VIOLATION:
- case ERROR_SHARING_BUFFER_EXCEEDED:
- errno = EACCES;
- break;
- case ERROR_BUFFER_OVERFLOW:
- errno = ENAMETOOLONG;
- break;
- case ERROR_NOT_ENOUGH_MEMORY:
- errno = ENOMEM;
- break;
- default:
- errno = ENOENT;
- break;
- }
return -1;
}
return fstat(fd, buf);
if (GetFileInformationByHandle(fh, &fdata)) {
- int fMode = S_IREAD;
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- fMode |= S_IFDIR;
- else
- fMode |= S_IFREG;
- if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
- fMode |= S_IWRITE;
-
buf->st_ino = 0;
buf->st_gid = 0;
buf->st_uid = 0;
buf->st_nlink = 1;
- buf->st_mode = fMode;
+ buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
- buf->st_dev = buf->st_rdev = (_getdrive() - 1);
+ buf->st_dev = buf->st_rdev = 0; /* not used by Git */
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
{
int i, pending;
- if (timeout != -1)
+ if (timeout >= 0) {
+ if (nfds == 0) {
+ Sleep(timeout);
+ return 0;
+ }
return errno = EINVAL, error("poll timeout not supported");
+ }
/* When there is only one fd to wait for, then we pretend that
* input is available and let the actual wait happen when the
* 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;
#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.
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;