summaryrefslogtreecommitdiff
path: root/nix
diff options
context:
space:
mode:
Diffstat (limited to 'nix')
-rw-r--r--nix/libutil/spawn.cc25
1 files changed, 24 insertions, 1 deletions
diff --git a/nix/libutil/spawn.cc b/nix/libutil/spawn.cc
index 2e3e1ac1a79..d3f4e5bf19a 100644
--- a/nix/libutil/spawn.cc
+++ b/nix/libutil/spawn.cc
@@ -538,8 +538,31 @@ void bindMount(Path source, Path target, bool readOnly)
538 return; 538 return;
539 } 539 }
540 else { 540 else {
541 struct stat st2;
541 createDirs(dirOf(target)); 542 createDirs(dirOf(target));
542 writeFile(target, ""); 543 /* Alternate between trying to create placeholder file at target and
544 * checking for its existence and type */
545 while(true){
546 if(lstat(target.c_str(), &st2) != -1) {
547 if(!S_ISREG(st2.st_mode))
548 throw Error(format("mount target `%1%' exists but is not a regular file") % target);
549 break;
550 }
551 if(errno != ENOENT) {
552 throw SysError(format("stat'ing path `%1%'") % target);
553 }
554 AutoCloseFD fd = open(target.c_str(),
555 O_WRONLY | O_NOFOLLOW | O_CREAT | O_EXCL,
556 0600);
557 if(fd != -1) {
558 fd.close(); /* Now exists and is a fresh regular file */
559 break;
560 }
561 /* Note: because of O_CREAT | O_EXCL, EACCES can only mean a
562 * permission issue with the parent directory */
563 if(errno != EEXIST)
564 throw SysError(format("Creating placeholder regular file target mount `%1%'") % target);
565 }
543 } 566 }
544 567
545 /* This may fail with EINVAL unless we specify MS_REC, specifically if we 568 /* This may fail with EINVAL unless we specify MS_REC, specifically if we