1 use std::fs::Metadata;
2 #[cfg(unix)]
3 use std::os::unix::fs::MetadataExt;
4 #[cfg(windows)]
5 use std::os::windows::fs::MetadataExt;
6 
get_mode(meta: &Metadata) -> String7 pub fn get_mode(meta: &Metadata) -> String {
8     #[cfg(unix)]
9     {
10         format_mode(meta.mode())
11     }
12 
13     #[cfg(windows)]
14     {
15         format_mode(meta.file_attributes())
16     }
17 }
18 
format_mode(mode: u32) -> String19 pub fn format_mode(mode: u32) -> String {
20     #[cfg(unix)]
21     {
22         get_mode_unix(mode)
23     }
24 
25     #[cfg(windows)]
26     {
27         get_mode_windows(mode)
28     }
29 }
30 
31 #[cfg(unix)]
get_mode_unix(mode: u32) -> String32 fn get_mode_unix(mode: u32) -> String {
33     let mut s = String::new();
34 
35     if mode_is_link(mode) {
36         s.push('l')
37     } else if mode_is_block_device(mode) {
38         s.push('b')
39     } else if mode_is_char_device(mode) {
40         s.push('c')
41     } else if mode_is_socket(mode) {
42         s.push('s')
43     } else if mode_is_pipe(mode) {
44         s.push('p')
45     } else if mode_is_directory(mode) {
46         s.push('d')
47     } else {
48         s.push('-')
49     }
50 
51     // user
52 
53     if mode_user_read(mode) {
54         s.push('r')
55     } else {
56         s.push('-')
57     }
58 
59     if mode_user_write(mode) {
60         s.push('w')
61     } else {
62         s.push('-')
63     }
64 
65     if mode_user_exec(mode) {
66         if mode_suid(mode) {
67             s.push('s')
68         } else {
69             s.push('x')
70         }
71     } else {
72         if mode_suid(mode) {
73             s.push('S')
74         } else {
75             s.push('-')
76         }
77     }
78 
79     // group
80 
81     if mode_group_read(mode) {
82         s.push('r')
83     } else {
84         s.push('-')
85     }
86 
87     if mode_group_write(mode) {
88         s.push('w')
89     } else {
90         s.push('-')
91     }
92 
93     if mode_group_exec(mode) {
94         if mode_sgid(mode) {
95             s.push('s')
96         } else {
97             s.push('x')
98         }
99     } else {
100         if mode_sgid(mode) {
101             s.push('S')
102         } else {
103             s.push('-')
104         }
105     }
106 
107     // other
108 
109     if mode_other_read(mode) {
110         s.push('r')
111     } else {
112         s.push('-')
113     }
114 
115     if mode_other_write(mode) {
116         s.push('w')
117     } else {
118         s.push('-')
119     }
120 
121     if mode_other_exec(mode) {
122         if mode_sticky(mode) {
123             s.push('t')
124         } else {
125             s.push('x')
126         }
127     } else {
128         if mode_sticky(mode) {
129             s.push('T')
130         } else {
131             s.push('-')
132         }
133     }
134 
135     s
136 }
137 
138 #[allow(unused)]
get_mode_from_boxed_unix_int(meta: &Metadata) -> Option<u32>139 pub fn get_mode_from_boxed_unix_int(meta: &Metadata) -> Option<u32> {
140     #[cfg(unix)]
141     {
142         Some(meta.mode())
143     }
144 
145     #[cfg(not(unix))]
146     {
147         None
148     }
149 }
150 
user_read(meta: &Metadata) -> bool151 pub fn user_read(meta: &Metadata) -> bool {
152     match get_mode_from_boxed_unix_int(meta) {
153         Some(mode) => mode_user_read(mode),
154         None => false
155     }
156 }
157 
mode_user_read(mode: u32) -> bool158 pub fn mode_user_read(mode: u32) -> bool {
159     mode & S_IRUSR == S_IRUSR
160 }
161 
user_write(meta: &Metadata) -> bool162 pub fn user_write(meta: &Metadata) -> bool {
163     match get_mode_from_boxed_unix_int(meta) {
164         Some(mode) => mode_user_write(mode),
165         None => false
166     }
167 }
168 
mode_user_write(mode: u32) -> bool169 pub fn mode_user_write(mode: u32) -> bool {
170     mode & S_IWUSR == S_IWUSR
171 }
172 
user_exec(meta: &Metadata) -> bool173 pub fn user_exec(meta: &Metadata) -> bool {
174     match get_mode_from_boxed_unix_int(meta) {
175         Some(mode) => mode_user_exec(mode),
176         None => false
177     }
178 }
179 
mode_user_exec(mode: u32) -> bool180 pub fn mode_user_exec(mode: u32) -> bool {
181     mode & S_IXUSR == S_IXUSR
182 }
183 
user_all(meta: &Metadata) -> bool184 pub fn user_all(meta: &Metadata) -> bool {
185     user_read(meta) && user_write(meta) && user_exec(meta)
186 }
187 
mode_user_all(mode: u32) -> bool188 pub fn mode_user_all(mode: u32) -> bool {
189     mode_user_read(mode) && mode_user_write(mode) && mode_user_exec(mode)
190 }
191 
group_read(meta: &Metadata) -> bool192 pub fn group_read(meta: &Metadata) -> bool {
193     match get_mode_from_boxed_unix_int(meta) {
194         Some(mode) => mode_group_read(mode),
195         None => false
196     }
197 }
198 
mode_group_read(mode: u32) -> bool199 pub fn mode_group_read(mode: u32) -> bool {
200     mode & S_IRGRP == S_IRGRP
201 }
202 
group_write(meta: &Metadata) -> bool203 pub fn group_write(meta: &Metadata) -> bool {
204     match get_mode_from_boxed_unix_int(meta) {
205         Some(mode) => mode_group_write(mode),
206         None => false
207     }
208 }
209 
mode_group_write(mode: u32) -> bool210 pub fn mode_group_write(mode: u32) -> bool {
211     mode & S_IWGRP == S_IWGRP
212 }
213 
group_exec(meta: &Metadata) -> bool214 pub fn group_exec(meta: &Metadata) -> bool {
215     match get_mode_from_boxed_unix_int(meta) {
216         Some(mode) => mode_group_exec(mode),
217         None => false
218     }
219 }
220 
mode_group_exec(mode: u32) -> bool221 pub fn mode_group_exec(mode: u32) -> bool {
222     mode & S_IXGRP == S_IXGRP
223 }
224 
group_all(meta: &Metadata) -> bool225 pub fn group_all(meta: &Metadata) -> bool {
226     group_read(meta) && group_write(meta) && group_exec(meta)
227 }
228 
mode_group_all(mode: u32) -> bool229 pub fn mode_group_all(mode: u32) -> bool {
230     mode_group_read(mode) && mode_group_write(mode) && mode_group_exec(mode)
231 }
232 
other_read(meta: &Metadata) -> bool233 pub fn other_read(meta: &Metadata) -> bool {
234     match get_mode_from_boxed_unix_int(meta) {
235         Some(mode) => mode_other_read(mode),
236         None => false
237     }
238 }
239 
mode_other_read(mode: u32) -> bool240 pub fn mode_other_read(mode: u32) -> bool {
241     mode & S_IROTH == S_IROTH
242 }
243 
other_write(meta: &Metadata) -> bool244 pub fn other_write(meta: &Metadata) -> bool {
245     match get_mode_from_boxed_unix_int(meta) {
246         Some(mode) => mode_other_write(mode),
247         None => false
248     }
249 }
250 
mode_other_write(mode: u32) -> bool251 pub fn mode_other_write(mode: u32) -> bool {
252     mode & S_IWOTH == S_IWOTH
253 }
254 
other_exec(meta: &Metadata) -> bool255 pub fn other_exec(meta: &Metadata) -> bool {
256     match get_mode_from_boxed_unix_int(meta) {
257         Some(mode) => mode_other_exec(mode),
258         None => false
259     }
260 }
261 
mode_other_exec(mode: u32) -> bool262 pub fn mode_other_exec(mode: u32) -> bool {
263     mode & S_IXOTH == S_IXOTH
264 }
265 
other_all(meta: &Metadata) -> bool266 pub fn other_all(meta: &Metadata) -> bool {
267     other_read(meta) && other_write(meta) && other_exec(meta)
268 }
269 
mode_other_all(mode: u32) -> bool270 pub fn mode_other_all(mode: u32) -> bool {
271     mode_other_read(mode) && mode_other_write(mode) && mode_other_exec(mode)
272 }
273 
suid_bit_set(meta: &Metadata) -> bool274 pub fn suid_bit_set(meta: &Metadata) -> bool {
275     match get_mode_from_boxed_unix_int(meta) {
276         Some(mode) => mode_suid(mode),
277         None => false
278     }
279 }
280 
mode_suid(mode: u32) -> bool281 pub fn mode_suid(mode: u32) -> bool {
282     mode & S_ISUID == S_ISUID
283 }
284 
sgid_bit_set(meta: &Metadata) -> bool285 pub fn sgid_bit_set(meta: &Metadata) -> bool {
286     match get_mode_from_boxed_unix_int(meta) {
287         Some(mode) => mode_sgid(mode),
288         None => false
289     }
290 }
291 
mode_sgid(mode: u32) -> bool292 pub fn mode_sgid(mode: u32) -> bool {
293     mode & S_ISGID == S_ISGID
294 }
295 
296 #[cfg(unix)]
mode_sticky(mode: u32) -> bool297 pub fn mode_sticky(mode: u32) -> bool {
298     mode & S_ISVTX == S_ISVTX
299 }
300 
is_pipe(meta: &Metadata) -> bool301 pub fn is_pipe(meta: &Metadata) -> bool {
302     match get_mode_from_boxed_unix_int(meta) {
303         Some(mode) => mode_is_pipe(mode),
304         None => false
305     }
306 }
307 
mode_is_pipe(mode: u32) -> bool308 pub fn mode_is_pipe(mode: u32) -> bool {
309     mode & S_IFIFO == S_IFIFO
310 }
311 
is_char_device(meta: &Metadata) -> bool312 pub fn is_char_device(meta: &Metadata) -> bool {
313     match get_mode_from_boxed_unix_int(meta) {
314         Some(mode) => mode_is_char_device(mode),
315         None => false
316     }
317 }
318 
mode_is_char_device(mode: u32) -> bool319 pub fn mode_is_char_device(mode: u32) -> bool {
320     mode & S_IFCHR == S_IFCHR
321 }
322 
is_block_device(meta: &Metadata) -> bool323 pub fn is_block_device(meta: &Metadata) -> bool {
324     match get_mode_from_boxed_unix_int(meta) {
325         Some(mode) => mode_is_block_device(mode),
326         None => false
327     }
328 }
329 
mode_is_block_device(mode: u32) -> bool330 pub fn mode_is_block_device(mode: u32) -> bool {
331     mode & S_IFBLK == S_IFBLK
332 }
333 
334 #[cfg(unix)]
mode_is_directory(mode: u32) -> bool335 pub fn mode_is_directory(mode: u32) -> bool {
336     mode & S_IFDIR == S_IFDIR
337 }
338 
339 #[cfg(unix)]
mode_is_link(mode: u32) -> bool340 pub fn mode_is_link(mode: u32) -> bool {
341     mode & S_IFLNK == S_IFLNK
342 }
343 
is_socket(meta: &Metadata) -> bool344 pub fn is_socket(meta: &Metadata) -> bool {
345     match get_mode_from_boxed_unix_int(meta) {
346         Some(mode) => mode_is_socket(mode),
347         None => false
348     }
349 }
350 
mode_is_socket(mode: u32) -> bool351 pub fn mode_is_socket(mode: u32) -> bool {
352     mode & S_IFSOCK == S_IFSOCK
353 }
354 
355 const S_IRUSR: u32 = 0o400;
356 const S_IWUSR: u32 = 0o200;
357 const S_IXUSR: u32 = 0o100;
358 
359 const S_IRGRP: u32 = 0o40;
360 const S_IWGRP: u32 = 0o20;
361 const S_IXGRP: u32 = 0o10;
362 
363 const S_IROTH: u32 = 0o4;
364 const S_IWOTH: u32 = 0o2;
365 const S_IXOTH: u32 = 0o1;
366 
367 const S_ISUID: u32 = 0o4000;
368 const S_ISGID: u32 = 0o2000;
369 #[cfg(unix)]
370 const S_ISVTX: u32 = 0o1000;
371 
372 const S_IFBLK: u32 = 0o60000;
373 #[cfg(unix)]
374 const S_IFDIR: u32 = 0o40000;
375 const S_IFCHR: u32 = 0o20000;
376 const S_IFIFO: u32 = 0o10000;
377 #[cfg(unix)]
378 const S_IFLNK: u32 = 0o120000;
379 const S_IFSOCK: u32 = 0o140000;
380 
381 #[cfg(windows)]
get_mode_windows(mode: u32) -> String382 fn get_mode_windows(mode: u32) -> String {
383     const FILE_ATTRIBUTE_ARCHIVE: u32 = 0x20;
384     const FILE_ATTRIBUTE_COMPRESSED: u32 = 0x800;
385     const FILE_ATTRIBUTE_DEVICE: u32 = 0x40;
386     const FILE_ATTRIBUTE_DIRECTORY: u32 = 0x10;
387     const FILE_ATTRIBUTE_ENCRYPTED: u32 = 0x4000;
388     const FILE_ATTRIBUTE_HIDDEN: u32 = 0x2;
389     const FILE_ATTRIBUTE_INTEGRITY_STREAM: u32 = 0x8000;
390     const FILE_ATTRIBUTE_NORMAL: u32 = 0x80;
391     const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: u32 = 0x2000;
392     const FILE_ATTRIBUTE_NO_SCRUB_DATA: u32 = 0x20000;
393     const FILE_ATTRIBUTE_OFFLINE: u32 = 0x1000;
394     const FILE_ATTRIBUTE_READONLY: u32 = 0x1;
395     const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS: u32 = 0x400000;
396     const FILE_ATTRIBUTE_RECALL_ON_OPEN: u32 = 0x40000;
397     const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x400;
398     const FILE_ATTRIBUTE_SPARSE_FILE: u32 = 0x200;
399     const FILE_ATTRIBUTE_SYSTEM: u32 = 0x4;
400     const FILE_ATTRIBUTE_TEMPORARY: u32 = 0x100;
401     const FILE_ATTRIBUTE_VIRTUAL: u32 = 0x10000;
402 
403     let mut v = vec![];
404 
405     if mode & FILE_ATTRIBUTE_ARCHIVE == FILE_ATTRIBUTE_ARCHIVE {
406         v.push("Archive");
407     }
408 
409     if mode & FILE_ATTRIBUTE_COMPRESSED == FILE_ATTRIBUTE_COMPRESSED {
410         v.push("Compressed");
411     }
412 
413     if mode & FILE_ATTRIBUTE_DEVICE == FILE_ATTRIBUTE_DEVICE {
414         v.push("Device");
415     }
416 
417     if mode & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY {
418         v.push("Directory");
419     }
420 
421     if mode & FILE_ATTRIBUTE_ENCRYPTED == FILE_ATTRIBUTE_ENCRYPTED {
422         v.push("Encrypted");
423     }
424 
425     if mode & FILE_ATTRIBUTE_HIDDEN == FILE_ATTRIBUTE_HIDDEN {
426         v.push("Hidden");
427     }
428 
429     if mode & FILE_ATTRIBUTE_INTEGRITY_STREAM == FILE_ATTRIBUTE_INTEGRITY_STREAM {
430         v.push("Integrity Stream");
431     }
432 
433     if mode & FILE_ATTRIBUTE_NORMAL == FILE_ATTRIBUTE_NORMAL {
434         v.push("Normal");
435     }
436 
437     if mode & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED == FILE_ATTRIBUTE_NOT_CONTENT_INDEXED {
438         v.push("Not indexed");
439     }
440 
441     if mode & FILE_ATTRIBUTE_NO_SCRUB_DATA == FILE_ATTRIBUTE_NO_SCRUB_DATA {
442         v.push("No scrub data");
443     }
444 
445     if mode & FILE_ATTRIBUTE_OFFLINE == FILE_ATTRIBUTE_OFFLINE {
446         v.push("Offline");
447     }
448 
449     if mode & FILE_ATTRIBUTE_READONLY == FILE_ATTRIBUTE_READONLY {
450         v.push("Readonly");
451     }
452 
453     if mode & FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS == FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS {
454         v.push("Recall on data access");
455     }
456 
457     if mode & FILE_ATTRIBUTE_RECALL_ON_OPEN == FILE_ATTRIBUTE_RECALL_ON_OPEN {
458         v.push("Recall on open");
459     }
460 
461     if mode & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT {
462         v.push("Reparse point");
463     }
464 
465     if mode & FILE_ATTRIBUTE_SPARSE_FILE == FILE_ATTRIBUTE_SPARSE_FILE {
466         v.push("Sparse");
467     }
468 
469     if mode & FILE_ATTRIBUTE_SYSTEM == FILE_ATTRIBUTE_SYSTEM {
470         v.push("System");
471     }
472 
473     if mode & FILE_ATTRIBUTE_TEMPORARY == FILE_ATTRIBUTE_TEMPORARY {
474         v.push("Temporary");
475     }
476 
477     if mode & FILE_ATTRIBUTE_VIRTUAL == FILE_ATTRIBUTE_VIRTUAL {
478         v.push("Virtual");
479     }
480 
481     v.join(", ")
482 }
483 
484 #[allow(unused)]
get_uid(meta: &Metadata) -> Option<u32>485 pub fn get_uid(meta: &Metadata) -> Option<u32> {
486     #[cfg(unix)]
487     {
488         Some(meta.uid())
489     }
490 
491     #[cfg(not(unix))]
492     {
493         None
494     }
495 }
496 
497 #[allow(unused)]
get_gid(meta: &Metadata) -> Option<u32>498 pub fn get_gid(meta: &Metadata) -> Option<u32> {
499     #[cfg(unix)]
500     {
501         Some(meta.gid())
502     }
503 
504     #[cfg(not(unix))]
505     {
506         None
507     }
508 }