3 #include <msp/core/systemerror.h>
4 #include <msp/strings/format.h>
5 #include <msp/time/rawtime_private.h>
7 #include "stat_private.h"
13 PSID copy_sid(PSID sid)
15 if(!sid || !IsValidSid(sid))
17 DWORD len = GetLengthSid(sid);
18 PSID copy = reinterpret_cast<PSID>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len));
19 if(!CopySid(len, copy, sid))
21 DWORD err = GetLastError();
22 HeapFree(GetProcessHeap(), 0, copy);
23 throw Msp::system_error("CopySid", err);
28 string get_account_name(PSID sid)
31 DWORD nlen = sizeof(name);
33 DWORD dlen = sizeof(domain);
35 if(!LookupAccountSid(nullptr, sid, name, &nlen, domain, &dlen, &use))
36 throw Msp::system_error("LookupAccountSid");
37 return Msp::format("%s/%s", name, domain);
46 Stat::Private::Private(const Private &other):
47 owner_id(copy_sid(other.owner_id)),
48 group_id(copy_sid(other.group_id))
51 Stat::Private::~Private()
53 if(owner_id!=INVALID_UID)
54 HeapFree(GetProcessHeap(), 0, owner_id);
55 if(group_id!=INVALID_GID)
56 HeapFree(GetProcessHeap(), 0, group_id);
59 void Stat::Private::fill_owner_info(Stat::OwnerInfo &result)
61 if(owner_id!=INVALID_UID)
62 result.owner = get_account_name(owner_id);
64 result.owner = "None";
66 if(group_id!=INVALID_GID)
67 result.group = get_account_name(group_id);
69 result.group = "None";
73 Stat Stat::stat(const Path &path)
76 handle = CreateFile(path.str().c_str(), READ_CONTROL, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, nullptr);
77 if(handle==INVALID_HANDLE_VALUE)
79 DWORD err = GetLastError();
80 if(err==ERROR_FILE_NOT_FOUND || err==ERROR_PATH_NOT_FOUND)
83 throw system_error(format("CreateFile(%s)", path), err);
86 BY_HANDLE_FILE_INFORMATION info;
87 if(!GetFileInformationByHandle(handle, &info))
90 throw system_error("GetFileInformationByHandle");
95 if(info.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
96 result.type = DIRECTORY;
98 result.type = REGULAR;
100 result.size = FileSize(info.nFileSizeHigh)<<32 | info.nFileSizeLow;
101 result.alloc_size = (result.size+511)&~511;
102 result.mtime = Time::TimeStamp(Time::filetime_to_rawtime(info.ftLastWriteTime));
104 PSECURITY_DESCRIPTOR sec_desc;
105 PSID owner = nullptr;
106 PSID group = nullptr;
107 const SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION;
108 DWORD err = GetSecurityInfo(handle, SE_FILE_OBJECT, sec_info, &owner, &group, nullptr, nullptr, &sec_desc);
112 throw system_error("GetSecurityInfo", err);
115 result.priv = new Private;
116 result.priv->owner_id = copy_sid(owner);
117 result.priv->group_id = copy_sid(group);
126 Stat Stat::lstat(const Path &path)
131 bool exists(const Path &path)
133 return GetFileAttributes(path.str().c_str())!=INVALID_FILE_ATTRIBUTES;