10 #include <sys/types.h> 21 #include <string_view> 22 #include <system_error> 36 int makeDir(
const std::filesystem::path &name) {
38 return ::_wmkdir(name.c_str());
40 return ::mkdir(name.c_str(), 0777);
44 bool makePathHelper(
const std::filesystem::path &name) {
45 if (makeDir(name) == 0) {
48 if (errno == EEXIST) {
50 return std::filesystem::is_directory(name, ec);
54 if (errno != ENOENT) {
58 if (!name.has_parent_path()) {
62 const auto parent = name.parent_path();
63 if (!makePathHelper(parent)) {
68 if (makeDir(name) == 0) {
71 return errno == EEXIST && std::filesystem::is_directory(name);
76 bool isdir(
const std::string &path) {
78 return (stat(path.c_str(), &stats) == 0 && S_ISDIR(stats.st_mode) &&
79 access(path.c_str(), R_OK | X_OK) == 0);
82 bool isreg(
const std::string &path) {
84 return (stat(path.c_str(), &stats) == 0 && S_ISREG(stats.st_mode) &&
85 access(path.c_str(), R_OK) == 0);
88 bool isexe(
const std::string &path) {
90 return (stat(path.c_str(), &stats) == 0 && S_ISREG(stats.st_mode) &&
91 access(path.c_str(), R_OK | X_OK) == 0);
94 bool islnk(
const std::string &path) {
100 return lstat(path.c_str(), &stats) == 0 && S_ISLNK(stats.st_mode);
112 while (path[i] ==
'/') {
113 buf.push_back(path[i]);
116 const size_t leading = i;
121 const size_t last = buf.size();
122 const size_t lasti = i;
124 if (last > leading) {
128 while (i < path.size() && path[i] !=
'/') {
129 if (path[i] ==
'.') {
133 buf.push_back(path[i]);
139 if (dotcount == i - lasti) {
142 }
else if (dotcount == 2) {
144 if (levels > 0 && last != leading) {
146 for (k = last; k > leading; k--) {
147 if (buf[k - 1] ==
'/') {
153 }
else if (buf[k - 1] ==
'/') {
165 while (i < path.size() && path[i] ==
'/') {
169 if (i >= path.size()) {
174 return buf.substr(2);
181 if (std::filesystem::is_directory(path, ec)) {
184 auto opath = path.lexically_normal();
189 return makePathHelper(opath);
192 std::string
dirName(
const std::string &path) {
195 while (result.size() > 1 && result.back() ==
'/') {
198 if (result.size() <= 1) {
202 auto iter = std::find(result.rbegin(), result.rend(),
'/');
203 if (iter != result.rend()) {
204 result.erase(iter.base(), result.end());
206 while (result.size() > 1 && result.back() ==
'/') {
217 while (path.size() > 1 && path.back() ==
'/') {
218 path.remove_suffix(1);
220 if (path.size() <= 1) {
221 return std::string{path};
224 auto iter = std::find(path.rbegin(), path.rend(),
'/');
225 if (iter != path.rend()) {
226 path.remove_prefix(std::distance(path.begin(), iter.base()));
228 return std::string{path};
231 ssize_t
safeRead(
int fd,
void *data,
size_t maxlen) {
234 ret = read(fd, data, maxlen);
235 }
while (ret == -1 && errno == EINTR);
238 ssize_t
safeWrite(
int fd,
const void *data,
size_t maxlen) {
241 ret = write(fd, data, maxlen);
242 }
while (ret == -1 && errno == EINTR);
246 std::optional<std::string>
readlink(
const std::string &path) {
255 readSize =
::readlink(path.data(), buffer.data(), buffer.size());
260 if (static_cast<size_t>(readSize) < buffer.size()) {
261 buffer.resize(readSize);
265 buffer.resize(buffer.size() * 2);
273 auto time = std::filesystem::last_write_time(path, ec);
275 !ec ? std::filesystem::file_time_type::clock::to_sys(time)
276 : std::chrono::time_point<std::chrono::system_clock>::min();
278 std::chrono::time_point_cast<std::chrono::seconds>(systime);
279 return timeInSeconds.time_since_epoch().count();
286 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 decriptor.
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.
bool startsWith(std::string_view str, std::string_view prefix)
Check if a string starts with a prefix.
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.