@ -1,10 +1,9 @@
use crate ::preview2 ::bindings ::clocks ::wall_clock ;
use crate ::preview2 ::bindings ::filesystem ::types ::{
DirectoryEntryStream , HostDescriptor , HostDirectoryEntryStream ,
} ;
use crate ::preview2 ::bindings ::filesystem ::types ::{ HostDescriptor , HostDirectoryEntryStream } ;
use crate ::preview2 ::bindings ::filesystem ::{ preopens , types } ;
use crate ::preview2 ::bindings ::io ::streams ;
use crate ::preview2 ::filesystem ::{ Dir , File , TableFsExt } ;
use crate ::preview2 ::bindings ::io ::streams ::{ InputStream , OutputStream } ;
use crate ::preview2 ::filesystem ::{ Descriptor , Dir , File , ReaddirIterator } ;
use crate ::preview2 ::filesystem ::{ FileInputStream , FileOutputStream } ;
use crate ::preview2 ::{ DirPerms , FilePerms , Table , TableError , WasiView } ;
use anyhow ::Context ;
use wasmtime ::component ::Resource ;
@ -27,7 +26,7 @@ impl<T: WasiView> preopens::Host for T {
for ( dir , name ) in self . ctx ( ) . preopens . clone ( ) {
let fd = self
. table_mut ( )
. push_d ir ( dir )
. push_resource ( Descriptor ::D ir ( dir ) )
. with_context ( | | format ! ( "failed to push preopen {name}" ) ) ? ;
results . push ( ( fd , name ) ) ;
}
@ -59,7 +58,7 @@ impl<T: WasiView> HostDescriptor for T {
Advice ::NoReuse = > A ::NoReuse ,
} ;
let f = self . table ( ) . get_fil e ( & fd ) ? ;
let f = self . table ( ) . get_resourc e ( & fd ) ? . file ( ) ? ;
f . spawn_blocking ( move | f | f . advise ( offset , len , advice ) )
. await ? ;
Ok ( ( ) )
@ -67,28 +66,28 @@ impl<T: WasiView> HostDescriptor for T {
async fn sync_data ( & mut self , fd : Resource < types ::Descriptor > ) -> Result < ( ) , types ::Error > {
let table = self . table ( ) ;
if table . is_file ( & fd ) {
let f = table . get_file ( & fd ) ? ;
match f . spawn_blocking ( | f | f . sync_data ( ) ) . await {
Ok ( ( ) ) = > Ok ( ( ) ) ,
// On windows, `sync_data` uses `FileFlushBuffers` which fails with
// `ERROR_ACCESS_DENIED` if the file is not upen for writing. Ignore
// this error, for POSIX compatibility.
#[ cfg(windows) ]
Err ( e )
if e . raw_os_error ( )
= = Some ( windows_sys ::Win32 ::Foundation ::ERROR_ACCESS_DENIED as _ ) = >
{
Ok ( ( ) )
match table . get_resource ( & fd ) ? {
Descriptor ::File ( f ) = > {
match f . spawn_blocking ( | f | f . sync_data ( ) ) . await {
Ok ( ( ) ) = > Ok ( ( ) ) ,
// On windows, `sync_data` uses `FileFlushBuffers` which fails with
// `ERROR_ACCESS_DENIED` if the file is not upen for writing. Ignore
// this error, for POSIX compatibility.
#[ cfg(windows) ]
Err ( e )
if e . raw_os_error ( )
= = Some ( windows_sys ::Win32 ::Foundation ::ERROR_ACCESS_DENIED as _ ) = >
{
Ok ( ( ) )
}
Err ( e ) = > Err ( e . into ( ) ) ,
}
Err ( e ) = > Err ( e . into ( ) ) ,
}
} else if table . is_dir ( & fd ) {
let d = table . get_dir ( & fd ) ? ;
d . spawn_blocking ( | d | Ok ( d . open ( std ::path ::Component ::CurDir ) ? . sync_data ( ) ? ) )
. await
} else {
Err ( ErrorCode ::BadDescriptor . into ( ) )
Descriptor ::Dir ( d ) = > {
d . spawn_blocking ( | d | Ok ( d . open ( std ::path ::Component ::CurDir ) ? . sync_data ( ) ? ) )
. await
}
}
}
@ -114,30 +113,29 @@ impl<T: WasiView> HostDescriptor for T {
}
let table = self . table ( ) ;
if table . is_file ( & fd ) {
let f = table . get_file ( & fd ) ? ;
let flags = f . spawn_blocking ( | f | f . get_fd_flags ( ) ) . await ? ;
let mut flags = get_from_fdflags ( flags ) ;
if f . perms . contains ( FilePerms ::READ ) {
flags | = DescriptorFlags ::READ ;
}
if f . perms . contains ( FilePerms ::WRITE ) {
flags | = DescriptorFlags ::WRITE ;
}
Ok ( flags )
} else if table . is_dir ( & fd ) {
let d = table . get_dir ( & fd ) ? ;
let flags = d . spawn_blocking ( | d | d . get_fd_flags ( ) ) . await ? ;
let mut flags = get_from_fdflags ( flags ) ;
if d . perms . contains ( DirPerms ::READ ) {
flags | = DescriptorFlags ::READ ;
match table . get_resource ( & fd ) ? {
Descriptor ::File ( f ) = > {
let flags = f . spawn_blocking ( | f | f . get_fd_flags ( ) ) . await ? ;
let mut flags = get_from_fdflags ( flags ) ;
if f . perms . contains ( FilePerms ::READ ) {
flags | = DescriptorFlags ::READ ;
}
if f . perms . contains ( FilePerms ::WRITE ) {
flags | = DescriptorFlags ::WRITE ;
}
Ok ( flags )
}
if d . perms . contains ( DirPerms ::MUTATE ) {
flags | = DescriptorFlags ::MUTATE_DIRECTORY ;
Descriptor ::Dir ( d ) = > {
let flags = d . spawn_blocking ( | d | d . get_fd_flags ( ) ) . await ? ;
let mut flags = get_from_fdflags ( flags ) ;
if d . perms . contains ( DirPerms ::READ ) {
flags | = DescriptorFlags ::READ ;
}
if d . perms . contains ( DirPerms ::MUTATE ) {
flags | = DescriptorFlags ::MUTATE_DIRECTORY ;
}
Ok ( flags )
}
Ok ( flags )
} else {
Err ( ErrorCode ::BadDescriptor . into ( ) )
}
}
@ -147,14 +145,12 @@ impl<T: WasiView> HostDescriptor for T {
) -> Result < types ::DescriptorType , types ::Error > {
let table = self . table ( ) ;
if table . is_file ( & fd ) {
let f = table . get_file ( & fd ) ? ;
let meta = f . spawn_blocking ( | f | f . metadata ( ) ) . await ? ;
Ok ( descriptortype_from ( meta . file_type ( ) ) )
} else if table . is_dir ( & fd ) {
Ok ( types ::DescriptorType ::Directory )
} else {
Err ( ErrorCode ::BadDescriptor . into ( ) )
match table . get_resource ( & fd ) ? {
Descriptor ::File ( f ) = > {
let meta = f . spawn_blocking ( | f | f . metadata ( ) ) . await ? ;
Ok ( descriptortype_from ( meta . file_type ( ) ) )
}
Descriptor ::Dir ( _ ) = > Ok ( types ::DescriptorType ::Directory ) ,
}
}
@ -163,7 +159,7 @@ impl<T: WasiView> HostDescriptor for T {
fd : Resource < types ::Descriptor > ,
size : types ::Filesize ,
) -> Result < ( ) , types ::Error > {
let f = self . table ( ) . get_fil e ( & fd ) ? ;
let f = self . table ( ) . get_resourc e ( & fd ) ? . file ( ) ? ;
if ! f . perms . contains ( FilePerms ::WRITE ) {
Err ( ErrorCode ::NotPermitted ) ? ;
}
@ -180,26 +176,25 @@ impl<T: WasiView> HostDescriptor for T {
use fs_set_times ::SetTimes ;
let table = self . table ( ) ;
if table . is_file ( & fd ) {
let f = table . get_file ( & fd ) ? ;
if ! f . perms . contains ( FilePerms ::WRITE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
match table . get_resource ( & fd ) ? {
Descriptor ::File ( f ) = > {
if ! f . perms . contains ( FilePerms ::WRITE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
let atim = systemtimespec_from ( atim ) ? ;
let mtim = systemtimespec_from ( mtim ) ? ;
f . spawn_blocking ( | f | f . set_times ( atim , mtim ) ) . await ? ;
Ok ( ( ) )
}
let atim = systemtimespec_from ( atim ) ? ;
let mtim = systemtimespec_from ( mtim ) ? ;
f . spawn_blocking ( | f | f . set_times ( atim , mtim ) ) . await ? ;
Ok ( ( ) )
} else if table . is_dir ( & fd ) {
let d = table . get_dir ( & fd ) ? ;
if ! d . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
Descriptor ::Dir ( d ) = > {
if ! d . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
let atim = systemtimespec_from ( atim ) ? ;
let mtim = systemtimespec_from ( mtim ) ? ;
d . spawn_blocking ( | d | d . set_times ( atim , mtim ) ) . await ? ;
Ok ( ( ) )
}
let atim = systemtimespec_from ( atim ) ? ;
let mtim = systemtimespec_from ( mtim ) ? ;
d . spawn_blocking ( | d | d . set_times ( atim , mtim ) ) . await ? ;
Ok ( ( ) )
} else {
Err ( ErrorCode ::BadDescriptor . into ( ) )
}
}
@ -214,7 +209,7 @@ impl<T: WasiView> HostDescriptor for T {
let table = self . table ( ) ;
let f = table . get_fil e ( & fd ) ? ;
let f = table . get_resourc e ( & fd ) ? . file ( ) ? ;
if ! f . perms . contains ( FilePerms ::READ ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -251,7 +246,7 @@ impl<T: WasiView> HostDescriptor for T {
use system_interface ::fs ::FileIoExt ;
let table = self . table ( ) ;
let f = table . get_fil e ( & fd ) ? ;
let f = table . get_resourc e ( & fd ) ? . file ( ) ? ;
if ! f . perms . contains ( FilePerms ::WRITE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -268,7 +263,7 @@ impl<T: WasiView> HostDescriptor for T {
fd : Resource < types ::Descriptor > ,
) -> Result < Resource < types ::DirectoryEntryStream > , types ::Error > {
let table = self . table_mut ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::READ ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -325,33 +320,33 @@ impl<T: WasiView> HostDescriptor for T {
Err ( ReaddirError ::Io ( e ) ) = > Err ( types ::Error ::from ( e ) ) ,
Err ( ReaddirError ::IllegalSequence ) = > Err ( ErrorCode ::IllegalByteSequence . into ( ) ) ,
} ) ;
Ok ( table . push_readdir ( ReaddirIterator ::new ( entries ) ) ? )
Ok ( table . push_resource ( ReaddirIterator ::new ( entries ) ) ? )
}
async fn sync ( & mut self , fd : Resource < types ::Descriptor > ) -> Result < ( ) , types ::Error > {
let table = self . table ( ) ;
if table . is_file ( & fd ) {
let f = table . get_file ( & fd ) ? ;
match f . spawn_blocking ( | f | f . sync_all ( ) ) . await {
Ok ( ( ) ) = > Ok ( ( ) ) ,
// On windows, `sync_data` uses `FileFlushBuffers` which fails with
// `ERROR_ACCESS_DENIED` if the file is not upen for writing. Ignore
// this error, for POSIX compatibility.
#[ cfg(windows) ]
Err ( e )
if e . raw_os_error ( )
= = Some ( windows_sys ::Win32 ::Foundation ::ERROR_ACCESS_DENIED as _ ) = >
{
Ok ( ( ) )
match table . get_resource ( & fd ) ? {
Descriptor ::File ( f ) = > {
match f . spawn_blocking ( | f | f . sync_all ( ) ) . await {
Ok ( ( ) ) = > Ok ( ( ) ) ,
// On windows, `sync_data` uses `FileFlushBuffers` which fails with
// `ERROR_ACCESS_DENIED` if the file is not upen for writing. Ignore
// this error, for POSIX compatibility.
#[ cfg(windows) ]
Err ( e )
if e . raw_os_error ( )
= = Some ( windows_sys ::Win32 ::Foundation ::ERROR_ACCESS_DENIED as _ ) = >
{
Ok ( ( ) )
}
Err ( e ) = > Err ( e . into ( ) ) ,
}
Err ( e ) = > Err ( e . into ( ) ) ,
}
} else if table . is_dir ( & fd ) {
let d = table . get_dir ( & fd ) ? ;
d . spawn_blocking ( | d | Ok ( d . open ( std ::path ::Component ::CurDir ) ? . sync_all ( ) ? ) )
. await
} else {
Err ( ErrorCode ::BadDescriptor . into ( ) )
Descriptor ::Dir ( d ) = > {
d . spawn_blocking ( | d | Ok ( d . open ( std ::path ::Component ::CurDir ) ? . sync_all ( ) ? ) )
. await
}
}
}
@ -361,7 +356,7 @@ impl<T: WasiView> HostDescriptor for T {
path : String ,
) -> Result < ( ) , types ::Error > {
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -374,18 +369,17 @@ impl<T: WasiView> HostDescriptor for T {
fd : Resource < types ::Descriptor > ,
) -> Result < types ::DescriptorStat , types ::Error > {
let table = self . table ( ) ;
if table . is_file ( & fd ) {
let f = table . get_file ( & fd ) ? ;
// No permissions check on stat: if opened, allowed to stat it
let meta = f . spawn_blocking ( | f | f . metadata ( ) ) . await ? ;
Ok ( descriptorstat_from ( meta ) )
} else if table . is_dir ( & fd ) {
let d = table . get_dir ( & fd ) ? ;
// No permissions check on stat: if opened, allowed to stat it
let meta = d . spawn_blocking ( | d | d . dir_metadata ( ) ) . await ? ;
Ok ( descriptorstat_from ( meta ) )
} else {
Err ( ErrorCode ::BadDescriptor . into ( ) )
match table . get_resource ( & fd ) ? {
Descriptor ::File ( f ) = > {
// No permissions check on stat: if opened, allowed to stat it
let meta = f . spawn_blocking ( | f | f . metadata ( ) ) . await ? ;
Ok ( descriptorstat_from ( meta ) )
}
Descriptor ::Dir ( d ) = > {
// No permissions check on stat: if opened, allowed to stat it
let meta = d . spawn_blocking ( | d | d . dir_metadata ( ) ) . await ? ;
Ok ( descriptorstat_from ( meta ) )
}
}
}
@ -396,7 +390,7 @@ impl<T: WasiView> HostDescriptor for T {
path : String ,
) -> Result < types ::DescriptorStat , types ::Error > {
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::READ ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -420,7 +414,7 @@ impl<T: WasiView> HostDescriptor for T {
use cap_fs_ext ::DirExt ;
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -458,11 +452,11 @@ impl<T: WasiView> HostDescriptor for T {
new_path : String ,
) -> Result < ( ) , types ::Error > {
let table = self . table ( ) ;
let old_dir = table . get_dir ( & fd ) ? ;
let old_dir = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! old_dir . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
let new_dir = table . get_dir ( & new_descriptor ) ? ;
let new_dir = table . get_resource ( & new_descriptor ) ? . dir ( ) ? ;
if ! new_dir . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -492,10 +486,7 @@ impl<T: WasiView> HostDescriptor for T {
use types ::{ DescriptorFlags , OpenFlags } ;
let table = self . table_mut ( ) ;
if table . is_file ( & fd ) {
Err ( ErrorCode ::NotDirectory ) ? ;
}
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::READ ) {
Err ( ErrorCode ::NotPermitted ) ? ;
}
@ -584,12 +575,15 @@ impl<T: WasiView> HostDescriptor for T {
. await ? ;
match opened {
OpenResult ::Dir ( dir ) = > Ok ( table . push_dir ( Dir ::new ( dir , d . perms , d . file_perms ) ) ? ) ,
OpenResult ::File ( file ) = > {
Ok ( table . push_file ( File ::new ( file , mask_file_perms ( d . file_perms , flags ) ) ) ? )
OpenResult ::Dir ( dir ) = > {
Ok ( table . push_resource ( Descriptor ::Dir ( Dir ::new ( dir , d . perms , d . file_perms ) ) ) ? )
}
OpenResult ::File ( file ) = > Ok ( table . push_resource ( Descriptor ::File ( File ::new (
file ,
mask_file_perms ( d . file_perms , flags ) ,
) ) ) ? ) ,
OpenResult ::NotDir = > Err ( ErrorCode ::NotDirectory . into ( ) ) ,
}
}
@ -602,9 +596,7 @@ impl<T: WasiView> HostDescriptor for T {
// tokio::fs::File just uses std::fs::File's Drop impl to close, so
// it doesn't appear anyone else has found this to be a problem.
// (Not that they could solve it without async drop...)
if table . delete_file ( Resource ::new_own ( fd . rep ( ) ) ) . is_err ( ) {
table . delete_dir ( fd ) ? ;
}
table . delete_resource ( fd ) ? ;
Ok ( ( ) )
}
@ -615,7 +607,7 @@ impl<T: WasiView> HostDescriptor for T {
path : String ,
) -> Result < String , types ::Error > {
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::READ ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -632,7 +624,7 @@ impl<T: WasiView> HostDescriptor for T {
path : String ,
) -> Result < ( ) , types ::Error > {
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -647,11 +639,11 @@ impl<T: WasiView> HostDescriptor for T {
new_path : String ,
) -> Result < ( ) , types ::Error > {
let table = self . table ( ) ;
let old_dir = table . get_dir ( & fd ) ? ;
let old_dir = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! old_dir . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
let new_dir = table . get_dir ( & new_fd ) ? ;
let new_dir = table . get_resource ( & new_fd ) ? . dir ( ) ? ;
if ! new_dir . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -672,7 +664,7 @@ impl<T: WasiView> HostDescriptor for T {
use cap_fs_ext ::DirExt ;
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -688,7 +680,7 @@ impl<T: WasiView> HostDescriptor for T {
use cap_fs_ext ::DirExt ;
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
if ! d . perms . contains ( DirPerms ::MUTATE ) {
return Err ( ErrorCode ::NotPermitted . into ( ) ) ;
}
@ -759,14 +751,9 @@ impl<T: WasiView> HostDescriptor for T {
& mut self ,
fd : Resource < types ::Descriptor > ,
offset : types ::Filesize ,
) -> Result < Resource < streams ::InputStream > , types ::Error > {
use crate ::preview2 ::{
filesystem ::FileInputStream ,
stream ::{ InternalInputStream , InternalTableStreamExt } ,
} ;
) -> Result < Resource < InputStream > , types ::Error > {
// Trap if fd lookup fails:
let f = self . table ( ) . get_fil e ( & fd ) ? ;
let f = self . table ( ) . get_resource ( & fd ) ? . file ( ) ? ;
if ! f . perms . contains ( FilePerms ::READ ) {
Err ( types ::ErrorCode ::BadDescriptor ) ? ;
@ -778,9 +765,7 @@ impl<T: WasiView> HostDescriptor for T {
let reader = FileInputStream ::new ( clone , offset ) ;
// Insert the stream view into the table. Trap if the table is full.
let index = self
. table_mut ( )
. push_internal_input_stream ( InternalInputStream ::File ( reader ) ) ? ;
let index = self . table_mut ( ) . push_resource ( InputStream ::File ( reader ) ) ? ;
Ok ( index )
}
@ -789,11 +774,9 @@ impl<T: WasiView> HostDescriptor for T {
& mut self ,
fd : Resource < types ::Descriptor > ,
offset : types ::Filesize ,
) -> Result < Resource < streams ::OutputStream > , types ::Error > {
use crate ::preview2 ::{ filesystem ::FileOutputStream , TableStreamExt } ;
) -> Result < Resource < OutputStream > , types ::Error > {
// Trap if fd lookup fails:
let f = self . table ( ) . get_fil e ( & fd ) ? ;
let f = self . table ( ) . get_resource ( & fd ) ? . file ( ) ? ;
if ! f . perms . contains ( FilePerms ::WRITE ) {
Err ( types ::ErrorCode ::BadDescriptor ) ? ;
@ -804,9 +787,10 @@ impl<T: WasiView> HostDescriptor for T {
// Create a stream view for it.
let writer = FileOutputStream ::write_at ( clone , offset ) ;
let writer : OutputStream = Box ::new ( writer ) ;
// Insert the stream view into the table. Trap if the table is full.
let index = self . table_mut ( ) . push_output_stream ( Box ::new ( writer ) ) ? ;
let index = self . table_mut ( ) . push_resource ( writer ) ? ;
Ok ( index )
}
@ -814,11 +798,9 @@ impl<T: WasiView> HostDescriptor for T {
fn append_via_stream (
& mut self ,
fd : Resource < types ::Descriptor > ,
) -> Result < Resource < streams ::OutputStream > , types ::Error > {
use crate ::preview2 ::{ filesystem ::FileOutputStream , TableStreamExt } ;
) -> Result < Resource < OutputStream > , types ::Error > {
// Trap if fd lookup fails:
let f = self . table ( ) . get_fil e ( & fd ) ? ;
let f = self . table ( ) . get_resource ( & fd ) ? . file ( ) ? ;
if ! f . perms . contains ( FilePerms ::WRITE ) {
Err ( types ::ErrorCode ::BadDescriptor ) ? ;
@ -828,9 +810,10 @@ impl<T: WasiView> HostDescriptor for T {
// Create a stream view for it.
let appender = FileOutputStream ::append ( clone ) ;
let appender : OutputStream = Box ::new ( appender ) ;
// Insert the stream view into the table. Trap if the table is full.
let index = self . table_mut ( ) . push_output_stream ( Box ::new ( appender ) ) ? ;
let index = self . table_mut ( ) . push_resource ( appender ) ? ;
Ok ( index )
}
@ -876,7 +859,7 @@ impl<T: WasiView> HostDescriptor for T {
path : String ,
) -> Result < types ::MetadataHashValue , types ::Error > {
let table = self . table ( ) ;
let d = table . get_dir ( & fd ) ? ;
let d = table . get_resource ( & fd ) ? . dir ( ) ? ;
// No permissions check on metadata: if dir opened, allowed to stat it
let meta = d
. spawn_blocking ( move | d | {
@ -898,12 +881,12 @@ impl<T: WasiView> HostDirectoryEntryStream for T {
stream : Resource < types ::DirectoryEntryStream > ,
) -> Result < Option < types ::DirectoryEntry > , types ::Error > {
let table = self . table ( ) ;
let readdir = table . get_readdir ( & stream ) ? ;
let readdir = table . get_resource ( & stream ) ? ;
readdir . next ( )
}
fn drop ( & mut self , stream : Resource < types ::DirectoryEntryStream > ) -> anyhow ::Result < ( ) > {
self . table_mut ( ) . delete_readdir ( stream ) ? ;
self . table_mut ( ) . delete_resource ( stream ) ? ;
Ok ( ( ) )
}
}
@ -912,16 +895,15 @@ async fn get_descriptor_metadata(
table : & Table ,
fd : Resource < types ::Descriptor > ,
) -> Result < cap_std ::fs ::Metadata , types ::Error > {
if table . is_file ( & fd ) {
let f = table . get_file ( & fd ) ? ;
// No permissions check on metadata: if opened, allowed to stat it
Ok ( f . spawn_blocking ( | f | f . metadata ( ) ) . await ? )
} else if table . is_dir ( & fd ) {
let d = table . get_dir ( & fd ) ? ;
// No permissions check on metadata: if opened, allowed to stat it
Ok ( d . spawn_blocking ( | d | d . dir_metadata ( ) ) . await ? )
} else {
Err ( ErrorCode ::BadDescriptor . into ( ) )
match table . get_resource ( & fd ) ? {
Descriptor ::File ( f ) = > {
// No permissions check on metadata: if opened, allowed to stat it
Ok ( f . spawn_blocking ( | f | f . metadata ( ) ) . await ? )
}
Descriptor ::Dir ( d ) = > {
// No permissions check on metadata: if opened, allowed to stat it
Ok ( d . spawn_blocking ( | d | d . dir_metadata ( ) ) . await ? )
}
}
}
@ -1105,69 +1087,6 @@ fn symlink_follow(path_flags: types::PathFlags) -> bool {
path_flags . contains ( types ::PathFlags ::SYMLINK_FOLLOW )
}
pub ( crate ) struct ReaddirIterator (
std ::sync ::Mutex <
Box < dyn Iterator < Item = Result < types ::DirectoryEntry , types ::Error > > + Send + 'static > ,
> ,
) ;
impl ReaddirIterator {
fn new (
i : impl Iterator < Item = Result < types ::DirectoryEntry , types ::Error > > + Send + 'static ,
) -> Self {
ReaddirIterator ( std ::sync ::Mutex ::new ( Box ::new ( i ) ) )
}
fn next ( & self ) -> Result < Option < types ::DirectoryEntry > , types ::Error > {
self . 0. lock ( ) . unwrap ( ) . next ( ) . transpose ( )
}
}
impl IntoIterator for ReaddirIterator {
type Item = Result < types ::DirectoryEntry , types ::Error > ;
type IntoIter = Box < dyn Iterator < Item = Self ::Item > + Send > ;
fn into_iter ( self ) -> Self ::IntoIter {
self . 0. into_inner ( ) . unwrap ( )
}
}
pub ( crate ) trait TableReaddirExt {
fn push_readdir (
& mut self ,
readdir : ReaddirIterator ,
) -> Result < Resource < DirectoryEntryStream > , TableError > ;
fn delete_readdir (
& mut self ,
fd : Resource < DirectoryEntryStream > ,
) -> Result < ReaddirIterator , TableError > ;
fn get_readdir (
& self ,
fd : & Resource < DirectoryEntryStream > ,
) -> Result < & ReaddirIterator , TableError > ;
}
impl TableReaddirExt for Table {
fn push_readdir (
& mut self ,
readdir : ReaddirIterator ,
) -> Result < Resource < DirectoryEntryStream > , TableError > {
Ok ( Resource ::new_own ( self . push ( Box ::new ( readdir ) ) ? ) )
}
fn delete_readdir (
& mut self ,
fd : Resource < DirectoryEntryStream > ,
) -> Result < ReaddirIterator , TableError > {
self . delete ( fd . rep ( ) )
}
fn get_readdir (
& self ,
fd : & Resource < DirectoryEntryStream > ,
) -> Result < & ReaddirIterator , TableError > {
self . get ( fd . rep ( ) )
}
}
fn mask_file_perms ( p : FilePerms , flags : types ::DescriptorFlags ) -> FilePerms {
use types ::DescriptorFlags ;
let mut out = FilePerms ::empty ( ) ;
@ -1187,9 +1106,9 @@ mod test {
fn table_readdir_works ( ) {
let mut table = Table ::new ( ) ;
let ix = table
. push_readdir ( ReaddirIterator ::new ( std ::iter ::empty ( ) ) )
. push_resource ( ReaddirIterator ::new ( std ::iter ::empty ( ) ) )
. unwrap ( ) ;
let _ = table . get_readdir ( & ix ) . unwrap ( ) ;
table . delete_readdir ( ix ) . unwrap ( ) ;
let _ = table . get_resource ( & ix ) . unwrap ( ) ;
table . delete_resource ( ix ) . unwrap ( ) ;
}
}