* [gentoo-commits] proj/portage:master commit in: pym/portage/, bin/
@ 2014-11-03 4:42 Zac Medico
0 siblings, 0 replies; 3+ messages in thread
From: Zac Medico @ 2014-11-03 4:42 UTC (permalink / raw
To: gentoo-commits
commit: f17448317166bfac42dc279b8795cd581c189582
Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sun Oct 26 09:49:02 2014 +0000
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sun Nov 2 23:19:46 2014 +0000
URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=f1744831
dispatch-conf: symlink support for bug #485598
This includes numerous logic adjustments that are needed to support
protected symlinks. The new diff_mixed function is used for diffs
between arbitrary file types. For example, a diff between two symlinks
looks like this:
-SYM: /foo/bar -> baz
+SYM: /foo/bar -> blah
X-Gentoo-Bug: 485598
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=485598
---
bin/dispatch-conf | 45 ++++++++-----
pym/portage/dispatch_conf.py | 157 +++++++++++++++++++++++++++++++++++++------
2 files changed, 164 insertions(+), 38 deletions(-)
diff --git a/bin/dispatch-conf b/bin/dispatch-conf
index 6d2ae94..8058d6f 100755
--- a/bin/dispatch-conf
+++ b/bin/dispatch-conf
@@ -13,17 +13,23 @@
from __future__ import print_function
+import atexit
+import io
+import re
+import shutil
+import sys
+
from stat import ST_GID, ST_MODE, ST_UID
from random import random
-import atexit, re, shutil, stat, sys
+
from os import path as osp
if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")):
sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
import portage
portage._internal_caller = True
from portage import os
-from portage import _unicode_decode
-from portage.dispatch_conf import diffstatusoutput
+from portage import _encodings, _unicode_decode
+from portage.dispatch_conf import diffstatusoutput, diff_mixed_wrapper
from portage.process import find_binary, spawn
FIND_EXTANT_CONFIGS = "find '%s' %s -name '._cfg????_%s' ! -name '.*~' ! -iname '.*.bak' -print"
@@ -72,6 +78,8 @@ def cmd_var_is_valid(cmd):
return find_binary(cmd[0]) is not None
+diff = diff_mixed_wrapper(diffstatusoutput, DIFF_CONTENTS)
+
class dispatch:
options = {}
@@ -89,8 +97,6 @@ class dispatch:
or not os.path.exists(self.options["log-file"]):
open(self.options["log-file"], 'w').close() # Truncate it
os.chmod(self.options["log-file"], 0o600)
- else:
- self.options["log-file"] = "/dev/null"
pager = self.options.get("pager")
if pager is None or not cmd_var_is_valid(pager):
@@ -148,9 +154,6 @@ class dispatch:
portage.util.shlex_split(
portage.settings.get('CONFIG_PROTECT_MASK', '')))
- def diff(file1, file2):
- return diffstatusoutput(DIFF_CONTENTS, file1, file2)
-
#
# Remove new configs identical to current
# and
@@ -166,7 +169,7 @@ class dispatch:
mrgfail = portage.dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf)
else:
mrgfail = portage.dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
- if os.path.exists(archive + '.dist'):
+ if os.path.lexists(archive + '.dist'):
unmodified = len(diff(conf['current'], archive + '.dist')[1]) == 0
else:
unmodified = 0
@@ -181,7 +184,7 @@ class dispatch:
if newconf == mrgconf and \
self.options.get('ignore-previously-merged') != 'yes' and \
- os.path.exists(archive+'.dist') and \
+ os.path.lexists(archive+'.dist') and \
len(diff(archive+'.dist', conf['new'])[1]) == 0:
# The current update is identical to the archived .dist
# version that has previously been merged.
@@ -254,6 +257,13 @@ class dispatch:
valid_input = "qhtnmlezu"
+ def diff_pager(file1, file2):
+ cmd = self.options['diff'] % (file1, file2)
+ cmd += pager
+ spawn_shell(cmd)
+
+ diff_pager = diff_mixed_wrapper(diff_pager)
+
for conf in confs:
count = count + 1
@@ -266,14 +276,10 @@ class dispatch:
while 1:
clear_screen()
if show_new_diff:
- cmd = self.options['diff'] % (conf['new'], mrgconf)
- cmd += pager
- spawn_shell(cmd)
+ diff_pager(conf['new'], mrgconf)
show_new_diff = 0
else:
- cmd = self.options['diff'] % (conf['current'], newconf)
- cmd += pager
- spawn_shell(cmd)
+ diff_pager(conf['current'], newconf)
print()
print('>> (%i of %i) -- %s' % (count, len(confs), conf ['current']))
@@ -357,7 +363,12 @@ class dispatch:
def replace (self, newconf, curconf):
"""Replace current config with the new/merged version. Also logs
the diff of what changed into the configured log file."""
- os.system((DIFF_CONTENTS % (curconf, newconf)) + '>>' + self.options["log-file"])
+ if "log-file" in self.options:
+ status, output = diff(curconf, newconf)
+ with io.open(self.options["log-file"], mode="a",
+ encoding=_encodings["stdio"]) as f:
+ f.write(output + "\n")
+
try:
os.rename(newconf, curconf)
except (IOError, os.error) as why:
diff --git a/pym/portage/dispatch_conf.py b/pym/portage/dispatch_conf.py
index 113d965..b27e68b 100644
--- a/pym/portage/dispatch_conf.py
+++ b/pym/portage/dispatch_conf.py
@@ -6,11 +6,19 @@
# Library by Wayne Davison <gentoo@blorf.net>, derived from code
# written by Jeremy Wohl (http://igmus.org)
-from __future__ import print_function
+from __future__ import print_function, unicode_literals
-import os, shutil, subprocess, sys
+import io
+import functools
+import os
+import shutil
+import stat
+import subprocess
+import sys
+import tempfile
import portage
+from portage import _encodings
from portage.env.loaders import KeyValuePairFileLoader
from portage.localization import _
from portage.util import shlex_split, varexpand
@@ -50,6 +58,66 @@ def diffstatusoutput(cmd, file1, file2):
output = output[:-1]
return (proc.wait(), output)
+def diff_mixed(func, file1, file2):
+ tempdir = None
+ try:
+ if os.path.islink(file1) and \
+ not os.path.islink(file2) and \
+ os.path.isfile(file1) and \
+ os.path.isfile(file2):
+ # If a regular file replaces a symlink to a regular
+ # file, then show the diff between the regular files
+ # (bug #330221).
+ diff_files = (file2, file2)
+ else:
+ files = [file1, file2]
+ diff_files = [file1, file2]
+ for i in range(len(diff_files)):
+ try:
+ st = os.lstat(diff_files[i])
+ except OSError:
+ st = None
+ if st is not None and stat.S_ISREG(st.st_mode):
+ continue
+
+ if tempdir is None:
+ tempdir = tempfile.mkdtemp()
+ diff_files[i] = os.path.join(tempdir, "%d" % i)
+ if st is None:
+ content = "/dev/null\n"
+ elif stat.S_ISLNK(st.st_mode):
+ link_dest = os.readlink(files[i])
+ content = "SYM: %s -> %s\n" % \
+ (file1, link_dest)
+ elif stat.S_ISDIR(st.st_mode):
+ content = "DIR: %s\n" % (file1,)
+ elif stat.S_ISFIFO(st.st_mode):
+ content = "FIF: %s\n" % (file1,)
+ else:
+ content = "DEV: %s\n" % (file1,)
+ with io.open(diff_files[i], mode='w',
+ encoding=_encodings['stdio']) as f:
+ f.write(content)
+
+ return func(diff_files[0], diff_files[1])
+
+ finally:
+ if tempdir is not None:
+ shutil.rmtree(tempdir)
+
+class diff_mixed_wrapper(object):
+
+ def __init__(self, f, *args):
+ self._func = f
+ self._args = args
+
+ def __call__(self, *args):
+ return diff_mixed(
+ functools.partial(self._func, *(self._args + args[:-2])),
+ *args[-2:])
+
+diffstatusoutput_mixed = diff_mixed_wrapper(diffstatusoutput)
+
def read_config(mandatory_opts):
eprefix = portage.settings["EPREFIX"]
if portage._not_installed:
@@ -103,35 +171,57 @@ def rcs_archive(archive, curconf, newconf, mrgconf):
except OSError:
pass
- if os.path.isfile(curconf):
+ try:
+ curconf_st = os.lstat(curconf)
+ except OSError:
+ curconf_st = None
+
+ if curconf_st is not None and \
+ (stat.S_ISREG(curconf_st.st_mode) or
+ stat.S_ISLNK(curconf_st.st_mode)):
try:
- shutil.copy2(curconf, archive)
+ if stat.S_ISLNK(curconf_st.st_mode):
+ os.symlink(os.readlink(curconf), archive)
+ else:
+ shutil.copy2(curconf, archive)
except(IOError, os.error) as why:
print(_('dispatch-conf: Error copying %(curconf)s to %(archive)s: %(reason)s; fatal') % \
{"curconf": curconf, "archive": archive, "reason": str(why)}, file=sys.stderr)
- if os.path.exists(archive + ',v'):
+ if os.path.lexists(archive + ',v'):
os.system(RCS_LOCK + ' ' + archive)
os.system(RCS_PUT + ' ' + archive)
ret = 0
- if newconf != '':
+ mystat = None
+ if newconf:
+ try:
+ mystat = os.lstat(newconf)
+ except OSError:
+ pass
+
+ if mystat is not None and \
+ (stat.S_ISREG(mystat.st_mode) or
+ stat.S_ISLNK(mystat.st_mode)):
os.system(RCS_GET + ' -r' + RCS_BRANCH + ' ' + archive)
- has_branch = os.path.exists(archive)
+ has_branch = os.path.lexists(archive)
if has_branch:
os.rename(archive, archive + '.dist')
try:
- shutil.copy2(newconf, archive)
+ if stat.S_ISLNK(mystat.st_mode):
+ os.symlink(os.readlink(newconf), archive)
+ else:
+ shutil.copy2(newconf, archive)
except(IOError, os.error) as why:
print(_('dispatch-conf: Error copying %(newconf)s to %(archive)s: %(reason)s; fatal') % \
{"newconf": newconf, "archive": archive, "reason": str(why)}, file=sys.stderr)
if has_branch:
- if mrgconf != '':
+ if mrgconf and os.path.isfile(archive) and \
+ os.path.isfile(mrgconf):
# This puts the results of the merge into mrgconf.
ret = os.system(RCS_MERGE % (archive, mrgconf))
- mystat = os.lstat(newconf)
os.chmod(mrgconf, mystat.st_mode)
os.chown(mrgconf, mystat.st_uid, mystat.st_gid)
os.rename(archive, archive + '.dist.new')
@@ -153,10 +243,11 @@ def file_archive(archive, curconf, newconf, mrgconf):
pass
# Archive the current config file if it isn't already saved
- if (os.path.exists(archive) and
- len(diffstatusoutput("diff -aq '%s' '%s'", curconf, archive)[1]) != 0):
+ if (os.path.lexists(archive) and
+ len(diffstatusoutput_mixed(
+ "diff -aq '%s' '%s'", curconf, archive)[1]) != 0):
suf = 1
- while suf < 9 and os.path.exists(archive + '.' + str(suf)):
+ while suf < 9 and os.path.lexists(archive + '.' + str(suf)):
suf += 1
while suf > 1:
@@ -165,26 +256,50 @@ def file_archive(archive, curconf, newconf, mrgconf):
os.rename(archive, archive + '.1')
- if os.path.isfile(curconf):
+ try:
+ curconf_st = os.lstat(curconf)
+ except OSError:
+ curconf_st = None
+
+ if curconf_st is not None and \
+ (stat.S_ISREG(curconf_st.st_mode) or
+ stat.S_ISLNK(curconf_st.st_mode)):
try:
- shutil.copy2(curconf, archive)
+ if stat.S_ISLNK(curconf_st.st_mode):
+ os.symlink(os.readlink(curconf), archive)
+ else:
+ shutil.copy2(curconf, archive)
except(IOError, os.error) as why:
print(_('dispatch-conf: Error copying %(curconf)s to %(archive)s: %(reason)s; fatal') % \
{"curconf": curconf, "archive": archive, "reason": str(why)}, file=sys.stderr)
- if newconf != '':
+ mystat = None
+ if newconf:
+ try:
+ mystat = os.lstat(newconf)
+ except OSError:
+ pass
+
+ if mystat is not None and \
+ (stat.S_ISREG(mystat.st_mode) or
+ stat.S_ISLNK(mystat.st_mode)):
# Save off new config file in the archive dir with .dist.new suffix
+ newconf_archive = archive + '.dist.new'
try:
- shutil.copy2(newconf, archive + '.dist.new')
+ if stat.S_ISLNK(mystat.st_mode):
+ os.symlink(os.readlink(newconf), newconf_archive)
+ else:
+ shutil.copy2(newconf, newconf_archive)
except(IOError, os.error) as why:
print(_('dispatch-conf: Error copying %(newconf)s to %(archive)s: %(reason)s; fatal') % \
{"newconf": newconf, "archive": archive + '.dist.new', "reason": str(why)}, file=sys.stderr)
ret = 0
- if mrgconf != '' and os.path.exists(archive + '.dist'):
+ if mrgconf and os.path.isfile(curconf) and \
+ os.path.isfile(newconf) and \
+ os.path.isfile(archive + '.dist'):
# This puts the results of the merge into mrgconf.
ret = os.system(DIFF3_MERGE % (curconf, archive + '.dist', newconf, mrgconf))
- mystat = os.lstat(newconf)
os.chmod(mrgconf, mystat.st_mode)
os.chown(mrgconf, mystat.st_uid, mystat.st_gid)
@@ -195,7 +310,7 @@ def rcs_archive_post_process(archive):
"""Check in the archive file with the .dist.new suffix on the branch
and remove the one with the .dist suffix."""
os.rename(archive + '.dist.new', archive)
- if os.path.exists(archive + '.dist'):
+ if os.path.lexists(archive + '.dist'):
# Commit the last-distributed version onto the branch.
os.system(RCS_LOCK + RCS_BRANCH + ' ' + archive)
os.system(RCS_PUT + ' -r' + RCS_BRANCH + ' ' + archive)
@@ -207,5 +322,5 @@ def rcs_archive_post_process(archive):
def file_archive_post_process(archive):
"""Rename the archive file with the .dist.new suffix to a .dist suffix"""
- if os.path.exists(archive + '.dist.new'):
+ if os.path.lexists(archive + '.dist.new'):
os.rename(archive + '.dist.new', archive + '.dist')
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [gentoo-commits] proj/portage:master commit in: pym/portage/, bin/
@ 2015-04-02 19:15 Zac Medico
0 siblings, 0 replies; 3+ messages in thread
From: Zac Medico @ 2015-04-02 19:15 UTC (permalink / raw
To: gentoo-commits
commit: f9a2d7025e22f5e1711f39c4740a020f6f0d2c8f
Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Wed Apr 1 22:27:42 2015 +0000
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Wed Apr 1 23:14:52 2015 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=f9a2d702
dispatch-conf: fix unicode handling (bug 545270)
This avoids UnicodeDecodeError problems by using UTF-8 encoding
regardless of the locale.
X-Gentoo-Bug: 545270
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=545270
bin/dispatch-conf | 9 +++++----
pym/portage/dispatch_conf.py | 4 +---
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/bin/dispatch-conf b/bin/dispatch-conf
index b679910..678a66d 100755
--- a/bin/dispatch-conf
+++ b/bin/dispatch-conf
@@ -11,12 +11,11 @@
# dialog menus
#
-from __future__ import print_function
+from __future__ import print_function, unicode_literals
import atexit
import io
import re
-import shutil
import sys
from stat import ST_GID, ST_MODE, ST_UID
@@ -27,7 +26,7 @@ if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".porta
sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
import portage
portage._internal_caller = True
-from portage import os
+from portage import os, shutil
from portage import _encodings, _unicode_decode
from portage.dispatch_conf import diffstatusoutput, diff_mixed_wrapper
from portage.process import find_binary, spawn
@@ -403,7 +402,9 @@ class dispatch:
newconfigs.sort ()
for nconf in newconfigs:
- nconf = nconf.rstrip ()
+ # Use strict mode here, because we want to know if it fails,
+ # and portage only merges files with valid UTF-8 encoding.
+ nconf = _unicode_decode(nconf, errors='strict').rstrip()
conf = re.sub (r'\._cfg\d+_', '', nconf)
dirname = os.path.dirname(nconf)
conf_map = {
diff --git a/pym/portage/dispatch_conf.py b/pym/portage/dispatch_conf.py
index 790eacb..98939fd 100644
--- a/pym/portage/dispatch_conf.py
+++ b/pym/portage/dispatch_conf.py
@@ -10,15 +10,13 @@ from __future__ import print_function, unicode_literals
import io
import functools
-import os
-import shutil
import stat
import subprocess
import sys
import tempfile
import portage
-from portage import _encodings
+from portage import _encodings, os, shutil
from portage.env.loaders import KeyValuePairFileLoader
from portage.localization import _
from portage.util import shlex_split, varexpand
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [gentoo-commits] proj/portage:master commit in: pym/portage/, bin/
@ 2018-02-22 17:32 Zac Medico
0 siblings, 0 replies; 3+ messages in thread
From: Zac Medico @ 2018-02-22 17:32 UTC (permalink / raw
To: gentoo-commits
commit: c01fdd27473a76d1c8b6edb1b9dfb2c29645b1c2
Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Thu Feb 22 02:44:06 2018 +0000
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Thu Feb 22 17:30:27 2018 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=c01fdd27
emerge/ebuild: sanitize file descriptors on startup
In order to ensure that any unintentionally inherited file descriptors
will not be inherited by child processes, set the inheritable flag to
False on startup, except for those corresponding to stdin, stdout, and
stderr. This mitigates potential problems that might result from
making the portage.process.spawn close_fds parameter default to False
for versions of python with PEP 446 support.
Bug: https://bugs.gentoo.org/648432
bin/ebuild | 2 ++
bin/emerge | 1 +
pym/portage/process.py | 24 ++++++++++++++++++++++++
3 files changed, 27 insertions(+)
diff --git a/bin/ebuild b/bin/ebuild
index bda746f78..b1ef0573b 100755
--- a/bin/ebuild
+++ b/bin/ebuild
@@ -58,6 +58,8 @@ import portage.util
from _emerge.Package import Package
from _emerge.RootConfig import RootConfig
+portage.process.sanitize_fds()
+
description = "See the ebuild(1) man page for more info"
usage = "Usage: ebuild <ebuild file> <command> [command] ..."
parser = argparse.ArgumentParser(description=description, usage=usage)
diff --git a/bin/emerge b/bin/emerge
index 43cfdcddb..5f08861e5 100755
--- a/bin/emerge
+++ b/bin/emerge
@@ -46,6 +46,7 @@ try:
if __name__ == "__main__":
from portage.exception import IsADirectory, ParseError, \
PermissionDenied
+ portage.process.sanitize_fds()
try:
retval = emerge_main()
except PermissionDenied as e:
diff --git a/pym/portage/process.py b/pym/portage/process.py
index 4d96f156e..2af783e22 100644
--- a/pym/portage/process.py
+++ b/pym/portage/process.py
@@ -91,6 +91,30 @@ sandbox_capable = (os.path.isfile(SANDBOX_BINARY) and
fakeroot_capable = (os.path.isfile(FAKEROOT_BINARY) and
os.access(FAKEROOT_BINARY, os.X_OK))
+
+def sanitize_fds():
+ """
+ Set the inheritable flag to False for all open file descriptors,
+ except for those corresponding to stdin, stdout, and stderr. This
+ ensures that any unintentionally inherited file descriptors will
+ not be inherited by child processes.
+ """
+ if _set_inheritable is not None:
+
+ whitelist = frozenset([
+ sys.__stdin__.fileno(),
+ sys.__stdout__.fileno(),
+ sys.__stderr__.fileno(),
+ ])
+
+ for fd in get_open_fds():
+ if fd not in whitelist:
+ try:
+ _set_inheritable(fd, False)
+ except OSError:
+ pass
+
+
def spawn_bash(mycommand, debug=False, opt_name=None, **keywords):
"""
Spawns a bash shell running a specific commands
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-02-22 17:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-02 19:15 [gentoo-commits] proj/portage:master commit in: pym/portage/, bin/ Zac Medico
-- strict thread matches above, loose matches on Subject: below --
2018-02-22 17:32 Zac Medico
2014-11-03 4:42 Zac Medico
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox