10 #include <sys/types.h> 21 #include <string_view> 22 #include <system_error> 35 int makeDir(
const std::filesystem::path &name) {
37 return ::_wmkdir(name.c_str());
39 return ::mkdir(name.c_str(), 0777);
43 bool makePathHelper(
const std::filesystem::path &name) {
44 if (makeDir(name) == 0) {
47 if (errno == EEXIST) {
49 return std::filesystem::is_directory(name, ec);
53 if (errno != ENOENT) {
57 if (!name.has_parent_path()) {
61 const auto parent = name.parent_path();
62 if (!makePathHelper(parent)) {
67 if (makeDir(name) == 0) {
70 return errno == EEXIST && std::filesystem::is_directory(name);
75 bool isdir(
const std::string &path) {
77 return (stat(path.c_str(), &stats) == 0 && S_ISDIR(stats.st_mode) &&
78 access(path.c_str(), R_OK | X_OK) == 0);
81 bool isreg(
const std::string &path) {
83 return (stat(path.c_str(), &stats) == 0 && S_ISREG(stats.st_mode) &&
84 access(path.c_str(), R_OK) == 0);
87 bool isexe(
const std::string &path) {
89 return (stat(path.c_str(), &stats) == 0 && S_ISREG(stats.st_mode) &&
90 access(path.c_str(), R_OK | X_OK) == 0);
93 bool islnk(
const std::string &path) {
99 return lstat(path.c_str(), &stats) == 0 && S_ISLNK(stats.st_mode);
111 while (path[i] ==
'/') {
112 buf.push_back(path[i]);
115 const size_t leading = i;
120 const size_t last = buf.size();
121 const size_t lasti = i;
123 if (last > leading) {
127 while (i < path.size() && path[i] !=
'/') {
128 if (path[i] ==
'.') {
132 buf.push_back(path[i]);
138 if (dotcount == i - lasti) {
141 }
else if (dotcount == 2) {
143 if (levels > 0 && last != leading) {
145 for (k = last; k > leading; k--) {
146 if (buf[k - 1] ==
'/') {
152 }
else if (buf[k - 1] ==
'/') {
164 while (i < path.size() && path[i] ==
'/') {
168 if (i >= path.size()) {
172 if (buf.starts_with(
"./")) {
173 return buf.substr(2);
180 if (std::filesystem::is_directory(path, ec)) {
183 auto opath = path.lexically_normal();
188 return makePathHelper(opath);
191 std::string
dirName(
const std::string &path) {
194 while (result.size() > 1 && result.back() ==
'/') {
197 if (result.size() <= 1) {
201 auto iter = std::find(result.rbegin(), result.rend(),
'/');
202 if (iter != result.rend()) {
203 result.erase(iter.base(), result.end());
205 while (result.size() > 1 && result.back() ==
'/') {
216 while (path.size() > 1 && path.back() ==
'/') {
217 path.remove_suffix(1);
219 if (path.size() <= 1) {
220 return std::string{path};
223 auto iter = std::find(path.rbegin(), path.rend(),
'/');
224 if (iter != path.rend()) {
225 path.remove_prefix(std::distance(path.begin(), iter.base()));
227 return std::string{path};
230 ssize_t
safeRead(
int fd,
void *data,
size_t maxlen) {
233 ret = read(fd, data, maxlen);
234 }
while (ret == -1 && errno == EINTR);
237 ssize_t
safeWrite(
int fd,
const void *data,
size_t maxlen) {
240 ret = write(fd, data, maxlen);
241 }
while (ret == -1 && errno == EINTR);
245 std::optional<std::string>
readlink(
const std::string &path) {
254 readSize =
::readlink(path.data(), buffer.data(), buffer.size());
259 if (static_cast<size_t>(readSize) < buffer.size()) {
260 buffer.resize(readSize);
264 buffer.resize(buffer.size() * 2);
272 auto time = std::filesystem::last_write_time(path, ec);
274 !ec ? std::filesystem::file_time_type::clock::to_sys(time)
275 : std::chrono::time_point<std::chrono::system_clock>::min();
277 std::chrono::time_point_cast<std::chrono::seconds>(systime);
278 return timeInSeconds.time_since_epoch().count();
285 UniqueFilePtr file(fdopen(fd.
fd(), modes));
Class wrap around the unix fd.
std::string baseName(std::string_view path)
Get base file name of path.
bool isValid() const noexcept
Check if fd is not empty.
bool islnk(const std::string &path)
check whether path is a link.
Simple file system related API for checking file status.
bool isexe(const std::string &path)
check whether path is an executable regular file.
bool isreg(const std::string &path)
check whether path is a regular file.
bool isdir(const std::string &path)
check whether path is a directory.
C++ Utility functions for handling utf8 strings.
Utility class to handle unix file descriptor.
int fd() const noexcept
Get the internal fd.
ssize_t safeWrite(int fd, const void *data, size_t maxlen)
a simple wrapper around write(), ignore EINTR.
std::string dirName(const std::string &path)
Get directory name of path.
std::optional< std::string > readlink(const std::string &path)
read symlink.
bool makePath(const std::filesystem::path &path)
Create directory recursively.
UniqueFilePtr openFD(UnixFD &fd, const char *modes)
open the unix fd with fdopen.
int64_t modifiedTime(const std::filesystem::path &path)
Return modified time in seconds of given path.
ssize_t safeRead(int fd, void *data, size_t maxlen)
a simple wrapper around read(), ignore EINTR.
std::string cleanPath(const std::string &path)
Get the clean path by removing . , .. , and duplicate / in the path.
int release() noexcept
Get the internal fd and release the ownership.