C++ 实验C++;17 MSVC2015上的文件系统:权限不一致

C++ 实验C++;17 MSVC2015上的文件系统:权限不一致,c++,visual-c++,visual-studio-2015,c++17,C++,Visual C++,Visual Studio 2015,C++17,我正在尝试使用实验库,它应该成为(更新1)上C++17的一部分(参见技术规范草案) 我可以设法递归显示目录的完整内容: using namespace std::tr2::sys; ... path dir = canonical("."); for (auto& p : recursive_directory_iterator(dir)) { if (is_regular_file(p))

我正在尝试使用实验库,它应该成为(更新1)上C++17的一部分(参见技术规范草案)

我可以设法递归显示目录的完整内容:

    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;     
    }
使用名称空间std::tr2::sys;
...
路径dir=规范(“.”);
for(自动&p:递归目录迭代器(dir)){
如果(是常规文件(p))

cout更新:我下面所说的关于Windows权限的内容是正确的,但由于某些原因,甚至
文件属性\u 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;
    }
}

perms对象上的按位(&on):编译器抱怨C2440错误导致从perms到bool的转换丢失。但根据规范,这应该是允许的。这是一个错误还是我遗漏了什么

通过重载的
运算符&
支持按位
&
,应该可以正常工作。没有到bool的转换。如果要转换到bool,正确的方法是与该
枚举类
声明的常量进行比较,例如:

if ((permsVar & perms::owner_read) != perms::none)
或使用该枚举类的直接初始化实例:

if ((permsVar & perms::owner_read) != perms{})
[bitmask.types]仅表示:

如果表达式X&Y非零,则在对象X中设置值Y

并不是说可以使用文本
0
进行一些转换,以与
枚举类进行比较

我通过将pe转换为未签名文件来解决此问题。我注意到,对于每个文件,包括我有意撤销写入授权的文件,该值始终为0xffff。windows上的权限是否会系统地返回一个常量伪值,或者我是否忘记了获取有效权限的某些内容

Windows的权限模型实际上与Unix权限模型没有相似之处——安全描述符确实具有所有者和组所有者值,但在Windows DACL(它可以表示比Unix权限更细粒度的权限结构)和Unix权限之间没有普遍接受的映射约定

因此,目前我们只寻找只读属性,或者一组特定的属性,如果不是,我们“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\u保护
(不从父级继承权限)和
DACL\u自动继承
(参与正常权限继承系统;例如,此文件系统对象的子级将从该文件系统继承权限)

  • (A;;WD;;;WD):授予
    写入DAC
    (更改安全描述符的DACL部分的权限)访问
    世界\EVERYONE
    。嗯,
    写入DAC
    不是读取、写入或执行的,那么我们在那里该怎么办
  • (A;;FA;;S-1-5-21-2127521184-1604012920-1887927527-9342113):授予
    文件所有访问权限
    REDMOND\bion
    。请注意,我不是所有者、组所有者或“其他人”,那么您如何映射这一点
  • (A;;0x4;;BA)授予
    文件\u附加数据到
    内置\ADMINISTRATORS
    。这有点像写入,但不允许更改文件中已有的内容
(我省略了一些东西,比如强制访问控制……)


我并不是说我们无法在这个映射方面做得更好,但是如果您需要执行非平凡的权限工作,
TS在支持访问控制列表的系统上并不能真正帮助您。

我不确定权限,但我也注意到文件系统功能无法区分符号链接和常规文件和目录。&运算符仅在
enum
上有效,而在
enum class
上无效。0xffff表示perms::unknown。这只是还没有实现,请在头文件中搜索
\u Todo
变量。文件系统受Unix敏感性的严重影响,使用八进制常量,将Windows访问权限连接到这不容易。@HansPassant说得通,谢谢。但perms是一个枚举类,必须遵守:因此它必须实现
&
。同时,由于删除了@Galik的答案,我发现我可以将&-子表达式转换为bool,所以问题缩小到转换问题。但是,BitmaskType定义声明结果应与0(=0或!=0)相比较。不幸的是,这也不可能。我对BitmaskType要求太高,还是MS实现目前还太不完整?引用:“或枚举(作用域和未作用域)和其他运算符重载”。没有过载。嗨,比利,如果你通过Connect提交了错误,你能在这里发布链接吗?不,我直接提交了。我现在要修复我们所有的
错误:)@ildjarn:我只是试图修复它;不要认为我们可以在更新中修复它,因为修复它会破坏我们的DLL的ABI。(错误是,
\u Read\u dir
不返回从
msvcp140.dll
导出的权限位,因此它们得到了默认值)可能是我首先要做的事情之一
O:BAG:SYD:PAI(A;;WD;;;WD)(A;;FA;;;S-1-5-21-2127521184-1604012920-1887927527-9342113)(A;;0x4;;;BA)