44
55use std:: io:: prelude:: * ;
66
7- use embedded_sdmmc:: { Error , RawDirectory , RawVolume , VolumeIdx , VolumeManager } ;
7+ use embedded_sdmmc:: { Error as EsError , RawDirectory , RawVolume , VolumeIdx , VolumeManager } ;
88
99use crate :: linux:: { Clock , LinuxBlockDevice } ;
1010
11+ type Error = EsError < std:: io:: Error > ;
12+
1113mod linux;
1214
1315struct VolumeState {
@@ -30,19 +32,149 @@ impl Context {
3032 s. path . clone ( )
3133 }
3234
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 > {
34176 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 ( ) ?;
46178 } else if line == "0:" {
47179 self . current_volume = 0 ;
48180 } else if line == "1:" {
@@ -51,108 +183,18 @@ impl Context {
51183 self . current_volume = 2 ;
52184 } else if line == "3:" {
53185 self . current_volume = 3 ;
54- } else if line == "stat" {
55- println ! ( "Status:\n {:#?}" , self . volume_mgr) ;
56186 } 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 ( ) ) ?;
156198 } else {
157199 println ! ( "Unknown command {line:?} - try 'help' for help" ) ;
158200 }
@@ -178,7 +220,7 @@ impl Drop for Context {
178220 }
179221}
180222
181- fn main ( ) -> Result < ( ) , Error < std :: io :: Error > > {
223+ fn main ( ) -> Result < ( ) , Error > {
182224 env_logger:: init ( ) ;
183225 let mut args = std:: env:: args ( ) . skip ( 1 ) ;
184226 let filename = args. next ( ) . unwrap_or_else ( || "/dev/mmcblk0" . into ( ) ) ;
0 commit comments