~ruther/guix-local

05a669efa51df40078df3d1f98f098464dd8e739 — Reepca Russelstein 1 year, 1 month ago 6b42df3
daemon: Gracefully handle target mount point already existing.

Fixes guix/guix#903.

* nix/libutil/spawn.cc (bindMount): in the "regular file" case, only create a
  placeholder file if one doesn't already exist.

Change-Id: Ie46b2fef2cea5b2a052c4ec48d00e97bfc1ee506
Reported-by: Hilton Chain <hako@ultrarare.space>
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
1 files changed, 24 insertions(+), 1 deletions(-)

M nix/libutil/spawn.cc
M nix/libutil/spawn.cc => nix/libutil/spawn.cc +24 -1
@@ 538,8 538,31 @@ void bindMount(Path source, Path target, bool readOnly)
        return;
    }
    else {
        struct stat st2;
        createDirs(dirOf(target));
        writeFile(target, "");
        /* Alternate between trying to create placeholder file at target and
         * checking for its existence and type */
        while(true){
            if(lstat(target.c_str(), &st2) != -1) {
                if(!S_ISREG(st2.st_mode))
                    throw Error(format("mount target `%1%' exists but is not a regular file") % target);
                break;
            }
            if(errno != ENOENT) {
                throw SysError(format("stat'ing path `%1%'") % target);
            }
            AutoCloseFD fd = open(target.c_str(),
                                  O_WRONLY | O_NOFOLLOW | O_CREAT | O_EXCL,
                                  0600);
            if(fd != -1) {
                fd.close(); /* Now exists and is a fresh regular file */
                break;
            }
            /* Note: because of O_CREAT | O_EXCL, EACCES can only mean a
             * permission issue with the parent directory */
            if(errno != EEXIST)
                throw SysError(format("Creating placeholder regular file target mount `%1%'") % target);
        }
    }

    /* This may fail with EINVAL unless we specify MS_REC, specifically if we