rune/
dired.rs

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