• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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