@@ -3,7 +3,7 @@ import { Node } from './Node';
33import { Link } from './Link' ;
44import { File } from './File' ;
55import { Buffer } from '@jsonjoy.com/fs-node-builtins/lib/internal/buffer' ;
6- import process from './process' ;
6+ import defaultProcess , { type IProcess } from './process' ;
77import { constants } from '@jsonjoy.com/fs-node-utils' ;
88import { ERRSTR , FLAGS , MODE } from '@jsonjoy.com/fs-node-utils' ;
99import {
@@ -34,14 +34,14 @@ const { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_DIRECT
3434 * @see https://lxr.linux.no/linux+v3.11.2/include/linux/fs.h#L1242
3535 */
3636export class Superblock {
37- static fromJSON ( json : DirectoryJSON , cwd ?: string ) : Superblock {
38- const vol = new Superblock ( ) ;
37+ static fromJSON ( json : DirectoryJSON , cwd ?: string , opts ?: { process ?: IProcess } ) : Superblock {
38+ const vol = new Superblock ( opts ) ;
3939 vol . fromJSON ( json , cwd ) ;
4040 return vol ;
4141 }
4242
43- static fromNestedJSON ( json : NestedDirectoryJSON , cwd ?: string ) : Superblock {
44- const vol = new Superblock ( ) ;
43+ static fromNestedJSON ( json : NestedDirectoryJSON , cwd ?: string , opts ?: { process ?: IProcess } ) : Superblock {
44+ const vol = new Superblock ( opts ) ;
4545 vol . fromNestedJSON ( json , cwd ) ;
4646 return vol ;
4747 }
@@ -84,7 +84,11 @@ export class Superblock {
8484 // Current number of open files.
8585 openFiles = 0 ;
8686
87- constructor ( props = { } ) {
87+ /** The `process`-like object used by this filesystem instance. */
88+ readonly process : IProcess ;
89+
90+ constructor ( opts : { process ?: IProcess } = { } ) {
91+ this . process = opts . process ?? defaultProcess ;
8892 const root = this . createLink ( ) ;
8993 root . setNode ( this . createNode ( constants . S_IFDIR | 0o777 ) ) ;
9094
@@ -144,7 +148,9 @@ export class Superblock {
144148 }
145149
146150 createNode ( mode : number ) : Node {
147- const node = new Node ( this . newInoNumber ( ) , mode ) ;
151+ const uid = this . process . getuid ?.( ) ?? 0 ;
152+ const gid = this . process . getgid ?.( ) ?? 0 ;
153+ const node = new Node ( this . newInoNumber ( ) , mode , uid , gid ) ;
148154 this . inodes [ node . ino ] = node ;
149155 return node ;
150156 }
@@ -205,11 +211,13 @@ export class Superblock {
205211
206212 let curr : Link | null = this . root ;
207213 let i = 0 ;
214+ const uid = this . process . getuid ?.( ) ?? 0 ;
215+ const gid = this . process . getgid ?.( ) ?? 0 ;
208216 while ( i < steps . length ) {
209217 let node : Node = curr . getNode ( ) ;
210218 // Check access permissions if current link is a directory
211219 if ( node . isDirectory ( ) ) {
212- if ( checkAccess && ! node . canExecute ( ) ) {
220+ if ( checkAccess && ! node . canExecute ( uid , gid ) ) {
213221 return Err ( createStatError ( ERROR_CODE . EACCES , funcName , filename ) ) ;
214222 }
215223 } else {
@@ -247,7 +255,7 @@ export class Superblock {
247255 if ( checkExistence && ! node . isDirectory ( ) && i < steps . length - 1 ) {
248256 // On Windows, use ENOENT for consistency with Node.js behavior
249257 // On other platforms, use ENOTDIR which is more semantically correct
250- const errorCode = process . platform === 'win32' ? ERROR_CODE . ENOENT : ERROR_CODE . ENOTDIR ;
258+ const errorCode = this . process . platform === 'win32' ? ERROR_CODE . ENOENT : ERROR_CODE . ENOTDIR ;
251259 return Err ( createStatError ( errorCode , funcName , filename ) ) ;
252260 }
253261
@@ -404,8 +412,7 @@ export class Superblock {
404412 return json ;
405413 }
406414
407- // TODO: `cwd` should probably not invoke `process.cwd()`.
408- fromJSON ( json : DirectoryJSON , cwd : string = process . cwd ( ) ) {
415+ fromJSON ( json : DirectoryJSON , cwd : string = this . process . cwd ( ) ) {
409416 for ( let filename in json ) {
410417 const data = json [ filename ] ;
411418 filename = resolve ( filename , cwd ) ;
0 commit comments