Skip to main content

shadow_rs/host/syscall/handler/
file.rs

1use linux_api::errno::Errno;
2use linux_api::posix_types::kernel_mode_t;
3use shadow_shim_helper_rs::syscall_types::ForeignPtr;
4
5use crate::cshadow;
6use crate::host::descriptor::CompatFile;
7use crate::host::syscall::File;
8use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
9use crate::host::syscall::type_formatting::SyscallStringArg;
10use crate::host::syscall::types::{SyscallError, SyscallResult};
11
12impl SyscallHandler {
13    log_syscall!(
14        open,
15        /* rv */ std::ffi::c_int,
16        /* pathname */ SyscallStringArg,
17        /* flags */ linux_api::fcntl::OFlag,
18        /* mode */ nix::sys::stat::Mode,
19    );
20    pub fn open(
21        ctx: &mut SyscallContext,
22        _path: ForeignPtr<()>,
23        _flags: std::ffi::c_int,
24        _mode: kernel_mode_t,
25    ) -> SyscallResult {
26        Self::legacy_syscall(cshadow::syscallhandler_open, ctx)
27    }
28
29    log_syscall!(
30        creat,
31        /* rv */ std::ffi::c_int,
32        /* pathname */ SyscallStringArg,
33        /* mode */ nix::sys::stat::Mode
34    );
35    pub fn creat(ctx: &mut SyscallContext) -> SyscallResult {
36        Self::legacy_syscall(cshadow::syscallhandler_creat, ctx)
37    }
38
39    log_syscall!(
40        fadvise64,
41        /* rv */ std::ffi::c_int,
42        /* fd */ std::ffi::c_int,
43        /* offset */ linux_api::types::loff_t,
44        /* len */ linux_api::types::size_t,
45        /* advice */ std::ffi::c_int
46    );
47    pub fn fadvise64(ctx: &mut SyscallContext) -> SyscallResult {
48        Self::legacy_syscall(cshadow::syscallhandler_fadvise64, ctx)
49    }
50
51    log_syscall!(
52        fallocate,
53        /* rv */ std::ffi::c_int,
54        /* fd */ std::ffi::c_int,
55        /* mode */ std::ffi::c_int,
56        /* offset */ linux_api::types::loff_t,
57        /* len */ linux_api::types::loff_t
58    );
59    pub fn fallocate(ctx: &mut SyscallContext) -> SyscallResult {
60        Self::legacy_syscall(cshadow::syscallhandler_fallocate, ctx)
61    }
62
63    log_syscall!(
64        fchmod,
65        /* rv */ std::ffi::c_int,
66        /* fd */ std::ffi::c_int,
67        /* mode */ linux_api::types::umode_t,
68    );
69    pub fn fchmod(ctx: &mut SyscallContext) -> SyscallResult {
70        Self::legacy_syscall(cshadow::syscallhandler_fchmod, ctx)
71    }
72
73    log_syscall!(
74        fchown,
75        /* rv */ std::ffi::c_int,
76        /* fd */ std::ffi::c_uint,
77        /* user */ linux_api::types::uid_t,
78        /* group */ linux_api::types::gid_t
79    );
80    pub fn fchown(ctx: &mut SyscallContext) -> SyscallResult {
81        Self::legacy_syscall(cshadow::syscallhandler_fchown, ctx)
82    }
83
84    log_syscall!(
85        fdatasync,
86        /* rv */ std::ffi::c_int,
87        /* fd */ std::ffi::c_uint
88    );
89    pub fn fdatasync(ctx: &mut SyscallContext) -> SyscallResult {
90        Self::legacy_syscall(cshadow::syscallhandler_fdatasync, ctx)
91    }
92
93    log_syscall!(
94        fgetxattr,
95        /* rv */ std::ffi::c_int,
96        /* fd */ std::ffi::c_int,
97        /* name */ SyscallStringArg,
98        /* value */ *const std::ffi::c_void,
99        /* size */ linux_api::types::size_t
100    );
101    pub fn fgetxattr(ctx: &mut SyscallContext) -> SyscallResult {
102        Self::legacy_syscall(cshadow::syscallhandler_fgetxattr, ctx)
103    }
104
105    log_syscall!(
106        flistxattr,
107        /* rv */ std::ffi::c_int,
108        /* fd */ std::ffi::c_int,
109        /* This is actually a *list* of strings: "The list is the set of
110         * (null-terminated) names, one after the other."
111         * TODO: log the whole list instead of just the first element */
112        /* list */
113        SyscallStringArg,
114        /* size */ linux_api::types::size_t
115    );
116    pub fn flistxattr(ctx: &mut SyscallContext) -> SyscallResult {
117        Self::legacy_syscall(cshadow::syscallhandler_flistxattr, ctx)
118    }
119
120    log_syscall!(
121        flock,
122        /* rv */ std::ffi::c_int,
123        /* fd */ std::ffi::c_uint,
124        /* cmd */ std::ffi::c_uint
125    );
126    pub fn flock(ctx: &mut SyscallContext) -> SyscallResult {
127        warn_once_then_debug!(
128            "Using flock implementation that assumes no lock contention. \
129            See https://github.com/shadow/shadow/issues/2258"
130        );
131        Self::legacy_syscall(cshadow::syscallhandler_flock, ctx)
132    }
133
134    log_syscall!(
135        fremovexattr,
136        /* rv */ std::ffi::c_int,
137        /* fd */ std::ffi::c_int,
138        /* name */ SyscallStringArg
139    );
140    pub fn fremovexattr(ctx: &mut SyscallContext) -> SyscallResult {
141        Self::legacy_syscall(cshadow::syscallhandler_fremovexattr, ctx)
142    }
143
144    log_syscall!(
145        fsetxattr,
146        /* rv */ std::ffi::c_int,
147        /* fd */ std::ffi::c_int,
148        /* name */ SyscallStringArg,
149        /* value */ *const std::ffi::c_void,
150        /* size */ linux_api::types::size_t,
151        /* flags */ std::ffi::c_int
152    );
153    pub fn fsetxattr(ctx: &mut SyscallContext) -> SyscallResult {
154        Self::legacy_syscall(cshadow::syscallhandler_fsetxattr, ctx)
155    }
156
157    log_syscall!(
158        fsync,
159        /* rv */ std::ffi::c_int,
160        /* fd */ std::ffi::c_uint
161    );
162    pub fn fsync(ctx: &mut SyscallContext) -> SyscallResult {
163        Self::legacy_syscall(cshadow::syscallhandler_fsync, ctx)
164    }
165
166    log_syscall!(
167        ftruncate,
168        /* rv */ std::ffi::c_int,
169        /* fd */ std::ffi::c_uint,
170        /* length */ linux_api::types::off_t
171    );
172    pub fn ftruncate(ctx: &mut SyscallContext) -> SyscallResult {
173        Self::legacy_syscall(cshadow::syscallhandler_ftruncate, ctx)
174    }
175
176    log_syscall!(
177        getdents,
178        /* rv */ std::ffi::c_int,
179        /* fd */ std::ffi::c_uint,
180        /* dirent */ *const std::ffi::c_void,
181        /* count */ std::ffi::c_uint
182    );
183    pub fn getdents(ctx: &mut SyscallContext) -> SyscallResult {
184        Self::legacy_syscall(cshadow::syscallhandler_getdents, ctx)
185    }
186
187    log_syscall!(
188        getdents64,
189        /* rv */ std::ffi::c_int,
190        /* fd */ std::ffi::c_uint,
191        /* dirent */ *const std::ffi::c_void,
192        /* count */ std::ffi::c_uint
193    );
194    pub fn getdents64(ctx: &mut SyscallContext) -> SyscallResult {
195        Self::legacy_syscall(cshadow::syscallhandler_getdents64, ctx)
196    }
197
198    log_syscall!(
199        lseek,
200        /* rv */ std::ffi::c_int,
201        /* fd */ std::ffi::c_uint,
202        /* offset */ linux_api::posix_types::kernel_off_t,
203        /* whence */ std::ffi::c_uint,
204    );
205    pub fn lseek(
206        ctx: &mut SyscallContext,
207        fd: std::ffi::c_uint,
208        _offset: linux_api::posix_types::kernel_off_t,
209        _whence: std::ffi::c_uint,
210    ) -> Result<linux_api::posix_types::kernel_off_t, SyscallError> {
211        let desc_table = ctx.objs.thread.descriptor_table_borrow(ctx.objs.host);
212
213        let file = {
214            match Self::get_descriptor(&desc_table, fd)?.file() {
215                CompatFile::New(file) => file,
216                // if it's a legacy file, use the C syscall handler instead
217                CompatFile::Legacy(_) => {
218                    drop(desc_table);
219                    return Self::legacy_syscall(cshadow::syscallhandler_lseek, ctx);
220                }
221            }
222        };
223
224        match file.inner_file() {
225            File::Pipe(_) => Err(Errno::ESPIPE.into()),
226            _ => {
227                warn_once_then_debug!("lseek() is not implemented for this type");
228                Err(Errno::ENOTSUP.into())
229            }
230        }
231    }
232
233    log_syscall!(
234        readahead,
235        /* rv */ std::ffi::c_int,
236        /* fd */ std::ffi::c_int,
237        /* offset */ linux_api::types::loff_t,
238        /* count */ linux_api::types::size_t
239    );
240    pub fn readahead(ctx: &mut SyscallContext) -> SyscallResult {
241        Self::legacy_syscall(cshadow::syscallhandler_readahead, ctx)
242    }
243
244    log_syscall!(
245        readlink,
246        /* rv */ std::ffi::c_int,
247        /* pathname */ SyscallStringArg,
248        /* TODO: format this when we have better support for output-buffers.
249         * https://github.com/shadow/shadow/issues/3694 */
250        /* buf */
251        *const std::ffi::c_void,
252        /* bufsize */ std::ffi::c_int,
253    );
254    pub fn readlink(_ctx: &mut SyscallContext) -> SyscallResult {
255        Err(SyscallError::Native)
256    }
257
258    log_syscall!(
259        sync_file_range,
260        /* rv */ std::ffi::c_int,
261        /* fd */ std::ffi::c_int,
262        /* offset */ linux_api::types::loff_t,
263        /* nbytes */ linux_api::types::loff_t,
264        /* flags */ std::ffi::c_uint
265    );
266    pub fn sync_file_range(ctx: &mut SyscallContext) -> SyscallResult {
267        Self::legacy_syscall(cshadow::syscallhandler_sync_file_range, ctx)
268    }
269
270    log_syscall!(
271        syncfs,
272        /* rv */ std::ffi::c_int,
273        /* fd */ std::ffi::c_int
274    );
275    pub fn syncfs(ctx: &mut SyscallContext) -> SyscallResult {
276        Self::legacy_syscall(cshadow::syscallhandler_syncfs, ctx)
277    }
278}