@@ -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 { data , attr } ) ) ,
369364 }
370365 }
371366}
@@ -464,6 +459,44 @@ 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): {filename:?}; {e}" ,
475+ ) ;
476+ Errno :: Inval
477+ } ) ?;
478+
479+ let mode = i. posix_header ( ) . mode . to_flags ( ) . map_err ( |e| {
480+ error ! (
481+ "[Hermit image] Tar entry {filename:?} has invalid mode: {:?}; {e}" ,
482+ i. posix_header( ) . mode,
483+ ) ;
484+ Errno :: Inval
485+ } ) ?;
486+ let mode = AccessPermission :: from_bits ( mode. bits ( ) as u32 ) . ok_or_else ( || {
487+ error ! ( "[Hermit image] Tar entry {filename:?} has invalid mode: {mode:?}" ) ;
488+ Errno :: Inval
489+ } ) ?;
490+
491+ this. traverse_create_file ( filename, i. data ( ) , mode)
492+ . inspect_err ( |e| {
493+ error ! ( "[Hermit image] Unable to write entry {filename:?}: {e}" ) ;
494+ } ) ?;
495+ }
496+
497+ Ok ( this)
498+ }
499+
467500 async fn async_traverse_open (
468501 & self ,
469502 path : & str ,
@@ -693,11 +726,16 @@ impl VfsNode for MemDirectory {
693726 return directory. traverse_create_file ( rest, data, mode) ;
694727 }
695728
696- let file = RomFile :: new ( data, mode) ;
697- self . inner
698- . write ( )
699- . await
700- . insert ( component. to_owned ( ) , Box :: new ( file) ) ;
729+ let file: Box < dyn VfsNode > = if mode. contains ( AccessPermission :: S_IWUSR )
730+ || mode. contains ( AccessPermission :: S_IWGRP )
731+ || mode. contains ( AccessPermission :: S_IWOTH )
732+ {
733+ Box :: new ( RamFile :: new_with_data ( data. to_vec ( ) , mode) )
734+ } else {
735+ Box :: new ( RomFile :: new ( data, mode) )
736+ } ;
737+
738+ self . inner . write ( ) . await . insert ( component. to_owned ( ) , file) ;
701739 Ok ( ( ) )
702740 } ,
703741 None ,
0 commit comments