1 |
commit: bdd7d6b82859c6cf1386619d36087e346f169795 |
2 |
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun May 31 08:28:35 2015 +0000 |
4 |
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun May 31 08:28:38 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=bdd7d6b8 |
7 |
|
8 |
xsystem: fix fchdir handling with <linux-3.5 |
9 |
|
10 |
We use O_PATH with the vdb dirs, and sometimes we try to fchdir with |
11 |
those fds. Unfortunately, fchdir doesn't work with O_PATH and linux-3.5 |
12 |
leading to errors like: |
13 |
>>> pkg_postrm |
14 |
merge: fchdir failed: Bad file descriptor |
15 |
|
16 |
When fchdir fails with EBADF, assume it's because of an older kernel, |
17 |
and fall back to using the /proc/self/fd/ path indirectly. |
18 |
|
19 |
libq/xsystem.c | 12 ++++++++++-- |
20 |
1 file changed, 10 insertions(+), 2 deletions(-) |
21 |
|
22 |
diff --git a/libq/xsystem.c b/libq/xsystem.c |
23 |
index d8a551a..71e8306 100644 |
24 |
--- a/libq/xsystem.c |
25 |
+++ b/libq/xsystem.c |
26 |
@@ -22,8 +22,16 @@ static void xsystembash(const char *command, int cwd) |
27 |
switch (p) { |
28 |
case 0: /* child */ |
29 |
if (cwd != AT_FDCWD) |
30 |
- if (fchdir(cwd)) |
31 |
- errp("fchdir failed"); |
32 |
+ if (fchdir(cwd)) { |
33 |
+ /* fchdir works with O_PATH starting w/linux-3.5 */ |
34 |
+ if (errno == EBADF) { |
35 |
+ char *path; |
36 |
+ xasprintf(&path, "/proc/self/fd/%i", cwd); |
37 |
+ if (chdir(path)) |
38 |
+ errp("chdir(%s) failed", path); |
39 |
+ } else |
40 |
+ errp("fchdir(%i) failed", cwd); |
41 |
+ } |
42 |
execl("/bin/bash", "bash", "--norc", "--noprofile", "-c", command, NULL); |
43 |
/* Hrm, still here ? Maybe no bash ... */ |
44 |
_exit(execl("/bin/sh", "sh", "-c", command, NULL)); |