1 // Copyright 2022 The Chromium OS Authors. All rights reserved.
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 crate::descriptor::AsRawDescriptor;
6 use std::io::{
7 Error, {self},
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
execute_punch_hole<T: AsRawDescriptor>( handle: &mut T, offset: u64, length: u64, ) -> io::Result<()>22 pub fn execute_punch_hole<T: AsRawDescriptor>(
23 handle: &mut T,
24 offset: u64,
25 length: u64,
26 ) -> io::Result<()> {
27 let large_offset = if offset > std::i64::MAX as u64 {
28 return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
29 } else {
30 LargeInteger::new(offset as i64)
31 };
32
33 if (offset + length) > std::i64::MAX as u64 {
34 return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
35 }
36
37 let end_offset = LargeInteger::new((offset + length) as i64);
38
39 let zero_data = FILE_ZERO_DATA_INFORMATION {
40 FileOffset: *large_offset,
41 BeyondFinalZero: *end_offset,
42 };
43
44 // Safe because we check the return value and all values should be set
45 let result =
46 unsafe { super::super::ioctl::ioctl_with_ref(handle, FSCTL_SET_ZERO_DATA, &zero_data) };
47
48 if result != 0 {
49 return Err(Error::from_raw_os_error(result));
50 }
51
52 Ok(())
53 }
54