在 OSX 系统用 rust 打开文件时提示 permission denied

最近用 rust 写一个小东西时,发现打开文件时总是会提示 permission denied, 记录一下解决过程

1 问题

我们看这样一段程序

pub fn get_file_buffer(path: &str) -> Vec<u8> {
    let mut file = File::open(path).unwrap();
    let mut file_buffer: Vec<u8> = Vec::new();
    file.read_to_end(&mut file_buffer).unwrap();
    return file_buffer;
}

fn main() {
    let file_name = "CALD.B";
    let file_buffer = get_file_buffer(file_name);
    println!("{} file length: {}", file_name, file_buffer.len());
}

这段程序把文件内容读取到一个 vector 中,很简单的逻辑对不对, 但是运行时总是会 panic

thread ‘main’ panicked at ‘called `Result::unwrap()` on an `Err` value: Os { code: 13, kind: PermissionDenied, message: “Permission denied” }’,

2 分析

CALD.B 这个文件我想之前关注我文章的人大概知道是什么, 我是从另一个目录拷过来的,permission denied 首先我想到的就是文件权限问题, 那么 ls -l 看一下:

-rwxrwxrwx@ 1 user staff 36528 Dec 5 1995 CALD.B

我感觉这个权限没什么问题,这下只能求助于 google 了,但是看了一圈, 也没有什么帮助,重新确认了下程序的运行目录没有问题, 我尝试打开了另一个文件 Cargo.toml

Cargo.toml file length: 234

这个就更奇怪了,赶快看一下 Cargo.toml 的权限

-rw-r–r– 1 user staff 234 Mar 26 16:26 Cargo.toml -rwxrwxrwx@ 1 user staff 36528 Dec 5 1995 CALD.B

这个权限更少,对比之下 CALD.B 那个 @ 就比较明显了,这个 @ 代表什么呢? 搜了一下,这个是扩展属性,可以用 ls -al@ 来查看

-rwxrwxrwx@ 1 user staff 36528 Dec 5 1995 CALD.B com.apple.fileutil.PlaceholderData 336

这个 com.apple.fileutil.PlaceholderData 就是两个文件的差别了, 那么我们可以用 xattr -c CALD.B 来清除所有扩展属性,然后再试试运行程序

CALD.B file length: 36528

成功!

3 结论

原来是因为文件多了一个扩展属性,而我的这个 com.apple.fileutil.PlaceholderData 属性似乎是 onedrive 引入的,这个是后话。