1 |
commit: 34532af167cff457c3cccda4ea4249a0bc26481a |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Feb 17 22:44:29 2019 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Feb 17 23:02:48 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=34532af1 |
7 |
|
8 |
locks: handle sshfs hardlink inode numbers (bug 678218) |
9 |
|
10 |
Since hardlinks on sshfs do not have matching inode numbers, detect |
11 |
this behavior and use a simple stat call to detect if lock_path has |
12 |
been removed. |
13 |
|
14 |
Bug: https://bugs.gentoo.org/678218 |
15 |
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> |
16 |
|
17 |
lib/portage/locks.py | 27 +++++++++++++++++++++++++++ |
18 |
1 file changed, 27 insertions(+) |
19 |
|
20 |
diff --git a/lib/portage/locks.py b/lib/portage/locks.py |
21 |
index 74c2c086a..510925da0 100644 |
22 |
--- a/lib/portage/locks.py |
23 |
+++ b/lib/portage/locks.py |
24 |
@@ -340,6 +340,33 @@ def _lockfile_was_removed(lock_fd, lock_path): |
25 |
|
26 |
hardlink_stat = os.stat(hardlink_path) |
27 |
if hardlink_stat.st_ino != fstat_st.st_ino or hardlink_stat.st_dev != fstat_st.st_dev: |
28 |
+ # Create another hardlink in order to detect whether or not |
29 |
+ # hardlink inode numbers are expected to match. For example, |
30 |
+ # inode numbers are not expected to match for sshfs. |
31 |
+ inode_test = hardlink_path + '-inode-test' |
32 |
+ try: |
33 |
+ os.unlink(inode_test) |
34 |
+ except OSError as e: |
35 |
+ if e.errno not in (errno.ENOENT, errno.ESTALE): |
36 |
+ _raise_exc(e) |
37 |
+ try: |
38 |
+ os.link(hardlink_path, inode_test) |
39 |
+ except OSError as e: |
40 |
+ if e.errno not in (errno.ENOENT, errno.ESTALE): |
41 |
+ _raise_exc(e) |
42 |
+ return True |
43 |
+ else: |
44 |
+ if not os.path.samefile(hardlink_path, inode_test): |
45 |
+ # This implies that inode numbers are not expected |
46 |
+ # to match for this file system, so use a simple |
47 |
+ # stat call to detect if lock_path has been removed. |
48 |
+ return not os.path.exists(lock_path) |
49 |
+ finally: |
50 |
+ try: |
51 |
+ os.unlink(inode_test) |
52 |
+ except OSError as e: |
53 |
+ if e.errno not in (errno.ENOENT, errno.ESTALE): |
54 |
+ _raise_exc(e) |
55 |
return True |
56 |
finally: |
57 |
try: |