1use std::io::{self, ErrorKind};
3use std::path::{Path, PathBuf};
4use std::os::unix::fs::FileTypeExt;
5
6#[derive(Clone, Debug, Hash, PartialEq)]
7pub enum FileType {
8 Regular,
9 Directory,
10 Symlink,
11 CharDevice,
12 BlockDevice,
13 Fifo,
14 Socket,
15}
16
17#[derive(Clone, Debug, Hash, PartialEq)]
19pub enum Regular {
20 ASCII,
21 OTHER,
22}
23
24pub trait PathFileType {
25 fn filetype(&self) -> io::Result<FileType>;
27
28 fn is_symlink(&self) -> bool;
30
31 fn is_char_device(&self) -> bool;
33
34 fn is_block_device(&self) -> bool;
36
37 fn is_fifo(&self) -> bool;
39
40 fn is_socket(&self) -> bool;
42}
43
44impl PathFileType for Path {
45 fn filetype(&self) -> io::Result<FileType> {
46 if ! self.exists() {
48 return Err(io::Error::from(ErrorKind::NotFound))
49 }
50
51 if self.is_block_device() {
52 Ok(FileType::BlockDevice)
53 } else if self.is_char_device() {
54 Ok(FileType::CharDevice)
55 } else if self.is_fifo() {
56 Ok(FileType::Fifo)
57 } else if self.is_socket() {
58 Ok(FileType::Socket)
59 } else if self.is_symlink() {
60 Ok(FileType::Symlink)
61 } else if self.is_dir() {
62 Ok(FileType::Directory)
63 } else {
64 Ok(FileType::Regular)
65 }
66 }
67
68 fn is_symlink(&self) -> bool {
69 self.symlink_metadata().unwrap().file_type().is_symlink()
70 }
71
72 fn is_char_device(&self) -> bool {
73 self.metadata().unwrap().file_type().is_char_device()
74 }
75
76 fn is_block_device(&self) -> bool {
77 self.metadata().unwrap().file_type().is_block_device()
78 }
79
80 fn is_fifo(&self) -> bool {
81 self.metadata().unwrap().file_type().is_fifo()
82 }
83
84 fn is_socket(&self) -> bool {
85 self.metadata().unwrap().file_type().is_socket()
86 }
87}
88
89impl PathFileType for PathBuf {
90 fn filetype(&self) -> io::Result<FileType> {
91 self.as_path().filetype()
92 }
93
94 fn is_symlink(&self) -> bool {
95 self.as_path().is_symlink()
96 }
97
98 fn is_char_device(&self) -> bool {
99 self.as_path().is_char_device()
100 }
101
102 fn is_block_device(&self) -> bool {
103 self.as_path().is_block_device()
104 }
105
106 fn is_fifo(&self) -> bool {
107 self.as_path().is_fifo()
108 }
109
110 fn is_socket(&self) -> bool {
111 self.as_path().is_socket()
112 }
113}