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(¶ms.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