mirror of
https://github.com/NixOS/nix
synced 2025-07-05 20:41:47 +02:00
Use std::filesystem
functions in more places
This makes for shorter and more portable code. The only tricky part is catching exceptions: I just searched for near by `catch (Error &)` or `catch (SysError &)` and adjusted them to `catch (std::filesystem::filesystem_error &)` according to my human judgement. Good for windows portability; will help @siddhantk232 with his GSOC project.
This commit is contained in:
parent
b4950404ba
commit
c371070580
14 changed files with 61 additions and 99 deletions
|
@ -120,10 +120,10 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
|||
|
||||
Path dirOf(const PathView path)
|
||||
{
|
||||
Path::size_type pos = path.rfind('/');
|
||||
Path::size_type pos = NativePathTrait::rfindPathSep(path);
|
||||
if (pos == path.npos)
|
||||
return ".";
|
||||
return pos == 0 ? "/" : Path(path, 0, pos);
|
||||
return fs::path{path}.parent_path().string();
|
||||
}
|
||||
|
||||
|
||||
|
@ -217,72 +217,36 @@ bool pathAccessible(const Path & path)
|
|||
|
||||
Path readLink(const Path & path)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
checkInterrupt();
|
||||
std::vector<char> buf;
|
||||
for (ssize_t bufSize = PATH_MAX/4; true; bufSize += bufSize/2) {
|
||||
buf.resize(bufSize);
|
||||
ssize_t rlSize = readlink(path.c_str(), buf.data(), bufSize);
|
||||
if (rlSize == -1)
|
||||
if (errno == EINVAL)
|
||||
throw Error("'%1%' is not a symlink", path);
|
||||
else
|
||||
throw SysError("reading symbolic link '%1%'", path);
|
||||
else if (rlSize < bufSize)
|
||||
return std::string(buf.data(), rlSize);
|
||||
}
|
||||
#else
|
||||
// TODO modern Windows does in fact support symlinks
|
||||
throw UnimplementedError("reading symbolic link '%1%'", path);
|
||||
#endif
|
||||
return fs::read_symlink(path).string();
|
||||
}
|
||||
|
||||
|
||||
bool isLink(const Path & path)
|
||||
{
|
||||
return getFileType(path) == DT_LNK;
|
||||
return getFileType(path) == fs::file_type::symlink;
|
||||
}
|
||||
|
||||
|
||||
DirEntries readDirectory(DIR *dir, const Path & path)
|
||||
DirEntries readDirectory(const Path & path)
|
||||
{
|
||||
DirEntries entries;
|
||||
entries.reserve(64);
|
||||
|
||||
struct dirent * dirent;
|
||||
while (errno = 0, dirent = readdir(dir)) { /* sic */
|
||||
for (auto & entry : fs::directory_iterator{path}) {
|
||||
checkInterrupt();
|
||||
std::string name = dirent->d_name;
|
||||
if (name == "." || name == "..") continue;
|
||||
entries.emplace_back(name, dirent->d_ino,
|
||||
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
||||
dirent->d_type
|
||||
#else
|
||||
DT_UNKNOWN
|
||||
#endif
|
||||
);
|
||||
entries.emplace_back(
|
||||
entry.path().filename().string(),
|
||||
entry.symlink_status().type());
|
||||
}
|
||||
if (errno) throw SysError("reading directory '%1%'", path);
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
DirEntries readDirectory(const Path & path)
|
||||
|
||||
fs::file_type getFileType(const Path & path)
|
||||
{
|
||||
AutoCloseDir dir(opendir(path.c_str()));
|
||||
if (!dir) throw SysError("opening directory '%1%'", path);
|
||||
|
||||
return readDirectory(dir.get(), path);
|
||||
}
|
||||
|
||||
|
||||
unsigned char getFileType(const Path & path)
|
||||
{
|
||||
struct stat st = lstat(path);
|
||||
if (S_ISDIR(st.st_mode)) return DT_DIR;
|
||||
if (S_ISLNK(st.st_mode)) return DT_LNK;
|
||||
if (S_ISREG(st.st_mode)) return DT_REG;
|
||||
return DT_UNKNOWN;
|
||||
return fs::symlink_status(path).type();
|
||||
}
|
||||
|
||||
|
||||
|
@ -432,8 +396,15 @@ static void _deletePath(Descriptor parentfd, const Path & path, uint64_t & bytes
|
|||
AutoCloseDir dir(fdopendir(fd));
|
||||
if (!dir)
|
||||
throw SysError("opening directory '%1%'", path);
|
||||
for (auto & i : readDirectory(dir.get(), path))
|
||||
_deletePath(dirfd(dir.get()), path + "/" + i.name, bytesFreed);
|
||||
|
||||
struct dirent * dirent;
|
||||
while (errno = 0, dirent = readdir(dir.get())) { /* sic */
|
||||
checkInterrupt();
|
||||
std::string childName = dirent->d_name;
|
||||
if (childName == "." || childName == "..") continue;
|
||||
_deletePath(dirfd(dir.get()), path + "/" + childName, bytesFreed);
|
||||
}
|
||||
if (errno) throw SysError("reading directory '%1%'", path);
|
||||
}
|
||||
|
||||
int flags = S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0;
|
||||
|
@ -611,13 +582,7 @@ std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
|
|||
|
||||
void createSymlink(const Path & target, const Path & link)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (symlink(target.c_str(), link.c_str()))
|
||||
throw SysError("creating symlink from '%1%' to '%2%'", link, target);
|
||||
#else
|
||||
// TODO modern Windows does in fact support symlinks
|
||||
throw UnimplementedError("createSymlink");
|
||||
#endif
|
||||
fs::create_symlink(target, link);
|
||||
}
|
||||
|
||||
void replaceSymlink(const Path & target, const Path & link)
|
||||
|
@ -627,8 +592,8 @@ void replaceSymlink(const Path & target, const Path & link)
|
|||
|
||||
try {
|
||||
createSymlink(target, tmp);
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo == EEXIST) continue;
|
||||
} catch (fs::filesystem_error & e) {
|
||||
if (e.code() == std::errc::file_exists) continue;
|
||||
throw;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,13 +27,6 @@
|
|||
#include <sstream>
|
||||
#include <optional>
|
||||
|
||||
#ifndef HAVE_STRUCT_DIRENT_D_TYPE
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_REG 1
|
||||
#define DT_LNK 2
|
||||
#define DT_DIR 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Polyfill for MinGW
|
||||
*
|
||||
|
@ -132,20 +125,16 @@ bool isLink(const Path & path);
|
|||
struct DirEntry
|
||||
{
|
||||
std::string name;
|
||||
ino_t ino;
|
||||
/**
|
||||
* one of DT_*
|
||||
*/
|
||||
unsigned char type;
|
||||
DirEntry(std::string name, ino_t ino, unsigned char type)
|
||||
: name(std::move(name)), ino(ino), type(type) { }
|
||||
std::filesystem::file_type type;
|
||||
DirEntry(std::string name, std::filesystem::file_type type)
|
||||
: name(std::move(name)), type(type) { }
|
||||
};
|
||||
|
||||
typedef std::vector<DirEntry> DirEntries;
|
||||
|
||||
DirEntries readDirectory(const Path & path);
|
||||
|
||||
unsigned char getFileType(const Path & path);
|
||||
std::filesystem::file_type getFileType(const Path & path);
|
||||
|
||||
/**
|
||||
* Read the contents of a file into a string.
|
||||
|
|
|
@ -65,7 +65,7 @@ static CgroupStats destroyCgroup(const Path & cgroup, bool returnStats)
|
|||
/* Otherwise, manually kill every process in the subcgroups and
|
||||
this cgroup. */
|
||||
for (auto & entry : readDirectory(cgroup)) {
|
||||
if (entry.type != DT_DIR) continue;
|
||||
if (entry.type != std::filesystem::file_type::directory) continue;
|
||||
destroyCgroup(cgroup + "/" + entry.name, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -134,13 +134,17 @@ SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath &
|
|||
DirEntries res;
|
||||
for (auto & entry : nix::readDirectory(makeAbsPath(path).string())) {
|
||||
std::optional<Type> type;
|
||||
// cannot exhaustively enumerate because implementation-specific
|
||||
// additional file types are allowed.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
||||
switch (entry.type) {
|
||||
case DT_REG: type = Type::tRegular; break;
|
||||
#ifndef _WIN32
|
||||
case DT_LNK: type = Type::tSymlink; break;
|
||||
#endif
|
||||
case DT_DIR: type = Type::tDirectory; break;
|
||||
case std::filesystem::file_type::regular: type = Type::tRegular; break;
|
||||
case std::filesystem::file_type::symlink: type = Type::tSymlink; break;
|
||||
case std::filesystem::file_type::directory: type = Type::tDirectory; break;
|
||||
default: type = tMisc;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
res.emplace(entry.name, type);
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -133,6 +133,7 @@ void closeMostFDs(const std::set<int> & exceptions)
|
|||
}
|
||||
return;
|
||||
} catch (SysError &) {
|
||||
} catch (std::filesystem::filesystem_error &) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue