@@ -32,6 +32,7 @@ pub struct OpenOptions {
3232 write : bool ,
3333 append : bool ,
3434 truncate : bool ,
35+ create : bool ,
3536 create_new : bool ,
3637}
3738
@@ -131,7 +132,7 @@ impl FileType {
131132 }
132133
133134 pub fn is_symlink ( & self ) -> bool {
134- // No symlinks in vexos; entries are either files or directories.
135+ // No symlinks in VEXos - entries are either files or directories.
135136 false
136137 }
137138}
@@ -170,7 +171,14 @@ impl DirEntry {
170171
171172impl OpenOptions {
172173 pub fn new ( ) -> OpenOptions {
173- OpenOptions { read : false , write : false , append : false , truncate : false , create_new : false }
174+ OpenOptions {
175+ read : false ,
176+ write : false ,
177+ append : false ,
178+ truncate : false ,
179+ create : false ,
180+ create_new : false ,
181+ }
174182 }
175183
176184 pub fn read ( & mut self , read : bool ) {
@@ -186,7 +194,7 @@ impl OpenOptions {
186194 self . truncate = truncate;
187195 }
188196 pub fn create ( & mut self , create : bool ) {
189- self . write = create;
197+ self . create = create;
190198 }
191199 pub fn create_new ( & mut self , create_new : bool ) {
192200 self . create_new = create_new;
@@ -195,51 +203,65 @@ impl OpenOptions {
195203
196204impl File {
197205 pub fn open ( path : & Path , opts : & OpenOptions ) -> io:: Result < File > {
198- // Mount sdcard volume as FAT filesystem
199- map_fresult ( unsafe { vex_sdk:: vexFileMountSD ( ) } ) ?;
200-
201206 let path = CString :: new ( path. as_os_str ( ) . as_encoded_bytes ( ) ) . map_err ( |_| {
202207 io:: Error :: new ( io:: ErrorKind :: InvalidData , "Path contained a null byte" )
203208 } ) ?;
204209
205- if opts. write && opts. read {
206- return Err ( io:: Error :: new (
207- io:: ErrorKind :: InvalidInput ,
208- "Files cannot be opened with read and write access" ,
209- ) ) ;
210- }
211- if opts. create_new {
212- let file_exists = unsafe { vex_sdk:: vexFileStatus ( path. as_ptr ( ) ) } ;
213- if file_exists != 0 {
214- return Err ( io:: Error :: new ( io:: ErrorKind :: AlreadyExists , "File already exists" ) ) ;
215- }
216- }
210+ let file =
211+ match ( opts. read , opts. write , opts. append , opts. truncate , opts. create , opts. create_new )
212+ {
213+ // read + write - unsupported
214+ ( true , true , _, _, _, _) => {
215+ return Err ( io:: Error :: new (
216+ io:: ErrorKind :: InvalidInput ,
217+ "Opening files in both read and write mode is unsupported" ,
218+ ) ) ;
219+ }
217220
218- let file = if opts. read && !opts. write {
219- // The second argument to this function is ignored.
220- // Open in read only mode
221- unsafe { vex_sdk:: vexFileOpen ( path. as_ptr ( ) , c"" . as_ptr ( ) ) }
222- } else if opts. write && opts. append {
223- // Open in write and append mode
224- unsafe { vex_sdk:: vexFileOpenWrite ( path. as_ptr ( ) ) }
225- } else if opts. write && opts. truncate {
226- // Open in write mode
227- unsafe { vex_sdk:: vexFileOpenCreate ( path. as_ptr ( ) ) }
228- } else if opts. write {
229- unsafe {
230- // Open in read/write and append mode
231- let fd = vex_sdk:: vexFileOpenWrite ( path. as_ptr ( ) ) ;
232- // Seek to beginning of the file
233- vex_sdk:: vexFileSeek ( fd, 0 , 0 ) ;
234-
235- fd
236- }
237- } else {
238- return Err ( io:: Error :: new (
239- io:: ErrorKind :: InvalidInput ,
240- "Files cannot be opened without read or write access" ,
241- ) ) ;
242- } ;
221+ // read
222+ ( true , false , _, false , false , false ) => unsafe {
223+ vex_sdk:: vexFileOpen ( path. as_ptr ( ) , c"" . as_ptr ( ) )
224+ } ,
225+
226+ // append
227+ ( false , _, true , false , create, create_new) => unsafe {
228+ if create_new && vex_sdk:: vexFileStatus ( path. as_ptr ( ) ) != 0 {
229+ return Err ( io:: Error :: new ( io:: ErrorKind :: AlreadyExists , "File exists" ) ) ;
230+ } else if !create && vex_sdk:: vexFileStatus ( path. as_ptr ( ) ) == 0 {
231+ return Err ( io:: Error :: new (
232+ io:: ErrorKind :: NotFound ,
233+ "No such file or directory" ,
234+ ) ) ;
235+ }
236+
237+ vex_sdk:: vexFileOpenWrite ( path. as_ptr ( ) )
238+ } ,
239+
240+ // write
241+ ( false , true , false , truncate, create, create_new) => unsafe {
242+ if create_new && vex_sdk:: vexFileStatus ( path. as_ptr ( ) ) != 0 {
243+ return Err ( io:: Error :: new ( io:: ErrorKind :: AlreadyExists , "File exists" ) ) ;
244+ } else if !create && vex_sdk:: vexFileStatus ( path. as_ptr ( ) ) == 0 {
245+ return Err ( io:: Error :: new (
246+ io:: ErrorKind :: NotFound ,
247+ "No such file or directory" ,
248+ ) ) ;
249+ }
250+
251+ if truncate {
252+ unsafe { vex_sdk:: vexFileOpenCreate ( path. as_ptr ( ) ) }
253+ } else {
254+ // Open in append, but jump to the start of the file.
255+ let fd = vex_sdk:: vexFileOpenWrite ( path. as_ptr ( ) ) ;
256+ vex_sdk:: vexFileSeek ( fd, 0 , 0 ) ;
257+ fd
258+ }
259+ } ,
260+
261+ _ => {
262+ return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput , "Invalid argument" ) ) ;
263+ }
264+ } ;
243265
244266 if file. is_null ( ) {
245267 Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "Could not open file" ) )
@@ -288,6 +310,7 @@ impl File {
288310 let len = buf. len ( ) as _ ;
289311 let buf_ptr = buf. as_mut_ptr ( ) ;
290312 let read = unsafe { vex_sdk:: vexFileRead ( buf_ptr. cast ( ) , 1 , len, self . fd . 0 ) } ;
313+
291314 if read < 0 {
292315 Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Could not read from file" ) )
293316 } else {
@@ -313,6 +336,7 @@ impl File {
313336 let buf_ptr = buf. as_ptr ( ) ;
314337 let written =
315338 unsafe { vex_sdk:: vexFileWrite ( buf_ptr. cast_mut ( ) . cast ( ) , 1 , len as _ , self . fd . 0 ) } ;
339+
316340 if written < 0 {
317341 Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Could not write to file" ) )
318342 } else {
@@ -338,6 +362,7 @@ impl File {
338362
339363 pub fn tell ( & self ) -> io:: Result < u64 > {
340364 let position = unsafe { vex_sdk:: vexFileTell ( self . fd . 0 ) } ;
365+
341366 position. try_into ( ) . map_err ( |_| {
342367 io:: Error :: new ( io:: ErrorKind :: InvalidData , "Failed to get current location in file" )
343368 } )
0 commit comments