in utils/include/utils/file/FileUtils.h [437:547]
inline std::optional<std::string> get_file_owner(const std::filesystem::path& file_path) {
#ifndef WIN32
struct stat info = {};
if (stat(file_path.c_str(), &info) != 0) {
return std::nullopt;
}
struct passwd pw = {};
pw.pw_name = nullptr;
struct passwd *result = nullptr;
char localbuf[1024] = {};
if (getpwuid_r(info.st_uid, &pw, localbuf, sizeof(localbuf), &result) != 0 || pw.pw_name == nullptr) {
return std::nullopt;
}
return std::string(pw.pw_name);
#else
DWORD return_code = 0;
PSID sid_owner = NULL;
BOOL bool_return = TRUE;
LPTSTR account_name = NULL;
LPTSTR domain_name = NULL;
DWORD account_name_dword = 1;
DWORD domain_name_dword = 1;
SID_NAME_USE sid_type = SidTypeUnknown;
HANDLE file_handle;
PSECURITY_DESCRIPTOR sec_descriptor = NULL;
// Get the handle of the file object.
file_handle = CreateFile(
TEXT(file_path.string().c_str()),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// Check GetLastError for CreateFile error code.
if (file_handle == INVALID_HANDLE_VALUE) {
return std::nullopt;
}
auto close_file_handle = gsl::finally([&file_handle] { CloseHandle(file_handle); });
// Get the owner SID of the file.
return_code = GetSecurityInfo(
file_handle,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
&sid_owner,
NULL,
NULL,
NULL,
&sec_descriptor);
// Check GetLastError for GetSecurityInfo error condition.
if (return_code != ERROR_SUCCESS) {
return std::nullopt;
}
// First call to LookupAccountSid to get the buffer sizes.
bool_return = LookupAccountSid(
NULL,
sid_owner,
account_name,
(LPDWORD)&account_name_dword,
domain_name,
(LPDWORD)&domain_name_dword,
&sid_type);
// Reallocate memory for the buffers.
account_name = (LPTSTR)GlobalAlloc(
GMEM_FIXED,
account_name_dword);
// Check GetLastError for GlobalAlloc error condition.
if (account_name == NULL) {
return std::nullopt;
}
auto cleanup_account_name = gsl::finally([&account_name] { GlobalFree(account_name); });
domain_name = (LPTSTR)GlobalAlloc(
GMEM_FIXED,
domain_name_dword);
// Check GetLastError for GlobalAlloc error condition.
if (domain_name == NULL) {
return std::nullopt;
}
auto cleanup_domain_name = gsl::finally([&domain_name] { GlobalFree(domain_name); });
// Second call to LookupAccountSid to get the account name.
bool_return = LookupAccountSid(
NULL, // name of local or remote computer
sid_owner, // security identifier
account_name, // account name buffer
(LPDWORD)&account_name_dword, // size of account name buffer
domain_name, // domain name
(LPDWORD)&domain_name_dword, // size of domain name buffer
&sid_type); // SID type
// Check GetLastError for LookupAccountSid error condition.
if (bool_return == FALSE) {
return std::nullopt;
}
auto result = std::string(account_name);
return result;
#endif
}