]> git.tdb.fi Git - libs/core.git/blobdiff - source/fs/stat.cpp
Add move semantics to Variant
[libs/core.git] / source / fs / stat.cpp
index d11867d99b6af41a427dba423673acc622390a65..e296ead3816b9317ecd44f0bc82bf6fbd12cbbed 100644 (file)
-#ifdef WIN32
-#include <windows.h>
-#include <aclapi.h>
-#else
-#define _FILE_OFFSET_BITS 64
-#include <sys/stat.h>
-#include <grp.h>
-#include <pwd.h>
-#endif
-#include <msp/core/systemerror.h>
-#include <msp/strings/format.h>
-#include <msp/time/rawtime_private.h>
 #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, FILE_FLAG_BACKUP_SEMANTICS, 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 = 0;
-       PSID group = 0;
-       if(!GetSecurityInfo(handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION, &owner, &group, 0, 0, &sec_desc))
-       {
-               CloseHandle(handle);
-               throw system_error("GetSecurityInfo");
-       }
-
-       if(owner)
-               result.owner = get_account_name(owner);
-       if(group)
-               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