@@ -70,6 +70,10 @@ export class OpenFile extends Fd {
7070 return wasi . ERRNO_SUCCESS ;
7171 }
7272
73+ fd_filestat_set_times ( atim : bigint , mtim : bigint , fst_flags : number ) : number {
74+ return this . file . set_times ( atim , mtim , fst_flags ) ;
75+ }
76+
7377 fd_read ( size : number ) : { ret : number ; data : Uint8Array } {
7478 const slice = this . file . data . slice (
7579 Number ( this . file_pos ) ,
@@ -237,11 +241,31 @@ export class OpenDirectory extends Fd {
237241 return { ret : 0 , filestat : entry . stat ( ) } ;
238242 }
239243
244+ path_filestat_set_times (
245+ _flags : number ,
246+ path_str : string ,
247+ atim : bigint ,
248+ mtim : bigint ,
249+ fst_flags : number ,
250+ ) : number {
251+ const { ret : path_err , path } = Path . from ( path_str ) ;
252+ if ( path == null ) {
253+ return path_err ;
254+ }
255+
256+ const { ret, entry } = this . dir . get_entry_for_path ( path ) ;
257+ if ( entry == null ) {
258+ return ret ;
259+ }
260+
261+ return entry . set_times ( atim , mtim , fst_flags ) ;
262+ }
263+
240264 path_lookup (
241265 path_str : string ,
242266 // eslint-disable-next-line @typescript-eslint/no-unused-vars
243267 dirflags : number ,
244- ) : { ret : number ; inode_obj : Inode | null } {
268+ ) : { ret : number ; inode_obj : InodeMem | null } {
245269 const { ret : path_ret , path } = Path . from ( path_str ) ;
246270 if ( path == null ) {
247271 return { ret : path_ret , inode_obj : null } ;
@@ -315,7 +339,7 @@ export class OpenDirectory extends Fd {
315339 ) . ret ;
316340 }
317341
318- path_link ( path_str : string , inode : Inode , allow_dir : boolean ) : number {
342+ path_link ( path_str : string , inode : InodeMem , allow_dir : boolean ) : number {
319343 const { ret : path_ret , path } = Path . from ( path_str ) ;
320344 if ( path == null ) {
321345 return path_ret ;
@@ -374,7 +398,7 @@ export class OpenDirectory extends Fd {
374398 return wasi . ERRNO_SUCCESS ;
375399 }
376400
377- path_unlink ( path_str : string ) : { ret : number ; inode_obj : Inode | null } {
401+ path_unlink ( path_str : string ) : { ret : number ; inode_obj : InodeMem | null } {
378402 const { ret : path_ret , path } = Path . from ( path_str ) ;
379403 if ( path == null ) {
380404 return { ret : path_ret , inode_obj : null } ;
@@ -461,6 +485,10 @@ export class OpenDirectory extends Fd {
461485 return wasi . ERRNO_BADF ;
462486 }
463487
488+ fd_filestat_set_times ( atim : bigint , mtim : bigint , fst_flags : number ) : number {
489+ return this . dir . set_times ( atim , mtim , fst_flags ) ;
490+ }
491+
464492 // eslint-disable-next-line @typescript-eslint/no-unused-vars
465493 fd_read ( size : number ) : { ret : number ; data : Uint8Array } {
466494 return { ret : wasi . ERRNO_BADF , data : new Uint8Array ( ) } ;
@@ -489,7 +517,7 @@ export class OpenDirectory extends Fd {
489517export class PreopenDirectory extends OpenDirectory {
490518 prestat_name : string ;
491519
492- constructor ( name : string , contents : Map < string , Inode > ) {
520+ constructor ( name : string , contents : Map < string , InodeMem > ) {
493521 super ( new Directory ( contents ) ) ;
494522 this . prestat_name = name ;
495523 }
@@ -502,7 +530,51 @@ export class PreopenDirectory extends OpenDirectory {
502530 }
503531}
504532
505- export class File extends Inode {
533+ function realtime ( ) : bigint {
534+ return BigInt ( Date . now ( ) ) * 1000000n ;
535+ }
536+
537+ export abstract class InodeMem extends Inode {
538+ atim : bigint ;
539+ mtim : bigint ;
540+ ctim : bigint ;
541+
542+ constructor ( ) {
543+ super ( ) ;
544+ const now = realtime ( ) ;
545+ this . atim = now ;
546+ this . mtim = now ;
547+ this . ctim = now ;
548+ }
549+
550+ set_times ( atim : bigint , mtim : bigint , fst_flags : number ) : number {
551+ const now = realtime ( ) ;
552+
553+ if ( fst_flags & wasi . FSTFLAGS_ATIM ) {
554+ this . atim = atim ;
555+ this . ctim = now ;
556+ }
557+
558+ if ( fst_flags & wasi . FSTFLAGS_ATIM_NOW ) {
559+ this . atim = now ;
560+ this . ctim = now ;
561+ }
562+
563+ if ( fst_flags & wasi . FSTFLAGS_MTIM ) {
564+ this . mtim = mtim ;
565+ this . ctim = now ;
566+ }
567+
568+ if ( fst_flags & wasi . FSTFLAGS_MTIM_NOW ) {
569+ this . mtim = now ;
570+ this . ctim = now ;
571+ }
572+
573+ return wasi . ERRNO_SUCCESS ;
574+ }
575+ }
576+
577+ export class File extends InodeMem {
506578 data : Uint8Array ;
507579 readonly : boolean ;
508580
@@ -542,7 +614,14 @@ export class File extends Inode {
542614 }
543615
544616 stat ( ) : wasi . Filestat {
545- return new wasi . Filestat ( this . ino , wasi . FILETYPE_REGULAR_FILE , this . size ) ;
617+ return new wasi . Filestat (
618+ this . ino ,
619+ wasi . FILETYPE_REGULAR_FILE ,
620+ this . size ,
621+ this . atim ,
622+ this . mtim ,
623+ this . ctim ,
624+ ) ;
546625 }
547626}
548627
@@ -586,11 +665,11 @@ class Path {
586665 }
587666}
588667
589- export class Directory extends Inode {
590- contents : Map < string , Inode > ;
668+ export class Directory extends InodeMem {
669+ contents : Map < string , InodeMem > ;
591670 parent : Directory | null = null ;
592671
593- constructor ( contents : Map < string , Inode > | [ string , Inode ] [ ] ) {
672+ constructor ( contents : Map < string , InodeMem > | [ string , InodeMem ] [ ] ) {
594673 super ( ) ;
595674 if ( contents instanceof Array ) {
596675 this . contents = new Map ( contents ) ;
@@ -618,11 +697,18 @@ export class Directory extends Inode {
618697 }
619698
620699 stat ( ) : wasi . Filestat {
621- return new wasi . Filestat ( this . ino , wasi . FILETYPE_DIRECTORY , 0n ) ;
700+ return new wasi . Filestat (
701+ this . ino ,
702+ wasi . FILETYPE_DIRECTORY ,
703+ 0n ,
704+ this . atim ,
705+ this . mtim ,
706+ this . ctim ,
707+ ) ;
622708 }
623709
624- get_entry_for_path ( path : Path ) : { ret : number ; entry : Inode | null } {
625- let entry : Inode = this ;
710+ get_entry_for_path ( path : Path ) : { ret : number ; entry : InodeMem | null } {
711+ let entry : InodeMem = this ;
626712 for ( const component of path . parts ) {
627713 if ( ! ( entry instanceof Directory ) ) {
628714 return { ret : wasi . ERRNO_NOTDIR , entry : null } ;
@@ -652,7 +738,7 @@ export class Directory extends Inode {
652738 ret : number ;
653739 parent_entry : Directory | null ;
654740 filename : string | null ;
655- entry : Inode | null ;
741+ entry : InodeMem | null ;
656742 } {
657743 const filename = path . parts . pop ( ) ;
658744
@@ -683,7 +769,8 @@ export class Directory extends Inode {
683769 entry : null ,
684770 } ;
685771 }
686- const entry : Inode | undefined | null = parent_entry . contents . get ( filename ) ;
772+ const entry : InodeMem | undefined | null =
773+ parent_entry . contents . get ( filename ) ;
687774 if ( entry === undefined ) {
688775 if ( ! allow_undefined ) {
689776 return {
@@ -714,7 +801,7 @@ export class Directory extends Inode {
714801 create_entry_for_path (
715802 path_str : string ,
716803 is_dir : boolean ,
717- ) : { ret : number ; entry : Inode | null } {
804+ ) : { ret : number ; entry : InodeMem | null } {
718805 const { ret : path_ret , path } = Path . from ( path_str ) ;
719806 if ( path == null ) {
720807 return { ret : path_ret , entry : null } ;
0 commit comments