Skip to main content

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}