5 #define _FILE_OFFSET_BITS 64
10 #include <msp/core/systemerror.h>
11 #include <msp/strings/format.h>
12 #include <msp/time/rawtime_private.h>
21 string get_account_name(PSID sid)
24 DWORD nlen = sizeof(name);
26 DWORD dlen = sizeof(domain);
28 if(!LookupAccountSid(0, sid, name, &nlen, domain, &dlen, &use))
29 throw Msp::system_error("LookupAccountSid");
30 return Msp::format("%s/%s", name, domain);
43 static Stat from_struct_stat(const struct stat &);
46 Stat Stat::Private::from_struct_stat(const struct stat &st)
49 if(S_ISREG(st.st_mode))
50 result.type = REGULAR;
51 else if(S_ISDIR(st.st_mode))
52 result.type = DIRECTORY;
53 else if(S_ISLNK(st.st_mode))
54 result.type = SYMLINK;
56 result.type = UNKNOWN;
57 result.size = st.st_size;
58 result.alloc_size = st.st_blocks*512;
59 result.mtime = Time::TimeStamp::from_unixtime(st.st_mtime);
65 if(!getpwuid_r(st.st_uid, &pw, buf, sizeof(buf), &owner) && owner)
66 result.owner = owner->pw_name;
68 result.owner = format("%d", st.st_uid);
72 if(!getgrgid_r(st.st_gid, &gr, buf, sizeof(buf), &group) && group)
73 result.group = group->gr_name;
75 result.group = format("%d", st.st_gid);
87 Stat Stat::stat(const Path &path)
91 handle = CreateFile(path.str().c_str(), 0, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
92 if(handle==INVALID_HANDLE_VALUE)
93 throw system_error("CreateFile");
95 BY_HANDLE_FILE_INFORMATION info;
96 if(!GetFileInformationByHandle(handle, &info))
99 throw system_error("GetFileInformationByHandle");
103 if(info.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
104 result.type = DIRECTORY;
106 result.type = REGULAR;
108 result.size = FileSize(info.nFileSizeHigh)<<32 | info.nFileSizeLow;
109 result.alloc_size = (result.size+511)&~511;
110 result.mtime = Time::TimeStamp(Time::filetime_to_rawtime(info.ftLastWriteTime));
112 PSECURITY_DESCRIPTOR sec_desc;
115 if(!GetSecurityInfo(handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION, &owner, &group, 0, 0, &sec_desc))
118 throw system_error("GetSecurityInfo");
122 result.owner = get_account_name(owner);
124 result.group = get_account_name(group);
133 int ret = ::stat(path.str().c_str(), &st);
135 throw system_error("stat");
137 return Private::from_struct_stat(st);
141 Stat Stat::lstat(const Path &path)
147 int ret = ::lstat(path.str().c_str(), &st);
149 throw system_error("lstat");
151 return Private::from_struct_stat(st);
155 bool exists(const Path &path)
158 return GetFileAttributes(path.str().c_str())!=INVALID_FILE_ATTRIBUTES;
160 return access(path.str().c_str(), F_OK)==0;