Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] unprivileged mode: use first_existing helper func
Date: Sat, 15 Nov 2014 07:22:21
Message-Id: 1416036114-13046-1-git-send-email-zmedico@gentoo.org
In Reply to: Re: [gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR by Zac Medico
1 Split out a first_existing function, in order to improve logic related
2 to the _unprivileged_mode function so that it checks whether it's
3 possible to create the specified target root (instead of requiring that
4 the target root already exists).
5 ---
6 pym/portage/data.py | 20 +++++++++------
7 pym/portage/package/ebuild/config.py | 23 ++++++-----------
8 pym/portage/util/path.py | 48 ++++++++++++++++++++++++++++++++++++
9 3 files changed, 67 insertions(+), 24 deletions(-)
10 create mode 100644 pym/portage/util/path.py
11
12 diff --git a/pym/portage/data.py b/pym/portage/data.py
13 index 3e03eef..d9b36ee 100644
14 --- a/pym/portage/data.py
15 +++ b/pym/portage/data.py
16 @@ -8,6 +8,7 @@ import portage
17 portage.proxy.lazyimport.lazyimport(globals(),
18 'portage.output:colorize',
19 'portage.util:writemsg',
20 + 'portage.util.path:first_existing',
21 'subprocess'
22 )
23 from portage.localization import _
24 @@ -94,14 +95,16 @@ def _get_global(k):
25 else:
26 # The config class has equivalent code, but we also need to
27 # do it here if _disable_legacy_globals() has been called.
28 - eroot = os.path.join(os.environ.get('ROOT', os.sep),
29 - portage.const.EPREFIX.lstrip(os.sep))
30 + eroot_or_parent = first_existing(os.path.join(
31 + os.environ.get('ROOT', os.sep),
32 + portage.const.EPREFIX.lstrip(os.sep)))
33 try:
34 - eroot_st = os.stat(eroot)
35 + eroot_st = os.stat(eroot_or_parent)
36 except OSError:
37 pass
38 else:
39 - unprivileged = _unprivileged_mode(eroot, eroot_st)
40 + unprivileged = _unprivileged_mode(
41 + eroot_or_parent, eroot_st)
42
43 v = 0
44 if uid == 0:
45 @@ -206,14 +209,15 @@ def _get_global(k):
46 else:
47 # The config class has equivalent code, but we also need to
48 # do it here if _disable_legacy_globals() has been called.
49 - eroot = os.path.join(os.environ.get('ROOT', os.sep),
50 - portage.const.EPREFIX.lstrip(os.sep))
51 + eroot_or_parent = first_existing(os.path.join(
52 + os.environ.get('ROOT', os.sep),
53 + portage.const.EPREFIX.lstrip(os.sep)))
54 try:
55 - eroot_st = os.stat(eroot)
56 + eroot_st = os.stat(eroot_or_parent)
57 except OSError:
58 pass
59 else:
60 - if _unprivileged_mode(eroot, eroot_st):
61 + if _unprivileged_mode(eroot_or_parent, eroot_st):
62 if k == '_portage_grpname':
63 try:
64 grp_struct = grp.getgrgid(eroot_st.st_gid)
65 diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
66 index c7308a4..bf39487 100644
67 --- a/pym/portage/package/ebuild/config.py
68 +++ b/pym/portage/package/ebuild/config.py
69 @@ -48,6 +48,7 @@ from portage.util import ensure_dirs, getconfig, grabdict, \
70 grabdict_package, grabfile, grabfile_package, LazyItemsDict, \
71 normalize_path, shlex_split, stack_dictlist, stack_dicts, stack_lists, \
72 writemsg, writemsg_level, _eapi_cache
73 +from portage.util.path import first_existing
74 from portage.util._path import exists_raise_eaccess, isdir_raise_eaccess
75 from portage.versions import catpkgsplit, catsplit, cpv_getkey, _pkg_str
76
77 @@ -848,14 +849,16 @@ class config(object):
78 "PORTAGE_INST_UID": "0",
79 }
80
81 + eroot_or_parent = first_existing(eroot)
82 unprivileged = False
83 try:
84 - eroot_st = os.stat(eroot)
85 + eroot_st = os.stat(eroot_or_parent)
86 except OSError:
87 pass
88 else:
89
90 - if portage.data._unprivileged_mode(eroot, eroot_st):
91 + if portage.data._unprivileged_mode(
92 + eroot_or_parent, eroot_st):
93 unprivileged = True
94
95 default_inst_ids["PORTAGE_INST_GID"] = str(eroot_st.st_gid)
96 @@ -897,20 +900,8 @@ class config(object):
97 # In unprivileged mode, automatically make
98 # depcachedir relative to target_root if the
99 # default depcachedir is not writable.
100 - current_dir = self.depcachedir
101 - found_dir = False
102 - while current_dir != os.sep and not found_dir:
103 - try:
104 - os.stat(current_dir)
105 - found_dir = True
106 - except OSError as e:
107 - if e.errno == errno.ENOENT:
108 - current_dir = os.path.dirname(
109 - current_dir)
110 - else:
111 - found_dir = True
112 -
113 - if not os.access(current_dir, os.W_OK):
114 + if not os.access(first_existing(self.depcachedir),
115 + os.W_OK):
116 self.depcachedir = os.path.join(eroot,
117 DEPCACHE_PATH.lstrip(os.sep))
118
119 diff --git a/pym/portage/util/path.py b/pym/portage/util/path.py
120 new file mode 100644
121 index 0000000..f77f30f
122 --- /dev/null
123 +++ b/pym/portage/util/path.py
124 @@ -0,0 +1,48 @@
125 +# Copyright 2014 Gentoo Foundation
126 +# Distributed under the terms of the GNU General Public License v2
127 +
128 +import errno
129 +
130 +from portage import os
131 +
132 +def first_existing(path):
133 + """
134 + Returns the first existing path element, traversing from the given
135 + path to the root directory. A path is considered to exists if lstat
136 + either succeeds or raises an error other than ENOENT or ESTALE.
137 +
138 + This can be particularly useful to check if there is permission to
139 + create a particular file or directory, without actually creating
140 + anything.
141 +
142 + @param path: a filesystem path
143 + @type path: str
144 + @rtype: str
145 + @return: the element that exists
146 + """
147 + existing = False
148 + for path in iter_parents(path):
149 + try:
150 + os.lstat(path)
151 + existing = True
152 + except OSError as e:
153 + if e.errno not in (errno.ENOENT, errno.ESTALE):
154 + existing = True
155 +
156 + if existing:
157 + return path
158 +
159 + return os.sep
160 +
161 +def iter_parents(path):
162 + """
163 + @param path: a filesystem path
164 + @type path: str
165 + @rtype: iterator
166 + @return: an iterator which yields path and all parents of path,
167 + ending with the root directory
168 + """
169 + yield path
170 + while path != os.sep:
171 + path = os.path.dirname(path)
172 + yield path
173 --
174 2.0.4

Replies