# which is unavailable.
from StringIO import StringIO
- from time import sleep
- from itertools import chain
import platform
import warnings
'stack_lists,unique_array,varexpand,writedict,writemsg,' + \
'writemsg_stdout,write_atomic',
'portage.util.digraph:digraph',
+ 'portage.util.env_update:env_update',
'portage.util.listdir:cacheddir,listdir',
'portage.versions',
'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,' + \
mylink=mydir+"/"+mylink
return os.path.normpath(mylink)
-#parse /etc/env.d and generate /etc/profile.env
-
-def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None,
- env=None, writemsg_level=None):
- if writemsg_level is None:
- writemsg_level = portage.util.writemsg_level
- if target_root is None:
- global settings
- target_root = settings["ROOT"]
- if prev_mtimes is None:
- global mtimedb
- prev_mtimes = mtimedb["ldpath"]
- if env is None:
- env = os.environ
- envd_dir = os.path.join(target_root, "etc", "env.d")
- portage.util.ensure_dirs(envd_dir, mode=0o755)
- fns = listdir(envd_dir, EmptyOnError=1)
- fns.sort()
- templist = []
- for x in fns:
- if len(x) < 3:
- continue
- if not x[0].isdigit() or not x[1].isdigit():
- continue
- if x.startswith(".") or x.endswith("~") or x.endswith(".bak"):
- continue
- templist.append(x)
- fns = templist
- del templist
-
- space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"])
- colon_separated = set(["ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH",
- "CLASSPATH", "INFODIR", "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH",
- "PATH", "PKG_CONFIG_PATH", "PRELINK_PATH", "PRELINK_PATH_MASK",
- "PYTHONPATH", "ROOTPATH"])
-
- config_list = []
-
- for x in fns:
- file_path = os.path.join(envd_dir, x)
- try:
- myconfig = getconfig(file_path, expand=False)
- except portage.exception.ParseError as e:
- writemsg("!!! '%s'\n" % str(e), noiselevel=-1)
- del e
- continue
- if myconfig is None:
- # broken symlink or file removed by a concurrent process
- writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1)
- continue
-
- config_list.append(myconfig)
- if "SPACE_SEPARATED" in myconfig:
- space_separated.update(myconfig["SPACE_SEPARATED"].split())
- del myconfig["SPACE_SEPARATED"]
- if "COLON_SEPARATED" in myconfig:
- colon_separated.update(myconfig["COLON_SEPARATED"].split())
- del myconfig["COLON_SEPARATED"]
-
- env = {}
- specials = {}
- for var in space_separated:
- mylist = []
- for myconfig in config_list:
- if var in myconfig:
- for item in myconfig[var].split():
- if item and not item in mylist:
- mylist.append(item)
- del myconfig[var] # prepare for env.update(myconfig)
- if mylist:
- env[var] = " ".join(mylist)
- specials[var] = mylist
-
- for var in colon_separated:
- mylist = []
- for myconfig in config_list:
- if var in myconfig:
- for item in myconfig[var].split(":"):
- if item and not item in mylist:
- mylist.append(item)
- del myconfig[var] # prepare for env.update(myconfig)
- if mylist:
- env[var] = ":".join(mylist)
- specials[var] = mylist
-
- for myconfig in config_list:
- """Cumulative variables have already been deleted from myconfig so that
- they won't be overwritten by this dict.update call."""
- env.update(myconfig)
-
- ldsoconf_path = os.path.join(target_root, "etc", "ld.so.conf")
- try:
- myld = codecs.open(_unicode_encode(ldsoconf_path,
- encoding=_encodings['fs'], errors='strict'),
- mode='r', encoding=_encodings['content'], errors='replace')
- myldlines=myld.readlines()
- myld.close()
- oldld=[]
- for x in myldlines:
- #each line has at least one char (a newline)
- if x[0]=="#":
- continue
- oldld.append(x[:-1])
- except (IOError, OSError) as e:
- if e.errno != errno.ENOENT:
- raise
- oldld = None
-
- ld_cache_update=False
-
- newld = specials["LDPATH"]
- if (oldld!=newld):
- #ld.so.conf needs updating and ldconfig needs to be run
- myfd = atomic_ofstream(ldsoconf_path)
- myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n")
- myfd.write("# contents of /etc/env.d directory\n")
- for x in specials["LDPATH"]:
- myfd.write(x+"\n")
- myfd.close()
- ld_cache_update=True
-
- # Update prelink.conf if we are prelink-enabled
- if prelink_capable:
- newprelink = atomic_ofstream(
- os.path.join(target_root, "etc", "prelink.conf"))
- newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n")
- newprelink.write("# contents of /etc/env.d directory\n")
-
- for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]:
- newprelink.write("-l "+x+"\n");
- for x in specials["LDPATH"]+specials["PATH"]+specials["PRELINK_PATH"]:
- if not x:
- continue
- if x[-1]!='/':
- x=x+"/"
- plmasked=0
- for y in specials["PRELINK_PATH_MASK"]:
- if not y:
- continue
- if y[-1]!='/':
- y=y+"/"
- if y==x[0:len(y)]:
- plmasked=1
- break
- if not plmasked:
- newprelink.write("-h "+x+"\n")
- for x in specials["PRELINK_PATH_MASK"]:
- newprelink.write("-b "+x+"\n")
- newprelink.close()
-
- # Portage stores mtimes with 1 second granularity but in >=python-2.5 finer
- # granularity is possible. In order to avoid the potential ambiguity of
- # mtimes that differ by less than 1 second, sleep here if any of the
- # directories have been modified during the current second.
- sleep_for_mtime_granularity = False
- current_time = long(time.time())
- mtime_changed = False
- lib_dirs = set()
- for lib_dir in portage.util.unique_array(specials["LDPATH"]+['usr/lib','usr/lib64','usr/lib32','lib','lib64','lib32']):
- x = os.path.join(target_root, lib_dir.lstrip(os.sep))
- try:
- newldpathtime = os.stat(x)[stat.ST_MTIME]
- lib_dirs.add(normalize_path(x))
- except OSError as oe:
- if oe.errno == errno.ENOENT:
- try:
- del prev_mtimes[x]
- except KeyError:
- pass
- # ignore this path because it doesn't exist
- continue
- raise
- if newldpathtime == current_time:
- sleep_for_mtime_granularity = True
- if x in prev_mtimes:
- if prev_mtimes[x] == newldpathtime:
- pass
- else:
- prev_mtimes[x] = newldpathtime
- mtime_changed = True
- else:
- prev_mtimes[x] = newldpathtime
- mtime_changed = True
-
- if mtime_changed:
- ld_cache_update = True
-
- if makelinks and \
- not ld_cache_update and \
- contents is not None:
- libdir_contents_changed = False
- for mypath, mydata in contents.items():
- if mydata[0] not in ("obj","sym"):
- continue
- head, tail = os.path.split(mypath)
- if head in lib_dirs:
- libdir_contents_changed = True
- break
- if not libdir_contents_changed:
- makelinks = False
-
- ldconfig = "/sbin/ldconfig"
- if "CHOST" in env and "CBUILD" in env and \
- env["CHOST"] != env["CBUILD"]:
- from portage.process import find_binary
- ldconfig = find_binary("%s-ldconfig" % env["CHOST"])
-
- # Only run ldconfig as needed
- if (ld_cache_update or makelinks) and ldconfig:
- # ldconfig has very different behaviour between FreeBSD and Linux
- if ostype=="Linux" or ostype.lower().endswith("gnu"):
- # We can't update links if we haven't cleaned other versions first, as
- # an older package installed ON TOP of a newer version will cause ldconfig
- # to overwrite the symlinks we just made. -X means no links. After 'clean'
- # we can safely create links.
- writemsg_level(_(">>> Regenerating %setc/ld.so.cache...\n") % \
- (target_root,))
- if makelinks:
- os.system("cd / ; %s -r '%s'" % (ldconfig, target_root))
- else:
- os.system("cd / ; %s -X -r '%s'" % (ldconfig, target_root))
- elif ostype in ("FreeBSD","DragonFly"):
- writemsg_level(_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % \
- target_root)
- os.system(("cd / ; %s -elf -i " + \
- "-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'") % \
- (ldconfig, target_root, target_root))
-
- del specials["LDPATH"]
-
- penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
- penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
- cenvnotice = penvnotice[:]
- penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
- cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"
-
- #create /etc/profile.env for bash support
- outfile = atomic_ofstream(os.path.join(target_root, "etc", "profile.env"))
- outfile.write(penvnotice)
-
- env_keys = [ x for x in env if x != "LDPATH" ]
- env_keys.sort()
- for k in env_keys:
- v = env[k]
- if v.startswith('$') and not v.startswith('${'):
- outfile.write("export %s=$'%s'\n" % (k, v[1:]))
- else:
- outfile.write("export %s='%s'\n" % (k, v))
- outfile.close()
-
- #create /etc/csh.env for (t)csh support
- outfile = atomic_ofstream(os.path.join(target_root, "etc", "csh.env"))
- outfile.write(cenvnotice)
- for x in env_keys:
- outfile.write("setenv %s '%s'\n" % (x, env[x]))
- outfile.close()
-
- if sleep_for_mtime_granularity:
- while current_time == long(time.time()):
- sleep(1)
-
def ExtractKernelVersion(base_dir):
"""
Try to figure out what kernel version we are running
'writemsg,writemsg_level,write_atomic,atomic_ofstream,writedict,' + \
'grabfile,grabdict,normalize_path,new_protect_filename,getlibpaths',
'portage.util.digraph:digraph',
+ 'portage.util.env_update:env_update',
'portage.util.listdir:dircache,listdir',
'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,pkgcmp,' + \
'_pkgsplit@pkgsplit',
FileNotFound, PermissionDenied, UnsupportedAPIException
from portage.localization import _
-from portage import dep_expand, env_update, \
+from portage import dep_expand, \
abssymlink, movefile, _movefile, bsd_chflags
# This is a special version of the os module, wrapped for unicode support.
--- /dev/null
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+__all__ = ['env_update']
+
+import codecs
+import errno
+import stat
+import time
+
+import portage
+from portage import os, _encodings, _unicode_encode
+from portage.checksum import prelink_capable
+from portage.data import ostype
+from portage.exception import ParseError
+from portage.localization import _
+from portage.process import find_binary
+from portage.util import atomic_ofstream, ensure_dirs, getconfig, \
+ normalize_path, writemsg
+from portage.util.listdir import listdir
+
+def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None,
+ env=None, writemsg_level=None):
+ """
+ Parse /etc/env.d and use it to generate /etc/profile.env, csh.env,
+ ld.so.conf, and prelink.conf. Finally, run ldconfig.
+ """
+ if writemsg_level is None:
+ writemsg_level = portage.util.writemsg_level
+ if target_root is None:
+ target_root = portage.settings["ROOT"]
+ if prev_mtimes is None:
+ prev_mtimes = portage.mtimedb["ldpath"]
+ if env is None:
+ env = os.environ
+ envd_dir = os.path.join(target_root, "etc", "env.d")
+ ensure_dirs(envd_dir, mode=0o755)
+ fns = listdir(envd_dir, EmptyOnError=1)
+ fns.sort()
+ templist = []
+ for x in fns:
+ if len(x) < 3:
+ continue
+ if not x[0].isdigit() or not x[1].isdigit():
+ continue
+ if x.startswith(".") or x.endswith("~") or x.endswith(".bak"):
+ continue
+ templist.append(x)
+ fns = templist
+ del templist
+
+ space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"])
+ colon_separated = set(["ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH",
+ "CLASSPATH", "INFODIR", "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH",
+ "PATH", "PKG_CONFIG_PATH", "PRELINK_PATH", "PRELINK_PATH_MASK",
+ "PYTHONPATH", "ROOTPATH"])
+
+ config_list = []
+
+ for x in fns:
+ file_path = os.path.join(envd_dir, x)
+ try:
+ myconfig = getconfig(file_path, expand=False)
+ except ParseError as e:
+ writemsg("!!! '%s'\n" % str(e), noiselevel=-1)
+ del e
+ continue
+ if myconfig is None:
+ # broken symlink or file removed by a concurrent process
+ writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1)
+ continue
+
+ config_list.append(myconfig)
+ if "SPACE_SEPARATED" in myconfig:
+ space_separated.update(myconfig["SPACE_SEPARATED"].split())
+ del myconfig["SPACE_SEPARATED"]
+ if "COLON_SEPARATED" in myconfig:
+ colon_separated.update(myconfig["COLON_SEPARATED"].split())
+ del myconfig["COLON_SEPARATED"]
+
+ env = {}
+ specials = {}
+ for var in space_separated:
+ mylist = []
+ for myconfig in config_list:
+ if var in myconfig:
+ for item in myconfig[var].split():
+ if item and not item in mylist:
+ mylist.append(item)
+ del myconfig[var] # prepare for env.update(myconfig)
+ if mylist:
+ env[var] = " ".join(mylist)
+ specials[var] = mylist
+
+ for var in colon_separated:
+ mylist = []
+ for myconfig in config_list:
+ if var in myconfig:
+ for item in myconfig[var].split(":"):
+ if item and not item in mylist:
+ mylist.append(item)
+ del myconfig[var] # prepare for env.update(myconfig)
+ if mylist:
+ env[var] = ":".join(mylist)
+ specials[var] = mylist
+
+ for myconfig in config_list:
+ """Cumulative variables have already been deleted from myconfig so that
+ they won't be overwritten by this dict.update call."""
+ env.update(myconfig)
+
+ ldsoconf_path = os.path.join(target_root, "etc", "ld.so.conf")
+ try:
+ myld = codecs.open(_unicode_encode(ldsoconf_path,
+ encoding=_encodings['fs'], errors='strict'),
+ mode='r', encoding=_encodings['content'], errors='replace')
+ myldlines=myld.readlines()
+ myld.close()
+ oldld=[]
+ for x in myldlines:
+ #each line has at least one char (a newline)
+ if x[:1] == "#":
+ continue
+ oldld.append(x[:-1])
+ except (IOError, OSError) as e:
+ if e.errno != errno.ENOENT:
+ raise
+ oldld = None
+
+ ld_cache_update=False
+
+ newld = specials["LDPATH"]
+ if (oldld != newld):
+ #ld.so.conf needs updating and ldconfig needs to be run
+ myfd = atomic_ofstream(ldsoconf_path)
+ myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n")
+ myfd.write("# contents of /etc/env.d directory\n")
+ for x in specials["LDPATH"]:
+ myfd.write(x + "\n")
+ myfd.close()
+ ld_cache_update=True
+
+ # Update prelink.conf if we are prelink-enabled
+ if prelink_capable:
+ newprelink = atomic_ofstream(
+ os.path.join(target_root, "etc", "prelink.conf"))
+ newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n")
+ newprelink.write("# contents of /etc/env.d directory\n")
+
+ for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]:
+ newprelink.write("-l %s\n" % (x,));
+ prelink_paths = []
+ prelink_paths += specials.get("LDPATH", [])
+ prelink_paths += specials.get("PATH", [])
+ prelink_paths += specials.get("PRELINK_PATH", [])
+ prelink_path_mask = specials.get("PRELINK_PATH_MASK", [])
+ for x in prelink_paths:
+ if not x:
+ continue
+ if x[-1:] != '/':
+ x += "/"
+ plmasked = 0
+ for y in prelink_path_mask:
+ if not y:
+ continue
+ if y[-1] != '/':
+ y += "/"
+ if y == x[0:len(y)]:
+ plmasked = 1
+ break
+ if not plmasked:
+ newprelink.write("-h %s\n" % (x,))
+ for x in prelink_path_mask:
+ newprelink.write("-b %s\n" % (x,))
+ newprelink.close()
+
+ # Portage stores mtimes with 1 second granularity but in >=python-2.5 finer
+ # granularity is possible. In order to avoid the potential ambiguity of
+ # mtimes that differ by less than 1 second, sleep here if any of the
+ # directories have been modified during the current second.
+ sleep_for_mtime_granularity = False
+ current_time = long(time.time())
+ mtime_changed = False
+ lib_dirs = set()
+ for lib_dir in set(specials["LDPATH"] + \
+ ['usr/lib','usr/lib64','usr/lib32','lib','lib64','lib32']):
+ x = os.path.join(target_root, lib_dir.lstrip(os.sep))
+ try:
+ newldpathtime = os.stat(x)[stat.ST_MTIME]
+ lib_dirs.add(normalize_path(x))
+ except OSError as oe:
+ if oe.errno == errno.ENOENT:
+ try:
+ del prev_mtimes[x]
+ except KeyError:
+ pass
+ # ignore this path because it doesn't exist
+ continue
+ raise
+ if newldpathtime == current_time:
+ sleep_for_mtime_granularity = True
+ if x in prev_mtimes:
+ if prev_mtimes[x] == newldpathtime:
+ pass
+ else:
+ prev_mtimes[x] = newldpathtime
+ mtime_changed = True
+ else:
+ prev_mtimes[x] = newldpathtime
+ mtime_changed = True
+
+ if mtime_changed:
+ ld_cache_update = True
+
+ if makelinks and \
+ not ld_cache_update and \
+ contents is not None:
+ libdir_contents_changed = False
+ for mypath, mydata in contents.items():
+ if mydata[0] not in ("obj", "sym"):
+ continue
+ head, tail = os.path.split(mypath)
+ if head in lib_dirs:
+ libdir_contents_changed = True
+ break
+ if not libdir_contents_changed:
+ makelinks = False
+
+ ldconfig = "/sbin/ldconfig"
+ if "CHOST" in env and "CBUILD" in env and \
+ env["CHOST"] != env["CBUILD"]:
+ ldconfig = find_binary("%s-ldconfig" % env["CHOST"])
+
+ # Only run ldconfig as needed
+ if (ld_cache_update or makelinks) and ldconfig:
+ # ldconfig has very different behaviour between FreeBSD and Linux
+ if ostype == "Linux" or ostype.lower().endswith("gnu"):
+ # We can't update links if we haven't cleaned other versions first, as
+ # an older package installed ON TOP of a newer version will cause ldconfig
+ # to overwrite the symlinks we just made. -X means no links. After 'clean'
+ # we can safely create links.
+ writemsg_level(_(">>> Regenerating %setc/ld.so.cache...\n") % \
+ (target_root,))
+ if makelinks:
+ os.system("cd / ; %s -r '%s'" % (ldconfig, target_root))
+ else:
+ os.system("cd / ; %s -X -r '%s'" % (ldconfig, target_root))
+ elif ostype in ("FreeBSD","DragonFly"):
+ writemsg_level(_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % \
+ target_root)
+ os.system(("cd / ; %s -elf -i " + \
+ "-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'") % \
+ (ldconfig, target_root, target_root))
+
+ del specials["LDPATH"]
+
+ penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
+ penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
+ cenvnotice = penvnotice[:]
+ penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
+ cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"
+
+ #create /etc/profile.env for bash support
+ outfile = atomic_ofstream(os.path.join(target_root, "etc", "profile.env"))
+ outfile.write(penvnotice)
+
+ env_keys = [ x for x in env if x != "LDPATH" ]
+ env_keys.sort()
+ for k in env_keys:
+ v = env[k]
+ if v.startswith('$') and not v.startswith('${'):
+ outfile.write("export %s=$'%s'\n" % (k, v[1:]))
+ else:
+ outfile.write("export %s='%s'\n" % (k, v))
+ outfile.close()
+
+ #create /etc/csh.env for (t)csh support
+ outfile = atomic_ofstream(os.path.join(target_root, "etc", "csh.env"))
+ outfile.write(cenvnotice)
+ for x in env_keys:
+ outfile.write("setenv %s '%s'\n" % (x, env[x]))
+ outfile.close()
+
+ if sleep_for_mtime_granularity:
+ while current_time == long(time.time()):
+ time.sleep(1)