commit:     34532af167cff457c3cccda4ea4249a0bc26481a
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sun Feb 17 22:44:29 2019 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sun Feb 17 23:02:48 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=34532af1

locks: handle sshfs hardlink inode numbers (bug 678218)

Since hardlinks on sshfs do not have matching inode numbers, detect
this behavior and use a simple stat call to detect if lock_path has
been removed.

Bug: https://bugs.gentoo.org/678218
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/portage/locks.py | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/lib/portage/locks.py b/lib/portage/locks.py
index 74c2c086a..510925da0 100644
--- a/lib/portage/locks.py
+++ b/lib/portage/locks.py
@@ -340,6 +340,33 @@ def _lockfile_was_removed(lock_fd, lock_path):
 
                hardlink_stat = os.stat(hardlink_path)
                if hardlink_stat.st_ino != fstat_st.st_ino or 
hardlink_stat.st_dev != fstat_st.st_dev:
+                       # Create another hardlink in order to detect whether or 
not
+                       # hardlink inode numbers are expected to match. For 
example,
+                       # inode numbers are not expected to match for sshfs.
+                       inode_test = hardlink_path + '-inode-test'
+                       try:
+                               os.unlink(inode_test)
+                       except OSError as e:
+                               if e.errno not in (errno.ENOENT, errno.ESTALE):
+                                       _raise_exc(e)
+                       try:
+                               os.link(hardlink_path, inode_test)
+                       except OSError as e:
+                               if e.errno not in (errno.ENOENT, errno.ESTALE):
+                                       _raise_exc(e)
+                               return True
+                       else:
+                               if not os.path.samefile(hardlink_path, 
inode_test):
+                                       # This implies that inode numbers are 
not expected
+                                       # to match for this file system, so use 
a simple
+                                       # stat call to detect if lock_path has 
been removed.
+                                       return not os.path.exists(lock_path)
+                       finally:
+                               try:
+                                       os.unlink(inode_test)
+                               except OSError as e:
+                                       if e.errno not in (errno.ENOENT, 
errno.ESTALE):
+                                               _raise_exc(e)
                        return True
        finally:
                try:

Reply via email to