[46954] trunk/base
jmr at macports.org
jmr at macports.org
Wed Feb 18 01:32:50 PST 2009
Revision: 46954
http://trac.macports.org/changeset/46954
Author: jmr at macports.org
Date: 2009-02-18 01:32:43 -0800 (Wed, 18 Feb 2009)
Log Message:
-----------
Merge gsoc08-privileges branch into trunk.
Modified Paths:
--------------
trunk/base/ChangeLog
trunk/base/Makefile.in
trunk/base/aclocal.m4
trunk/base/configure
trunk/base/configure.ac
trunk/base/doc/macports.conf.in
trunk/base/doc/portfile.7
trunk/base/src/macports1.0/macports.tcl
trunk/base/src/port/port.tcl
trunk/base/src/port1.0/port_autoconf.tcl.in
trunk/base/src/port1.0/portbuild.tcl
trunk/base/src/port1.0/portclean.tcl
trunk/base/src/port1.0/portconfigure.tcl
trunk/base/src/port1.0/portdestroot.tcl
trunk/base/src/port1.0/portextract.tcl
trunk/base/src/port1.0/portfetch.tcl
trunk/base/src/port1.0/portinstall.tcl
trunk/base/src/port1.0/portmain.tcl
trunk/base/src/port1.0/portpatch.tcl
trunk/base/src/port1.0/portutil.tcl
Property Changed:
----------------
trunk/base/
Property changes on: trunk/base
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/variant-descs-14482/base:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes:45682-46060
/users/perry/base-select:44044-44692
+ /branches/gsoc08-privileges/base:37343-46937
/branches/variant-descs-14482/base:34469-34855,34900-37508,37511-37512,41040-41463,42575-42626,42640-42659
/users/perry/base-bugs_and_notes:45682-46060
/users/perry/base-select:44044-44692
Modified: trunk/base/ChangeLog
===================================================================
--- trunk/base/ChangeLog 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/ChangeLog 2009-02-18 09:32:43 UTC (rev 46954)
@@ -5,6 +5,43 @@
Release 1.8.0 (unreleased):
+ - MacPorts now performs fetch, extract, patch, configure and build in a
+ user rather than system owned location. By default, this is
+ ~/.macports/opt. This allows MacPorts to do all but the install of the
+ port without root privileges. (gsoc08-privileges)
+
+ - MacPorts now automatically drops privileges whenever possible so as to
+ avoid running as root whenever possible. (gsoc08-privileges)
+
+ - MacPorts will prompt for the root password if you attempt to install a
+ port into the /opt hierarchy and did not start MacPorts with sudo. It
+ will not do so however until the install stage. The fetch, extract,
+ patch, configure and build will proceed first under the privileges
+ MacPorts is started with. (gsoc08-privileges)
+
+ - The Portfile format has a number of new boolean attributes to indicate
+ when an action should or should not be run with root privileges:
+ 'patch.asroot', 'build.asroot', 'configure.asroot', 'destroot.asroot',
+ and 'install.asroot'. The default for all is "no". If the prefix folder
+ (by default /opt/local) is not writable, MacPorts will attempt to
+ elevate privileges to root for the install phase. (gsoc08-privileges)
+
+ - A "make group" command has been added to the Makefile and a
+ "--with-shared-directory" switch to the configure script. Running "make
+ group" will create a macports group. "--with-shared-directory" will let
+ let the group specified by "--with-install-group" have full read write
+ access to the /opt/local hierarchy. This will allow users who are
+ members of the new macports group to have full write permissions to /opt
+ and its subfolders, and hence to install ports which only affect that
+ hierarchy to install those ports without requiring root privileges.
+ (gsoc08-privileges)
+
+ - A switch called "--with-no-root-privileges" has been added for use by
+ user installing MacPorts for their own use only. An example configure
+ command would be "./configure
+ --prefix=/Users/{your-user-name-here}/.macports/opt
+ --with-no-root-privileges" (gsoc08-privileges)
+
- Add new "use_7z yes" port option to allow distfiles in 7z format
(#18521, ryandesign)
Modified: trunk/base/Makefile.in
===================================================================
--- trunk/base/Makefile.in 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/Makefile.in 2009-02-18 09:32:43 UTC (rev 46954)
@@ -50,6 +50,13 @@
@echo "Please read \"man port\", the MacPorts guide at http://guide.macports.org/ and Wiki at http://trac.macports.org/ for full documentation."; echo ""
@echo "Stray sources might have been left in the legacy ${localstatedir}/db/dports directory after this upgrade, which moved most of what it could to ${localstatedir}/macports, so you might want to look in the former and cleanup manually."; echo ""
+group::
+ @echo "creating a macports group..." && sudo dseditgroup -o create -n . macports && echo "done! use './configure --with-install-group=macports --with-shared-directory' if you haven't already"
+
+rmgroup::
+ @echo "deleting macports group..." && sudo dseditgroup -o delete -n . macports && echo "done! use 'make group' to re-create"
+
+
clean::
distclean::
Modified: trunk/base/aclocal.m4
===================================================================
--- trunk/base/aclocal.m4 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/aclocal.m4 2009-02-18 09:32:43 UTC (rev 46954)
@@ -288,6 +288,86 @@
])
+
+# MP_CHECK_NOROOTPRIVILEGES
+#-------------------------------------------------
+AC_DEFUN([MP_CHECK_NOROOTPRIVILEGES],[
+ dnl if with user specifies --with-no-root-privileges,
+ dnl use current user and group.
+ dnl use ~/Library/Tcl as Tcl package directory
+ AC_REQUIRE([MP_PATH_MPCONFIGDIR])
+
+ AC_ARG_WITH(no-root-privileges, [AC_HELP_STRING([--with-no-root-privileges], [Specify that MacPorts should be installed in your home directory])], [ROOTPRIVS=$withval] )
+
+ if test "${ROOTPRIVS+set}" = set; then
+
+ # Set install-user to current user
+ AC_MSG_CHECKING([for install user])
+ DSTUSR=`id -un`
+ AC_MSG_RESULT([$DSTUSR])
+ AC_SUBST(DSTUSR)
+
+ # Set install-group to current user
+ AC_MSG_CHECKING([for install group])
+ DSTGRP=`id -gn`
+ AC_MSG_RESULT([$DSTGRP])
+ AC_SUBST(DSTGRP)
+
+ # Set Tcl package directory to ~/Library/Tcl
+ AC_MSG_CHECKING(for Tcl package directory)
+ ac_cv_c_tclpkgd="~$DSTUSR/Library/Tcl"
+ # Convert to a native path and substitute into the output files.
+ PACKAGE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclpkgd}`
+ TCL_PACKAGE_DIR=${PACKAGE_DIR_NATIVE}
+ AC_SUBST(TCL_PACKAGE_DIR)
+ if test x"${ac_cv_c_tclpkgd}" = x ; then
+ AC_MSG_ERROR(Tcl package directory not found. Please specify its location with --with-tclpackage)
+ else
+ AC_MSG_RESULT(${ac_cv_c_tclpkgd})
+ fi
+ fi
+
+])
+
+# MP_CHECK_RUNUSER
+#-------------------------------------------------
+AC_DEFUN([MP_CHECK_RUNUSER],[
+ dnl if with user specifies --with-macports-user,
+ dnl use it. otherwise default to platform defaults
+ AC_REQUIRE([MP_PATH_MPCONFIGDIR])
+
+ AC_ARG_WITH(macports-user, [AC_HELP_STRING([--with-macports-user=USER], [Specify user to drop privileges to, if possible, during compiles etc.])], [ RUNUSR=$withval ] )
+
+ AC_MSG_CHECKING([for macports user])
+ if test "x$RUNUSR" = "x" ; then
+# dropping root privs is still buggy
+# RUNUSR=`id -un`
+ RUNUSR=root
+ fi
+
+ AC_MSG_RESULT([$RUNUSR])
+ AC_SUBST(RUNUSR)
+])
+
+
+# MP_SHARED_DIRECTORY
+#-------------------------------------------------
+AC_DEFUN([MP_SHARED_DIRECTORY],[
+ dnl if with user specifies --with-shared-directory,
+ dnl use 0775 permissions for ${prefix} directories
+ AC_REQUIRE([MP_PATH_MPCONFIGDIR])
+
+ AC_ARG_WITH(shared-directory, [AC_HELP_STRING([--with-shared-directory], [Use 0775 permissions for installed directories])], [ SHAREDIR=$withval ] )
+
+ if test "${SHAREDIR+set}" = set; then
+ AC_MSG_CHECKING([whether to share the install directory with all members of the install group])
+ DSTMODE=0775
+
+ AC_MSG_RESULT([$DSTMODE])
+ AC_SUBST(DSTMODE)
+ fi
+])
+
# MP_CHECK_INSTALLUSER
#-------------------------------------------------
AC_DEFUN([MP_CHECK_INSTALLUSER],[
Modified: trunk/base/configure
===================================================================
--- trunk/base/configure 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/configure 2009-02-18 09:32:43 UTC (rev 46954)
@@ -661,7 +661,6 @@
LDFLAGS_LIBCURL
CFLAGS_LIBCURL
CURL_CONFIG
-TCL_PACKAGE_DIR
TCLSH
TCL_INCLUDES
TCL_STUB_LIB_SPEC
@@ -689,6 +688,8 @@
MPFRAMEWORKSDIR
MPAPPLICATIONSDIR
DSTMODE
+RUNUSR
+TCL_PACKAGE_DIR
DSTGRP
DSTUSR
MPCONFIGDIR
@@ -807,9 +808,12 @@
with_objc_runtime
with_objc_foundation
with_ports_dir
+with_no_root_privileges
with_install_user
with_install_group
+with_macports_user
with_directory_mode
+with_shared_directory
with_applications_dir
with_frameworks_dir
with_universal_target
@@ -1495,12 +1499,19 @@
--with-objc-runtime Specify either "GNU" or "apple"
--with-objc-foundation Specify either "GNUstep" or "apple"
--with-ports-dir=DIR Specify alternate ports directory
+ --with-no-root-privileges
+ Specify that MacPorts should be installed in your
+ home directory
--with-install-user=USER
Specify user ownership of installed files
--with-install-group=GROUP
Specify group ownership of installed files
+ --with-macports-user=USER
+ Specify user to drop privileges to, if possible,
+ during compiles etc.
--with-directory-mode=MODE
Specify directory mode of installed directories
+ --with-shared-directory Use 0775 permissions for installed directories
--with-applications-dir Applications installation directory.
--with-frameworks-dir Frameworks installation directory.
--with-universal-target=MDT
@@ -6947,6 +6958,55 @@
+# Check whether to install without root privileges
+
+
+
+
+# Check whether --with-no-root-privileges was given.
+if test "${with_no_root_privileges+set}" = set; then
+ withval=$with_no_root_privileges; ROOTPRIVS=$withval
+fi
+
+
+ if test "${ROOTPRIVS+set}" = set; then
+
+ # Set install-user to current user
+ { $as_echo "$as_me:$LINENO: checking for install user" >&5
+$as_echo_n "checking for install user... " >&6; }
+ DSTUSR=`id -un`
+ { $as_echo "$as_me:$LINENO: result: $DSTUSR" >&5
+$as_echo "$DSTUSR" >&6; }
+
+
+ # Set install-group to current user
+ { $as_echo "$as_me:$LINENO: checking for install group" >&5
+$as_echo_n "checking for install group... " >&6; }
+ DSTGRP=`id -gn`
+ { $as_echo "$as_me:$LINENO: result: $DSTGRP" >&5
+$as_echo "$DSTGRP" >&6; }
+
+
+ # Set Tcl package directory to ~/Library/Tcl
+ { $as_echo "$as_me:$LINENO: checking for Tcl package directory" >&5
+$as_echo_n "checking for Tcl package directory... " >&6; }
+ ac_cv_c_tclpkgd="~$DSTUSR/Library/Tcl"
+ # Convert to a native path and substitute into the output files.
+ PACKAGE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclpkgd}`
+ TCL_PACKAGE_DIR=${PACKAGE_DIR_NATIVE}
+
+ if test x"${ac_cv_c_tclpkgd}" = x ; then
+ { { $as_echo "$as_me:$LINENO: error: Tcl package directory not found. Please specify its location with --with-tclpackage" >&5
+$as_echo "$as_me: error: Tcl package directory not found. Please specify its location with --with-tclpackage" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ { $as_echo "$as_me:$LINENO: result: ${ac_cv_c_tclpkgd}" >&5
+$as_echo "${ac_cv_c_tclpkgd}" >&6; }
+ fi
+ fi
+
+
+
# Check for install ownership
@@ -7006,6 +7066,28 @@
+# Check whether --with-macports-user was given.
+if test "${with_macports_user+set}" = set; then
+ withval=$with_macports_user; RUNUSR=$withval
+fi
+
+
+ { $as_echo "$as_me:$LINENO: checking for macports user" >&5
+$as_echo_n "checking for macports user... " >&6; }
+ if test "x$RUNUSR" = "x" ; then
+# dropping root privs is still buggy
+# RUNUSR=`id -un`
+ RUNUSR=root
+ fi
+
+ { $as_echo "$as_me:$LINENO: result: $RUNUSR" >&5
+$as_echo "$RUNUSR" >&6; }
+
+
+
+
+
+
# Check whether --with-directory-mode was given.
if test "${with_directory_mode+set}" = set; then
withval=$with_directory_mode; DSTMODE=$withval
@@ -7023,6 +7105,26 @@
+
+
+
+# Check whether --with-shared-directory was given.
+if test "${with_shared_directory+set}" = set; then
+ withval=$with_shared_directory; SHAREDIR=$withval
+fi
+
+
+ if test "${SHAREDIR+set}" = set; then
+ { $as_echo "$as_me:$LINENO: checking whether to share the install directory with all members of the install group" >&5
+$as_echo_n "checking whether to share the install directory with all members of the install group... " >&6; }
+ DSTMODE=0775
+
+ { $as_echo "$as_me:$LINENO: result: $DSTMODE" >&5
+$as_echo "$DSTMODE" >&6; }
+
+ fi
+
+
# Check for default directories
Modified: trunk/base/configure.ac
===================================================================
--- trunk/base/configure.ac 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/configure.ac 2009-02-18 09:32:43 UTC (rev 46954)
@@ -139,10 +139,15 @@
MP_PATH_PORTSDIR([$PORTS_DIR_DEFAULT])
MP_PATH_MPCONFIGDIR
+# Check whether to install without root privileges
+MP_CHECK_NOROOTPRIVILEGES
+
# Check for install ownership
MP_CHECK_INSTALLUSER
MP_CHECK_INSTALLGROUP
+MP_CHECK_RUNUSER
MP_DIRECTORY_MODE
+MP_SHARED_DIRECTORY
# Check for default directories
MP_PATH_APPLICATIONS
Modified: trunk/base/doc/macports.conf.in
===================================================================
--- trunk/base/doc/macports.conf.in 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/doc/macports.conf.in 2009-02-18 09:32:43 UTC (rev 46954)
@@ -4,6 +4,9 @@
# Set the directory in which to install ports
prefix @prefix_expanded@
+# Set the user to run MacPorts compiles, etc as when privileges are dropped during an install
+macportsuser @RUNUSR@
+
# Where to store MacPorts working data
portdbpath @localstatedir_expanded@/macports
Modified: trunk/base/doc/portfile.7
===================================================================
--- trunk/base/doc/portfile.7 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/doc/portfile.7 2009-02-18 09:32:43 UTC (rev 46954)
@@ -322,6 +322,13 @@
.Cm test .
The hooks are:
.Bl -tag -width lc
+.It Va target Ns Ic .asroot
+Run the
+.Va target
+with root privileges.
+.br
+.Sy Example:
+.Dl install.asroot yes
.It Va target Ns Ic .dir
Directory in which to run the
.Va target .
Modified: trunk/base/src/macports1.0/macports.tcl
===================================================================
--- trunk/base/src/macports1.0/macports.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/macports1.0/macports.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -45,7 +45,8 @@
porttrace portverbose destroot_umask variants_conf rsync_server rsync_options \
rsync_dir startupitem_type place_worksymlink xcodeversion xcodebuildcmd \
mp_remote_url mp_remote_submit_url configureccache configuredistcc configurepipe buildnicevalue buildmakejobs \
- applications_dir frameworks_dir universal_target universal_sysroot universal_archs"
+ applications_dir frameworks_dir universal_target universal_sysroot universal_archs \
+ macportsuser"
variable user_options "submitter_name submitter_email submitter_key"
variable portinterp_options "\
portdbpath porturl portpath portbuildpath auto_path prefix prefix_frozen x11prefix portsharepath \
@@ -332,6 +333,7 @@
global macports::destroot_umask
global macports::libpath
global macports::prefix
+ global macports::macportsuser
global macports::prefix_frozen
global macports::x11prefix
global macports::registry.installtype
Modified: trunk/base/src/port/port.tcl
===================================================================
--- trunk/base/src/port/port.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port/port.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -367,7 +367,11 @@
array set options $portspec(options)
}
uplevel 1 $block
- cd $savedir
+ if {[file exists $savedir]} {
+ cd $savedir
+ } else {
+ cd ~
+ }
}
}
@@ -2053,6 +2057,16 @@
if { [catch {portuninstall::uninstall $portname [composite_version $portversion [array get variations]] [array get options]} result] } {
global errorInfo
ui_debug "$errorInfo"
+
+ # start gsoc08-privileges
+ if { [string first "permission denied" $result] != -1 } {
+ set result "port requires root privileges for this action and needs you to execute 'sudo port uninstall $portname' to continue."
+ #ui_msg [exec sudo port uninstall $portname]
+ # The above line is what should be here to let the user simply enter his/her password to uninstall as root.
+ # However, for some as yet unknown reason, executing it here will not work.
+ }
+ # end gsoc08-privileges
+
break_softcontinue "port uninstall failed: $result" 1 status
}
}
@@ -2783,6 +2797,25 @@
mportclose $workername
+ # start gsoc08-privileges
+ if { [geteuid] != 0 && $result == 2} {
+ # mportexec will return an error result code 2 if eval_targets fails due to insufficient privileges.
+
+ set portbinary "${macports::prefix}/bin/port"
+
+ ui_info "Attempting port action with 'sudo port': 'sudo $portbinary $target $portname'."
+ set result 0
+ if {[catch {set sudomsgs [exec sudo $portbinary $target $portname]} sudomsgs]} {
+ global errorInfo
+ ui_debug "$errorInfo"
+ break_softcontinue "Unable to execute port: $errorInfo" 1 status
+ }
+
+ ui_msg $sudomsgs
+ ui_debug "'sudo $portbinary $target $portname' has completed."
+ }
+ # end gsoc08-privileges
+
# Process any error that wasn't thrown and handled already
if {$result} {
break_softcontinue "Status $result encountered during processing." 1 status
Modified: trunk/base/src/port1.0/port_autoconf.tcl.in
===================================================================
--- trunk/base/src/port1.0/port_autoconf.tcl.in 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/port_autoconf.tcl.in 2009-02-18 09:32:43 UTC (rev 46954)
@@ -46,5 +46,6 @@
variable install_user "@DSTUSR@"
variable install_group "@DSTGRP@"
variable prefix "@prefix_expanded@"
+ variable macportsuser "@RUNUSR@"
variable x11prefix "@x11prefix@"
}
Modified: trunk/base/src/port1.0/portbuild.tcl
===================================================================
--- trunk/base/src/port1.0/portbuild.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portbuild.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -42,8 +42,10 @@
options build.target
options build.nice
options build.jobs
+options build.asroot
commands build parallel_build
# defaults
+default build.asroot no
default build.dir {${workpath}/${worksrcdir}}
default build.cmd {[build_getmaketype]}
default build.nice {${buildnicevalue}}
@@ -133,9 +135,17 @@
}
proc build_start {args} {
- global UI_PREFIX
+ global UI_PREFIX build.asroot
ui_msg "$UI_PREFIX [format [msgcat::mc "Building %s"] [option portname]]"
+
+ # start gsoc08-privileges
+ if { [tbool build.asroot] } {
+ # if port is marked as needing root
+ elevateToRoot "build"
+ }
+ # end gsoc08-privileges
+
}
proc build_main {args} {
Modified: trunk/base/src/port1.0/portclean.tcl
===================================================================
--- trunk/base/src/port1.0/portclean.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portclean.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -54,7 +54,7 @@
proc clean_main {args} {
global UI_PREFIX
global ports_clean_dist ports_clean_work ports_clean_archive
- global ports_clean_all
+ global ports_clean_all usealtworkpath
if {[info exists ports_clean_all] && $ports_clean_all == "yes" || \
[info exists ports_clean_dist] && $ports_clean_dist == "yes"} {
@@ -74,9 +74,34 @@
clean_work
}
+ # start gsoc-08 privileges
+ if {$usealtworkpath == "yes"} {
+ ui_info "$UI_PREFIX [format [msgcat::mc "Removing alt source directory for %s"] [option portname]]"
+ clean_altsource
+ }
+ # end gsoc-08 privileges
+
return 0
}
+proc clean_altsource {args} {
+ global usealtworkpath worksymlink
+
+ set sourcepath [string map {"work" ""} $worksymlink]
+
+ if {[file isdirectory $sourcepath]} {
+ ui_debug "Removing directory: ${sourcepath}"
+ if {[catch {delete $sourcepath} result]} {
+ ui_debug "$::errorInfo"
+ ui_error "$result"
+ }
+ } else {
+ ui_debug "No alt source directory found to remove."
+ }
+
+ return 0
+}
+
#
# Remove the directory where the distfiles reside.
# This is crude, but works.
@@ -104,7 +129,7 @@
if {$count > 0} {
ui_debug "$count distfile(s) removed."
} else {
- ui_debug "No distfiles found to remove."
+ ui_debug "No distfiles found to remove at $distpath"
}
# next remove dist_subdir if only needed for this port,
@@ -158,7 +183,7 @@
ui_error "$result"
}
} else {
- ui_debug "No work directory found to remove."
+ ui_debug "No work directory found to remove at: ${portbuildpath}"
}
# Clean symlink, if necessary
@@ -215,7 +240,7 @@
if {$count > 0} {
ui_debug "$count archive(s) removed."
} else {
- ui_debug "No archives found to remove."
+ ui_debug "No archives found to remove at $archivepath"
}
return 0
Modified: trunk/base/src/port1.0/portconfigure.tcl
===================================================================
--- trunk/base/src/port1.0/portconfigure.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portconfigure.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -78,6 +78,9 @@
}
}
+options configure.asroot
+default configure.asroot no
+
# Configure special environment variables.
# We could have m32/m64/march/mtune be global configurable at some point.
options configure.m32 configure.m64 configure.march configure.mtune
@@ -188,6 +191,13 @@
default { return -code error "Invalid value for configure.compiler" }
}
ui_debug "Using compiler '$name'"
+
+ # start gsoc08-privileges
+ if { [tbool configure.asroot] } {
+ # if port is marked as needing root
+ elevateToRoot "configure"
+ }
+ # end gsoc08-privileges
}
# internal function to determine canonical system name for configure
Modified: trunk/base/src/port1.0/portdestroot.tcl
===================================================================
--- trunk/base/src/port1.0/portdestroot.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portdestroot.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -42,7 +42,7 @@
# define options
options destroot.target destroot.destdir destroot.clean destroot.keepdirs destroot.umask
-options destroot.violate_mtree
+options destroot.violate_mtree destroot.asroot
options startupitem.create startupitem.requires startupitem.init
options startupitem.name startupitem.start startupitem.stop startupitem.restart
options startupitem.type startupitem.executable
@@ -51,6 +51,7 @@
commands destroot
# Set defaults
+default destroot.asroot no
default destroot.dir {${build.dir}}
default destroot.cmd {${build.cmd}}
default destroot.pre_args {${destroot.target}}
@@ -87,11 +88,38 @@
proc destroot_start {args} {
global UI_PREFIX prefix portname porturl destroot os.platform destroot.clean portsharepath
- global destroot::oldmask destroot.umask
+ global destroot::oldmask destroot.umask destroot.asroot macportsuser euid egid usealtworkpath altprefix
global applications_dir frameworks_dir
ui_msg "$UI_PREFIX [format [msgcat::mc "Staging %s into destroot"] ${portname}]"
+ # start gsoc08-privileges
+ if { [getuid] == 0 && [geteuid] == [name_to_uid "$macportsuser"] } {
+ # if started with sudo but have dropped the privileges
+ ui_debug "Can't run destroot under sudo without elevated privileges (due to mtree)."
+ ui_debug "Run destroot without sudo to avoid root privileges."
+ ui_debug "Going to escalate privileges back to root."
+ setegid $egid
+ seteuid $euid
+ ui_debug "euid changed to: [geteuid]. egid changed to: [getegid]."
+ }
+
+ if { [tbool destroot.asroot] && [getuid] != 0 } {
+ global errorisprivileges
+ set errorisprivileges yes
+ return -code error "You can not run this port without elevated privileges. You need to re-run with 'sudo port'.";
+ }
+
+ if {$usealtworkpath} {
+ # rewrite destroot.args
+ set argprefix "=[option prefix]"
+ set newargprefix "=${altprefix}[option prefix]"
+ set newdestrootargs [string map [list $argprefix $newargprefix] [option destroot.args]]
+ option destroot.args $newdestrootargs
+ }
+
+ # end gsoc08-privileges
+
set oldmask [umask ${destroot.umask}]
set mtree ${portutil::autoconf::mtree_path}
@@ -293,6 +321,10 @@
# Restore umask
umask $oldmask
+
+ # start gsoc08-privileges
+ chownAsRoot $destroot
+ # end gsoc08-privileges
return 0
}
Modified: trunk/base/src/port1.0/portextract.tcl
===================================================================
--- trunk/base/src/port1.0/portextract.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portextract.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -98,7 +98,7 @@
}
proc extract_main {args} {
- global UI_PREFIX filespath
+ global UI_PREFIX filespath worksrcpath
if {![exists distfiles] && ![exists extract.only]} {
# nothing to do
@@ -115,6 +115,11 @@
if {[catch {command_exec extract} result]} {
return -code error "$result"
}
+
+ # start gsoc08-privileges
+ chownAsRoot $worksrcpath
+ # end gsoc08-privileges
+
}
return 0
}
Modified: trunk/base/src/port1.0/portfetch.tcl
===================================================================
--- trunk/base/src/port1.0/portfetch.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portfetch.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -723,8 +723,18 @@
# Initialize fetch target and call checkfiles.
proc fetch_init {args} {
global distfiles distname distpath all_dist_files dist_subdir fetch.type fetch_init_done
+ global altprefix usealtworkpath
if {[info exists distpath] && [info exists dist_subdir] && ![info exists fetch_init_done]} {
+
+ # start gsoc08-privileges
+ if { $usealtworkpath } {
+ # I have removed ![file writable $distpath] from the if condition as
+ # the writable condition seems to get confused by effective uids.
+ set distpath "$altprefix/[ string range $distpath 1 end ]"
+ ui_debug "Going to use $distpath for fetch."
+ }
+ # end gsoc08-privileges
set distpath ${distpath}/${dist_subdir}
set fetch_init_done yes
}
Modified: trunk/base/src/port1.0/portinstall.tcl
===================================================================
--- trunk/base/src/port1.0/portinstall.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portinstall.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -44,11 +44,29 @@
}
target_prerun ${org.macports.install} install_start
+# define options
+options install.asroot
+
+# Set defaults
+default install.asroot no
+
set_ui_prefix
proc install_start {args} {
global UI_PREFIX portname portversion portrevision variations portvariants
+ global install.asroot prefix
ui_msg "$UI_PREFIX [format [msgcat::mc "Installing %s @%s_%s%s"] $portname $portversion $portrevision $portvariants]"
+
+ # start gsoc08-privileges
+ if { [tbool install.asroot] } {
+ # if port is marked as needing root
+ elevateToRoot "install"
+ } elseif { ![file writable $prefix] } {
+ # if install location is not writable, need root privileges to install
+ elevateToRoot "install"
+ }
+ # end gsoc08-privileges
+
}
proc install_element {src_element dst_element} {
Modified: trunk/base/src/port1.0/portmain.tcl
===================================================================
--- trunk/base/src/port1.0/portmain.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portmain.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -41,7 +41,7 @@
target_state ${org.macports.main} no
# define options
-options prefix name version revision epoch categories maintainers
+options prefix macportsuser name version revision epoch categories maintainers
options long_description description homepage
options worksrcdir filesdir distname portdbpath libpath distpath sources_conf os.platform os.version os.major os.arch os.endian platforms default_variants install.user install.group macosx_deployment_target
options universal_variant os.universal_supported
@@ -72,6 +72,7 @@
default worksrcpath {[file join $workpath $worksrcdir]}
# Configure settings
+default macportsuser {${portutil::autoconf::macportsuser}}
default install.user {${portutil::autoconf::install_user}}
default install.group {${portutil::autoconf::install_group}}
Modified: trunk/base/src/port1.0/portpatch.tcl
===================================================================
--- trunk/base/src/port1.0/portpatch.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portpatch.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -41,7 +41,10 @@
# Add command patch
commands patch
+
+options patch.asroot
# Set up defaults
+default patch.asroot no
default patch.dir {${worksrcpath}}
default patch.cmd patch
default patch.pre_args -p0
@@ -55,6 +58,13 @@
}
ui_msg "$UI_PREFIX [format [msgcat::mc "Applying patches to %s"] [option portname]]"
+
+ # start gsoc08-privileges
+ if { [tbool patch.asroot] } {
+ # if port is marked as needing root
+ elevateToRoot "patch"
+ }
+ # end gsoc08-privileges
foreach patch [option patchfiles] {
set patch_file [getdistname $patch]
Modified: trunk/base/src/port1.0/portutil.tcl
===================================================================
--- trunk/base/src/port1.0/portutil.tcl 2009-02-18 09:03:06 UTC (rev 46953)
+++ trunk/base/src/port1.0/portutil.tcl 2009-02-18 09:32:43 UTC (rev 46954)
@@ -768,6 +768,8 @@
# reinplace
# Provides "sed in place" functionality
proc reinplace {args} {
+ global euid macportsuser
+
set extended 0
while 1 {
set arg [lindex $args 0]
@@ -827,6 +829,10 @@
close $tmpfd
+ # start gsoc08-privileges
+ chownAsRoot $file
+ # end gsoc08-privileges
+
set attributes [file attributes $file]
# We need to overwrite this file
if {[catch {file attributes $file -permissions u+w} error]} {
@@ -1146,7 +1152,7 @@
set ports_dry_last_skipped ""
proc target_run {ditem} {
- global target_state_fd portpath portname portversion portrevision portvariants ports_force variations workpath ports_trace PortInfo ports_dryrun ports_dry_last_skipped
+ global target_state_fd portpath portname portversion portrevision portvariants ports_force variations workpath ports_trace PortInfo ports_dryrun ports_dry_last_skipped errorisprivileges
set result 0
set skipped 0
set procedure [ditem_key $ditem procedure]
@@ -1358,7 +1364,11 @@
write_statefile target $name $target_state_fd
}
} else {
- ui_error "Target $name returned: $errstr"
+ if {$errorisprivileges != "yes"} {
+ ui_error "Target $name returned: $errstr"
+ } else {
+ ui_msg "Target $name returned: $errstr"
+ }
set result 1
}
@@ -1408,8 +1418,9 @@
proc eval_targets {target} {
- global targets target_state_fd portname
+ global targets target_state_fd portname errorisprivileges
set dlist $targets
+ set errorisprivileges "no"
# Select the subset of targets under $target
if {$target != ""} {
@@ -1438,6 +1449,12 @@
set result 0
}
+ # start gsoc08-privileges
+ if { $result == 1 && $errorisprivileges == "yes" } {
+ set result 2
+ }
+ # end gsoc08-privileges
+
return $result
}
@@ -1445,7 +1462,87 @@
# open file to store name of completed targets
proc open_statefile {args} {
global workpath worksymlink place_worksymlink portname portpath ports_ignore_older
+ global altprefix usealtworkpath env applications_dir portbuildpath distpath
+ # start gsoc08-privileges
+
+ # descalate privileges - only ran if macports stated with sudo
+ dropPrivileges
+
+ if { ![file exists $workpath] } {
+ if {[catch {set result [file mkdir $workpath]} result]} {
+ global errorInfo
+ ui_debug "mkdir $workpath: $errorInfo"
+ }
+ }
+
+ # if unable to write to workpath, implies running without either root privileges
+ # or a shared directory owned by the group so use ~/.macports
+ if { ![file writable $workpath] } {
+
+ set userid [getuid]
+ set username [uid_to_name $userid]
+
+ if { $userid !=0 } {
+ ui_msg "MacPorts running without privileges.\
+ You may be prompted for your sudo password in order to complete certain actions (eg install)."
+ }
+
+ # set global variable indicating to other functions to use ~/.macports as well
+ set usealtworkpath yes
+
+ # do tilde expansion manually - tcl won't expand tildes automatically for curl, etc.
+ if {[info exists env(HOME)]} {
+ # HOME environment var is set, use it.
+ set userhome "$env(HOME)"
+ } else {
+ # the environment var isn't set, make an educated guess
+ if {[option os.platform] == "darwin"} {
+ set userhome "/Users/${username}"
+ } else {
+ set userhome "/home/${username}"
+ }
+ }
+
+ # set alternative prefix global variables
+ set altprefix "$userhome/.macports"
+
+ # get alternative paths
+ set newworkpath "$altprefix$workpath"
+ set newworksymlink "$altprefix$worksymlink"
+ set newportbuildpath "$altprefix$portbuildpath"
+ set newdistpath "$altprefix$distpath"
+
+ set sourcepath [string map {"work" ""} $worksymlink]
+ set newsourcepath "$altprefix/[ string range $sourcepath 1 end ]"
+
+ # copy Portfile (and patch files) if not there already
+ # note to maintainers/devs: the original portfile in /opt is ALWAYS the one that will be
+ # read by macports. The copying of the portfile is done to preserve the symlink provided
+ # historically by macports from the portfile directory to the work directory.
+ # It is NOT read by MacPorts.
+ if {![file exists ${newsourcepath}Portfile] } {
+ file mkdir $newsourcepath
+ ui_debug "$newsourcepath created"
+ ui_debug "Going to copy: ${sourcepath}Portfile"
+ file copy ${sourcepath}Portfile $newsourcepath
+ if {[file exists ${sourcepath}files] } {
+ ui_debug "Going to copy: ${sourcepath}files"
+ file copy ${sourcepath}files $newsourcepath
+ }
+ }
+
+ set workpath $newworkpath
+ set worksymlink $newworksymlink
+ set portbuildpath $newportbuildpath
+ set distpath $newdistpath
+
+ ui_debug "Going to use $newworkpath for statefile."
+ } else {
+ set usealtworkpath no
+ }
+ # end gsoc08-privileges
+
if {![file isdirectory $workpath]} {
file mkdir $workpath
}
@@ -1465,6 +1562,7 @@
# Create a symlink to the workpath for port authors
if {[tbool place_worksymlink] && ![file isdirectory $worksymlink]} {
+ ui_debug "Attempting ln -sf $workpath $worksymlink"
ln -sf $workpath $worksymlink
}
@@ -2253,3 +2351,95 @@
return $str
}
+##
+# Recusively chown the given file or directory to the specified user.
+#
+# @param path the file/directory to be chowned
+# @param user the user to chown file to
+proc chown {path user} {
+ file attributes $path -owner [name_to_uid "$user"]
+
+ if {[file isdirectory $path]} {
+ fs-traverse myfile ${path} {
+ file attributes $myfile -owner [name_to_uid "$user"]
+ }
+ }
+
+}
+
+##
+# Recusively chown the given file or directory to $macportsuser, using root privileges.
+#
+# @param path the file/directory to be chowned
+proc chownAsRoot {path} {
+ global euid macportsuser
+
+ if { [getuid] == 0 && [geteuid] == [name_to_uid "$macportsuser"] } {
+ # if started with sudo but have dropped the privileges
+ seteuid $euid
+ ui_debug "euid changed to: [geteuid]"
+ chown ${path} ${macportsuser}
+ ui_debug "chowned $path to $macportsuser"
+ seteuid [name_to_uid "$macportsuser"]
+ ui_debug "euid changed to: [geteuid]"
+ } elseif { [getuid] == 0 } {
+ # if started with sudo but have elevated back to root already
+ chown ${path} ${macportsuser}
+ } else {
+ ui_debug "no need to chown $path. uid=[getuid]. euid=[geteuid]."
+ }
+}
+
+##
+# Elevate privileges back to root.
+#
+# @param action the action for which privileges are being elevated
+proc elevateToRoot {action} {
+ global euid egid macportsuser errorisprivileges
+
+ if { [getuid] == 0 && [geteuid] == [name_to_uid "$macportsuser"] } {
+ # if started with sudo but have dropped the privileges
+ ui_debug "Can't run $action on this port without elevated privileges. Escalating privileges back to root."
+ setegid $egid
+ seteuid $euid
+ ui_debug "euid changed to: [geteuid]. egid changed to: [getegid]."
+ }
+
+ if { [getuid] != 0 } {
+ set errorisprivileges yes
+ return -code error "port requires root privileges for this action and needs you to type your password for sudo.";
+ }
+}
+
+##
+# Descalate privileges from root to those of $macportsuser.
+#
+proc dropPrivileges {} {
+ global euid egid macportsuser workpath
+ if { [geteuid] == 0 } {
+ if { [catch {
+ set euid [geteuid]
+ set egid [getegid]
+ ui_debug "changing euid/egid - current euid: $euid - current egid: $egid"
+
+ #seteuid [name_to_uid [file attributes $workpath -owner]]
+ #setegid [name_to_gid [file attributes $workpath -group]]
+
+ setegid [name_to_gid "$macportsuser"]
+ seteuid [name_to_uid "$macportsuser"]
+ ui_debug "egid changed to: [getegid]"
+ ui_debug "euid changed to: [geteuid]"
+
+ if {![file writable $workpath]} {
+ ui_debug "Privileges successfully descalated. Unable to write to default workpath."
+ }
+ }]
+ } {
+ ui_debug "$::errorInfo"
+ ui_error "Failed to descalate privileges."
+ }
+ } else {
+ ui_debug "Privilege desclation not attempted as not running as root."
+ }
+}
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20090218/0a776bd7/attachment-0001.html>
More information about the macports-changes
mailing list