Skip to content

Commit 40b2515

Browse files
committed
libutil: Implement second overload of createDirectory for RestoreSink
Now the intermediate symlink following issue should be completely plugged.
1 parent 09755e6 commit 40b2515

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

src/libutil/fs-sink.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,29 @@ static std::filesystem::path append(const std::filesystem::path & src, const Can
7171
return dst;
7272
}
7373

74+
#ifndef _WIN32
75+
void RestoreSink::createDirectory(const CanonPath & path, DirectoryCreatedCallback callback)
76+
{
77+
if (path.isRoot()) {
78+
createDirectory(path);
79+
callback(*this, path);
80+
return;
81+
}
82+
83+
createDirectory(path);
84+
assert(dirFd); // If that's not true the above call must have thrown an exception.
85+
86+
RestoreSink dirSink{startFsync};
87+
dirSink.dstPath = append(dstPath, path);
88+
dirSink.dirFd = ::openat(dirFd.get(), path.rel_c_str(), O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
89+
90+
if (!dirSink.dirFd)
91+
throw SysError("opening directory '%s'", dirSink.dstPath.string());
92+
93+
callback(dirSink, CanonPath::root);
94+
}
95+
#endif
96+
7497
void RestoreSink::createDirectory(const CanonPath & path)
7598
{
7699
auto p = append(dstPath, path);

src/libutil/include/nix/util/fs-sink.hh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ struct RestoreSink : FileSystemObjectSink
120120

121121
void createDirectory(const CanonPath & path) override;
122122

123+
#ifndef _WIN32
124+
void createDirectory(const CanonPath & path, DirectoryCreatedCallback callback) override;
125+
#endif
126+
123127
void createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)>) override;
124128

125129
void createSymlink(const CanonPath & path, const std::string & target) override;

tests/functional/nars.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ if (( unicodeTestCode == 1 )); then
114114
# If the command failed (MacOS or ZFS + normalization), checks that it failed
115115
# with the expected "already exists" error, and that this is the same
116116
# behavior as `touch`
117-
echo "$unicodeTestOut" | grepQuiet "path '.*/out/â' already exists"
117+
echo "$unicodeTestOut" | grepQuiet "creating directory '.*/out/â': File exists"
118118

119119
(( touchFilesCount == 1 ))
120120
elif (( unicodeTestCode == 0 )); then

0 commit comments

Comments
 (0)