• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

olukowski / celer / 23215512358

17 Mar 2026 08:42PM UTC coverage: 98.305% (-1.7%) from 100.0%
23215512358

Pull #7

github

web-flow
Merge 20b0c5c1e into 2ededf578
Pull Request #7: feat(syscalls): full coverage of Linux 1.0 syscalls (WIP)

5 of 6 branches covered (83.33%)

Branch coverage included in aggregate %.

111 of 112 new or added lines in 5 files covered. (99.11%)

111 of 112 relevant lines covered (99.11%)

42.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.08
/system/linux/syscalls/src/sys/read.rs
1
use celer_system_linux_ctypes::{Char, Long, SizeT, UnsignedInt};
2

3
use crate::arch::current::{Sysno, syscall3};
4

5
/// Attempt to read up to `count` bytes from file descriptor `fd`
6
/// into the buffer starting at `buf`.
7
///
8
/// # Safety
9
/// - `buf` must be writable for `count` bytes (see [`core::ptr::write`]).
10
///
11
/// # Kernel Support
12
/// - Introduced: Linux 1.0
13
/// - Behavior changes: none known
14
/// - Availability: always present
15
///
16
/// # Required Privileges
17
/// - None
18
///
19
/// # Behavior
20
/// - On files that support seeking, the read starts at the current file offset
21
///   and the offset is incremented by the number of bytes read.
22
///   If the the file offset is at or beyond the end of the file,
23
///   [`read`] returns 0 to indicate end of file.
24
/// - If `count` is 0, [`read`] returns 0 without reading any data,
25
///   but may still detect errors.
26
/// - On success, returns the number of bytes read, or `0` to indicate
27
///   end of file. The number of bytes read lies in the range `1..=count`.
28
///   A partial read is *not* considered an error, it can occur naturally
29
///   (i.e., the end of the file is reached before `count` bytes are read).
30
///
31
/// # Errors
32
/// - `EAGAIN`: The file descriptor does not refer to a socket,
33
///   is marked nonblocking, and the read would block.
34
/// - `EAGAIN` or `EWOULDBLOCK`: The file descriptor refers to a socket that
35
///   is marked nonblocking, and the read would block.
36
/// - `EBADF`: The file descriptor is invalid, or not open for reading.
37
/// - `EFAULT`: The `buf` pointer is outside the process's accessible address
38
///   space.
39
/// - `EINTR`: The read was interrupted by a signal (before any data was read).
40
/// - `EINVAL`: The file descriptor is unsuitable for reading or the file was
41
///   opened with the `O_DIRECT` flag and `buf`, `count` or the file offset are
42
///   not suitably aligned.
43
/// - `EINVAL`: `fd` was created via a call to `timerfd_create` and the wrong
44
///   size buffer was passed to [`read`].
45
/// - `EIO`: An I/O error occurred while reading from the file.
46
/// - `EISDIR`: The file descriptor refers to a directory, not a regular file.
47
///
48
/// Other errors may also occur, depending on the type of object being read.
49
///
50
/// # References
51
/// - `man` [page](https://man7.org/linux/man-pages/man2/read.2.html)
52
/// - Stable: [v6.19](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/read_write.c?h=v6.19#n722)
53
/// - LTS: [v6.18.18](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/fs/read_write.c?h=v6.18.18#n722)
54
/// - First stable: [Linux 1.0](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/tree/fs/read_write.c?h=1.0#n70)
55
///
56
/// # Historical References
57
/// - First appearance: [Linux 0.10](https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/tree/fs/read_write.c?h=0.10#n55)
58
pub unsafe fn read(fd: UnsignedInt, buf: *mut Char, count: SizeT) -> Long {
1✔
59
    // SAFETY: guaranteed by caller.
60
    (unsafe {
1✔
61
        syscall3(
1✔
62
            Sysno::Read,
1✔
63
            fd as isize,
1✔
64
            buf.addr() as isize,
1✔
65
            count as isize,
1✔
66
        )
1✔
67
    }) as Long
1✔
68
}
1✔
69

70
#[cfg(test)]
71
mod tests {
72
    use std::{
73
        env,
74
        fs::{self, OpenOptions},
75
        io::{Seek as _, Write as _},
76
        os::fd::AsRawFd as _,
77
        path::PathBuf,
78
        time::{SystemTime, UNIX_EPOCH},
79
    };
80

81
    use celer_system_linux_ctypes::{SizeT, UnsignedInt};
82

83
    use super::read;
84

85
    fn create_temp_path() -> PathBuf {
1✔
86
        let mut path = env::temp_dir();
1✔
87
        let now = SystemTime::now()
1✔
88
            .duration_since(UNIX_EPOCH)
1✔
89
            .unwrap()
1✔
90
            .as_nanos();
1✔
91

92
        path.push(format!("test_read_{now}"));
1✔
93

94
        path
1✔
95
    }
1✔
96

97
    #[test]
98
    fn test_read() {
1✔
99
        let path = create_temp_path();
1✔
100
        let mut file = OpenOptions::new()
1✔
101
            .create(true)
1✔
102
            .truncate(true)
1✔
103
            .write(true)
1✔
104
            .read(true)
1✔
105
            .open(&path)
1✔
106
            .unwrap();
1✔
107

108
        let mut contents_to_check: &[u8] = b"Hello, World!";
1✔
109
        file.write_all(contents_to_check).unwrap();
1✔
110
        file.rewind().unwrap();
1✔
111

112
        let mut buf = [0u8; 32];
1✔
113

114
        while !contents_to_check.is_empty() {
2✔
115
            let n = unsafe {
1✔
116
                read(
1✔
117
                    file.as_raw_fd() as UnsignedInt,
1✔
118
                    buf.as_mut_ptr().cast(),
1✔
119
                    contents_to_check.len() as SizeT,
1✔
120
                )
1✔
121
            } as usize;
1✔
122

123
            assert_ne!(n, 0); // we should NOT reach EOF
1✔
124

125
            // just retry on error
126
            if n > 0 {
1!
127
                assert_eq!(&buf[..n], &contents_to_check[..n]);
1✔
128

129
                contents_to_check = &contents_to_check[n..];
1✔
NEW
130
            }
×
131
        }
132

133
        fs::remove_file(&path).unwrap()
1✔
134
    }
1✔
135
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc