5 #define _FILE_OFFSET_BITS 64
12 #include <msp/core/systemerror.h>
13 #include <msp/strings/format.h>
14 #include <msp/time/rawtime_private.h>
23 string get_account_name(PSID sid)
26 DWORD nlen = sizeof(name);
28 DWORD dlen = sizeof(domain);
30 if(!LookupAccountSid(0, sid, name, &nlen, domain, &dlen, &use))
31 throw Msp::system_error("LookupAccountSid");
32 return Msp::format("%s/%s", name, domain);
45 static Stat from_struct_stat(const struct stat &);
48 Stat Stat::Private::from_struct_stat(const struct stat &st)
52 if(S_ISREG(st.st_mode))
53 result.type = REGULAR;
54 else if(S_ISDIR(st.st_mode))
55 result.type = DIRECTORY;
56 else if(S_ISLNK(st.st_mode))
57 result.type = SYMLINK;
59 result.type = UNKNOWN;
60 result.size = st.st_size;
61 result.alloc_size = st.st_blocks*512;
62 result.mtime = Time::TimeStamp::from_unixtime(st.st_mtime);
68 if(!getpwuid_r(st.st_uid, &pw, buf, sizeof(buf), &owner) && owner)
69 result.owner = owner->pw_name;
71 result.owner = format("%d", st.st_uid);
75 if(!getgrgid_r(st.st_gid, &gr, buf, sizeof(buf), &group) && group)
76 result.group = group->gr_name;
78 result.group = format("%d", st.st_gid);
91 Stat Stat::stat(const Path &path)
95 handle = CreateFile(path.str().c_str(), 0, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
96 if(handle==INVALID_HANDLE_VALUE)
97 throw system_error("CreateFile");
99 BY_HANDLE_FILE_INFORMATION info;
100 if(!GetFileInformationByHandle(handle, &info))
103 throw system_error("GetFileInformationByHandle");
107 if(info.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
108 result.type = DIRECTORY;
110 result.type = REGULAR;
112 result.size = FileSize(info.nFileSizeHigh)<<32 | info.nFileSizeLow;
113 result.alloc_size = (result.size+511)&~511;
114 result.mtime = Time::TimeStamp(Time::filetime_to_rawtime(info.ftLastWriteTime));
116 PSECURITY_DESCRIPTOR sec_desc;
119 if(!GetSecurityInfo(handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION, &owner, &group, 0, 0, &sec_desc))
122 throw system_error("GetSecurityInfo");
126 result.owner = get_account_name(owner);
128 result.group = get_account_name(group);
137 int ret = ::stat(path.str().c_str(), &st);
143 throw system_error("stat");
146 return Private::from_struct_stat(st);
150 Stat Stat::lstat(const Path &path)
156 int ret = ::lstat(path.str().c_str(), &st);
162 throw system_error("lstat");
165 return Private::from_struct_stat(st);
169 bool exists(const Path &path)
172 return GetFileAttributes(path.str().c_str())!=INVALID_FILE_ATTRIBUTES;
174 return access(path.str().c_str(), F_OK)==0;