From 9b4190f1e6fb93da08945b6f579b448207887845 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 13 Apr 2025 18:13:31 -0700 Subject: [PATCH] fix mount on macOS when filesystem contains parenthesis --- jc/parsers/mount.py | 31 +++++++++++-------- .../generic/mount-parens-in-filesystem.json | 1 + .../generic/mount-parens-in-filesystem.out | 14 +++++++++ tests/test_mount.py | 12 +++++++ 4 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 tests/fixtures/generic/mount-parens-in-filesystem.json create mode 100644 tests/fixtures/generic/mount-parens-in-filesystem.out diff --git a/jc/parsers/mount.py b/jc/parsers/mount.py index 9fe67558..8e9765c4 100644 --- a/jc/parsers/mount.py +++ b/jc/parsers/mount.py @@ -77,7 +77,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.10' + version = '1.11' description = '`mount` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -111,19 +111,24 @@ def _osx_parse(data): for entry in data: output_line = {} - filesystem = entry.split(' on ') - filesystem = filesystem[0] - output_line['filesystem'] = filesystem + pattern = re.compile( + r''' + (?P.*) + \son\s + (?P.*?) + \s + \((?P.*?)\)\s* + ''', re.VERBOSE + ) - mount_point = entry.split(' on ') - mount_point = mount_point[1].split(' (') - mount_point = mount_point[0] - output_line['mount_point'] = mount_point + mymatch = pattern.match(entry) + groups = mymatch.groupdict() - options = entry.split('(', maxsplit=1) - options = options[1].rstrip(')') - options = options.split(', ') - output_line['options'] = options + if groups: + output_line['filesystem'] = groups['filesystem'] + output_line['mount_point'] = groups['mount_point'] + options = groups['options'].split(', ') + output_line['options'] = options output.append(output_line) @@ -218,7 +223,7 @@ def parse(data, raw=False, quiet=False): # check for OSX and AIX output if ' type ' not in cleandata[0]: - if 'node' in cleandata[0]: + if ' node ' in cleandata[0]: raw_output = _aix_parse(cleandata) else: raw_output = _osx_parse(cleandata) diff --git a/tests/fixtures/generic/mount-parens-in-filesystem.json b/tests/fixtures/generic/mount-parens-in-filesystem.json new file mode 100644 index 00000000..2c6cfbbe --- /dev/null +++ b/tests/fixtures/generic/mount-parens-in-filesystem.json @@ -0,0 +1 @@ +[{"filesystem":"/dev/disk3s1s1","mount_point":"/","options":["apfs","sealed","local","read-only","journaled"]},{"filesystem":"devfs","mount_point":"/dev","options":["devfs","local","nobrowse"]},{"filesystem":"/dev/disk3s6","mount_point":"/System/Volumes/VM","options":["apfs","local","noexec","journaled","noatime","nobrowse"]},{"filesystem":"/dev/disk3s2","mount_point":"/System/Volumes/Preboot","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk3s4","mount_point":"/System/Volumes/Update","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk2s2","mount_point":"/System/Volumes/xarts","options":["apfs","local","noexec","journaled","noatime","nobrowse"]},{"filesystem":"/dev/disk2s1","mount_point":"/System/Volumes/iSCPreboot","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk2s3","mount_point":"/System/Volumes/Hardware","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk3s5","mount_point":"/System/Volumes/Data","options":["apfs","local","journaled","nobrowse","protect","root data"]},{"filesystem":"map auto_home","mount_point":"/System/Volumes/Data/home","options":["autofs","automounted","nobrowse"]},{"filesystem":"MN - mydomain.com (ftp.mydomain.com):/","mount_point":"/Users/muescha/Library/Application Support/Mountain Duck/Volumes.noindex/MN - mydomain.com.localized","options":["nfs","asynchronous","nodev","nosuid","noowners","noatime","mounted by muescha"]},{"filesystem":"/dev/disk5s1","mount_point":"/Library/Developer/CoreSimulator/Volumes/iOS_21F79","options":["apfs","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]},{"filesystem":"/dev/disk7s1","mount_point":"/Library/Developer/CoreSimulator/Cryptex/Images/bundle/SimRuntimeBundle-A3CF7B3B-543B-4D71-BA03-12F939EA0B4D","options":["apfs","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]},{"filesystem":"/dev/disk9s1","mount_point":"/Library/Developer/CoreSimulator/Volumes/iOS_22C150","options":["apfs","sealed","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]}] diff --git a/tests/fixtures/generic/mount-parens-in-filesystem.out b/tests/fixtures/generic/mount-parens-in-filesystem.out new file mode 100644 index 00000000..f7d37c03 --- /dev/null +++ b/tests/fixtures/generic/mount-parens-in-filesystem.out @@ -0,0 +1,14 @@ +/dev/disk3s1s1 on / (apfs, sealed, local, read-only, journaled) +devfs on /dev (devfs, local, nobrowse) +/dev/disk3s6 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse) +/dev/disk3s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse) +/dev/disk3s4 on /System/Volumes/Update (apfs, local, journaled, nobrowse) +/dev/disk2s2 on /System/Volumes/xarts (apfs, local, noexec, journaled, noatime, nobrowse) +/dev/disk2s1 on /System/Volumes/iSCPreboot (apfs, local, journaled, nobrowse) +/dev/disk2s3 on /System/Volumes/Hardware (apfs, local, journaled, nobrowse) +/dev/disk3s5 on /System/Volumes/Data (apfs, local, journaled, nobrowse, protect, root data) +map auto_home on /System/Volumes/Data/home (autofs, automounted, nobrowse) +MN - mydomain.com (ftp.mydomain.com):/ on /Users/muescha/Library/Application Support/Mountain Duck/Volumes.noindex/MN - mydomain.com.localized (nfs, asynchronous, nodev, nosuid, noowners, noatime, mounted by muescha) +/dev/disk5s1 on /Library/Developer/CoreSimulator/Volumes/iOS_21F79 (apfs, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse) +/dev/disk7s1 on /Library/Developer/CoreSimulator/Cryptex/Images/bundle/SimRuntimeBundle-A3CF7B3B-543B-4D71-BA03-12F939EA0B4D (apfs, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse) +/dev/disk9s1 on /Library/Developer/CoreSimulator/Volumes/iOS_22C150 (apfs, sealed, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse) diff --git a/tests/test_mount.py b/tests/test_mount.py index 895730cb..2d6b88f9 100644 --- a/tests/test_mount.py +++ b/tests/test_mount.py @@ -30,6 +30,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.out'), 'r', encoding='utf-8') as f: generic_mount_spaces_in_filename = f.read() + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-parens-in-filesystem.out'), 'r', encoding='utf-8') as f: + generic_mount_parens_in_filesystem = f.read() + # output with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/mount.json'), 'r', encoding='utf-8') as f: @@ -53,6 +56,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.json'), 'r', encoding='utf-8') as f: generic_mount_spaces_in_filename_json = json.loads(f.read()) + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-parens-in-filesystem.json'), 'r', encoding='utf-8') as f: + generic_mount_parens_in_filesystem_json = json.loads(f.read()) + def test_mount_nodata(self): """ @@ -102,6 +108,12 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.mount.parse(self.generic_mount_spaces_in_filename, quiet=True), self.generic_mount_spaces_in_filename_json) + def test_mount_parens_in_filesystem(self): + """ + Test 'mount' with parenthesis in the filesystem + """ + self.assertEqual(jc.parsers.mount.parse(self.generic_mount_parens_in_filesystem, quiet=True), self.generic_mount_parens_in_filesystem_json) + if __name__ == '__main__': unittest.main()