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}