summaryrefslogtreecommitdiffstats
path: root/scripts/removablectl
blob: 926067fd16e8d64fe3ce6a49785b0a6b827f9dd1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env scriptisto

// scriptisto-begin
// script_src: src/main.rs
// build_cmd: cargo build --release && strip ./target/release/script
// target_bin: ./target/release/script
// files:
//  - path: Cargo.toml
//    content: |
//     package = { name = "script", version = "0.1.0", edition = "2018"}
//     [dependencies]
//     structopt="*"
//     cmd_lib = "0.7.8"
//     atty = "0.2"
// scriptisto-end

use structopt::StructOpt;
use cmd_lib::*;

#[derive(Debug, StructOpt)]
#[structopt(name = "removablectl", about = "Manages removable drives.")]
enum Opt {
    /// Mount a drive
    Mount,
    /// Unmount a drive
    Unmount,
}

fn main() -> CmdResult {
    let opt = Opt::from_args();
    match opt {
        Opt::Mount => mount(),
        Opt::Unmount => unmount(),
    }
}

fn mount () -> CmdResult {
    let unmounted = Process::new("lsblk --noheadings --raw -o NAME,MOUNTPOINT")
                    .pipe("awk '$1~/[[:digit:]]/ && $2 == \"\"'")
                    .wait::<FunResult>()?;
    let filtered = unmounted
                    .split_whitespace()
                    .filter(|s| !s.starts_with("sda"))
                    .filter(|s| !s.starts_with("loop"))
                    .map(|s| format!("/dev/{}", s))
                    .collect::<Vec<_>>();

    if filtered.is_empty() {
        die!("No unmounted drives were found");
    }

    let selected = chooser(filtered)?;
    run_cmd!("udisksctl mount -b {}", selected)
}

fn unmount () -> CmdResult {
    let mounted = Process::new("cat /etc/mtab")
                    .pipe("grep ^/")
                    .pipe("awk '{print $1}'")
                    .wait::<FunResult>()?;
    let filtered = mounted
                    .split_whitespace()
                    .filter(|s| !s.starts_with("/dev/sda"))
                    .map(|s| s.to_owned())
                    .collect::<Vec<_>>();

    if filtered.is_empty() {
        die!("No mounted drives were found");
    }

    let selected = chooser(filtered)?;
    run_cmd!("udisksctl unmount -b {}", selected)
}

fn chooser(list: Vec<String>) -> FunResult {
    let selected = if atty::is(atty::Stream::Stdout) {
        run_fun!("enquirer select -m \"Choose a drive\" {}", list.join(" "))?
    } else {
        run_fun!("echo -e \"{}\" | rofi -dmenu -p \"Choose a drive\"", list.join("\\n"))?
    };

    if selected.is_empty() {
        die!("Nothing was selected");
    }

    Ok(selected)
}

// vim: filetype=rust