Commit 2dbc6857 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

utils.ListVisibleFiles: Hide “lost+found” directories

If a “lost+found” directory is found at a filesystem's root path it is
ignored. In all other cases directory entries named “lost+found” are
treated normally. Unittests are included. Fixes issue 153.
Signed-off-by: default avatarMichael Hanselmann <>
Reviewed-by: default avatarIustin Pop <>
parent fbd55434
...@@ -38,6 +38,10 @@ from ganeti.utils import filelock ...@@ -38,6 +38,10 @@ from ganeti.utils import filelock
#: Path generating random UUID #: Path generating random UUID
_RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid" _RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid"
#: Directory used by fsck(8) to store recovered data, usually at a file
#: system's root directory
_LOST_AND_FOUND = "lost+found"
def ReadFile(file_name, size=-1, preread=None): def ReadFile(file_name, size=-1, preread=None):
"""Reads a file. """Reads a file.
...@@ -467,7 +471,7 @@ def CreateBackup(file_name): ...@@ -467,7 +471,7 @@ def CreateBackup(file_name):
return backup_name return backup_name
def ListVisibleFiles(path): def ListVisibleFiles(path, _is_mountpoint=os.path.ismount):
"""Returns a list of visible files in a directory. """Returns a list of visible files in a directory.
@type path: str @type path: str
...@@ -480,8 +484,22 @@ def ListVisibleFiles(path): ...@@ -480,8 +484,22 @@ def ListVisibleFiles(path):
if not IsNormAbsPath(path): if not IsNormAbsPath(path):
raise errors.ProgrammerError("Path passed to ListVisibleFiles is not" raise errors.ProgrammerError("Path passed to ListVisibleFiles is not"
" absolute/normalized: '%s'" % path) " absolute/normalized: '%s'" % path)
files = [i for i in os.listdir(path) if not i.startswith(".")]
return files mountpoint = _is_mountpoint(path)
def fn(name):
"""File name filter.
Ignores files starting with a dot (".") as by Unix convention they're
considered hidden. The "lost+found" directory found at the root of some
filesystems is also hidden.
return not (name.startswith(".") or
(mountpoint and name == _LOST_AND_FOUND and
os.path.isdir(os.path.join(path, name))))
return filter(fn, os.listdir(path))
def EnsureDirs(dirs): def EnsureDirs(dirs):
...@@ -239,6 +239,27 @@ class TestListVisibleFiles(unittest.TestCase): ...@@ -239,6 +239,27 @@ class TestListVisibleFiles(unittest.TestCase):
self.failUnlessRaises(errors.ProgrammerError, utils.ListVisibleFiles, self.failUnlessRaises(errors.ProgrammerError, utils.ListVisibleFiles,
"/bin/../tmp") "/bin/../tmp")
def testMountpoint(self):
lvfmp_fn = compat.partial(utils.ListVisibleFiles,
_is_mountpoint=lambda _: True)
self.assertEqual(lvfmp_fn(self.path), [])
# Create "lost+found" as a regular file
self._CreateFiles(["foo", "bar", ".baz", "lost+found"])
set(["foo", "bar", "lost+found"]))
# Replace "lost+found" with a directory
laf_path = utils.PathJoin(self.path, "lost+found")
self.assertEqual(set(lvfmp_fn(self.path)), set(["foo", "bar"]))
def testLostAndFoundNoMountpoint(self):
files = ["foo", "bar", ".Hello World", "lost+found"]
expected = ["foo", "bar", "lost+found"]
self._test(files, expected)
class TestWriteFile(unittest.TestCase): class TestWriteFile(unittest.TestCase):
def setUp(self): def setUp(self):
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment