FileInformation FileDescriptor::getInfo() const { #ifndef _WIN32 struct stat st; if (fstat(fd_, &st)) { int err = errno; throw std::system_error(err, std::generic_category(), "fstat"); } return FileInformation(st); #else // _WIN32 FILE_BASIC_INFO binfo; FILE_STANDARD_INFO sinfo; if (!GetFileInformationByHandleEx( (HANDLE)handle(), FileBasicInfo, &binfo, sizeof(binfo))) { throw std::system_error( GetLastError(), std::system_category(), "GetFileInformationByHandleEx FileBasicInfo"); } FileInformation info(binfo.FileAttributes); FILETIME_LARGE_INTEGER_to_timespec(binfo.CreationTime, &info.ctime); FILETIME_LARGE_INTEGER_to_timespec(binfo.LastAccessTime, &info.atime); FILETIME_LARGE_INTEGER_to_timespec(binfo.LastWriteTime, &info.mtime); if (!GetFileInformationByHandleEx( (HANDLE)handle(), FileStandardInfo, &sinfo, sizeof(sinfo))) { throw std::system_error( GetLastError(), std::system_category(), "GetFileInformationByHandleEx FileStandardInfo"); } info.size = sinfo.EndOfFile.QuadPart; info.nlink = sinfo.NumberOfLinks; return info; #endif }
int lstat(const char *path, struct stat *st) { FILE_BASIC_INFO binfo; FILE_STANDARD_INFO sinfo; WCHAR *wpath = w_utf8_to_win_unc(path, -1); HANDLE h; DWORD err; memset(st, 0, sizeof(*st)); if (!wpath) { return -1; } h = CreateFileW(wpath, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL); err = GetLastError(); free(wpath); if (h == INVALID_HANDLE_VALUE) { w_log(W_LOG_DBG, "lstat(%s): %s\n", path, win32_strerror(err)); errno = map_win32_err(err); return -1; } if (path[1] == ':') { int drive_letter = tolower(path[0]); st->st_rdev = st->st_dev = drive_letter - 'a'; } if (GetFileInformationByHandleEx(h, FileBasicInfo, &binfo, sizeof(binfo))) { FILETIME_LARGE_INTEGER_to_timespec(binfo.CreationTime, &st->st_ctim); st->st_ctime = st->st_ctim.tv_sec; FILETIME_LARGE_INTEGER_to_timespec(binfo.LastAccessTime, &st->st_atim); st->st_atime = st->st_atim.tv_sec; FILETIME_LARGE_INTEGER_to_timespec(binfo.LastWriteTime, &st->st_mtim); st->st_mtime = st->st_mtim.tv_sec; if (binfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { // This is a symlink, but msvcrt has no way to indicate that. // We'll treat it as a regular file until we have a better // representation :-/ st->st_mode = _S_IFREG; } else if (binfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { st->st_mode |= _S_IFDIR|S_IEXEC|S_IXGRP|S_IXOTH; } else { st->st_mode |= _S_IFREG; } if (binfo.FileAttributes & FILE_ATTRIBUTE_READONLY) { st->st_mode |= 0444; } else { st->st_mode |= 0666; } } if (GetFileInformationByHandleEx(h, FileStandardInfo, &sinfo, sizeof(sinfo))) { st->st_size = sinfo.EndOfFile.QuadPart; st->st_nlink = sinfo.NumberOfLinks; } CloseHandle(h); return 0; }