我正在尝试使用实验性<filesystem>
库,该库应该成为MSVC2015(更新 1)上的 C++17(请参阅技术规范 N4100 草案)的一部分。
我可以设法递归显示目录的完整内容:
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
对象上的按位&
:编译器抱怨 C2440 错误,指出缺少从 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:UsersbionDesktoptest> ..fs.exe
68494859 r- C:UsersbionDesktoptestread-only.mp3
93805063 rw C:UsersbionDesktoptestread-write.mp3
PS C:UsersbionDesktoptest>
按位和在perms对象上:编译器抱怨C2440错误,关于缺少从perms到bool的转换。但根据规格,这应该是允许的。这是一个错误还是我错过了什么?
按位&
通过重载operator&
受支持,应该可以正常工作。没有转换为布尔值。如果你想转换为布尔值,正确的方法是与该enum class
声明的常量进行比较,例如:
if ((permsVar & perms::owner_read) != perms::none)
或者使用该枚举类的直接初始化实例:
if ((permsVar & perms::owner_read) != perms{})
[bitmask.types] 只说:
如果表达式 X 和 Y 不为零,则在对象 X 中设置值 Y。
并不是说您可以使用文字0
进行一些转换 与enum class
进行比较.
我通过将 pe 转换为未签名来解决这个问题。在那里,我注意到对于每个文件,该值始终是0xffff的,包括我故意撤回写作授权的文件。是否会系统地为Windows上的权限返回常量虚拟值,还是我忘记了获取有效权限的内容?
Windows的权限模型实际上与Unix权限模型没有类似之处 - 安全描述符确实具有所有者和组所有者值,但是在Windows DACL(可以表达比Unix权限更细粒度的权限构造)和Unix权限之间没有普遍接受的约定。
因此,目前我们只查找只读属性或一组特定的属性,如果不是,我们会"平底"并说权限未知。如果你想便携,你需要对未知常量做一些事情。
// 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:主人BUILTINADMINISTRATORS
。
G:SY:组所有者是NT AUTHORITYLOCAL SYSTEM
。请注意,该组通常根本不在Windows权限中使用,并且仅用于与Interix兼容,在这种情况下,Interix是唯一读取或写入安全描述符的人,因此可以执行任何它想要的操作。
:)D:PAI:DACL 是DACL_PROTECTED
的(不从父级继承权限)和DACL_AUTO_INHERIT
(参与正常的权限继承系统;例如,此文件系统对象的子对象将从中继承权限)
- (一;;白矮星;;;WD):授予
WRITE_DAC
(更改安全描述符的 DACL 部分的权限)对WORLDEVERYONE
的访问权限。嗯,WRITE_DAC
不是读、写或执行,那么我们会在那里做什么? - (一;;发;;;S-1-5-21-2127521184-1604012920-1887927527-9342113):授予
FILE_ALL_ACCESS
REDMONDbion
。请注意,我不是所有者、组所有者或"其他人",那么您将如何映射它? - (A;;0x4;;;BA) 授予
FILE_APPEND_DATA
BUILTINADMINISTRATORS
。这有点像写入,但不允许您更改文件中已有的内容......
(而且我省略了一堆东西,比如强制访问控制......
我并不是说我们不能尝试在这个映射上做得更好,但是如果您需要执行重要的权限工作,<filesystem>
TS 无法真正帮助您支持访问控制列表的系统。