summaryrefslogtreecommitdiffstats
path: root/src/unix.rs
blob: 2ebb3412e8195ee17bd932691c42b62fe6008b41 (plain)
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::path::{Path, PathBuf};
use std::process;

use crate::config::mimetype;

pub fn is_executable(mode: u32) -> bool {
    const LIBC_PERMISSION_VALS: [libc::mode_t; 3] = [libc::S_IXUSR, libc::S_IXGRP, libc::S_IXOTH];

    for val in LIBC_PERMISSION_VALS.iter() {
        let val: u32 = (*val).into();
        if mode & val != 0 {
            return true;
        }
    }
    false
}

pub fn stringify_mode(mode: u32) -> String {
    let mut mode_str: String = String::with_capacity(10);

    const LIBC_FILE_VALS: [(libc::mode_t, char); 7] = [
        (libc::S_IFREG, '-'),
        (libc::S_IFDIR, 'd'),
        (libc::S_IFLNK, 'l'),
        (libc::S_IFSOCK, 's'),
        (libc::S_IFBLK, 'b'),
        (libc::S_IFCHR, 'c'),
        (libc::S_IFIFO, 'f'),
    ];

    const LIBC_PERMISSION_VALS: [(libc::mode_t, char); 9] = [
        (libc::S_IRUSR, 'r'),
        (libc::S_IWUSR, 'w'),
        (libc::S_IXUSR, 'x'),
        (libc::S_IRGRP, 'r'),
        (libc::S_IWGRP, 'w'),
        (libc::S_IXGRP, 'x'),
        (libc::S_IROTH, 'r'),
        (libc::S_IWOTH, 'w'),
        (libc::S_IXOTH, 'x'),
    ];

    let mode_shifted = mode >> 9;

    for (val, ch) in LIBC_FILE_VALS.iter() {
        let val: u32 = (*val >> 9).into();
        if mode_shifted & val == mode_shifted {
            mode_str.push(*ch);
            break;
        }
    }

    for (val, ch) in LIBC_PERMISSION_VALS.iter() {
        let val: u32 = (*val).into();
        if mode & val != 0 {
            mode_str.push(*ch);
        } else {
            mode_str.push('-');
        }
    }
    mode_str
}

pub fn set_mode(path: &Path, mode: u32) {
    let os_path = path.as_os_str();
    if let Some(s) = os_path.to_str() {
        let svec: Vec<i8> = s.bytes().map(|ch| ch as i8).collect();
        unsafe {
            libc::chmod(svec.as_ptr(), mode.into());
        }
    }
}

pub fn open_with_entry(paths: &[PathBuf], entry: &mimetype::JoshutoMimetypeEntry) {
    let program = entry.program.clone();

    let mut command = process::Command::new(program);
    if let Some(true) = entry.silent {
        command.stdout(process::Stdio::null());
        command.stderr(process::Stdio::null());
    }
    if let Some(args) = entry.args.as_ref() {
        for arg in args {
            command.arg(arg.clone());
        }
    }
    for path in paths {
        command.arg(path.as_os_str());
    }

    match command.spawn() {
        Ok(mut handle) => {
            if let Some(true) = entry.fork {
            } else {
                match handle.wait() {
                    Ok(_) => {}
                    Err(e) => eprintln!("{}", e),
                }
            }
        }
        Err(e) => eprintln!("{}", e),
    }
}

pub fn open_with_args(paths: &[PathBuf], args: &[String]) {
    let program = args[0].clone();

    let mut command = process::Command::new(program);
    for arg in &args[1..] {
        command.arg(arg.clone());
    }
    for path in paths {
        command.arg(path.as_os_str());
    }

    match command.spawn() {
        Ok(mut handle) => match handle.wait() {
            Ok(_) => {}
            Err(e) => eprintln!("{}", e),
        },
        Err(e) => eprintln!("{}", e),
    }
}