From e74975d2f9365c7dc179f4180aa3fbc8ffa8277f Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Sat, 30 Sep 2017 20:24:59 -0600
Subject: [PATCH] Add UUID matching

---
 src/bin/mount.rs | 195 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 157 insertions(+), 38 deletions(-)

diff --git a/src/bin/mount.rs b/src/bin/mount.rs
index 98db27e..8ec6910 100644
--- a/src/bin/mount.rs
+++ b/src/bin/mount.rs
@@ -8,13 +8,16 @@ extern crate libc;
 extern crate syscall;
 
 extern crate redoxfs;
+extern crate uuid;
 
 use std::env;
 use std::fs::File;
+use std::io::{Read, Write};
 use std::os::unix::io::FromRawFd;
 use std::process;
 
 use redoxfs::{DiskCache, DiskFile, mount};
+use uuid::Uuid;
 
 #[cfg(unix)]
 fn fork() -> isize {
@@ -37,56 +40,172 @@ fn pipe(pipes: &mut [usize; 2]) -> isize {
 }
 
 fn usage() {
-    println!("redoxfs [disk] [mountpoint]");
+    println!("redoxfs [--uuid] [disk or uuid] [mountpoint]");
+}
+
+enum DiskId {
+    Path(String),
+    Uuid(Uuid),
+}
+
+#[cfg(not(target_os = "redox"))]
+fn disk_paths(_paths: &mut Vec<String>) {}
+
+#[cfg(target_os = "redox")]
+fn disk_paths(paths: &mut Vec<String>) {
+    use std::fs;
+
+    let mut schemes = vec![];
+    match fs::read_dir(":") {
+        Ok(entries) => for entry_res in entries {
+            if let Ok(entry) = entry_res {
+                if let Ok(path) = entry.path().into_os_string().into_string() {
+                    let scheme = path.trim_left_matches(':');
+                    if scheme.starts_with("disk") {
+                        schemes.push(format!("{}:", scheme));
+                    }
+                }
+            }
+        },
+        Err(err) => {
+            println!("redoxfs: failed to list schemes: {}", err);
+        }
+    }
+
+    for scheme in schemes {
+        match fs::read_dir(&scheme) {
+            Ok(entries) => for entry_res in entries {
+                if let Ok(entry) = entry_res {
+                    if let Ok(path) = entry.path().into_os_string().into_string() {
+                        paths.push(path);
+                    }
+                }
+            },
+            Err(err) => {
+                println!("redoxfs: failed to list '{}': {}", scheme, err);
+            }
+        }
+    }
+}
+
+fn daemon(disk_id: &DiskId, mountpoint: &str, mut write: File) -> ! {
+    let mut paths = vec![];
+    let mut uuid_opt = None;
+
+    match *disk_id {
+        DiskId::Path(ref path) => {
+            paths.push(path.clone());
+        },
+        DiskId::Uuid(ref uuid) => {
+            disk_paths(&mut paths);
+            uuid_opt = Some(uuid.clone());
+        },
+    }
+
+    for path in paths {
+        println!("redoxfs: opening {}", path);
+        match DiskFile::open(&path).map(|image| DiskCache::new(image)) {
+            Ok(disk) => match redoxfs::FileSystem::open(disk) {
+                Ok(filesystem) => {
+                    println!("redoxfs: opened filesystem on {} with uuid {}", path,
+                             Uuid::from_bytes(&filesystem.header.1.uuid).unwrap().hyphenated());
+
+                    let matches = if let Some(uuid) = uuid_opt {
+                        if &filesystem.header.1.uuid == uuid.as_bytes() {
+                            println!("redoxfs: filesystem on {} matches uuid {}", path, uuid.hyphenated());
+                            true
+                        } else {
+                            println!("redoxfs: filesystem on {} does not match uuid {}", path, uuid.hyphenated());
+                            false
+                        }
+                    } else {
+                        true
+                    };
+
+                    if matches {
+                        match mount(filesystem, &mountpoint, || {
+                            println!("redoxfs: mounted filesystem on {} to {}", path, mountpoint);
+                            let _ = write.write(&[0]);
+                        }) {
+                            Ok(()) => {
+                                process::exit(0);
+                            },
+                            Err(err) => {
+                                println!("redoxfs: failed to mount {} to {}: {}", path, mountpoint, err);
+                            }
+                        }
+                    }
+                },
+                Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
+            },
+            Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
+        }
+    }
+
+    match *disk_id {
+        DiskId::Path(ref path) => {
+            println!("redoxfs: not able to mount path {}", path);
+        },
+        DiskId::Uuid(ref uuid) => {
+            println!("redoxfs: not able to mount uuid {}", uuid.hyphenated());
+        },
+    }
+
+    let _ = write.write(&[1]);
+    process::exit(1);
 }
 
 fn main() {
-    use std::io::{Read, Write};
+    let mut args = env::args().skip(1);
+
+    let disk_id = match args.next() {
+        Some(arg) => if arg == "--uuid" {
+            let uuid = match args.next() {
+                Some(arg) => match Uuid::parse_str(&arg) {
+                    Ok(uuid) => uuid,
+                    Err(err) => {
+                        println!("redoxfs: invalid uuid '{}': {}", arg, err);
+                        usage();
+                        process::exit(1);
+                    }
+                },
+                None => {
+                    println!("redoxfs: no uuid provided");
+                    usage();
+                    process::exit(1);
+                }
+            };
+
+            DiskId::Uuid(uuid)
+        } else {
+            DiskId::Path(arg)
+        },
+        None => {
+            println!("redoxfs: no disk provided");
+            usage();
+            process::exit(1);
+        }
+    };
+
+    let mountpoint = match args.next() {
+        Some(arg) => arg,
+        None => {
+            println!("redoxfs: no mountpoint provided");
+            usage();
+            process::exit(1);
+        }
+    };
 
     let mut pipes = [0; 2];
     if pipe(&mut pipes) == 0 {
         let mut read = unsafe { File::from_raw_fd(pipes[0]) };
-        let mut write = unsafe { File::from_raw_fd(pipes[1]) };
+        let write = unsafe { File::from_raw_fd(pipes[1]) };
 
         let pid = fork();
         if pid == 0 {
             drop(read);
 
-            if let Some(path) = env::args().nth(1) {
-                //Open an existing image
-                match DiskFile::open(&path).map(|image| DiskCache::new(image)) {
-                    Ok(disk) => match redoxfs::FileSystem::open(disk) {
-                        Ok(filesystem) => {
-                            println!("redoxfs: opened filesystem {}", path);
-
-                            if let Some(mountpoint) = env::args().nth(2) {
-                                match mount(filesystem, &mountpoint, || {
-                                    println!("redoxfs: mounted filesystem on {}:", mountpoint);
-                                    let _ = write.write(&[0]);
-                                }) {
-                                    Ok(()) => {
-                                        process::exit(0);
-                                    },
-                                    Err(err) => {
-                                        println!("redoxfs: failed to mount {} to {}: {}", path, mountpoint, err);
-                                    }
-                                }
-                            } else {
-                                println!("redoxfs: no mount point provided");
-                                usage();
-                            }
-                        },
-                        Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
-                    },
-                    Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
-                }
-
-                let _ = write.write(&[1]);
-                process::exit(1);
-            } else {
-                println!("redoxfs: no disk image provided");
-                usage();
-            }
+            daemon(&disk_id, &mountpoint, write);
         } else if pid > 0 {
             drop(write);
 
-- 
GitLab