MSVC2015 上的实验性 C++17 文件系统:权限不一致
Experimental C++17 filesystem on MSVC2015: inconsistencies with permissions
我正在尝试使用实验性 <filesystem>
library that should become part of C++17 (See draft technical spec N4100) on MSVC2015(更新 1)。
我可以设法递归显示目录的全部内容:
using namespace std::tr2::sys;
...
path dir = canonical(".");
for (auto& p : recursive_directory_iterator(dir)) {
if (is_regular_file(p))
cout << file_size(p);
perms pe = p.status().permissions(); // get authorisations
cout <<"\t"<< (pe & perms::owner_read ? "r" : "-") // <== error should be allowed
<< (pe & perms::owner_write ? "w" : "-");
cout <<"\t" << p << endl;
}
问题与疑问:
perms
object: The compiler complains with a C2440 error 上的按位 &
关于缺少从 perms 到 bool 的转换。但根据规范,这应该是允许的。这是一个错误还是我错过了什么?
我通过将 pe
转换为无符号来绕过这个问题。在那里我注意到每个文件的值总是 0xffff
,包括我故意撤回写作授权的文件。系统会为 windows 上的权限返回一个恒定的虚拟值,还是我忘记了一些东西来获得有效权限?
更新:我在下面所说的关于 Windows' 权限的内容是正确的,但由于某些原因甚至 FILE_ATTRIBUTE_READONLY
位似乎也不是在职的。我会提交错误 :)
作为目前的解决方法,您可以对生成的路径记录执行 status()
,例如
#include <filesystem>
#include <iostream>
using namespace std;
using namespace std::tr2::sys;
int main() {
path dir = canonical(".");
for (auto& p : recursive_directory_iterator(dir)) {
if (is_regular_file(p))
cout << file_size(p);
file_status stat = status(p); // Workaround bug in MSVC++2015
perms pe = stat.permissions(); // get authorizations
cout <<"\t"<< ((pe & perms::owner_read) != perms::none ? "r" : "-")
<< ((pe & perms::owner_write) != perms::none ? "w" : "-");
cout <<"\t" << p << endl;
}
}
在我的系统上产生:
PS C:\Users\bion\Desktop\test> ..\fs.exe
68494859 r- C:\Users\bion\Desktop\test\read-only.mp3
93805063 rw C:\Users\bion\Desktop\test\read-write.mp3
PS C:\Users\bion\Desktop\test>
Bitwise & on the perms object: The compiler complains with a C2440 error about a missing conversion from perms to bool. But this should be allowed according to specs. Is this a bug or did I miss something ?
按位 &
通过重载 operator&
得到支持,应该可以正常工作。没有转换为 bool。如果你想转换为 bool,正确的方法是与 enum class
声明的常量进行比较,例如:
if ((permsVar & perms::owner_read) != perms::none)
或使用该枚举的 direct-initialized 实例 class:
if ((permsVar & perms::owner_read) != perms{})
[bitmask.types] 只会说:
The value Y is set in the object X if the expression X & Y is nonzero.
并不是说有一些文字 0
的转换可以用来与 enum class
进行比较。
I cirumvented the issue by converting pe an unsigned. There I noted that the value is always 0xffff, for every files, including a file where I have intentionally withdrawn writing authorisations. Will a constant dummy value be returned for permissions on windows systematically or did I forget something to get the valid permissions ?
Windows' 权限模型确实与 Unix 权限模型没有类似之处——安全描述符确实具有所有者和组所有者值,但是没有普遍接受的约定来映射 Windows DACL(它可以表达比 Unix 权限更多的 finer-grained 权限结构)和 Unix 权限。
因此,目前我们只查找 readonly 属性,或者一组特定的属性,如果不是,我们 "punt" 并说权限未知。如果你想便携,你需要用未知常量做一些事情。
// FILE STATUS FUNCTIONS
_FS_DLL _File_type __CLRCALL_PURE_OR_CDECL _Stat(const TCHAR *_Fname, _Perms *_Pmode)
{ // get file status
WIN32_FILE_ATTRIBUTE_DATA _Data;
if (TFUN(GetFileAttributesEx)(_Fname, GetFileExInfoStandard, &_Data))
{ // get file type and return permissions
// !!! Here's where we check
if (_Pmode != 0)
*_Pmode = _Data.dwFileAttributes & FILE_ATTRIBUTE_READONLY
? READONLY_PERMS : perms::all;
return (_Map_mode(_Data.dwFileAttributes));
}
else
{ // invalid, get error code
// error mapping code omitted
}
}
您希望我们使用以下安全描述符做什么:
O:BAG:SYD:PAI(A;;WD;;;WD)(A;;FA;;;S-1-5-21-2127521184-1604012920-1887927527-9342113)(A;;0x4;;;BA)
上面写着:
O:BA: 拥有者是BUILTIN\ADMINISTRATORS
.
G:SY: 群主是NT AUTHORITY\LOCAL SYSTEM
。请注意,在 Windows 权限中通常根本不使用该组,它的存在只是为了与 Interix 兼容,在这种情况下,Interix 是唯一一个读取或写入安全描述符的组,因此可以为所欲为。 :)
D:PAI:DACL为DACL_PROTECTED
(不继承parents的权限)和DACL_AUTO_INHERIT
(参与正常的权限继承系统;例如,此文件系统 object 的 children 将从中继承权限)
- (A;;WD;;;WD):授予
WRITE_DAC
(更改安全描述符的DACL部分的权限)访问WORLD\EVERYONE
.嗯,WRITE_DAC
不是读取、写入或执行,那么我们在那里做什么?
- (A;;FA;;;S-1-5-21-2127521184-1604012920-1887927527-9342113): 将
FILE_ALL_ACCESS
授予 REDMOND\bion
.请注意,我不是所有者、组所有者或 "others" 那么您将如何映射它?
- (A;;0x4;;;BA) 将
FILE_APPEND_DATA
授予 BUILTIN\ADMINISTRATORS
。这有点像写入,但不允许您更改文件中已有的内容...
(我遗漏了一堆东西,比如强制访问控制....)
我并不是说我们不能尝试在这个映射上做得更好,但是如果你需要做重要的权限工作,<filesystem>
TS 不能在支持访问的系统上真正帮助你控制列表。
我正在尝试使用实验性 <filesystem>
library that should become part of C++17 (See draft technical spec N4100) on MSVC2015(更新 1)。
我可以设法递归显示目录的全部内容:
using namespace std::tr2::sys;
...
path dir = canonical(".");
for (auto& p : recursive_directory_iterator(dir)) {
if (is_regular_file(p))
cout << file_size(p);
perms pe = p.status().permissions(); // get authorisations
cout <<"\t"<< (pe & perms::owner_read ? "r" : "-") // <== error should be allowed
<< (pe & perms::owner_write ? "w" : "-");
cout <<"\t" << p << endl;
}
问题与疑问:
perms
object: The compiler complains with a C2440 error 上的按位&
关于缺少从 perms 到 bool 的转换。但根据规范,这应该是允许的。这是一个错误还是我错过了什么?我通过将
pe
转换为无符号来绕过这个问题。在那里我注意到每个文件的值总是0xffff
,包括我故意撤回写作授权的文件。系统会为 windows 上的权限返回一个恒定的虚拟值,还是我忘记了一些东西来获得有效权限?
更新:我在下面所说的关于 Windows' 权限的内容是正确的,但由于某些原因甚至 FILE_ATTRIBUTE_READONLY
位似乎也不是在职的。我会提交错误 :)
作为目前的解决方法,您可以对生成的路径记录执行 status()
,例如
#include <filesystem>
#include <iostream>
using namespace std;
using namespace std::tr2::sys;
int main() {
path dir = canonical(".");
for (auto& p : recursive_directory_iterator(dir)) {
if (is_regular_file(p))
cout << file_size(p);
file_status stat = status(p); // Workaround bug in MSVC++2015
perms pe = stat.permissions(); // get authorizations
cout <<"\t"<< ((pe & perms::owner_read) != perms::none ? "r" : "-")
<< ((pe & perms::owner_write) != perms::none ? "w" : "-");
cout <<"\t" << p << endl;
}
}
在我的系统上产生:
PS C:\Users\bion\Desktop\test> ..\fs.exe
68494859 r- C:\Users\bion\Desktop\test\read-only.mp3
93805063 rw C:\Users\bion\Desktop\test\read-write.mp3
PS C:\Users\bion\Desktop\test>
Bitwise & on the perms object: The compiler complains with a C2440 error about a missing conversion from perms to bool. But this should be allowed according to specs. Is this a bug or did I miss something ?
按位 &
通过重载 operator&
得到支持,应该可以正常工作。没有转换为 bool。如果你想转换为 bool,正确的方法是与 enum class
声明的常量进行比较,例如:
if ((permsVar & perms::owner_read) != perms::none)
或使用该枚举的 direct-initialized 实例 class:
if ((permsVar & perms::owner_read) != perms{})
[bitmask.types] 只会说:
The value Y is set in the object X if the expression X & Y is nonzero.
并不是说有一些文字 0
的转换可以用来与 enum class
进行比较。
I cirumvented the issue by converting pe an unsigned. There I noted that the value is always 0xffff, for every files, including a file where I have intentionally withdrawn writing authorisations. Will a constant dummy value be returned for permissions on windows systematically or did I forget something to get the valid permissions ?
Windows' 权限模型确实与 Unix 权限模型没有类似之处——安全描述符确实具有所有者和组所有者值,但是没有普遍接受的约定来映射 Windows DACL(它可以表达比 Unix 权限更多的 finer-grained 权限结构)和 Unix 权限。
因此,目前我们只查找 readonly 属性,或者一组特定的属性,如果不是,我们 "punt" 并说权限未知。如果你想便携,你需要用未知常量做一些事情。
// FILE STATUS FUNCTIONS
_FS_DLL _File_type __CLRCALL_PURE_OR_CDECL _Stat(const TCHAR *_Fname, _Perms *_Pmode)
{ // get file status
WIN32_FILE_ATTRIBUTE_DATA _Data;
if (TFUN(GetFileAttributesEx)(_Fname, GetFileExInfoStandard, &_Data))
{ // get file type and return permissions
// !!! Here's where we check
if (_Pmode != 0)
*_Pmode = _Data.dwFileAttributes & FILE_ATTRIBUTE_READONLY
? READONLY_PERMS : perms::all;
return (_Map_mode(_Data.dwFileAttributes));
}
else
{ // invalid, get error code
// error mapping code omitted
}
}
您希望我们使用以下安全描述符做什么:
O:BAG:SYD:PAI(A;;WD;;;WD)(A;;FA;;;S-1-5-21-2127521184-1604012920-1887927527-9342113)(A;;0x4;;;BA)
上面写着:
O:BA: 拥有者是BUILTIN\ADMINISTRATORS
.
G:SY: 群主是NT AUTHORITY\LOCAL SYSTEM
。请注意,在 Windows 权限中通常根本不使用该组,它的存在只是为了与 Interix 兼容,在这种情况下,Interix 是唯一一个读取或写入安全描述符的组,因此可以为所欲为。 :)
D:PAI:DACL为DACL_PROTECTED
(不继承parents的权限)和DACL_AUTO_INHERIT
(参与正常的权限继承系统;例如,此文件系统 object 的 children 将从中继承权限)
- (A;;WD;;;WD):授予
WRITE_DAC
(更改安全描述符的DACL部分的权限)访问WORLD\EVERYONE
.嗯,WRITE_DAC
不是读取、写入或执行,那么我们在那里做什么? - (A;;FA;;;S-1-5-21-2127521184-1604012920-1887927527-9342113): 将
FILE_ALL_ACCESS
授予REDMOND\bion
.请注意,我不是所有者、组所有者或 "others" 那么您将如何映射它? - (A;;0x4;;;BA) 将
FILE_APPEND_DATA
授予BUILTIN\ADMINISTRATORS
。这有点像写入,但不允许您更改文件中已有的内容...
(我遗漏了一堆东西,比如强制访问控制....)
我并不是说我们不能尝试在这个映射上做得更好,但是如果你需要做重要的权限工作,<filesystem>
TS 不能在支持访问的系统上真正帮助你控制列表。