BufReader read File failed

I am writing a test. However when 11 line is commented , the program report "Read line failed: Os { code: 5, kind: PermissionDenied, message: "Access denied。" }". Why report this error??

When I debug this program , it looks like the read_buf has some questions, but I can't confirm where the question is !

1. use std::fs::File;
2. use std::io::{Write, BufReader, BufRead };
3. fn main() {
4.     let mut file = File::create("file.txt").expect("Create file failed");

5.     // file.set_permissions();
6.     for i in 0..10 {
7.         let mut buf = String::new();
8.         buf.push_str(&format!("Line {}\n", i));
9.         file.write_all(buf.as_bytes()).expect("Write to file failed");
10.     }
11.     // let file = File::open("file.txt").expect("Open file failed");
12.     let read_buf = BufReader::new(file);

13.     for line in read_buf.lines() {
14.         let data = line.expect("Read line failed");
15.         println!("{}", data);
16.     }
17. }

When you File::create, you open the file in write-only mode. So you can't read from it (you don't have the permission from the OS to do so, hence your error message). If you shadow file with File::open as you do in line 11 when it is not commented out, you open the file in read-only mode. So you can read from it. You can use OpenOptions to open a file in both read and write mode at the same time.

2 Likes

I try modify the permission, like this:

    let mut perms = file.metadata().expect("").permissions();
    perms.set_readonly(true);
    file.set_permissions(perms).expect("change permissions failed");

fn main() {
    let mut file = File::create("file.txt").expect("Create file failed");

    
    for i in 0..10 {
        let mut buf = String::new();
        buf.push_str(&format!("Line {}\n", i));
        file.write_all(buf.as_bytes()).expect("Write to file failed");
    }
    // let file = File::open("file.txt").expect("Open file failed");
    let mut perms = file.metadata().expect("").permissions();
    perms.set_readonly(true);
    file.set_permissions(perms).expect("change permissions failed");
    let read_buf = BufReader::new(file);

    for line in read_buf.lines() {
        let data = line.expect("Read line failed");
        println!("{}", data);
    }
}

It still report error like origin code.If I modify the permissions correct ? If does , it can't be a permissions question. And I test the permisson attr. Whatever open and create function , the permission are all

Permissions(
    FilePermissions {
        attrs: 32,
    },
)

Here something that compiles on the playground:

use std::fs::OpenOptions;
use std::io::{BufRead, BufReader, Seek, SeekFrom, Write};

fn main() {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open("file.txt")
        .unwrap();

    for i in 0..10 {
        let mut buf = String::new();
        buf.push_str(&format!("Line {}\n", i));
        file.write_all(buf.as_bytes())
            .expect("Write to file failed");
    }

    file.seek(SeekFrom::Start(0)).unwrap();

    let read_buf = BufReader::new(file);

    for line in read_buf.lines() {
        let data = line.expect("Read line failed");
        println!("{}", data);
    }
}
1 Like

Yes, your code is OK.Thinks a lot. My way to change permission looks failed.

1 Like

Explanation: You tried to change the permissions of the file on disk, but those permissions are not relevant (they are already sufficiently permissive). The relevant permissions are a part of the open file object itself — the thing that std::io::File is a Rust wrapper for. There's no way (at least, no cross-platform way in Rust std) to change those permissions after the File is created, and the right way to solve this problem is to choose them when opening the file, as @jofas showed with OpenOptions.

3 Likes

Yeah,my way that changes the file permission just changes the permissions of the file on disk.I want to change permissions of the file that is opened,but I fount no way.This feels terrible.

This is something that you can't directly do on many OSes (certainly macOS, Windows and Linux). Checks for permissions are done at file open time, and you cannot add extra permissions after that point. This causes freopen (for example) to fail if you ask it to reopen and add permissions, because the underlying OS-level file descriptor or handle cannot have its permissions changed.

What you can do, but Rust doesn't currently allow, is drop permissions that you have at the OS level from the higher-level language object; so you could have a File that you opened with write and read permissions, but where the Rust File object no longer lets you write to it. However, since you still have read and write permissions at OS level, this is of limited use.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.