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        Self::legacy_syscall(cshadow::syscallhandler_flock, ctx)
128    }
129
130    log_syscall!(
131        fremovexattr,
132        /* rv */ std::ffi::c_int,
133        /* fd */ std::ffi::c_int,
134        /* name */ SyscallStringArg
135    );
136    pub fn fremovexattr(ctx: &mut SyscallContext) -> SyscallResult {
137        Self::legacy_syscall(cshadow::syscallhandler_fremovexattr, ctx)
138    }
139
140    log_syscall!(
141        fsetxattr,
142        /* rv */ std::ffi::c_int,
143        /* fd */ std::ffi::c_int,
144        /* name */ SyscallStringArg,
145        /* value */ *const std::ffi::c_void,
146        /* size */ linux_api::types::size_t,
147        /* flags */ std::ffi::c_int
148    );
149    pub fn fsetxattr(ctx: &mut SyscallContext) -> SyscallResult {
150        Self::legacy_syscall(cshadow::syscallhandler_fsetxattr, ctx)
151    }
152
153    log_syscall!(
154        fsync,
155        /* rv */ std::ffi::c_int,
156        /* fd */ std::ffi::c_uint
157    );
158    pub fn fsync(ctx: &mut SyscallContext) -> SyscallResult {
159        Self::legacy_syscall(cshadow::syscallhandler_fsync, ctx)
160    }
161
162    log_syscall!(
163        ftruncate,
164        /* rv */ std::ffi::c_int,
165        /* fd */ std::ffi::c_uint,
166        /* length */ linux_api::types::off_t
167    );
168    pub fn ftruncate(ctx: &mut SyscallContext) -> SyscallResult {
169        Self::legacy_syscall(cshadow::syscallhandler_ftruncate, ctx)
170    }
171
172    log_syscall!(
173        getdents,
174        /* rv */ std::ffi::c_int,
175        /* fd */ std::ffi::c_uint,
176        /* dirent */ *const std::ffi::c_void,
177        /* count */ std::ffi::c_uint
178    );
179    pub fn getdents(ctx: &mut SyscallContext) -> SyscallResult {
180        Self::legacy_syscall(cshadow::syscallhandler_getdents, ctx)
181    }
182
183    log_syscall!(
184        getdents64,
185        /* rv */ std::ffi::c_int,
186        /* fd */ std::ffi::c_uint,
187        /* dirent */ *const std::ffi::c_void,
188        /* count */ std::ffi::c_uint
189    );
190    pub fn getdents64(ctx: &mut SyscallContext) -> SyscallResult {
191        Self::legacy_syscall(cshadow::syscallhandler_getdents64, ctx)
192    }
193
194    log_syscall!(
195        lseek,
196        /* rv */ std::ffi::c_int,
197        /* fd */ std::ffi::c_uint,
198        /* offset */ linux_api::posix_types::kernel_off_t,
199        /* whence */ std::ffi::c_uint,
200    );
201    pub fn lseek(
202        ctx: &mut SyscallContext,
203        fd: std::ffi::c_uint,
204        _offset: linux_api::posix_types::kernel_off_t,
205        _whence: std::ffi::c_uint,
206    ) -> Result<linux_api::posix_types::kernel_off_t, SyscallError> {
207        let desc_table = ctx.objs.thread.descriptor_table_borrow(ctx.objs.host);
208
209        let file = {
210            match Self::get_descriptor(&desc_table, fd)?.file() {
211                CompatFile::New(file) => file,
212                // if it's a legacy file, use the C syscall handler instead
213                CompatFile::Legacy(_) => {
214                    drop(desc_table);
215                    return Self::legacy_syscall(cshadow::syscallhandler_lseek, ctx);
216                }
217            }
218        };
219
220        match file.inner_file() {
221            File::Pipe(_) => Err(Errno::ESPIPE.into()),
222            _ => {
223                warn_once_then_debug!("lseek() is not implemented for this type");
224                Err(Errno::ENOTSUP.into())
225            }
226        }
227    }
228
229    log_syscall!(
230        readahead,
231        /* rv */ std::ffi::c_int,
232        /* fd */ std::ffi::c_int,
233        /* offset */ linux_api::types::loff_t,
234        /* count */ linux_api::types::size_t
235    );
236    pub fn readahead(ctx: &mut SyscallContext) -> SyscallResult {
237        Self::legacy_syscall(cshadow::syscallhandler_readahead, ctx)
238    }
239
240    log_syscall!(
241        sync_file_range,
242        /* rv */ std::ffi::c_int,
243        /* fd */ std::ffi::c_int,
244        /* offset */ linux_api::types::loff_t,
245        /* nbytes */ linux_api::types::loff_t,
246        /* flags */ std::ffi::c_uint
247    );
248    pub fn sync_file_range(ctx: &mut SyscallContext) -> SyscallResult {
249        Self::legacy_syscall(cshadow::syscallhandler_sync_file_range, ctx)
250    }
251
252    log_syscall!(
253        syncfs,
254        /* rv */ std::ffi::c_int,
255        /* fd */ std::ffi::c_int
256    );
257    pub fn syncfs(ctx: &mut SyscallContext) -> SyscallResult {
258        Self::legacy_syscall(cshadow::syscallhandler_syncfs, ctx)
259    }
260}