X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Ffs%2Fstat.cpp;h=e296ead3816b9317ecd44f0bc82bf6fbd12cbbed;hp=245dd4ea9e05e4510768343ad8a5ff62a066313f;hb=HEAD;hpb=e240e074ce15c17d644e378067c2941aefcd5611 diff --git a/source/fs/stat.cpp b/source/fs/stat.cpp index 245dd4e..e296ead 100644 --- a/source/fs/stat.cpp +++ b/source/fs/stat.cpp @@ -1,161 +1,56 @@ -#ifdef WIN32 -#include -#include -#else -#include -#include -#include -#endif -#include -#include -#include #include "path.h" #include "stat.h" +#include "stat_private.h" using namespace std; -namespace { - -#ifdef WIN32 -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 { -#ifndef WIN32 -struct Stat::Private -{ - static Stat from_struct_stat(const struct stat &); -}; +Stat::Stat(const Stat &other): + exists(other.exists), + type(other.type), + size(other.type), + alloc_size(other.alloc_size), + mtime(other.mtime), + owner_info(other.owner_info), + priv(other.priv ? new Private(*other.priv) : nullptr) +{ } -Stat Stat::Private::from_struct_stat(const struct stat &st) +Stat &Stat::operator=(const Stat &other) { - Stat result; - 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); - - char buf[1024]; - - struct passwd pw; - struct passwd *owner; - if(!getpwuid_r(st.st_uid, &pw, buf, sizeof(buf), &owner) && owner) - result.owner = owner->pw_name; - else - result.owner = format("%d", st.st_uid); - - struct group gr; - struct group *group; - if(!getgrgid_r(st.st_gid, &gr, buf, sizeof(buf), &group) && group) - result.group = group->gr_name; - else - result.group = format("%d", st.st_gid); - - return result; + if(&other==this) + return *this; + + exists = other.exists; + type = other.type; + size = other.size; + alloc_size = other.alloc_size; + mtime = other.mtime; + owner_info = other.owner_info; + delete priv; + priv = (other.priv ? new Private(*other.priv) : nullptr); + + return *this; } -#endif -Stat::Stat(): - type(UNKNOWN), - size(0), - alloc_size(0) -{ } - -Stat Stat::stat(const Path &path) +Stat::~Stat() { -#ifdef WIN32 - HANDLE handle; - handle = CreateFile(path.str().c_str(), 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); - if(handle==INVALID_HANDLE_VALUE) - throw system_error("CreateFile"); - - 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; - PSID group; - if(!GetSecurityInfo(handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION, &owner, &group, 0, 0, &sec_desc)) - { - CloseHandle(handle); - throw system_error("GetSecurityInfo"); - } - - result.owner = get_account_name(owner); - result.group = get_account_name(group); - - LocalFree(sec_desc); - - CloseHandle(handle); - - return result; -#else - struct stat st; - int ret = ::stat(path.str().c_str(), &st); - if(ret==-1) - throw system_error("stat"); - - return Private::from_struct_stat(st); -#endif + delete priv; } -Stat Stat::lstat(const Path &path) +const string &Stat::get_owner() const { -#ifdef WIN32 - return stat(path); -#else - struct stat st; - int ret = ::lstat(path.str().c_str(), &st); - if(ret==-1) - throw system_error("lstat"); - - return Private::from_struct_stat(st); -#endif + if(priv && owner_info.owner.empty()) + priv->fill_owner_info(owner_info); + return owner_info.owner; } -bool exists(const Path &path) +const string &Stat::get_group() const { -#ifdef WIN32 - return GetFileAttributes(path.str().c_str())!=INVALID_FILE_ATTRIBUTES; -#else - return access(path.str().c_str(), F_OK)==0; -#endif + if(priv && owner_info.group.empty()) + priv->fill_owner_info(owner_info); + return owner_info.group; } } // namespace FS