[gentoo-commits] proj/portage:master commit in: pym/portage/cache/
commit: d10bafb2c84be84ee47a2204938df4b3b9f238c0 Author: Zac Medico gentoo org> AuthorDate: Mon Sep 19 16:39:38 2016 + Commit: Zac Medico gentoo org> CommitDate: Mon Sep 19 16:41:56 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=d10bafb2 cache.fs_template: set 0o644 defaut perms Fixes 5652bc88514b ("flat_hash: use mkstemp in _setitem) X-Gentoo-Bug: 594358 X-Gentoo-Bug-URL: https://bugs.gentoo.org/594358 pym/portage/cache/fs_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pym/portage/cache/fs_template.py b/pym/portage/cache/fs_template.py index fa44abc..e3c3c12 100644 --- a/pym/portage/cache/fs_template.py +++ b/pym/portage/cache/fs_template.py @@ -24,7 +24,7 @@ class FsBased(template.database): def __init__(self, *args, **config): - for x, y in (("gid", -1), ("perms", -1)): + for x, y in (("gid", -1), ("perms", 0o644)): if x in config: # Since Python 3.4, chown requires int type (no proxies). setattr(self, "_" + x, int(config[x]))
[gentoo-commits] proj/portage:master commit in: pym/portage/cache/
commit: 5652bc88514bdb36b36b544f7fc7e623cf25caae Author: Zac Medico gentoo org> AuthorDate: Sun Jul 24 22:44:31 2016 + Commit: Zac Medico gentoo org> CommitDate: Sun Jul 24 23:10:01 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=5652bc88 flat_hash: use mkstemp in _setitem Fix the _setitem method to use mkstemp in order to avoid a race condition when multiple pid namespaces share the same cache directory. Reported-by: Mike Frysinger chromium.org> X-Chromium-Bug: 477727 X-Chromium-Bug-url: https://bugs.chromium.org/p/chromium/issues/detail?id=477727 pym/portage/cache/flat_hash.py | 49 +- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/pym/portage/cache/flat_hash.py b/pym/portage/cache/flat_hash.py index 3a899c0..7978324 100644 --- a/pym/portage/cache/flat_hash.py +++ b/pym/portage/cache/flat_hash.py @@ -1,4 +1,4 @@ -# Copyright 2005-2014 Gentoo Foundation +# Copyright 2005-2016 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # Author(s): Brian Harring (ferri...@gentoo.org) @@ -10,6 +10,7 @@ import errno import io import stat import sys +import tempfile import os as _os from portage import os from portage import _encodings @@ -66,27 +67,14 @@ class database(fs_template.FsBased): raise cache_errors.CacheCorruption(cpv, e) def _setitem(self, cpv, values): - s = cpv.rfind("/") - fp = os.path.join(self.location,cpv[:s],".update.%i.%s" % (os.getpid(), cpv[s+1:])) try: - myf = io.open(_unicode_encode(fp, - encoding=_encodings['fs'], errors='strict'), - mode='w', encoding=_encodings['repo.content'], - errors='backslashreplace') - except (IOError, OSError) as e: - if errno.ENOENT == e.errno: - try: - self._ensure_dirs(cpv) - myf = io.open(_unicode_encode(fp, - encoding=_encodings['fs'], errors='strict'), - mode='w', encoding=_encodings['repo.content'], - errors='backslashreplace') - except (OSError, IOError) as e: - raise cache_errors.CacheCorruption(cpv, e) - else: - raise cache_errors.CacheCorruption(cpv, e) + fd, fp = tempfile.mkstemp(dir=self.location) + except EnvironmentError as e: + raise cache_errors.CacheCorruption(cpv, e) - try: + with io.open(fd, mode='w', + encoding=_encodings['repo.content'], + errors='backslashreplace') as myf: for k in self._write_keys: v = values.get(k) if not v: @@ -95,8 +83,7 @@ class database(fs_template.FsBased): # k and v are coerced to unicode, in order to prevent TypeError # when writing raw bytes to TextIOWrapper with Python 2. myf.write("%s=%s\n" % (k, v)) - finally: - myf.close() + self._ensure_access(fp) #update written. now we move it. @@ -104,9 +91,21 @@ class database(fs_template.FsBased): new_fp = os.path.join(self.location,cpv) try: os.rename(fp, new_fp) - except (OSError, IOError) as e: - os.remove(fp) - raise cache_errors.CacheCorruption(cpv, e) + except EnvironmentError as e: + success = False + try: + if errno.ENOENT == e.errno: + try: + self._ensure_dirs(cpv) + os.rename(fp, new_fp) + success = True + except EnvironmentError as e: + raise cache_errors.CacheCorruption(cpv, e) + else: + raise cache_errors.CacheCorruption(cpv, e) + finally: + if not success: + os.remove(fp) def _delitem(self, cpv): # import pdb;pdb.set_trace()
[gentoo-commits] proj/portage:master commit in: pym/portage/cache/
commit: 9abbda7d054761ae6c333d3e6d420632b9658b6d Author: Zac Medico gentoo org> AuthorDate: Sun Jul 10 06:11:41 2016 + Commit: Zac Medico gentoo org> CommitDate: Wed Jul 13 11:29:34 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=9abbda7d portage.cache: write md5 instead of mtime (bug 568934) Change cache modules to write md5 in cache entries, instead of mtime. Since portage-2.2.27, the relevant cache modules have had the ability to read cache entries containing either md5 or mtime, therefore this change is backward-compatible with portage-2.2.27 and later. Also fix the reconstruct_eclasses function to raise CacheCorruption when the specified chf_type is md5 and the cache entry contains mtime data, and optimize __getitem__ to skip reconstruct_eclasses calls when the entry appears to have a different chf_type. X-Gentoo-Bug: 568934 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=568934 Acked-by: Alexander Berntsen gentoo.org> pym/portage/cache/anydbm.py| 4 ++-- pym/portage/cache/flat_hash.py | 4 ++-- pym/portage/cache/sqlite.py| 4 ++-- pym/portage/cache/template.py | 36 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/pym/portage/cache/anydbm.py b/pym/portage/cache/anydbm.py index 80d24e5..88d85b0 100644 --- a/pym/portage/cache/anydbm.py +++ b/pym/portage/cache/anydbm.py @@ -36,8 +36,8 @@ from portage.cache import cache_errors class database(fs_template.FsBased): - validation_chf = 'mtime' - chf_types = ('mtime', 'md5') + validation_chf = 'md5' + chf_types = ('md5', 'mtime') autocommits = True cleanse_keys = True diff --git a/pym/portage/cache/flat_hash.py b/pym/portage/cache/flat_hash.py index cca0f10..3a899c0 100644 --- a/pym/portage/cache/flat_hash.py +++ b/pym/portage/cache/flat_hash.py @@ -163,5 +163,5 @@ class md5_database(database): class mtime_md5_database(database): - validation_chf = 'mtime' - chf_types = ('mtime', 'md5') + validation_chf = 'md5' + chf_types = ('md5', 'mtime') diff --git a/pym/portage/cache/sqlite.py b/pym/portage/cache/sqlite.py index 32e4076..69150f6 100644 --- a/pym/portage/cache/sqlite.py +++ b/pym/portage/cache/sqlite.py @@ -18,8 +18,8 @@ if sys.hexversion >= 0x300: class database(fs_template.FsBased): - validation_chf = 'mtime' - chf_types = ('mtime', 'md5') + validation_chf = 'md5' + chf_types = ('md5', 'mtime') autocommits = False synchronous = False diff --git a/pym/portage/cache/template.py b/pym/portage/cache/template.py index a7c6de0..8662d85 100644 --- a/pym/portage/cache/template.py +++ b/pym/portage/cache/template.py @@ -54,6 +54,15 @@ class database(object): if self.serialize_eclasses and "_eclasses_" in d: for chf_type in chf_types: + if '_%s_' % chf_type not in d: + # Skip the reconstruct_eclasses call, since it's + # a waste of time if it contains a different chf_type + # than the current one. In the past, it was possible + # for reconstruct_eclasses called with chf_type='md5' + # to "successfully" return invalid data here, because + # it was unable to distinguish between md5 data and + # mtime data. + continue try: d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"], chf_type, paths=self.store_eclass_paths) @@ -62,6 +71,9 @@ class database(object): raise else: break + else: + raise cache_errors.CacheCorruption(cpv, + 'entry does not contain a recognized chf_type') elif "_eclasses_" not in d: d["_eclasses_"] = {} @@ -310,6 +322,23 @@ def serialize_eclasses(eclass_dict, chf_type='mtime', paths=True): for k, v in sorted(eclass_dict.items(), key=_keysorter)) +def _md5_deserializer(md5): + """ + Without this validation, it's possible for reconstruct_eclasses to + mistakenly interpret mtime data as md5 data, and return an invalid + data structure containing strings where ints are expected. + """ + if len(md5) != 32: + raise ValueError('expected 32 hex digits') + return md5 + + +_chf_deserializers = { + 'md5': _md5_deserializer, + 'mtime': long, +} + + def
[gentoo-commits] proj/portage:master commit in: pym/portage/cache/
commit: 7bef8d93aa79ad7a4001e30c74f7aa267ac95771 Author: Zac Medico gentoo org> AuthorDate: Thu Dec 24 11:19:32 2015 + Commit: Zac Medico gentoo org> CommitDate: Tue Dec 29 16:40:02 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=7bef8d93 sqlite: enable md5 validation (bug 568934) Add forward-compatibility for cache entries containing md5 digests instead of mtimes for validation. X-Gentoo-Bug: 568934 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=568934 Acked-by: Alexander Berntsen gentoo.org> pym/portage/cache/sqlite.py | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pym/portage/cache/sqlite.py b/pym/portage/cache/sqlite.py index 310ac94..32e4076 100644 --- a/pym/portage/cache/sqlite.py +++ b/pym/portage/cache/sqlite.py @@ -18,6 +18,9 @@ if sys.hexversion >= 0x300: class database(fs_template.FsBased): + validation_chf = 'mtime' + chf_types = ('mtime', 'md5') + autocommits = False synchronous = False # cache_bytes is used together with page_size (set at sqlite build time) @@ -28,10 +31,12 @@ class database(fs_template.FsBased): def __init__(self, *args, **config): super(database, self).__init__(*args, **config) self._import_sqlite() - self._allowed_keys = ["_mtime_", "_eclasses_"] + self._allowed_keys = ["_eclasses_"] self._allowed_keys.extend(self._known_keys) - self._allowed_keys.sort() + self._allowed_keys.extend('_%s_' % k for k in self.chf_types) self._allowed_keys_set = frozenset(self._allowed_keys) + self._allowed_keys = sorted(self._allowed_keys_set) + self.location = os.path.join(self.location, self.label.lstrip(os.path.sep).rstrip(os.path.sep))
[gentoo-commits] proj/portage:master commit in: pym/portage/cache/
commit: 6c09ab7d6c6b2ffcf7e2641874167b0bff12ff91 Author: Zac Medico gentoo org> AuthorDate: Thu Dec 24 11:08:54 2015 + Commit: Zac Medico gentoo org> CommitDate: Tue Dec 29 16:39:57 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=6c09ab7d template.database.__getitem__: allow missing mtime (bug 568934) Fix __getitem__ to allow missing mtime when a suitable alternative (such as md5) is available. Fixes: 669d11bd8af5 ("flat_hash: enable md5 validation for /var/cache/edb/dep (bug 568934)") Acked-by: Alexander Berntsen gentoo.org> pym/portage/cache/template.py | 36 ++-- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/pym/portage/cache/template.py b/pym/portage/cache/template.py index a942b36..a7c6de0 100644 --- a/pym/portage/cache/template.py +++ b/pym/portage/cache/template.py @@ -46,12 +46,13 @@ class database(object): self.commit() self.updates = 0 d=self._getitem(cpv) - if self.serialize_eclasses and "_eclasses_" in d: - try: - chf_types = self.chf_types - except AttributeError: - chf_types = (self.validation_chf,) + try: + chf_types = self.chf_types + except AttributeError: + chf_types = (self.validation_chf,) + + if self.serialize_eclasses and "_eclasses_" in d: for chf_type in chf_types: try: d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"], @@ -69,16 +70,23 @@ class database(object): # to omit it in comparisons between cache entries like # those that egencache uses to avoid redundant writes. d.pop("INHERITED", None) + + mtime_required = not any(d.get('_%s_' % x) + for x in chf_types if x != 'mtime') + mtime = d.get('_mtime_') - if mtime is None: - raise cache_errors.CacheCorruption(cpv, - '_mtime_ field is missing') - try: - mtime = long(mtime) - except ValueError: - raise cache_errors.CacheCorruption(cpv, - '_mtime_ conversion to long failed: %s' % (mtime,)) - d['_mtime_'] = mtime + if not mtime: + if mtime_required: + raise cache_errors.CacheCorruption(cpv, + '_mtime_ field is missing') + d.pop('_mtime_', None) + else: + try: + mtime = long(mtime) + except ValueError: + raise cache_errors.CacheCorruption(cpv, + '_mtime_ conversion to long failed: %s' % (mtime,)) + d['_mtime_'] = mtime return d def _getitem(self, cpv):
[gentoo-commits] proj/portage:master commit in: pym/portage/cache/
commit: 7e663905063ca92ad82127a797356e35bfc5bdfa Author: Zac Medico gentoo org> AuthorDate: Fri Dec 25 05:56:18 2015 + Commit: Zac Medico gentoo org> CommitDate: Tue Dec 29 16:40:04 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=7e663905 anydbm: enable md5 validation (bug 568934) Add forward-compatibility for cache entries containing md5 digests instead of mtimes for validation. X-Gentoo-Bug: 568934 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=568934 Acked-by: Alexander Berntsen gentoo.org> pym/portage/cache/anydbm.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pym/portage/cache/anydbm.py b/pym/portage/cache/anydbm.py index 1d56b14..80d24e5 100644 --- a/pym/portage/cache/anydbm.py +++ b/pym/portage/cache/anydbm.py @@ -36,6 +36,9 @@ from portage.cache import cache_errors class database(fs_template.FsBased): + validation_chf = 'mtime' + chf_types = ('mtime', 'md5') + autocommits = True cleanse_keys = True serialize_eclasses = False
[gentoo-commits] proj/portage:master commit in: pym/portage/cache/, pym/portage/package/ebuild/
commit: 669d11bd8af5a2bd4cca1710a09c94294ad1e4dd Author: Zac Medico gentoo org> AuthorDate: Mon Dec 21 07:59:55 2015 + Commit: Zac Medico gentoo org> CommitDate: Tue Dec 22 17:34:32 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=669d11bd flat_hash: enable md5 validation for /var/cache/edb/dep (bug 568934) Since operations like `git reset --hard` (useful to implement shallow pull) will reset timestamps of all files in the tree, the status quo of using timestamps for validation of cache in /var/cache/edb/dep is sub-optimal. For forward-compatibility, add a flat_hash.mtime_md5_database cache module which is capable of validating cache entries containing either mtimes or md5 digests. Update the config class to use this cache module by default for /var/cache/edb/dep. X-Gentoo-Bug: 568934 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=568934 Acked-by: Alexander Berntsen gentoo.org> pym/portage/cache/flat_hash.py | 5 + pym/portage/cache/template.py| 35 ++- pym/portage/package/ebuild/config.py | 6 +++--- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/pym/portage/cache/flat_hash.py b/pym/portage/cache/flat_hash.py index 5304296..cca0f10 100644 --- a/pym/portage/cache/flat_hash.py +++ b/pym/portage/cache/flat_hash.py @@ -160,3 +160,8 @@ class md5_database(database): validation_chf = 'md5' store_eclass_paths = False + + +class mtime_md5_database(database): + validation_chf = 'mtime' + chf_types = ('mtime', 'md5') diff --git a/pym/portage/cache/template.py b/pym/portage/cache/template.py index bc81b86..a942b36 100644 --- a/pym/portage/cache/template.py +++ b/pym/portage/cache/template.py @@ -47,8 +47,21 @@ class database(object): self.updates = 0 d=self._getitem(cpv) if self.serialize_eclasses and "_eclasses_" in d: - d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"], - self.validation_chf, paths=self.store_eclass_paths) + try: + chf_types = self.chf_types + except AttributeError: + chf_types = (self.validation_chf,) + + for chf_type in chf_types: + try: + d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"], + chf_type, paths=self.store_eclass_paths) + except cache_errors.CacheCorruption: + if chf_type is chf_types[-1]: + raise + else: + break + elif "_eclasses_" not in d: d["_eclasses_"] = {} # Never return INHERITED, since portdbapi.aux_get() will @@ -204,15 +217,27 @@ class database(object): return x def validate_entry(self, entry, ebuild_hash, eclass_db): - hash_key = '_%s_' % self.validation_chf + try: + chf_types = self.chf_types + except AttributeError: + chf_types = (self.validation_chf,) + + for chf_type in chf_types: + if self._validate_entry(chf_type, entry, ebuild_hash, eclass_db): + return True + + return False + + def _validate_entry(self, chf_type, entry, ebuild_hash, eclass_db): + hash_key = '_%s_' % chf_type try: entry_hash = entry[hash_key] except KeyError: return False else: - if entry_hash != getattr(ebuild_hash, self.validation_chf): + if entry_hash != getattr(ebuild_hash, chf_type): return False - update = eclass_db.validate_and_rewrite_cache(entry['_eclasses_'], self.validation_chf, + update = eclass_db.validate_and_rewrite_cache(entry['_eclasses_'], chf_type, self.store_eclass_paths) if update is None: return False diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index d45c2a0..0bae55b 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -160,8 +160,8 @@ class config(object): 'repository', 'RESTRICT', 'LICENSE',) _module_aliases = { - "cache.metadata_overlay.database" : "portage.cache.flat_hash.database", - "portage.cache.metadata_overlay.database" : "portage.cache.flat_hash.database", +
[gentoo-commits] proj/portage:master commit in: pym/portage/cache/
commit: 9f6967dbc38ea55c0de5fbf5ad663ca676c54743 Author: Zac Medico zmedico AT gentoo DOT org AuthorDate: Thu Nov 13 19:35:48 2014 + Commit: Zac Medico zmedico AT gentoo DOT org CommitDate: Fri Nov 14 17:30:31 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=9f6967db fs_template._ensure_dirs: handle EEXIST (529120) There was a race inside fs_template._ensure_dirs which could cause it to raise EEXIST if a concurrent process created the directory after os.path.exists returned False. Fix it by using the util.ensure_dirs function, which already handles EEXIST. X-Gentoo-Bug: 529120 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=529120 Acked-by: Alexander Berntsen bernalex AT gentoo.org --- pym/portage/cache/fs_template.py | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/pym/portage/cache/fs_template.py b/pym/portage/cache/fs_template.py index de4fe4b..fa44abc 100644 --- a/pym/portage/cache/fs_template.py +++ b/pym/portage/cache/fs_template.py @@ -10,7 +10,7 @@ from portage import os from portage.proxy.lazyimport import lazyimport lazyimport(globals(), 'portage.exception:PortageException', - 'portage.util:apply_permissions', + 'portage.util:apply_permissions,ensure_dirs', ) del lazyimport @@ -61,20 +61,15 @@ class FsBased(template.database): for dir in path.lstrip(os.path.sep).rstrip(os.path.sep).split(os.path.sep): base = os.path.join(base,dir) - if not os.path.exists(base): - if self._perms != -1: - um = os.umask(0) - try: - perms = self._perms - if perms == -1: - perms = 0 - perms |= 0o755 - os.mkdir(base, perms) - if self._gid != -1: - os.chown(base, -1, self._gid) - finally: - if self._perms != -1: - os.umask(um) + if ensure_dirs(base): + # We only call apply_permissions if ensure_dirs created + # a new directory, so as not to interfere with + # permissions of existing directories. + mode = self._perms + if mode == -1: + mode = 0 + mode |= 0o755 + apply_permissions(base, mode=mode, gid=self._gid) def _prune_empty_dirs(self): all_dirs = []