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