diff --git a/configure.ac b/configure.ac index ef3a060c4..54b8dff08 100644 --- a/configure.ac +++ b/configure.ac @@ -106,6 +106,7 @@ AC_LANG_POP(C++) # Check for chroot support (requires chroot() and bind mounts). AC_CHECK_FUNCS([chroot]) AC_CHECK_FUNCS([unshare]) +AC_CHECK_FUNCS([statvfs]) AC_CHECK_HEADERS([sched.h]) AC_CHECK_HEADERS([sys/param.h]) AC_CHECK_HEADERS([sys/mount.h], [], [], diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 4b8203efe..4086e553c 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -19,8 +19,9 @@ #include #include -#if HAVE_UNSHARE +#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H #include +#include #include #endif @@ -434,30 +435,20 @@ void LocalStore::openDB(bool create) bind mount. So make the Nix store writable for this process. */ void LocalStore::makeStoreWritable() { -#if HAVE_UNSHARE +#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_REMOUNT) if (getuid() != 0) return; - - if (!pathExists("/proc/self/mountinfo")) return; - /* Check if /nix/store is a read-only bind mount. */ - bool found = false; - Strings mounts = tokenizeString(readFile("/proc/self/mountinfo", true), "\n"); - foreach (Strings::iterator, i, mounts) { - vector fields = tokenizeString >(*i, " "); - if (fields.at(3) == "/" || fields.at(4) != settings.nixStore) continue; - Strings options = tokenizeString(fields.at(5), ","); - if (std::find(options.begin(), options.end(), "ro") == options.end()) continue; - found = true; - break; + struct statvfs stat; + if (statvfs(settings.nixStore.c_str(), &stat) !=0) + throw SysError("Getting info of nix store mountpoint"); + + if (stat.f_flag & (ST_RDONLY | MS_BIND)) { + if (unshare(CLONE_NEWNS) == -1) + throw SysError("setting up a private mount namespace"); + + if (mount(0, settings.nixStore.c_str(), 0, MS_REMOUNT | MS_BIND, 0) == -1) + throw SysError(format("remounting %1% writable") % settings.nixStore); } - - if (!found) return; - - if (unshare(CLONE_NEWNS) == -1) - throw SysError("setting up a private mount namespace"); - - if (mount(0, settings.nixStore.c_str(), 0, MS_REMOUNT | MS_BIND, 0) == -1) - throw SysError(format("remounting %1% writable") % settings.nixStore); #endif }