1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 pub(crate) static DEFAULT_IO_DEPTH: u16 = 2;
16 pub(crate) static DEFAULT_MAX_FDS: u16 = 128;
17 pub(crate) static DEFAULT_EXIT_ON_ERROR: bool = false;
18
19 mod args_argh;
20 use args_argh as args_internal;
21
22 use std::path::Path;
23 use std::path::PathBuf;
24 use std::process::exit;
25
26 pub use args_internal::OutputFormat;
27 pub use args_internal::ReplayArgs;
28 pub use args_internal::TracerType;
29 pub use args_internal::{DumpArgs, MainArgs, RecordArgs, SubCommands};
30 use serde::Deserialize;
31 use serde::Serialize;
32
33 use crate::Error;
34 use log::error;
35
36 // Deserialized form of the config file
37 #[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
38 pub struct ConfigFile {
39 // Files to be excluded in prefetch. These files might have been
40 // added in the record file while recording,but we do not want to
41 // replay these files. These can be two types of files:
42 // 1) installation-specific files (e.g. files in /data) and
43 // 2) large files which we do not want to load in replay (e.g. APK files).
44 pub files_to_exclude_regex: Vec<String>,
45 // Files that are not in the record file, but need to be loaded during replay
46 pub additional_replay_files: Vec<String>,
47 }
48
verify_and_fix(args: &mut MainArgs) -> Result<(), Error>49 fn verify_and_fix(args: &mut MainArgs) -> Result<(), Error> {
50 match &mut args.nested {
51 SubCommands::Record(arg) => {
52 if arg.debug && arg.int_path.is_none() {
53 arg.int_path = Some(PathBuf::from(format!("{}.int", arg.path.to_str().unwrap())));
54 }
55
56 if let Some(p) = &arg.int_path {
57 ensure_path_doesnt_exist(p)?;
58 }
59 }
60 SubCommands::Replay(arg) => {
61 ensure_path_exists(&arg.path)?;
62 if !arg.config_path.as_os_str().is_empty() {
63 ensure_path_exists(&arg.config_path)?;
64 }
65 }
66 SubCommands::Dump(arg) => {
67 ensure_path_exists(&arg.path)?;
68 }
69 }
70 Ok(())
71 }
72
73 /// Returns error if the given path at `p` exist.
ensure_path_doesnt_exist(p: &Path) -> Result<(), Error>74 pub(crate) fn ensure_path_doesnt_exist(p: &Path) -> Result<(), Error> {
75 if p.exists() {
76 Err(Error::InvalidArgs {
77 arg_name: "path".to_string(),
78 arg_value: p.display().to_string(),
79 error: "Path already exists".to_string(),
80 })
81 } else {
82 Ok(())
83 }
84 }
85
86 /// Returns error if the given path at `p` doesn't exist.
ensure_path_exists(p: &Path) -> Result<(), Error>87 pub(crate) fn ensure_path_exists(p: &Path) -> Result<(), Error> {
88 if p.is_file() {
89 Ok(())
90 } else {
91 Err(Error::InvalidArgs {
92 arg_name: "path".to_string(),
93 arg_value: p.display().to_string(),
94 error: "Path does not exist".to_string(),
95 })
96 }
97 }
98
99 /// Builds `MainArgs` from command line arguments. On error prints error/help message
100 /// and exits.
args_from_env() -> MainArgs101 pub fn args_from_env() -> MainArgs {
102 let mut args = args_internal::args_from_env();
103 if let Err(e) = verify_and_fix(&mut args) {
104 error!("failed to verify args: {}", e);
105 exit(1);
106 }
107 args
108 }
109