eden: implement mount parsing for macOS

Summary:
Parse the `mount` command output to understand the mount table on macOS.

This is helpful both for eden doctor and the upcoming redirection feature.

Reviewed By: strager

Differential Revision: D15701554

fbshipit-source-id: 6e17e1682dc609ae6f1e9f82bf7b9c729addea27
This commit is contained in:
Wez Furlong 2019-06-11 16:37:25 -07:00 committed by Facebook Github Bot
parent ac89061656
commit 5bcff17a7f
2 changed files with 59 additions and 2 deletions

View File

@ -11,6 +11,7 @@ import errno
import logging
import os
import random
import re
import subprocess
import sys
from typing import List, NamedTuple, Union
@ -105,6 +106,32 @@ class LinuxMountTable(MountTable):
)
def parse_macos_mount_output(contents: bytes) -> List[MountInfo]:
mounts = []
for line in contents.splitlines():
m = re.match(b"^(\\S+) on (.+) \\(([^,]+),.*\\)$", line)
if m:
mounts.append(
MountInfo(device=m.group(1), mount_point=m.group(2), vfstype=m.group(3))
)
return mounts
class MacOSMountTable(MountTable):
def read(self) -> List[MountInfo]:
contents = subprocess.check_output(["mount"])
return parse_macos_mount_output(contents)
def unmount_lazy(self, mount_point: bytes) -> bool:
return False
def unmount_force(self, mount_point: bytes) -> bool:
return False
def create_bind_mount(self, source_path, dest_path) -> bool:
return False
class NopMountTable(MountTable):
def read(self) -> List[MountInfo]:
return []
@ -122,4 +149,6 @@ class NopMountTable(MountTable):
def new() -> MountTable:
if "linux" in sys.platform:
return LinuxMountTable()
if sys.platform == "darwin":
return MacOSMountTable()
return NopMountTable()

View File

@ -9,7 +9,7 @@
import unittest
from eden.cli import mtab
from eden.cli.mtab import MountInfo, parse_macos_mount_output, parse_mtab
class MTabTest(unittest.TestCase):
@ -23,9 +23,37 @@ squashfuse_ll /mnt/xarfuse/uid-0/2c071047-ns-4026531840 fuse.squashfuse_ll rw,no
bogus line here
edenfs /tmp/eden_test.4rec6drf/mounts/main fuse rw,nosuid,relatime,user_id=138655,group_id=100,default_permissions,allow_other 0 0
"""
mount_infos = mtab.parse_mtab(contents)
mount_infos = parse_mtab(contents)
self.assertEqual(3, len(mount_infos))
one, two, three = mount_infos
self.assertEqual("edenfs", three.device)
self.assertEqual("/tmp/eden_test.4rec6drf/mounts/main", three.mount_point)
self.assertEqual("fuse", three.vfstype)
def test_parse_mtab_macos(self):
contents = b"""\
/dev/disk1s1 on / (apfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
/dev/disk1s4 on /private/var/vm (apfs, local, noexec, journaled, noatime, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
map -fstab on /Network/Servers (autofs, automounted, nobrowse)
eden@osxfuse0 on /Users/wez/fbsource (osxfuse_eden, nosuid, synchronous)
"""
self.assertEqual(
[
MountInfo(device=b"/dev/disk1s1", mount_point=b"/", vfstype=b"apfs"),
MountInfo(device=b"devfs", mount_point=b"/dev", vfstype=b"devfs"),
MountInfo(
device=b"/dev/disk1s4",
mount_point=b"/private/var/vm",
vfstype=b"apfs",
),
MountInfo(
device=b"eden@osxfuse0",
mount_point=b"/Users/wez/fbsource",
vfstype=b"osxfuse_eden",
),
],
parse_macos_mount_output(contents),
)