Gentoo Archives: gentoo-portage-dev

From: Brian Dolbec <dolsen@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH v3] ro_checker: only check nearest parent (bug 547390)
Date: Tue, 28 Apr 2015 20:48:57
Message-Id: 20150428134852.481b1d7d.dolsen@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH v3] ro_checker: only check nearest parent (bug 547390) by Zac Medico
1 On Sun, 26 Apr 2015 21:30:28 -0700
2 Zac Medico <zmedico@g.o> wrote:
3
4 > The ro_checker code added in commit
5 > 47ef9a0969474f963dc8e52bfbbb8bc075e8d73c incorrectly asserts that all
6 > parent directories be writable. Fix it to only assert that the nearest
7 > parent directory be writable.
8 >
9 > Fixes 47ef9a096947: ("Test for read-only filesystems, fixes bug
10 > 378869") X-Gentoo-Bug: 547390
11 > X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=547390
12 > ---
13 > [PATCH v3] fixes writeable_check to return paths from mountinfo
14 >
15 > pym/portage/dbapi/vartree.py | 44
16 > +++++++++++++++++++++----------------
17 > pym/portage/util/writeable_check.py | 24 ++++++++++++++++++-- 2 files
18 > changed, 47 insertions(+), 21 deletions(-)
19 >
20 > diff --git a/pym/portage/dbapi/vartree.py
21 > b/pym/portage/dbapi/vartree.py index 1c0deab..c59d778 100644
22 > --- a/pym/portage/dbapi/vartree.py
23 > +++ b/pym/portage/dbapi/vartree.py
24 > @@ -33,7 +33,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
25 > 'portage.util.env_update:env_update',
26 > 'portage.util.listdir:dircache,listdir',
27 > 'portage.util.movefile:movefile',
28 > - 'portage.util.path:first_existing',
29 > + 'portage.util.path:first_existing,iter_parents',
30 > 'portage.util.writeable_check:get_ro_checker',
31 > 'portage.util._dyn_libs.PreservedLibsRegistry:PreservedLibsRegistry',
32 > 'portage.util._dyn_libs.LinkageMapELF:LinkageMapELF@LinkageMap',
33 > @@ -3325,6 +3325,8 @@ class dblink(object):
34 > showMessage = self._display_merge
35 > stopmerge = False
36 > collisions = []
37 > + dirs = set()
38 > + dirs_ro = set()
39 > symlink_collisions = []
40 > destroot = self.settings['ROOT']
41 > showMessage(_(" %s checking %d files for
42 > package collisions\n") % \ @@ -3337,6 +3339,18 @@ class
43 > dblink(object):
44 > dest_path = normalize_path(
45 > os.path.join(destroot,
46 > f.lstrip(os.path.sep))) +
47 > + parent = os.path.dirname(dest_path)
48 > + if parent not in dirs:
49 > + for x in
50 > iter_parents(parent):
51 > + if x in dirs:
52 > + break
53 > + dirs.add(x)
54 > + if os.path.isdir(x):
55 > + if not
56 > os.access(x, os.W_OK):
57 > +
58 > dirs_ro.add(x)
59 > + break
60 > +
61 > try:
62 > dest_lstat =
63 > os.lstat(dest_path) except EnvironmentError as e:
64 > @@ -3410,7 +3424,7 @@ class dblink(object):
65 > break
66 > if stopmerge:
67 > collisions.append(f)
68 > - return collisions, symlink_collisions,
69 > plib_collisions
70 > + return collisions, dirs_ro,
71 > symlink_collisions, plib_collisions
72 > def _lstat_inode_map(self, path_iter):
73 > """
74 > @@ -3759,7 +3773,6 @@ class dblink(object):
75 > eagain_error = False
76 >
77 > filelist = []
78 > - dirlist = []
79 > linklist = []
80 > paths_with_newlines = []
81 > def onerror(e):
82 > @@ -3792,13 +3805,6 @@ class dblink(object):
83 > unicode_errors.append(new_parent[ed_len:])
84 > break
85 >
86 > - relative_path = parent[srcroot_len:]
87 > - if len(relative_path) >= eprefix_len:
88 > - # Files are never installed
89 > outside of the prefix,
90 > - # therefore we skip the
91 > readonly filesystem check for
92 > - # parent directories of the
93 > prefix (see bug 544624).
94 > -
95 > dirlist.append(os.path.join(destroot, relative_path)) -
96 > for fname in files:
97 > try:
98 > fname =
99 > _unicode_decode(fname, @@ -3911,9 +3917,17 @@ class dblink(object):
100 > for other in others_in_slot])
101 > prepare_build_dirs(settings=self.settings,
102 > cleanup=cleanup)
103 > + # check for package collisions
104 > + blockers = self._blockers
105 > + if blockers is None:
106 > + blockers = []
107 > + collisions, dirs_ro, symlink_collisions,
108 > plib_collisions = \
109 > + self._collision_protect(srcroot, destroot,
110 > + others_in_slot + blockers, filelist,
111 > linklist) +
112 > # Check for read-only filesystems.
113 > ro_checker = get_ro_checker()
114 > - rofilesystems = ro_checker(dirlist)
115 > + rofilesystems = ro_checker(dirs_ro)
116 >
117 > if rofilesystems:
118 > msg = _("One or more files installed to this
119 > package are " @@ -3935,14 +3949,6 @@ class dblink(object):
120 > eerror(msg)
121 > return 1
122 >
123 > - # check for package collisions
124 > - blockers = self._blockers
125 > - if blockers is None:
126 > - blockers = []
127 > - collisions, symlink_collisions, plib_collisions = \
128 > - self._collision_protect(srcroot, destroot,
129 > - others_in_slot + blockers, filelist,
130 > linklist) -
131 > if symlink_collisions:
132 > # Symlink collisions need to be
133 > distinguished from other types # of collisions, in order to avoid
134 > confusion (see bug #409359). diff --git
135 > a/pym/portage/util/writeable_check.py
136 > b/pym/portage/util/writeable_check.py index 445b2c2..ac6c039 100644
137 > --- a/pym/portage/util/writeable_check.py +++
138 > b/pym/portage/util/writeable_check.py @@ -1,5 +1,5 @@
139 > #-*- coding:utf-8 -*-
140 > -# Copyright 2014 Gentoo Foundation
141 > +# Copyright 2014-2015 Gentoo Foundation
142 > # Distributed under the terms of the GNU General Public License v2
143 > """
144 > Methods to check whether Portage is going to write to read-only
145 > filesystems. @@ -13,6 +13,7 @@ from __future__ import unicode_literals
146 >
147 > import io
148 > import logging
149 > +import os
150 >
151 > from portage import _encodings
152 > from portage.util import writemsg_level
153 > @@ -68,7 +69,26 @@ def linux_ro_checker(dir_list):
154 > level=logging.WARNING, noiselevel=-1)
155 > return []
156 >
157 > - return set.intersection(ro_filesystems, set(dir_list))
158 > + ro_devs = {}
159 > + for x in ro_filesystems:
160 > + try:
161 > + ro_devs[os.stat(x).st_dev] = x
162 > + except OSError:
163 > + pass
164 > +
165 > + ro_filesystems.clear()
166 > + for x in set(dir_list):
167 > + try:
168 > + dev = os.stat(x).st_dev
169 > + except OSError:
170 > + pass
171 > + else:
172 > + try:
173 > + ro_filesystems.add(ro_devs[dev])
174 > + except KeyError:
175 > + pass
176 > +
177 > + return ro_filesystems
178 >
179 >
180 > def empty_ro_checker(dir_list):
181
182 looks fine
183
184 --
185 Brian Dolbec <dolsen>