xref: /aosp_15_r20/external/crosvm/base/src/sys/windows/punch_hole.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::fs::File;
6 use std::io;
7 use std::io::Error;
8 
9 use win_util::LargeInteger;
10 pub use winapi::um::winioctl::FSCTL_SET_ZERO_DATA;
11 use winapi::um::winnt::LARGE_INTEGER;
12 
13 // This struct is not implemented in the winapi so we need to implement it ourselves
14 #[repr(C)]
15 #[allow(non_snake_case)] // to match win32 naming api.
16 #[allow(non_camel_case_types)]
17 struct FILE_ZERO_DATA_INFORMATION {
18     FileOffset: LARGE_INTEGER,
19     BeyondFinalZero: LARGE_INTEGER,
20 }
21 
file_punch_hole(handle: &File, offset: u64, length: u64) -> io::Result<()>22 pub(crate) fn file_punch_hole(handle: &File, offset: u64, length: u64) -> io::Result<()> {
23     let large_offset = if offset > i64::MAX as u64 {
24         return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
25     } else {
26         LargeInteger::new(offset as i64)
27     };
28 
29     if (offset + length) > i64::MAX as u64 {
30         return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
31     }
32 
33     let end_offset = LargeInteger::new((offset + length) as i64);
34 
35     let zero_data = FILE_ZERO_DATA_INFORMATION {
36         FileOffset: *large_offset,
37         BeyondFinalZero: *end_offset,
38     };
39 
40     // SAFETY:
41     // Safe because we check the return value and all values should be set
42     let result = unsafe { super::ioctl::ioctl_with_ref(handle, FSCTL_SET_ZERO_DATA, &zero_data) };
43 
44     if result != 0 {
45         return Err(Error::from_raw_os_error(result));
46     }
47 
48     Ok(())
49 }
50