idb/cli/app.rs
1use clap::{Parser, Subcommand, ValueEnum};
2
3#[derive(Parser)]
4#[command(name = "inno")]
5#[command(about = "InnoDB file analysis toolkit")]
6#[command(version)]
7pub struct Cli {
8 /// Control colored output
9 #[arg(long, default_value = "auto", global = true)]
10 pub color: ColorMode,
11
12 /// Write output to a file instead of stdout
13 #[arg(short, long, global = true)]
14 pub output: Option<String>,
15
16 #[command(subcommand)]
17 pub command: Commands,
18}
19
20#[derive(Clone, Copy, ValueEnum)]
21pub enum ColorMode {
22 Auto,
23 Always,
24 Never,
25}
26
27#[derive(Subcommand)]
28pub enum Commands {
29 /// Parse .ibd file and display page summary
30 Parse {
31 /// Path to InnoDB data file (.ibd)
32 #[arg(short, long)]
33 file: String,
34
35 /// Display a specific page number
36 #[arg(short, long)]
37 page: Option<u64>,
38
39 /// Display additional information
40 #[arg(short, long)]
41 verbose: bool,
42
43 /// Skip empty/allocated pages
44 #[arg(short = 'e', long = "no-empty")]
45 no_empty: bool,
46
47 /// Output in JSON format
48 #[arg(long)]
49 json: bool,
50
51 /// Override page size (default: auto-detect)
52 #[arg(long = "page-size")]
53 page_size: Option<u32>,
54 },
55
56 /// Detailed page structure analysis
57 Pages {
58 /// Path to InnoDB data file (.ibd)
59 #[arg(short, long)]
60 file: String,
61
62 /// Display a specific page number
63 #[arg(short, long)]
64 page: Option<u64>,
65
66 /// Display additional information
67 #[arg(short, long)]
68 verbose: bool,
69
70 /// Show empty/allocated pages
71 #[arg(short = 'e', long = "show-empty")]
72 show_empty: bool,
73
74 /// Compact list mode (one line per page)
75 #[arg(short, long)]
76 list: bool,
77
78 /// Filter by page type (e.g., INDEX)
79 #[arg(short = 't', long = "type")]
80 filter_type: Option<String>,
81
82 /// Output in JSON format
83 #[arg(long)]
84 json: bool,
85
86 /// Override page size (default: auto-detect)
87 #[arg(long = "page-size")]
88 page_size: Option<u32>,
89 },
90
91 /// Hex dump of raw page bytes
92 Dump {
93 /// Path to InnoDB data file
94 #[arg(short, long)]
95 file: String,
96
97 /// Page number to dump (default: 0)
98 #[arg(short, long)]
99 page: Option<u64>,
100
101 /// Absolute byte offset to start dumping (bypasses page mode)
102 #[arg(long)]
103 offset: Option<u64>,
104
105 /// Number of bytes to dump (default: page size or 256 for offset mode)
106 #[arg(short, long)]
107 length: Option<usize>,
108
109 /// Output raw binary bytes (no formatting)
110 #[arg(long)]
111 raw: bool,
112
113 /// Override page size (default: auto-detect)
114 #[arg(long = "page-size")]
115 page_size: Option<u32>,
116 },
117
118 /// Intentionally corrupt pages for testing
119 Corrupt {
120 /// Path to data file
121 #[arg(short, long)]
122 file: String,
123
124 /// Page number to corrupt (random if not specified)
125 #[arg(short, long)]
126 page: Option<u64>,
127
128 /// Number of bytes to corrupt
129 #[arg(short, long, default_value = "1")]
130 bytes: usize,
131
132 /// Corrupt the FIL header area
133 #[arg(short = 'k', long = "header")]
134 header: bool,
135
136 /// Corrupt the record data area
137 #[arg(short, long)]
138 records: bool,
139
140 /// Absolute byte offset to corrupt (bypasses page calculation)
141 #[arg(long)]
142 offset: Option<u64>,
143
144 /// Show before/after checksum comparison
145 #[arg(long)]
146 verify: bool,
147
148 /// Output in JSON format
149 #[arg(long)]
150 json: bool,
151
152 /// Override page size (default: auto-detect)
153 #[arg(long = "page-size")]
154 page_size: Option<u32>,
155 },
156
157 /// Search for pages across data directory
158 Find {
159 /// MySQL data directory path
160 #[arg(short, long)]
161 datadir: String,
162
163 /// Page number to search for
164 #[arg(short, long)]
165 page: u64,
166
167 /// Checksum to match
168 #[arg(short, long)]
169 checksum: Option<u32>,
170
171 /// Space ID to match
172 #[arg(short, long)]
173 space_id: Option<u32>,
174
175 /// Stop at first match
176 #[arg(long)]
177 first: bool,
178
179 /// Output in JSON format
180 #[arg(long)]
181 json: bool,
182
183 /// Override page size (default: auto-detect)
184 #[arg(long = "page-size")]
185 page_size: Option<u32>,
186 },
187
188 /// List/find tablespace IDs
189 Tsid {
190 /// MySQL data directory path
191 #[arg(short, long)]
192 datadir: String,
193
194 /// List all tablespace IDs
195 #[arg(short, long)]
196 list: bool,
197
198 /// Find table file by tablespace ID
199 #[arg(short = 't', long = "tsid")]
200 tablespace_id: Option<u32>,
201
202 /// Output in JSON format
203 #[arg(long)]
204 json: bool,
205
206 /// Override page size (default: auto-detect)
207 #[arg(long = "page-size")]
208 page_size: Option<u32>,
209 },
210
211 /// Extract SDI metadata (MySQL 8.0+)
212 Sdi {
213 /// Path to InnoDB data file (.ibd)
214 #[arg(short, long)]
215 file: String,
216
217 /// Pretty-print JSON output
218 #[arg(short, long)]
219 pretty: bool,
220
221 /// Override page size (default: auto-detect)
222 #[arg(long = "page-size")]
223 page_size: Option<u32>,
224 },
225
226 /// Analyze InnoDB redo log files
227 Log {
228 /// Path to redo log file (ib_logfile0, ib_logfile1, or #ib_redo*)
229 #[arg(short, long)]
230 file: String,
231
232 /// Limit to first N data blocks
233 #[arg(short, long)]
234 blocks: Option<u64>,
235
236 /// Skip empty blocks
237 #[arg(long)]
238 no_empty: bool,
239
240 /// Display additional information
241 #[arg(short, long)]
242 verbose: bool,
243
244 /// Output in JSON format
245 #[arg(long)]
246 json: bool,
247 },
248
249 /// Show InnoDB file and system information
250 Info {
251 /// Inspect ibdata1 page 0 header
252 #[arg(long)]
253 ibdata: bool,
254
255 /// Compare ibdata1 and redo log LSNs
256 #[arg(long = "lsn-check")]
257 lsn_check: bool,
258
259 /// MySQL data directory path
260 #[arg(short, long)]
261 datadir: Option<String>,
262
263 /// Database name (for table/index info)
264 #[arg(short = 'D', long)]
265 database: Option<String>,
266
267 /// Table name (for table/index info)
268 #[arg(short, long)]
269 table: Option<String>,
270
271 /// MySQL host
272 #[arg(long)]
273 host: Option<String>,
274
275 /// MySQL port
276 #[arg(long)]
277 port: Option<u16>,
278
279 /// MySQL user
280 #[arg(long)]
281 user: Option<String>,
282
283 /// MySQL password
284 #[arg(long)]
285 password: Option<String>,
286
287 /// Path to MySQL defaults file (.my.cnf)
288 #[arg(long = "defaults-file")]
289 defaults_file: Option<String>,
290
291 /// Output in JSON format
292 #[arg(long)]
293 json: bool,
294
295 /// Override page size (default: auto-detect)
296 #[arg(long = "page-size")]
297 page_size: Option<u32>,
298 },
299
300 /// Validate page checksums
301 Checksum {
302 /// Path to InnoDB data file (.ibd)
303 #[arg(short, long)]
304 file: String,
305
306 /// Show per-page checksum details
307 #[arg(short, long)]
308 verbose: bool,
309
310 /// Output in JSON format
311 #[arg(long)]
312 json: bool,
313
314 /// Override page size (default: auto-detect)
315 #[arg(long = "page-size")]
316 page_size: Option<u32>,
317 },
318}