rune/dired.rs
1use crate::core::{
2 gc::Context,
3 object::{NIL, Object, OptionalFlag, TRUE},
4};
5use rune_core::macros::list;
6use rune_macros::defun;
7use std::path::Path;
8
9#[defun]
10fn file_attributes<'ob>(filename: &str, _id_format: OptionalFlag, cx: &'ob Context) -> Object<'ob> {
11 let file = Path::new(filename);
12 if file.exists() { metadata_attributes(file, cx) } else { NIL }
13}
14
15#[cfg(unix)]
16fn metadata_attributes<'ob>(file: &Path, cx: &'ob Context) -> Object<'ob> {
17 use std::os::unix::fs::MetadataExt;
18 let metadata = &file.metadata().unwrap();
19
20 // 0. t for directory, string (name linked to) for symbolic link, or nil.
21 let file_type = get_file_type(file, cx);
22 // 1. Number of hardlinks to file.
23 let links = metadata.nlink();
24 // 2. File uid as a string or (if ID-FORMAT is integer or a string value
25 // cannot be looked up) as an integer.
26 let uid = metadata.uid();
27 // 3. File gid, likewise.
28 let gid = metadata.gid();
29 // 4. Last access time, in the style of current-time.
30 // (See a note below about access time on FAT-based filesystems.)
31 let atime = metadata.atime();
32 // 5. Last modification time, likewise. This is the time of the last
33 // change to the file's contents.
34 let mtime = metadata.mtime();
35 // 6. Last status change time, likewise. This is the time of last change
36 // to the file's attributes: owner and group, access mode bits, etc.
37 let ctime = metadata.ctime();
38 // 7. Size in bytes, as an integer.
39 let size = metadata.size();
40 // 8. File modes, as a string of ten letters or dashes as in ls -l.
41 let mode = metadata.mode();
42 // 9. An unspecified value, present only for backward compatibility.
43 // 10. inode number, as a nonnegative integer.
44 let inode = metadata.ino();
45 // 11. Filesystem device identifier, as an integer or a cons cell of integers.
46 let dev = metadata.dev();
47 list![file_type, links, uid, gid, atime, mtime, ctime, size, mode, TRUE, inode, dev; cx]
48}
49
50#[cfg(windows)]
51fn metadata_attributes<'ob>(file: &Path, cx: &'ob Context) -> Object<'ob> {
52 use std::os::windows::fs::MetadataExt;
53 let metadata = &file.metadata().unwrap();
54
55 // 0. t for directory, string (name linked to) for symbolic link, or nil.
56 let file_type = get_file_type(file, cx);
57 // TODO: implement the rest of the attributes
58 // 1. Number of hardlinks to file.
59 // 2. File uid as a string or (if ID-FORMAT is integer or a string value
60 // cannot be looked up) as an integer.
61 // 3. File gid, likewise.
62 // 4. Last access time, in the style of current-time.
63 // (See a note below about access time on FAT-based filesystems.)
64 // 5. Last modification time, likewise. This is the time of the last
65 // change to the file's contents.
66 // 6. Last status change time, likewise. This is the time of last change
67 // to the file's attributes: owner and group, access mode bits, etc.
68 // 7. Size in bytes, as an integer.
69 // 8. File modes, as a string of ten letters or dashes as in ls -l.
70 // 9. An unspecified value, present only for backward compatibility.
71 // 10. inode number, as a nonnegative integer.
72 // 11. Filesystem device identifier, as an integer or a cons cell of integers.
73 panic!("file-attributes are not yet implemented for non-unix systems");
74}
75
76fn get_file_type<'ob>(file: &Path, cx: &'ob Context) -> Object<'ob> {
77 if file.is_dir() {
78 TRUE
79 } else if file.is_symlink() {
80 let target = file.read_link().unwrap();
81 cx.add(target.to_str().unwrap())
82 } else {
83 NIL
84 }
85}