[Win32] Fix mode of character/pipe device stat [Bug #18732]

This commit is contained in:
Nobuyoshi Nakada 2022-04-15 02:33:08 +09:00
Родитель a0eb4b14d6
Коммит a0040af671
2 изменённых файлов: 44 добавлений и 11 удалений

Просмотреть файл

@ -173,9 +173,7 @@ class TestFileExhaustive < Test::Unit::TestCase
end end
def chardev def chardev
return @chardev if defined? @chardev File::NULL
@chardev = File::NULL == "/dev/null" ? "/dev/null" : nil
@chardev
end end
def blockdev def blockdev
@ -332,7 +330,7 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_file.not_chardev?(regular_file) assert_file.not_chardev?(regular_file)
assert_file.not_chardev?(utf8_file) assert_file.not_chardev?(utf8_file)
assert_file.not_chardev?(nofile) assert_file.not_chardev?(nofile)
assert_file.chardev?(chardev) if chardev assert_file.chardev?(chardev)
end end
def test_exist_p def test_exist_p
@ -1513,6 +1511,31 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_equal(File.executable?(f), test(?x, f), f) assert_equal(File.executable?(f), test(?x, f), f)
assert_equal(File.executable_real?(f), test(?X, f), f) assert_equal(File.executable_real?(f), test(?X, f), f)
assert_equal(File.zero?(f), test(?z, f), f) assert_equal(File.zero?(f), test(?z, f), f)
stat = File.stat(f)
assert_equal(stat.atime, File.atime(f), f)
assert_equal(stat.ctime, File.ctime(f), f)
assert_equal(stat.mtime, File.mtime(f), f)
assert_equal(stat.blockdev?, File.blockdev?(f), f)
assert_equal(stat.chardev?, File.chardev?(f), f)
assert_equal(stat.directory?, File.directory?(f), f)
assert_equal(stat.file?, File.file?(f), f)
assert_equal(stat.setgid?, File.setgid?(f), f)
assert_equal(stat.grpowned?, File.grpowned?(f), f)
assert_equal(stat.sticky?, File.sticky?(f), f)
assert_equal(File.lstat(f).symlink?, File.symlink?(f), f)
assert_equal(stat.owned?, File.owned?(f), f)
assert_equal(stat.pipe?, File.pipe?(f), f)
assert_equal(stat.readable?, File.readable?(f), f)
assert_equal(stat.readable_real?, File.readable_real?(f), f)
assert_equal(stat.size?, File.size?(f), f)
assert_equal(stat.socket?, File.socket?(f), f)
assert_equal(stat.setuid?, File.setuid?(f), f)
assert_equal(stat.writable?, File.writable?(f), f)
assert_equal(stat.writable_real?, File.writable_real?(f), f)
assert_equal(stat.executable?, File.executable?(f), f)
assert_equal(stat.executable_real?, File.executable_real?(f), f)
assert_equal(stat.zero?, File.zero?(f), f)
end end
assert_equal(false, test(?-, @dir, fn1)) assert_equal(false, test(?-, @dir, fn1))
assert_equal(true, test(?-, fn1, fn1)) assert_equal(true, test(?-, fn1, fn1))
@ -1622,7 +1645,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_stat_chardev_p def test_stat_chardev_p
assert_not_predicate(File::Stat.new(@dir), :chardev?) assert_not_predicate(File::Stat.new(@dir), :chardev?)
assert_not_predicate(File::Stat.new(regular_file), :chardev?) assert_not_predicate(File::Stat.new(regular_file), :chardev?)
assert_predicate(File::Stat.new(chardev), :chardev?) if chardev assert_predicate(File::Stat.new(chardev), :chardev?)
end end
def test_stat_readable_p def test_stat_readable_p

Просмотреть файл

@ -5613,10 +5613,8 @@ filetime_to_nsec(const FILETIME *ft)
/* License: Ruby's */ /* License: Ruby's */
static unsigned static unsigned
fileattr_to_unixmode(DWORD attr, const WCHAR *path) fileattr_to_unixmode(DWORD attr, const WCHAR *path, unsigned mode)
{ {
unsigned mode = 0;
if (attr & FILE_ATTRIBUTE_READONLY) { if (attr & FILE_ATTRIBUTE_READONLY) {
mode |= S_IREAD; mode |= S_IREAD;
} }
@ -5624,7 +5622,10 @@ fileattr_to_unixmode(DWORD attr, const WCHAR *path)
mode |= S_IREAD | S_IWRITE | S_IWUSR; mode |= S_IREAD | S_IWRITE | S_IWUSR;
} }
if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { if (mode & S_IFMT) {
/* format is already set */
}
else if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
if (rb_w32_reparse_symlink_p(path)) if (rb_w32_reparse_symlink_p(path))
mode |= S_IFLNK | S_IEXEC; mode |= S_IFLNK | S_IEXEC;
else else
@ -5719,7 +5720,7 @@ stat_by_find(const WCHAR *path, struct stati128 *st)
return -1; return -1;
} }
FindClose(h); FindClose(h);
st->st_mode = fileattr_to_unixmode(wfd.dwFileAttributes, path); st->st_mode = fileattr_to_unixmode(wfd.dwFileAttributes, path, 0);
st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime); st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
st->st_atimensec = filetime_to_nsec(&wfd.ftLastAccessTime); st->st_atimensec = filetime_to_nsec(&wfd.ftLastAccessTime);
st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime); st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
@ -5752,6 +5753,15 @@ winnt_stat(const WCHAR *path, struct stati128 *st, BOOL lstat)
if (f != INVALID_HANDLE_VALUE) { if (f != INVALID_HANDLE_VALUE) {
DWORD attr = stati128_handle(f, st); DWORD attr = stati128_handle(f, st);
const DWORD len = get_final_path(f, finalname, numberof(finalname), 0); const DWORD len = get_final_path(f, finalname, numberof(finalname), 0);
unsigned mode = 0;
switch (GetFileType(f)) {
case FILE_TYPE_CHAR:
mode = S_IFCHR;
break;
case FILE_TYPE_PIPE:
mode = S_IFIFO;
break;
}
CloseHandle(f); CloseHandle(f);
if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
/* TODO: size in which encoding? */ /* TODO: size in which encoding? */
@ -5763,7 +5773,7 @@ winnt_stat(const WCHAR *path, struct stati128 *st, BOOL lstat)
if (attr & FILE_ATTRIBUTE_DIRECTORY) { if (attr & FILE_ATTRIBUTE_DIRECTORY) {
if (check_valid_dir(path)) return -1; if (check_valid_dir(path)) return -1;
} }
st->st_mode = fileattr_to_unixmode(attr, path); st->st_mode = fileattr_to_unixmode(attr, path, mode);
if (len) { if (len) {
finalname[min(len, numberof(finalname)-1)] = L'\0'; finalname[min(len, numberof(finalname)-1)] = L'\0';
path = finalname; path = finalname;