xref: /aosp_15_r20/external/crosvm/disk/src/sys/windows.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Seek;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::SeekFrom;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::os::windows::fs::OpenOptionsExt;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::read_overlapped_blocking;
13*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::Executor;
14*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::FILE_FLAG_NO_BUFFERING;
15*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
16*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winnt::FILE_SHARE_READ;
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::DiskFileParams;
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::SingleFileDisk;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker impl SingleFileDisk {
new(disk: File, ex: &Executor) -> Result<Self>24*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(disk: File, ex: &Executor) -> Result<Self> {
25*bb4ee6a4SAndroid Build Coastguard Worker         ex.async_overlapped_from(disk)
26*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::CreateSingleFileDisk)
27*bb4ee6a4SAndroid Build Coastguard Worker             .map(|inner| SingleFileDisk { inner })
28*bb4ee6a4SAndroid Build Coastguard Worker     }
29*bb4ee6a4SAndroid Build Coastguard Worker }
30*bb4ee6a4SAndroid Build Coastguard Worker 
open_raw_disk_image(params: &DiskFileParams) -> Result<File>31*bb4ee6a4SAndroid Build Coastguard Worker pub fn open_raw_disk_image(params: &DiskFileParams) -> Result<File> {
32*bb4ee6a4SAndroid Build Coastguard Worker     let mut options = File::options();
33*bb4ee6a4SAndroid Build Coastguard Worker     options.read(true).write(!params.is_read_only);
34*bb4ee6a4SAndroid Build Coastguard Worker     if params.lock {
35*bb4ee6a4SAndroid Build Coastguard Worker         if params.is_read_only {
36*bb4ee6a4SAndroid Build Coastguard Worker             // Shared read-only file access.
37*bb4ee6a4SAndroid Build Coastguard Worker             options.share_mode(FILE_SHARE_READ);
38*bb4ee6a4SAndroid Build Coastguard Worker         } else {
39*bb4ee6a4SAndroid Build Coastguard Worker             // Exclusive file access.
40*bb4ee6a4SAndroid Build Coastguard Worker             options.share_mode(0);
41*bb4ee6a4SAndroid Build Coastguard Worker         }
42*bb4ee6a4SAndroid Build Coastguard Worker     }
43*bb4ee6a4SAndroid Build Coastguard Worker 
44*bb4ee6a4SAndroid Build Coastguard Worker     let mut flags = 0;
45*bb4ee6a4SAndroid Build Coastguard Worker     if params.is_direct {
46*bb4ee6a4SAndroid Build Coastguard Worker         info!("Opening disk file with no buffering");
47*bb4ee6a4SAndroid Build Coastguard Worker         flags |= FILE_FLAG_NO_BUFFERING;
48*bb4ee6a4SAndroid Build Coastguard Worker     }
49*bb4ee6a4SAndroid Build Coastguard Worker     if params.is_overlapped {
50*bb4ee6a4SAndroid Build Coastguard Worker         info!("Opening disk file for overlapped IO");
51*bb4ee6a4SAndroid Build Coastguard Worker         flags |= FILE_FLAG_OVERLAPPED;
52*bb4ee6a4SAndroid Build Coastguard Worker     }
53*bb4ee6a4SAndroid Build Coastguard Worker     if flags != 0 {
54*bb4ee6a4SAndroid Build Coastguard Worker         options.custom_flags(flags);
55*bb4ee6a4SAndroid Build Coastguard Worker     }
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker     let raw_image = base::open_file_or_duplicate(&params.path, &options)
58*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|e| Error::OpenFile(params.path.display().to_string(), e))?;
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker     Ok(raw_image)
61*bb4ee6a4SAndroid Build Coastguard Worker }
62*bb4ee6a4SAndroid Build Coastguard Worker 
63*bb4ee6a4SAndroid Build Coastguard Worker /// On Windows, if the file is sparse, we set the option. On Linux this is not needed.
apply_raw_disk_file_options(raw_image: &File, is_sparse_file: bool) -> Result<()>64*bb4ee6a4SAndroid Build Coastguard Worker pub fn apply_raw_disk_file_options(raw_image: &File, is_sparse_file: bool) -> Result<()> {
65*bb4ee6a4SAndroid Build Coastguard Worker     if is_sparse_file {
66*bb4ee6a4SAndroid Build Coastguard Worker         base::set_sparse_file(raw_image).map_err(Error::SetSparseFailure)?;
67*bb4ee6a4SAndroid Build Coastguard Worker     }
68*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
69*bb4ee6a4SAndroid Build Coastguard Worker }
70*bb4ee6a4SAndroid Build Coastguard Worker 
read_from_disk( mut file: &File, offset: u64, buf: &mut [u8], overlapped_mode: bool, ) -> Result<()>71*bb4ee6a4SAndroid Build Coastguard Worker pub fn read_from_disk(
72*bb4ee6a4SAndroid Build Coastguard Worker     mut file: &File,
73*bb4ee6a4SAndroid Build Coastguard Worker     offset: u64,
74*bb4ee6a4SAndroid Build Coastguard Worker     buf: &mut [u8],
75*bb4ee6a4SAndroid Build Coastguard Worker     overlapped_mode: bool,
76*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
77*bb4ee6a4SAndroid Build Coastguard Worker     file.seek(SeekFrom::Start(offset))
78*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::SeekingFile)?;
79*bb4ee6a4SAndroid Build Coastguard Worker     if overlapped_mode {
80*bb4ee6a4SAndroid Build Coastguard Worker         read_overlapped_blocking(file, offset, buf)
81*bb4ee6a4SAndroid Build Coastguard Worker             .map(|_| ())
82*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::ReadingHeader)
83*bb4ee6a4SAndroid Build Coastguard Worker     } else {
84*bb4ee6a4SAndroid Build Coastguard Worker         file.read_exact(buf).map_err(Error::ReadingHeader)
85*bb4ee6a4SAndroid Build Coastguard Worker     }
86*bb4ee6a4SAndroid Build Coastguard Worker }
87