Hello everyone, I've made a PR on github to fix the user/group creation when using a ROOT different than /.
This is the link of the PR: https://github.com/gentoo/gentoo/pull/19204 Could you please take a moment to take a look at it ? To test it, you need to create a new minimalist ROOT with: $ export ROOT=/tmp/test-root $ export SYSROOT=/tmp/sysroot $ mkdir -p ${ROOT}/etc/portage $ cp {,${ROOT}}/etc/portage/make.conf $ ln -s /var/db/repos/gentoo/profiles/default/linux/<arch>/<profile> ${ROOT}/etc/portage/make.profile $ emerge baselayout coreutils Once it is done, you can emerge a new user for this ROOT, with this patch, the user will be created in ROOT, without the user will be installed on your system. Note, this PR work with other arch too. Thanks for your attention -- Jérémy
diff --git a/eclass/acct-user.eclass b/eclass/acct-user.eclass
index ee4358b5c75..efa637a7efa 100644
--- a/eclass/acct-user.eclass
+++ b/eclass/acct-user.eclass
@@ -194,8 +194,15 @@ eislocked() {
*)
# NB: 'no password' and 'locked' are indistinguishable
# but we also expire the account which is more clear
- [[ $(getent shadow "$1" | cut -d: -f2) == '!'* ]] &&
- [[ $(getent shadow "$1" | cut -d: -f8) == 1 ]]
+ local shadow
+ if [[ -n "${ROOT}" ]]; then
+ shadow=$(grep "^$1:" "${ROOT}/etc/shadow")
+ else
+ shadow=$(getent shadow "$1")
+ fi
+
+ [[ $( echo ${shadow} | cut -d: -f2) == '!'* ]] &&
+ [[ $(echo ${shadow} | cut -d: -f8) == 1 ]]
;;
esac
}
@@ -222,14 +229,22 @@ elockuser() {
eislocked "$1"
[[ $? -eq 0 ]] && return 0
+ local opts
+ [[ -n ${ROOT} ]] && opts=( --prefix "${ROOT}" )
+
case ${CHOST} in
*-freebsd*|*-dragonfly*)
- pw lock "$1" || die "Locking account $1 failed"
- pw user mod "$1" -e 1 || die "Expiring account $1 failed"
+ pw lock "${opts[@]}" "$1" || die "Locking account $1 failed"
+ pw user mod "${opts[@]}" "$1" -e 1 || die "Expiring account $1 failed"
;;
*-netbsd*)
- usermod -e 1 -C yes "$1" || die "Locking account $1 failed"
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix <dir> option."
+ ewarn "Please use: usermod ${opts[@]} -e 1 -C yes \"$1\" in a chroot"
+ else
+ usermod "${opts[@]}" -e 1 -C yes "$1" || die "Locking account $1 failed"
+ fi
;;
*-openbsd*)
@@ -237,7 +252,7 @@ elockuser() {
;;
*)
- usermod -e 1 -L "$1" || die "Locking account $1 failed"
+ usermod "${opts[@]}" -e 1 -L "$1" || die "Locking account $1 failed"
;;
esac
@@ -265,14 +280,22 @@ eunlockuser() {
eislocked "$1"
[[ $? -eq 1 ]] && return 0
+ local opts
+ [[ -n ${ROOT} ]] && opts=( --prefix "${ROOT}" )
+
case ${CHOST} in
*-freebsd*|*-dragonfly*)
- pw user mod "$1" -e 0 || die "Unexpiring account $1 failed"
- pw unlock "$1" || die "Unlocking account $1 failed"
+ pw user mod "${opts[@]}" "$1" -e 0 || die "Unexpiring account $1 failed"
+ pw unlock "${opts[@]}" "$1" || die "Unlocking account $1 failed"
;;
*-netbsd*)
- usermod -e 0 -C no "$1" || die "Unlocking account $1 failed"
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix <dir> option."
+ ewarn "Please use: \"usermod ${opts[@]} -e 0 -C no $1\" in a chroot"
+ else
+ usermod "${opts[@]}" -e 0 -C no "$1" || die "Unlocking account $1 failed"
+ fi
;;
*-openbsd*)
@@ -281,7 +304,7 @@ eunlockuser() {
*)
# silence warning if account does not have a password
- usermod -e "" -U "$1" 2>/dev/null || die "Unlocking account $1 failed"
+ usermod "${opts[@]}" -e "" -U "$1" 2>/dev/null || die "Unlocking account $1 failed"
;;
esac
@@ -417,7 +440,13 @@ acct-user_pkg_preinst() {
# default ownership to user:group
if [[ -z ${_ACCT_USER_HOME_OWNER} ]]; then
local group_array=( ${_ACCT_USER_GROUPS} )
- _ACCT_USER_HOME_OWNER=${ACCT_USER_NAME}:${group_array[0]}
+ if [[ -n "${ROOT}" ]]; then
+ local euid=$(egetent passwd ${ACCT_USER_NAME} | cut -d: -f3)
+ local egid=$(egetent passwd ${ACCT_USER_NAME} | cut -d: -f4)
+ _ACCT_USER_HOME_OWNER=${euid}:${egid}
+ else
+ _ACCT_USER_HOME_OWNER=${ACCT_USER_NAME}:${group_array[0]}
+ fi
fi
# Path might be missing due to INSTALL_MASK, etc.
# https://bugs.gentoo.org/691478
diff --git a/eclass/user-info.eclass b/eclass/user-info.eclass
index 15e9238ab44..5e2d3f70490 100644
--- a/eclass/user-info.eclass
+++ b/eclass/user-info.eclass
@@ -6,7 +6,6 @@
# [email protected] (Linux)
# MichaŠGórny <[email protected]> (NetBSD)
# @BLURB: Read-only access to user and group information
-
if [[ -z ${_USER_INFO_ECLASS} ]]; then
_USER_INFO_ECLASS=1
@@ -17,6 +16,7 @@ _USER_INFO_ECLASS=1
# dscl (Mac OS X 10.5), and pw (FreeBSD) used in enewuser()/enewgroup().
#
# Supported databases: group passwd
+# Warning: This function can be used only in pkg_* phases when ROOT is valid.
egetent() {
local db=$1 key=$2
@@ -37,18 +37,31 @@ egetent() {
# lookup by uid/gid
local opts
if [[ ${key} == [[:digit:]]* ]] ; then
- [[ ${db} == "user" ]] && opts="-u" || opts="-g"
+ [[ ${db} == "user" ]] && opts=( -u ) || opts=( -g )
fi
+ # Handle different ROOT
+ [[ -n ${ROOT} ]] && opts+=( -R "${ROOT}" )
+
pw show ${db} ${opts} "${key}" -q
;;
*-openbsd*)
- grep "${key}:\*:" /etc/${db}
+ grep "${key}:\*:" "${EROOT}/etc/${db}"
;;
*)
- # ignore nscd output if we're not running as root
- type -p nscd >/dev/null && nscd -i "${db}" 2>/dev/null
- getent "${db}" "${key}"
+ # getent does not support -R option, if we are working on a different
+ # ROOT than /, fallback to grep technique.
+ if [[ -z ${ROOT} ]]; then
+ # ignore nscd output if we're not running as root
+ type -p nscd >/dev/null && nscd -i "${db}" 2>/dev/null
+ getent "${db}" "${key}"
+ else
+ if [[ ${key} =~ ^[[:digit:]]+$ ]]; then
+ grep -E "^([^:]*:){2}${key}" "${ROOT}/etc/${db}"
+ else
+ grep "^${key}:" "${ROOT}/etc/${db}"
+ fi
+ fi
;;
esac
}
@@ -145,7 +158,16 @@ egetgroups() {
[[ $# -eq 1 ]] || die "usage: egetgroups <user>"
local egroups_arr
- read -r -a egroups_arr < <(id -G -n "$1")
+ if [[ -n "${ROOT}" ]]; then
+ local pgroup=$(egetent passwd "$1" | cut -d: -f1)
+ local sgroups=( $(grep -E ":([^:]*,)?$1(,[^:]*)?$" "${ROOT}/etc/group" | cut -d: -f1) )
+
+ # Remove primary group from list
+ sgroups=${sgroups#${pgroup}}
+ egroups_arr=( ${pgroup} ${sgroups[@]} )
+ else
+ read -r -a egroups_arr < <(id -G -n "$1")
+ fi
local g groups=${egroups_arr[0]}
# sort supplementary groups to make comparison possible
diff --git a/eclass/user.eclass b/eclass/user.eclass
index f8993b82774..a6bd3455a67 100644
--- a/eclass/user.eclass
+++ b/eclass/user.eclass
@@ -113,6 +113,9 @@ enewuser() {
# options to pass to useradd
local opts=()
+ # handle for ROOT != /
+ [[ -n ${ROOT} ]] && opts+=( --prefix "${ROOT}" )
+
# handle uid
local euid=$1; shift
if [[ -n ${euid} && ${euid} != -1 ]] ; then
@@ -203,13 +206,24 @@ enewuser() {
;;
*-netbsd*)
- useradd "${opts[@]}" "${euser}" || die
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix option."
+ ewarn "Please use: \"useradd ${opts[@]} ${euser}\" in a chroot"
+ else
+ useradd "${opts[@]}" "${euser}" || die
+ fi
;;
*-openbsd*)
- # all ops the same, except the -g vs -g/-G ...
- useradd -u ${euid} -s "${eshell}" \
- -d "${ehome}" -g "${egroups}" "${euser}" || die
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "OpenBSD's usermod does not support --prefix option."
+ ewarn "Please use: \"useradd ${opts[@]} ${euser}\" in a chroot"
+ else
+ # all ops the same, except the -g vs -g/-G ...
+ useradd -u ${euid} -s "${eshell}" \
+ -d "${ehome}" -g "${egroups}" "${euser}" || die
+ fi
+
;;
*)
@@ -220,6 +234,10 @@ enewuser() {
if [[ -n ${create_home} && ! -e ${ROOT}/${ehome} ]] ; then
elog " - Creating ${ehome} in ${ROOT}"
mkdir -p "${ROOT}/${ehome}"
+ # Use UID if we are in another ROOT than /
+ if [[ -n "${ROOT}" ]]; then
+ euser=$(egetent passwd ${euser} | cut -d: -f3)
+ fi
chown "${euser}" "${ROOT}/${ehome}"
chmod 755 "${ROOT}/${ehome}"
fi
@@ -282,6 +300,10 @@ enewgroup() {
fi
elog " - Groupid: ${egid}"
+ # handle different ROOT
+ local opts
+ [[ -n ${ROOT} ]] && opts=( --prefix "${ROOT}" )
+
# handle extra
if [[ $# -gt 0 ]] ; then
die "extra arguments no longer supported; please file a bug"
@@ -302,24 +324,29 @@ enewgroup() {
case ${CHOST} in
*-freebsd*|*-dragonfly*)
_enewgroup_next_gid
- pw groupadd "${egroup}" -g ${egid} || die
+ pw groupadd "${opts[@]}" "${egroup}" -g ${egid} || die
;;
*-netbsd*)
- _enewgroup_next_gid
- groupadd -g ${egid} "${egroup}" || die
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix <dir> option."
+ ewarn "Please use: \"groupadd -g ${egid} ${opts[@]} ${egroup}\" in a chroot"
+ else
+ _enewgroup_next_gid
+ groupadd -g ${egid} "${opts[@]}" "${egroup}" || die
+ fi
;;
*)
- local opts
if [[ ${egid} == *[!0-9]* ]] ; then
# Non numeric; let groupadd figure out a GID for us
- opts=""
+ #
+ true # Do nothing but keep the previous comment.
else
- opts="-g ${egid}"
+ opts+=( -g ${egid} )
fi
# We specify -r so that we get a GID in the system range from login.defs
- groupadd -r ${opts} "${egroup}" || die
+ groupadd -r "${opts[@]}" "${egroup}" || die
;;
esac
}
@@ -349,6 +376,10 @@ esethome() {
return 1
fi
+ # Handle different ROOT
+ local opts
+ [[ -n ${ROOT} ]] && opts=( --prefix "${ROOT}" )
+
# handle homedir
local ehome=$1; shift
if [[ -z ${ehome} ]] ; then
@@ -379,15 +410,28 @@ esethome() {
# update the home directory
case ${CHOST} in
*-freebsd*|*-dragonfly*)
- pw usermod "${euser}" -d "${ehome}" && return 0
+ pw usermod "${opts[@]}" "${euser}" -d "${ehome}" && return 0
[[ $? == 8 ]] && eerror "${euser} is in use, cannot update home"
eerror "There was an error when attempting to update the home directory for ${euser}"
eerror "Please update it manually on your system:"
eerror "\t pw usermod \"${euser}\" -d \"${ehome}\""
;;
+ *-netbsd*)
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix <dir> option."
+ ewarn "Please use: \"usermod ${opts[@]} -d ${ehome} ${euser}\" in a chroot"
+ else
+ usermod "${opts[@]}" -d "${ehome}" "${euser}" && return 0
+ [[ $? == 8 ]] && eerror "${euser} is in use, cannot update home"
+ eerror "There was an error when attempting to update the home directory for ${euser}"
+ eerror "Please update it manually on your system (as root):"
+ eerror "\t usermod -d \"${ehome}\" \"${euser}\""
+ fi
+ ;;
+
*)
- usermod -d "${ehome}" "${euser}" && return 0
+ usermod "${opts[@]}" -d "${ehome}" "${euser}" && return 0
[[ $? == 8 ]] && eerror "${euser} is in use, cannot update home"
eerror "There was an error when attempting to update the home directory for ${euser}"
eerror "Please update it manually on your system (as root):"
@@ -418,6 +462,10 @@ esetshell() {
return 1
fi
+ # Handle different ROOT
+ local opts
+ [[ -n ${ROOT} ]] && opts=( --prefix "${ROOT}" )
+
# handle shell
local eshell=$1; shift
if [[ -z ${eshell} ]] ; then
@@ -440,15 +488,28 @@ esetshell() {
# update the shell
case ${CHOST} in
*-freebsd*|*-dragonfly*)
- pw usermod "${euser}" -s "${eshell}" && return 0
+ pw usermod "${opts[@]}" "${euser}" -s "${eshell}" && return 0
[[ $? == 8 ]] && eerror "${euser} is in use, cannot update shell"
eerror "There was an error when attempting to update the shell for ${euser}"
eerror "Please update it manually on your system:"
eerror "\t pw usermod \"${euser}\" -s \"${eshell}\""
;;
+ *-netbsd*)
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix <dir> option."
+ ewarn "Please use: \"usermod ${opts[@]} -s ${eshell} ${euser}\" in a chroot"
+ else
+ usermod "${opts[@]}" -s "${eshell}" "${euser}" && return 0
+ [[ $? == 8 ]] && eerror "${euser} is in use, cannot update shell"
+ eerror "There was an error when attempting to update the shell for ${euser}"
+ eerror "Please update it manually on your system (as root):"
+ eerror "\t usermod -s \"${eshell}\" \"${euser}\""
+ fi
+ ;;
+
*)
- usermod -s "${eshell}" "${euser}" && return 0
+ usermod "${opts[@]}" -s "${eshell}" "${euser}" && return 0
[[ $? == 8 ]] && eerror "${euser} is in use, cannot update shell"
eerror "There was an error when attempting to update the shell for ${euser}"
eerror "Please update it manually on your system (as root):"
@@ -478,6 +539,10 @@ esetcomment() {
return 1
fi
+ # Handle different ROOT
+ local opts
+ [[ -n ${ROOT} ]] && opts=( --prefix "${ROOT}" )
+
# handle comment
local ecomment=$1; shift
if [[ -z ${ecomment} ]] ; then
@@ -496,15 +561,28 @@ esetcomment() {
# update the comment
case ${CHOST} in
*-freebsd*|*-dragonfly*)
- pw usermod "${euser}" -c "${ecomment}" && return 0
+ pw usermod "${opts[@]}" "${euser}" -c "${ecomment}" && return 0
[[ $? == 8 ]] && eerror "${euser} is in use, cannot update comment"
eerror "There was an error when attempting to update the comment for ${euser}"
eerror "Please update it manually on your system:"
eerror "\t pw usermod \"${euser}\" -c \"${ecomment}\""
;;
+ *-netbsd*)
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix <dir> option."
+ ewarn "Please use: \"usermod ${opts[@]} -c ${ecomment} ${euser}\" in a chroot"
+ else
+ usermod "${opts[@]}" -c "${ecomment}" "${euser}" && return 0
+ [[ $? == 8 ]] && eerror "${euser} is in use, cannot update shell"
+ eerror "There was an error when attempting to update the shell for ${euser}"
+ eerror "Please update it manually on your system (as root):"
+ eerror "\t usermod -s \"${eshell}\" \"${euser}\""
+ fi
+ ;;
+
*)
- usermod -c "${ecomment}" "${euser}" && return 0
+ usermod "${opts[@]}" -c "${ecomment}" "${euser}" && return 0
[[ $? == 8 ]] && eerror "${euser} is in use, cannot update comment"
eerror "There was an error when attempting to update the comment for ${euser}"
eerror "Please update it manually on your system (as root):"
@@ -563,6 +641,9 @@ esetgroups() {
elog "Updating groups for user '${euser}' ..."
elog " - Groups: ${egroups}"
+ # Handle different ROOT
+ [[ -n ${ROOT} ]] && opts+=( --prefix "${ROOT}" )
+
# update the group
case ${CHOST} in
*-freebsd*|*-dragonfly*)
@@ -573,6 +654,19 @@ esetgroups() {
eerror "\t pw usermod \"${euser}\" ${opts[*]}"
;;
+ *-netbsd*)
+ if [[ -n "${ROOT}" ]]; then
+ ewarn "NetBSD's usermod does not support --prefix <dir> option."
+ ewarn "Please use: \"usermod ${opts[@]} ${euser}\" in a chroot"
+ else
+ usermod "${opts[@]}" "${euser}" && return 0
+ [[ $? == 8 ]] && eerror "${euser} is in use, cannot update shell"
+ eerror "There was an error when attempting to update the shell for ${euser}"
+ eerror "Please update it manually on your system (as root):"
+ eerror "\t usermod -s \"${eshell}\" \"${euser}\""
+ fi
+ ;;
+
*)
usermod "${opts[@]}" "${euser}" && return 0
[[ $? == 8 ]] && eerror "${euser} is in use, cannot update groups"
pgpxET9AiruhC.pgp
Description: OpenPGP digital signature
