diff --git a/nix-change-permissions b/nix-change-permissions new file mode 100755 index 000000000000..9caaf2fac30a --- /dev/null +++ b/nix-change-permissions @@ -0,0 +1,36 @@ +#!/bin/bash + +set -e + +usage() { + >&2 echo "Usage: [gid]" +} + +mode="$1" +path="$2" +perm_uid="$3" +gid="$4" + +if [ "$mode" == "chown" ] && [ "$#" -ne 4 ]; then + usage + exit -1 +elif [ "$mode" == "chmod" ] && [ "$#" -ne 3 ]; then + usage + exit -1 +fi + +if [[ "$(readlink -e $path)" != /nix* ]]; then + usage + exit -1 +fi + +if [ "$mode" == "chmod" ]; then + chmod "$perm_uid" "$path" +elif [ "$mode" == "chown" ]; then + chown -R "$perm_uid":"$gid" "$path" +else + usage + exit -1 +fi + +## diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 84ddd964b469..e834448cc1aa 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -36,6 +36,33 @@ #include +int chownx(const char *__file, __uid_t __owner, __gid_t __group) { + char *envVar = std::getenv("NIX_CHANGE_PERM_BIN"); + std::string changePermissionsScript = + envVar == nullptr ? "nix-change-permissions" : std::string{envVar}; + std::ostringstream stringStream; + stringStream << "/bin/bash -c 'sudo " << changePermissionsScript + << " chown " << __file << " " << __owner << " " << __group + << "'"; + return system(stringStream.str().c_str()); +} + +int chmodx(const char *__file, __mode_t __mode) { + if (chmod(__file, __mode) == 0) { + return 0; + } + char *envVar = std::getenv("NIX_CHANGE_PERM_BIN"); + std::string changePermissionsScript = + envVar == nullptr ? "nix-change-permissions" : std::string{envVar}; + std::ostringstream stringStream; + stringStream << "/bin/bash -c 'sudo " << changePermissionsScript + << " chmod " << __file << " " << std::oct << (__mode & 0xfff) + << "'"; + return system(stringStream.str().c_str()); +} + +#define chmod(file, mode) chmodx(file, mode) +#define chown(file, owner, group) chownx(file, owner, group) namespace nix {