@@ -546,10 +546,12 @@ export function createChunkedVfs(options: ChunkedVfsOptions): VirtualFileSystem
546546 if ( existingIno !== null ) {
547547 const release = await mutex . acquire ( existingIno ) ;
548548 try {
549- const meta = await requireInode ( existingIno ) ;
550- writeBuffers . delete ( existingIno ) ;
551- await writeInodeContent ( existingIno , data , meta ) ;
552- await metadata . updateInode ( existingIno , { nlink : Math . max ( meta . nlink , 1 ) } ) ;
549+ await metadata . transaction ( async ( ) => {
550+ const meta = await requireInode ( existingIno ) ;
551+ writeBuffers . delete ( existingIno ) ;
552+ await writeInodeContent ( existingIno , data , meta ) ;
553+ await metadata . updateInode ( existingIno , { nlink : Math . max ( meta . nlink , 1 ) } ) ;
554+ } ) ;
553555 } finally {
554556 release ( ) ;
555557 }
@@ -655,9 +657,8 @@ export function createChunkedVfs(options: ChunkedVfsOptions): VirtualFileSystem
655657 } ,
656658
657659 async pwrite ( path : string , offset : number , data : Uint8Array ) : Promise < void > {
658- if ( data . length === 0 ) return ;
659-
660660 const ino = await resolveIno ( path ) ;
661+ if ( data . length === 0 ) return ;
661662 const release = await mutex . acquire ( ino ) ;
662663 try {
663664 const meta = await requireInode ( ino ) ;
@@ -971,10 +972,45 @@ export function createChunkedVfs(options: ChunkedVfsOptions): VirtualFileSystem
971972 }
972973 } ,
973974
974- async mkdir ( path : string , _options ?: { recursive ?: boolean } ) : Promise < void > {
975+ async mkdir ( path : string , options ?: { recursive ?: boolean } ) : Promise < void > {
976+ const recursive = options ?. recursive ?? false ;
975977 const parts = splitPath ( normalizePath ( path ) ) ;
976- let currentIno = 1 ; // root
977978
979+ if ( ! recursive ) {
980+ // Non-recursive: parent must exist, target must not.
981+ if ( parts . length === 0 ) {
982+ throw new KernelError ( "EEXIST" , `directory already exists: '${ path } '` ) ;
983+ }
984+ let parentIno = 1 ; // root
985+ for ( let i = 0 ; i < parts . length - 1 ; i ++ ) {
986+ const childIno = await metadata . lookup ( parentIno , parts [ i ] ! ) ;
987+ if ( childIno === null ) {
988+ throw new KernelError ( "ENOENT" , `no such file or directory: '${ path } '` ) ;
989+ }
990+ parentIno = childIno ;
991+ }
992+ const targetName = parts [ parts . length - 1 ] ! ;
993+ const existingIno = await metadata . lookup ( parentIno , targetName ) ;
994+ if ( existingIno !== null ) {
995+ throw new KernelError ( "EEXIST" , `directory already exists: '${ path } '` ) ;
996+ }
997+ const dirIno = await metadata . createInode ( {
998+ type : "directory" ,
999+ mode : 0o755 ,
1000+ uid : 0 ,
1001+ gid : 0 ,
1002+ } ) ;
1003+ await metadata . createDentry ( parentIno , targetName , dirIno , "directory" ) ;
1004+ await metadata . updateInode ( dirIno , { nlink : 2 , size : 4096 } ) ;
1005+ const parentMeta = await metadata . getInode ( parentIno ) ;
1006+ if ( parentMeta ) {
1007+ await metadata . updateInode ( parentIno , { nlink : parentMeta . nlink + 1 } ) ;
1008+ }
1009+ return ;
1010+ }
1011+
1012+ // Recursive: create all intermediate directories.
1013+ let currentIno = 1 ; // root
9781014 for ( const part of parts ) {
9791015 const childIno = await metadata . lookup ( currentIno , part ) ;
9801016 if ( childIno !== null ) {
@@ -1433,5 +1469,14 @@ export function createChunkedVfs(options: ChunkedVfsOptions): VirtualFileSystem
14331469 Object . assign ( vfs , { versioning : versioningApi } ) ;
14341470 }
14351471
1472+ // Expose dispose() to clear the auto-flush timer.
1473+ const dispose = ( ) : void => {
1474+ if ( autoFlushTimer !== undefined ) {
1475+ clearInterval ( autoFlushTimer ) ;
1476+ autoFlushTimer = undefined ;
1477+ }
1478+ } ;
1479+ Object . assign ( vfs , { dispose } ) ;
1480+
14361481 return vfs ;
14371482}
0 commit comments