X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Ffs%2Fstat.cpp;fp=source%2Ffs%2Fstat.cpp;h=f4566ae8b6ef8363cd68f709f2d66924137a58a2;hp=85fead5e7de1327eac1ade4c2e511d199badd8c8;hb=609c9a508cfdc7b42c46c4f21d17639204165a00;hpb=b4806214e905752617691f851717033fd3f266c2 diff --git a/source/fs/stat.cpp b/source/fs/stat.cpp index 85fead5..f4566ae 100644 --- a/source/fs/stat.cpp +++ b/source/fs/stat.cpp @@ -1,163 +1,17 @@ -#ifdef WIN32 -#include -#include -#else -#define _FILE_OFFSET_BITS 64 -#include -#include -#include -#include -#include -#endif -#include -#include -#include #include "path.h" #include "stat.h" +#include "stat_private.h" using namespace std; -namespace { - -#ifdef WIN32 -PSID copy_sid(PSID sid) -{ - if(!sid || !IsValidSid(sid)) - return 0; - DWORD len = GetLengthSid(sid); - PSID copy = reinterpret_cast(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len)); - if(!CopySid(len, copy, sid)) - { - DWORD err = GetLastError(); - HeapFree(GetProcessHeap(), 0, copy); - throw Msp::system_error("CopySid", err); - } - return copy; -} - -string get_account_name(PSID sid) -{ - char name[1024]; - DWORD nlen = sizeof(name); - char domain[1024]; - DWORD dlen = sizeof(domain); - SID_NAME_USE use; - if(!LookupAccountSid(0, sid, name, &nlen, domain, &dlen, &use)) - throw Msp::system_error("LookupAccountSid"); - return Msp::format("%s/%s", name, domain); -} -#endif - -} - - namespace Msp { namespace FS { -struct Stat::Private -{ -#ifdef WIN32 - PSID owner_id; - PSID group_id; -#else - uid_t owner_id; - gid_t group_id; -#endif - - Private(); - Private(const Private &); - ~Private(); - -#ifndef WIN32 - /* This is here because it needs access to private members of Stat, but we - can't expose the system stat struct in the public header */ - static Stat from_struct_stat(const struct stat &); -#endif - - void fill_owner_info(Stat::OwnerInfo &); -}; - Stat::Private::Private(): owner_id(0), group_id(0) { } -Stat::Private::Private(const Private &other): -#ifdef WIN32 - owner_id(copy_sid(other.owner_id)), - group_id(copy_sid(other.group_id)) -#else - owner_id(other.owner_id), - group_id(other.group_id) -#endif -{ } - -Stat::Private::~Private() -{ -#ifdef WIN32 - if(owner_id) - HeapFree(GetProcessHeap(), 0, owner_id); - if(group_id) - HeapFree(GetProcessHeap(), 0, group_id); -#endif -} - -#ifndef WIN32 -Stat Stat::Private::from_struct_stat(const struct stat &st) -{ - Stat result; - result.exists = true; - if(S_ISREG(st.st_mode)) - result.type = REGULAR; - else if(S_ISDIR(st.st_mode)) - result.type = DIRECTORY; - else if(S_ISLNK(st.st_mode)) - result.type = SYMLINK; - else - result.type = UNKNOWN; - result.size = st.st_size; - result.alloc_size = st.st_blocks*512; - result.mtime = Time::TimeStamp::from_unixtime(st.st_mtime); - - result.priv = new Private; - result.priv->owner_id = st.st_uid; - result.priv->group_id = st.st_gid; - - return result; -} -#endif - -void Stat::Private::fill_owner_info(Stat::OwnerInfo &result) -{ -#ifdef WIN32 - if(owner_id) - result.owner = get_account_name(owner_id); - else - result.owner = "None"; - - if(group_id) - result.group = get_account_name(group_id); - else - result.group = "None"; -#else - char buf[1024]; - - struct passwd pw; - struct passwd *owner; - if(!getpwuid_r(owner_id, &pw, buf, sizeof(buf), &owner) && owner) - result.owner = owner->pw_name; - else - result.owner = format("%d", owner_id); - - struct group gr; - struct group *group; - if(!getgrgid_r(group_id, &gr, buf, sizeof(buf), &group) && group) - result.group = group->gr_name; - else - result.group = format("%d", group_id); -#endif -} - Stat::Stat(): exists(false), @@ -196,72 +50,6 @@ Stat::~Stat() delete priv; } -Stat Stat::stat(const Path &path) -{ -#ifdef WIN32 - HANDLE handle; - handle = CreateFile(path.str().c_str(), READ_CONTROL, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 0); - if(handle==INVALID_HANDLE_VALUE) - { - DWORD err = GetLastError(); - if(err==ERROR_FILE_NOT_FOUND) - return Stat(); - else - throw system_error("CreateFile", err); - } - - BY_HANDLE_FILE_INFORMATION info; - if(!GetFileInformationByHandle(handle, &info)) - { - CloseHandle(handle); - throw system_error("GetFileInformationByHandle"); - } - - Stat result; - if(info.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - result.type = DIRECTORY; - else - result.type = REGULAR; - - result.size = FileSize(info.nFileSizeHigh)<<32 | info.nFileSizeLow; - result.alloc_size = (result.size+511)&~511; - result.mtime = Time::TimeStamp(Time::filetime_to_rawtime(info.ftLastWriteTime)); - - PSECURITY_DESCRIPTOR sec_desc; - PSID owner = 0; - PSID group = 0; - const SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION; - DWORD err = GetSecurityInfo(handle, SE_FILE_OBJECT, sec_info, &owner, &group, 0, 0, &sec_desc); - if(err) - { - CloseHandle(handle); - throw system_error("GetSecurityInfo", err); - } - - result.priv = new Private; - result.priv->owner_id = copy_sid(owner); - result.priv->group_id = copy_sid(group); - - LocalFree(sec_desc); - - CloseHandle(handle); - - return result; -#else - struct stat st; - int ret = ::stat(path.str().c_str(), &st); - if(ret==-1) - { - if(errno==ENOENT) - return Stat(); - else - throw system_error("stat"); - } - - return Private::from_struct_stat(st); -#endif -} - const std::string &Stat::get_owner() const { if(priv && owner_info.owner.empty()) @@ -276,33 +64,5 @@ const std::string &Stat::get_group() const return owner_info.group; } -Stat Stat::lstat(const Path &path) -{ -#ifdef WIN32 - return stat(path); -#else - struct stat st; - int ret = ::lstat(path.str().c_str(), &st); - if(ret==-1) - { - if(errno==ENOENT) - return Stat(); - else - throw system_error("lstat"); - } - - return Private::from_struct_stat(st); -#endif -} - -bool exists(const Path &path) -{ -#ifdef WIN32 - return GetFileAttributes(path.str().c_str())!=INVALID_FILE_ATTRIBUTES; -#else - return access(path.str().c_str(), F_OK)==0; -#endif -} - } // namespace FS } // namespace Msp