4
4
5
5
use std:: io:: prelude:: * ;
6
6
7
- use embedded_sdmmc:: { Error , RawDirectory , RawVolume , VolumeIdx , VolumeManager } ;
7
+ use embedded_sdmmc:: { Error as EsError , RawDirectory , RawVolume , VolumeIdx , VolumeManager } ;
8
8
9
9
use crate :: linux:: { Clock , LinuxBlockDevice } ;
10
10
11
+ type Error = EsError < std:: io:: Error > ;
12
+
11
13
mod linux;
12
14
13
15
struct VolumeState {
@@ -30,19 +32,149 @@ impl Context {
30
32
s. path . clone ( )
31
33
}
32
34
33
- fn process_line ( & mut self , line : & str ) -> Result < ( ) , Error < std:: io:: Error > > {
35
+ /// Print some help text
36
+ fn help ( & mut self ) -> Result < ( ) , Error > {
37
+ println ! ( "Commands:" ) ;
38
+ println ! ( "\t help -> this help text" ) ;
39
+ println ! ( "\t <volume>: -> change volume/partition" ) ;
40
+ println ! ( "\t stat -> print volume manager status" ) ;
41
+ println ! ( "\t dir [<path>] -> do a directory listing" ) ;
42
+ println ! ( "\t cd .. -> go up a level" ) ;
43
+ println ! ( "\t cd <path> -> change into directory <path>" ) ;
44
+ println ! ( "\t cat <path> -> print a text file" ) ;
45
+ println ! ( "\t hexdump <path> -> print a binary file" ) ;
46
+ println ! ( "\t mkdir <path> -> create an empty directory" ) ;
47
+ println ! ( "\t quit -> exits the program" ) ;
48
+ println ! ( ) ;
49
+ println ! ( "Paths can be:" ) ;
50
+ println ! ( ) ;
51
+ println ! ( "\t * Bare names, like `FILE.DAT`" ) ;
52
+ println ! ( "\t * Relative, like `../SOMEDIR/FILE.DAT` or `./FILE.DAT`" ) ;
53
+ println ! ( "\t * Absolute, like `1:/SOMEDIR/FILE.DAT`" ) ;
54
+ Ok ( ( ) )
55
+ }
56
+
57
+ /// Print volume manager status
58
+ fn stat ( & mut self ) -> Result < ( ) , Error > {
59
+ println ! ( "Status:\n {:#?}" , self . volume_mgr) ;
60
+ Ok ( ( ) )
61
+ }
62
+
63
+ /// Print a directory listing
64
+ fn dir ( & mut self ) -> Result < ( ) , Error > {
65
+ let Some ( s) = & self . volumes [ self . current_volume ] else {
66
+ println ! ( "That volume isn't available" ) ;
67
+ return Ok ( ( ) ) ;
68
+ } ;
69
+ self . volume_mgr . iterate_dir ( s. directory , |entry| {
70
+ println ! (
71
+ "{:12} {:9} {} {} {:X?} {:?}" ,
72
+ entry. name, entry. size, entry. ctime, entry. mtime, entry. cluster, entry. attributes
73
+ ) ;
74
+ } ) ?;
75
+ Ok ( ( ) )
76
+ }
77
+
78
+ /// Change into <dir>
79
+ ///
80
+ /// An arg of `..` goes up one level
81
+ fn cd ( & mut self , filename : & str ) -> Result < ( ) , Error > {
82
+ let Some ( s) = & mut self . volumes [ self . current_volume ] else {
83
+ println ! ( "This volume isn't available" ) ;
84
+ return Ok ( ( ) ) ;
85
+ } ;
86
+ let d = self . volume_mgr . open_dir ( s. directory , filename) ?;
87
+ self . volume_mgr . close_dir ( s. directory ) ?;
88
+ s. directory = d;
89
+ if filename == ".." {
90
+ s. path . pop ( ) ;
91
+ } else {
92
+ s. path . push ( filename. to_owned ( ) ) ;
93
+ }
94
+ Ok ( ( ) )
95
+ }
96
+
97
+ /// print a text file
98
+ fn cat ( & mut self , filename : & str ) -> Result < ( ) , Error > {
99
+ let Some ( s) = & mut self . volumes [ self . current_volume ] else {
100
+ println ! ( "This volume isn't available" ) ;
101
+ return Ok ( ( ) ) ;
102
+ } ;
103
+ let mut f = self
104
+ . volume_mgr
105
+ . open_file_in_dir ( s. directory , filename, embedded_sdmmc:: Mode :: ReadOnly ) ?
106
+ . to_file ( & mut self . volume_mgr ) ;
107
+ let mut data = Vec :: new ( ) ;
108
+ while !f. is_eof ( ) {
109
+ let mut buffer = vec ! [ 0u8 ; 65536 ] ;
110
+ let n = f. read ( & mut buffer) ?;
111
+ // read n bytes
112
+ data. extend_from_slice ( & buffer[ 0 ..n] ) ;
113
+ println ! ( "Read {} bytes, making {} total" , n, data. len( ) ) ;
114
+ }
115
+ if let Ok ( s) = std:: str:: from_utf8 ( & data) {
116
+ println ! ( "{}" , s) ;
117
+ } else {
118
+ println ! ( "I'm afraid that file isn't UTF-8 encoded" ) ;
119
+ }
120
+ Ok ( ( ) )
121
+ }
122
+
123
+ /// print a binary file
124
+ fn hexdump ( & mut self , filename : & str ) -> Result < ( ) , Error > {
125
+ let Some ( s) = & mut self . volumes [ self . current_volume ] else {
126
+ println ! ( "This volume isn't available" ) ;
127
+ return Ok ( ( ) ) ;
128
+ } ;
129
+ let mut f = self
130
+ . volume_mgr
131
+ . open_file_in_dir ( s. directory , filename, embedded_sdmmc:: Mode :: ReadOnly ) ?
132
+ . to_file ( & mut self . volume_mgr ) ;
133
+ let mut data = Vec :: new ( ) ;
134
+ while !f. is_eof ( ) {
135
+ let mut buffer = vec ! [ 0u8 ; 65536 ] ;
136
+ let n = f. read ( & mut buffer) ?;
137
+ // read n bytes
138
+ data. extend_from_slice ( & buffer[ 0 ..n] ) ;
139
+ println ! ( "Read {} bytes, making {} total" , n, data. len( ) ) ;
140
+ }
141
+ for ( idx, chunk) in data. chunks ( 16 ) . enumerate ( ) {
142
+ print ! ( "{:08x} | " , idx * 16 ) ;
143
+ for b in chunk {
144
+ print ! ( "{:02x} " , b) ;
145
+ }
146
+ for _padding in 0 ..( 16 - chunk. len ( ) ) {
147
+ print ! ( " " ) ;
148
+ }
149
+ print ! ( "| " ) ;
150
+ for b in chunk {
151
+ print ! (
152
+ "{}" ,
153
+ if b. is_ascii_graphic( ) {
154
+ * b as char
155
+ } else {
156
+ '.'
157
+ }
158
+ ) ;
159
+ }
160
+ println ! ( ) ;
161
+ }
162
+ Ok ( ( ) )
163
+ }
164
+
165
+ /// create a directory
166
+ fn mkdir ( & mut self , dir_name : & str ) -> Result < ( ) , Error > {
167
+ let Some ( s) = & mut self . volumes [ self . current_volume ] else {
168
+ println ! ( "This volume isn't available" ) ;
169
+ return Ok ( ( ) ) ;
170
+ } ;
171
+ // make the dir
172
+ self . volume_mgr . make_dir_in_dir ( s. directory , dir_name)
173
+ }
174
+
175
+ fn process_line ( & mut self , line : & str ) -> Result < ( ) , Error > {
34
176
if line == "help" {
35
- println ! ( "Commands:" ) ;
36
- println ! ( "\t help -> this help text" ) ;
37
- println ! ( "\t <volume>: -> change volume/partition" ) ;
38
- println ! ( "\t dir -> do a directory listing" ) ;
39
- println ! ( "\t stat -> print volume manager status" ) ;
40
- println ! ( "\t cat <file> -> print a text file" ) ;
41
- println ! ( "\t hexdump <file> -> print a binary file" ) ;
42
- println ! ( "\t cd .. -> go up a level" ) ;
43
- println ! ( "\t cd <dir> -> change into <dir>" ) ;
44
- println ! ( "\t mkdir <dir> -> create a directory called <dir>" ) ;
45
- println ! ( "\t quit -> exits the program" ) ;
177
+ self . help ( ) ?;
46
178
} else if line == "0:" {
47
179
self . current_volume = 0 ;
48
180
} else if line == "1:" {
@@ -51,108 +183,18 @@ impl Context {
51
183
self . current_volume = 2 ;
52
184
} else if line == "3:" {
53
185
self . current_volume = 3 ;
54
- } else if line == "stat" {
55
- println ! ( "Status:\n {:#?}" , self . volume_mgr) ;
56
186
} else if line == "dir" {
57
- let Some ( s) = & self . volumes [ self . current_volume ] else {
58
- println ! ( "That volume isn't available" ) ;
59
- return Ok ( ( ) ) ;
60
- } ;
61
- self . volume_mgr . iterate_dir ( s. directory , |entry| {
62
- println ! (
63
- "{:12} {:9} {} {} {:X?} {:?}" ,
64
- entry. name,
65
- entry. size,
66
- entry. ctime,
67
- entry. mtime,
68
- entry. cluster,
69
- entry. attributes
70
- ) ;
71
- } ) ?;
72
- } else if let Some ( arg) = line. strip_prefix ( "cd " ) {
73
- let arg = arg. trim ( ) ;
74
- let Some ( s) = & mut self . volumes [ self . current_volume ] else {
75
- println ! ( "This volume isn't available" ) ;
76
- return Ok ( ( ) ) ;
77
- } ;
78
- let d = self . volume_mgr . open_dir ( s. directory , arg) ?;
79
- self . volume_mgr . close_dir ( s. directory ) ?;
80
- s. directory = d;
81
- if arg == ".." {
82
- s. path . pop ( ) ;
83
- } else {
84
- s. path . push ( arg. to_owned ( ) ) ;
85
- }
86
- } else if let Some ( arg) = line. strip_prefix ( "cat " ) {
87
- let arg = arg. trim ( ) ;
88
- let Some ( s) = & mut self . volumes [ self . current_volume ] else {
89
- println ! ( "This volume isn't available" ) ;
90
- return Ok ( ( ) ) ;
91
- } ;
92
- let mut f = self
93
- . volume_mgr
94
- . open_file_in_dir ( s. directory , arg, embedded_sdmmc:: Mode :: ReadOnly ) ?
95
- . to_file ( & mut self . volume_mgr ) ;
96
- let mut data = Vec :: new ( ) ;
97
- while !f. is_eof ( ) {
98
- let mut buffer = vec ! [ 0u8 ; 65536 ] ;
99
- let n = f. read ( & mut buffer) ?;
100
- // read n bytes
101
- data. extend_from_slice ( & buffer[ 0 ..n] ) ;
102
- println ! ( "Read {} bytes, making {} total" , n, data. len( ) ) ;
103
- }
104
- if let Ok ( s) = std:: str:: from_utf8 ( & data) {
105
- println ! ( "{}" , s) ;
106
- } else {
107
- println ! ( "I'm afraid that file isn't UTF-8 encoded" ) ;
108
- }
109
- } else if let Some ( arg) = line. strip_prefix ( "hexdump " ) {
110
- let arg = arg. trim ( ) ;
111
- let Some ( s) = & mut self . volumes [ self . current_volume ] else {
112
- println ! ( "This volume isn't available" ) ;
113
- return Ok ( ( ) ) ;
114
- } ;
115
- let mut f = self
116
- . volume_mgr
117
- . open_file_in_dir ( s. directory , arg, embedded_sdmmc:: Mode :: ReadOnly ) ?
118
- . to_file ( & mut self . volume_mgr ) ;
119
- let mut data = Vec :: new ( ) ;
120
- while !f. is_eof ( ) {
121
- let mut buffer = vec ! [ 0u8 ; 65536 ] ;
122
- let n = f. read ( & mut buffer) ?;
123
- // read n bytes
124
- data. extend_from_slice ( & buffer[ 0 ..n] ) ;
125
- println ! ( "Read {} bytes, making {} total" , n, data. len( ) ) ;
126
- }
127
- for ( idx, chunk) in data. chunks ( 16 ) . enumerate ( ) {
128
- print ! ( "{:08x} | " , idx * 16 ) ;
129
- for b in chunk {
130
- print ! ( "{:02x} " , b) ;
131
- }
132
- for _padding in 0 ..( 16 - chunk. len ( ) ) {
133
- print ! ( " " ) ;
134
- }
135
- print ! ( "| " ) ;
136
- for b in chunk {
137
- print ! (
138
- "{}" ,
139
- if b. is_ascii_graphic( ) {
140
- * b as char
141
- } else {
142
- '.'
143
- }
144
- ) ;
145
- }
146
- println ! ( ) ;
147
- }
148
- } else if let Some ( arg) = line. strip_prefix ( "mkdir " ) {
149
- let arg = arg. trim ( ) ;
150
- let Some ( s) = & mut self . volumes [ self . current_volume ] else {
151
- println ! ( "This volume isn't available" ) ;
152
- return Ok ( ( ) ) ;
153
- } ;
154
- // make the dir
155
- self . volume_mgr . make_dir_in_dir ( s. directory , arg) ?;
187
+ self . dir ( ) ?;
188
+ } else if line == "stat" {
189
+ self . stat ( ) ?;
190
+ } else if let Some ( dirname) = line. strip_prefix ( "cd " ) {
191
+ self . cd ( dirname. trim ( ) ) ?;
192
+ } else if let Some ( filename) = line. strip_prefix ( "cat " ) {
193
+ self . cat ( filename. trim ( ) ) ?;
194
+ } else if let Some ( filename) = line. strip_prefix ( "hexdump " ) {
195
+ self . hexdump ( filename. trim ( ) ) ?;
196
+ } else if let Some ( dirname) = line. strip_prefix ( "mkdir " ) {
197
+ self . mkdir ( dirname. trim ( ) ) ?;
156
198
} else {
157
199
println ! ( "Unknown command {line:?} - try 'help' for help" ) ;
158
200
}
@@ -178,7 +220,7 @@ impl Drop for Context {
178
220
}
179
221
}
180
222
181
- fn main ( ) -> Result < ( ) , Error < std :: io :: Error > > {
223
+ fn main ( ) -> Result < ( ) , Error > {
182
224
env_logger:: init ( ) ;
183
225
let mut args = std:: env:: args ( ) . skip ( 1 ) ;
184
226
let filename = args. next ( ) . unwrap_or_else ( || "/dev/mmcblk0" . into ( ) ) ;
0 commit comments