@@ -122,15 +122,6 @@ pub(crate) struct RamFileInner {
122122 pub attr : FileAttr ,
123123}
124124
125- impl RamFileInner {
126- pub fn new ( attr : FileAttr ) -> Self {
127- Self {
128- data : Vec :: new ( ) ,
129- attr,
130- }
131- }
132- }
133-
134125pub struct RamFileInterface {
135126 /// Position within the file
136127 pos : Mutex < usize > ,
@@ -354,6 +345,10 @@ impl VfsNode for RamFile {
354345
355346impl RamFile {
356347 pub fn new ( mode : AccessPermission ) -> Self {
348+ Self :: new_with_data ( Vec :: new ( ) , mode)
349+ }
350+
351+ fn new_with_data ( data : Vec < u8 > , mode : AccessPermission ) -> Self {
357352 let microseconds = arch:: kernel:: systemtime:: now_micros ( ) ;
358353 let t = timespec:: from_usec ( microseconds as i64 ) ;
359354 let attr = FileAttr {
@@ -365,7 +360,7 @@ impl RamFile {
365360 } ;
366361
367362 Self {
368- data : Arc :: new ( RwLock :: new ( RamFileInner :: new ( attr) ) ) ,
363+ data : Arc :: new ( RwLock :: new ( RamFileInner { attr, data } ) ) ,
369364 }
370365 }
371366}
@@ -464,6 +459,50 @@ impl MemDirectory {
464459 }
465460 }
466461
462+ pub fn try_from_image ( image : & ' static [ u8 ] ) -> io:: Result < Self > {
463+ let this = Self :: new ( AccessPermission :: S_IRUSR ) ;
464+
465+ let taref = tar_no_std:: TarArchiveRef :: new ( image) . map_err ( |e| {
466+ error ! ( "[Hermit image] Tar file has invalid format: {e:?}" ) ;
467+ Errno :: Inval
468+ } ) ?;
469+
470+ for i in taref. entries ( ) {
471+ let filename = i. filename ( ) ;
472+ let filename = filename. as_str ( ) . map_err ( |e| {
473+ error ! (
474+ "[Hermit image] Tar entry has not supported filename (non UTF-8): {:?}; {}" ,
475+ filename, e,
476+ ) ;
477+ Errno :: Inval
478+ } ) ?;
479+
480+ let mode = i. posix_header ( ) . mode . to_flags ( ) . map_err ( |e| {
481+ error ! (
482+ "[Hermit image] Tar entry {:?} has invalid mode: {:?}; {}" ,
483+ filename,
484+ i. posix_header( ) . mode,
485+ e,
486+ ) ;
487+ Errno :: Inval
488+ } ) ?;
489+ let mode = AccessPermission :: from_bits ( mode. bits ( ) as u32 ) . ok_or_else ( || {
490+ error ! (
491+ "[Hermit image] Tar entry {:?} has invalid mode: {:?}" ,
492+ filename, mode,
493+ ) ;
494+ Errno :: Inval
495+ } ) ?;
496+
497+ this. traverse_create_file ( filename, i. data ( ) , mode)
498+ . inspect_err ( |e| {
499+ error ! ( "[Hermit image] Unable to write entry {:?}: {}" , filename, e, ) ;
500+ } ) ?;
501+ }
502+
503+ Ok ( this)
504+ }
505+
467506 async fn async_traverse_open (
468507 & self ,
469508 path : & str ,
@@ -693,11 +732,16 @@ impl VfsNode for MemDirectory {
693732 return directory. traverse_create_file ( rest, data, mode) ;
694733 }
695734
696- let file = RomFile :: new ( data, mode) ;
697- self . inner
698- . write ( )
699- . await
700- . insert ( component. to_owned ( ) , Box :: new ( file) ) ;
735+ let file: Box < dyn VfsNode > = if mode. contains ( AccessPermission :: S_IWUSR )
736+ || mode. contains ( AccessPermission :: S_IWGRP )
737+ || mode. contains ( AccessPermission :: S_IWOTH )
738+ {
739+ Box :: new ( RamFile :: new_with_data ( data. to_vec ( ) , mode) )
740+ } else {
741+ Box :: new ( RomFile :: new ( data, mode) )
742+ } ;
743+
744+ self . inner . write ( ) . await . insert ( component. to_owned ( ) , file) ;
701745 Ok ( ( ) )
702746 } ,
703747 None ,
0 commit comments