Add Stat.is_symbolic_link_.

This commit is contained in:
levlam 2023-01-04 16:39:33 +03:00
parent 0d35ce485f
commit 8df67f0c3a
5 changed files with 27 additions and 2 deletions

View File

@ -182,6 +182,8 @@ Result<FileFd> FileFd::open(CSlice filepath, int32 flags, int32 mode) {
// TODO: share mode
DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE;
DWORD native_flags = 0;
DWORD creation_disposition = 0;
if (flags & Create) {
if (flags & Truncate) {
@ -197,9 +199,9 @@ Result<FileFd> FileFd::open(CSlice filepath, int32 flags, int32 mode) {
} else {
creation_disposition = OPEN_EXISTING;
}
native_flags |= FILE_FLAG_OPEN_REPARSE_POINT;
}
DWORD native_flags = 0;
if (flags & Direct) {
native_flags |= FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING;
}
@ -593,7 +595,19 @@ Result<Stat> FileFd::stat() const {
res.atime_nsec_ = filetime_to_unix_time_nsec(basic_info.LastAccessTime.QuadPart);
res.mtime_nsec_ = filetime_to_unix_time_nsec(basic_info.LastWriteTime.QuadPart);
res.is_dir_ = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
res.is_reg_ = !res.is_dir_; // TODO this is still wrong
if ((basic_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
FILE_ATTRIBUTE_TAG_INFO tag_info;
status = GetFileInformationByHandleEx(get_native_fd().fd(), FileAttributeTagInfo, &tag_info, sizeof(tag_info));
if (!status) {
return OS_ERROR("Get FileAttributeTagInfo failed");
}
res.is_reg_ = false;
res.is_symbolic_link_ =
(tag_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 && tag_info.ReparseTag == IO_REPARSE_TAG_SYMLINK;
} else {
res.is_reg_ = !res.is_dir_;
res.is_symbolic_link_ = false;
}
TRY_RESULT(file_size, get_file_size(*this));
res.size_ = file_size.size_;

View File

@ -126,6 +126,7 @@ Stat from_native_stat(const struct ::stat &buf) {
res.real_size_ = buf.st_blocks * 512;
res.is_dir_ = (buf.st_mode & S_IFMT) == S_IFDIR;
res.is_reg_ = (buf.st_mode & S_IFMT) == S_IFREG;
res.is_symbolic_link_ = (buf.st_mode & S_IFMT) == S_IFLNK;
return res;
}

View File

@ -17,6 +17,7 @@ namespace td {
struct Stat {
bool is_dir_;
bool is_reg_;
bool is_symbolic_link_;
int64 size_;
int64 real_size_;
uint64 atime_nsec_;

View File

@ -434,6 +434,7 @@ Result<string> realpath(CSlice slice, bool ignore_access_denied) {
if (res.empty()) {
return Status::Error("Empty path");
}
// TODO GetFullPathName doesn't resolve symbolic links
if (!slice.empty() && slice.end()[-1] == TD_DIR_SLASH) {
if (res.back() != TD_DIR_SLASH) {
res += TD_DIR_SLASH;

View File

@ -167,6 +167,14 @@ TEST(Port, Writev) {
td::string content(expected_content.size(), '\0');
ASSERT_EQ(content.size(), fd.read(content).move_as_ok());
ASSERT_EQ(expected_content, content);
auto stat = td::stat(test_file_path).move_as_ok();
CHECK(!stat.is_dir_);
CHECK(stat.is_reg_);
CHECK(!stat.is_symbolic_link_);
CHECK(stat.size_ == static_cast<td::int64>(expected_content.size()));
td::unlink(test_file_path).ignore();
}
#if TD_PORT_POSIX && !TD_THREAD_UNSUPPORTED