From 23c0734a62daafd4926079c96b1ed677abfe282b Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Fri, 17 Dec 2021 11:10:14 -0600 Subject: [PATCH] uucore::fsext: Fix mountinfo parsing w/ multiple optional fields proc(5) mentions the following for the fields section and hyphen: > (7) optional fields: zero or more fields of the form "tag[:value]"; > see below. > (8) separator: the end of the optional fields is marked by a single > hyphen. IOW, there may actually be multiple optional fields, not just one, in which case the previously hardcoded indexes for the filesystem type and device name are now incorrect. Now, the filesystem type and device name are parsed relative to the hypen's location, ensuring that they will be correct regardless of the number of optional fields. Signed-off-by: Ryan Gonzalez --- src/uucore/src/lib/features/fsext.rs | 50 ++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 97c1da79c..0461555e7 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -203,10 +203,14 @@ impl MountInfo { // Format: 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue // "man proc" for more details LINUX_MOUNTINFO => { + const FIELDS_OFFSET: usize = 6; + let after_fields = raw[FIELDS_OFFSET..].iter().position(|c| *c == "-").unwrap() + + FIELDS_OFFSET + + 1; let mut m = MountInfo { dev_id: "".to_string(), - dev_name: raw[9].to_string(), - fs_type: raw[8].to_string(), + dev_name: raw[after_fields + 1].to_string(), + fs_type: raw[after_fields].to_string(), mount_root: raw[3].to_string(), mount_dir: raw[4].to_string(), mount_option: raw[5].to_string(), @@ -891,4 +895,46 @@ mod tests { assert_eq!("UNKNOWN (0x1234)", pretty_fstype(0x1234)); // spell-checker:enable } + + #[test] + #[cfg(target_os = "linux")] + fn test_mountinfo() { + // spell-checker:ignore (word) relatime + let info = MountInfo::new( + LINUX_MOUNTINFO, + "106 109 253:6 / /mnt rw,relatime - xfs /dev/fs0 rw" + .split_ascii_whitespace() + .collect(), + ) + .unwrap(); + + assert_eq!(info.mount_root, "/"); + assert_eq!(info.mount_dir, "/mnt"); + assert_eq!(info.mount_option, "rw,relatime"); + assert_eq!(info.fs_type, "xfs"); + assert_eq!(info.dev_name, "/dev/fs0"); + + // Test parsing with different amounts of optional fields. + let info = MountInfo::new( + LINUX_MOUNTINFO, + "106 109 253:6 / /mnt rw,relatime master:1 - xfs /dev/fs0 rw" + .split_ascii_whitespace() + .collect(), + ) + .unwrap(); + + assert_eq!(info.fs_type, "xfs"); + assert_eq!(info.dev_name, "/dev/fs0"); + + let info = MountInfo::new( + LINUX_MOUNTINFO, + "106 109 253:6 / /mnt rw,relatime master:1 shared:2 - xfs /dev/fs0 rw" + .split_ascii_whitespace() + .collect(), + ) + .unwrap(); + + assert_eq!(info.fs_type, "xfs"); + assert_eq!(info.dev_name, "/dev/fs0"); + } }