Skip to content

Instantly share code, notes, and snippets.

@corford
Created September 18, 2017 23:53
Show Gist options
  • Save corford/5d67e808ec11e1fab44dd0796e12eb60 to your computer and use it in GitHub Desktop.
Save corford/5d67e808ec11e1fab44dd0796e12eb60 to your computer and use it in GitHub Desktop.
mingw.c
int mingw_lstat(const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
WIN32_FIND_DATAW findbuf;
wchar_t wfilename[MAX_LONG_PATH];
int wlen = xutftowcs_long_path(wfilename, file_name);
if (wlen < 0)
return -1;
/* strip trailing '/', or GetFileAttributes will fail */
while (wlen && is_dir_sep(wfilename[wlen - 1]))
wfilename[--wlen] = 0;
if (!wlen) {
errno = ENOENT;
return -1;
}
error("getting attribs for: %s", file_name);
if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
/* for reparse points, use FindFirstFile to get the reparse tag */
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
if (handle == INVALID_HANDLE_VALUE)
goto error;
FindClose(handle);
}
buf->st_ino = 0;
buf->st_gid = 0;
buf->st_uid = 0;
buf->st_nlink = 1;
error("dwFileAttributes: %lu", fdata.dwFileAttributes);
error("dwReserved0: %lu", findbuf.dwReserved0);
error("translated attribs: %x", (int)file_attr_to_st_mode(fdata.dwFileAttributes, findbuf.dwReserved0));
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes,
findbuf.dwReserved0);
buf->st_size = S_ISLNK(buf->st_mode) ? MAX_LONG_PATH :
fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
return 0;
}
error:
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;
case ERROR_PATH_NOT_FOUND:
if (!has_valid_directory_prefix(wfilename)) {
errno = ENOTDIR;
break;
}
/* fallthru */
default:
errno = ENOENT;
break;
}
return -1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment