first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
@@ -0,0 +1,11 @@
import type * as struct from '../../structs';
export declare class ByteRangeLock {
readonly stateid: struct.Nfsv4Stateid;
readonly path: string;
readonly locktype: number;
readonly offset: bigint;
readonly length: bigint;
readonly lockOwnerKey: string;
constructor(stateid: struct.Nfsv4Stateid, path: string, locktype: number, offset: bigint, length: bigint, lockOwnerKey: string);
overlaps(offset: bigint, length: bigint): boolean;
}
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ByteRangeLock = void 0;
class ByteRangeLock {
constructor(stateid, path, locktype, offset, length, lockOwnerKey) {
this.stateid = stateid;
this.path = path;
this.locktype = locktype;
this.offset = offset;
this.length = length;
this.lockOwnerKey = lockOwnerKey;
}
overlaps(offset, length) {
const MAX_UINT64 = BigInt('0xFFFFFFFFFFFFFFFF');
const thisEnd = this.length === MAX_UINT64 ? MAX_UINT64 : this.offset + this.length;
const otherEnd = length === MAX_UINT64 ? MAX_UINT64 : offset + length;
return this.offset < otherEnd && offset < thisEnd;
}
}
exports.ByteRangeLock = ByteRangeLock;
//# sourceMappingURL=ByteRangeLock.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ByteRangeLock.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/ByteRangeLock.ts"],"names":[],"mappings":";;;AAMA,MAAa,aAAa;IACxB,YAKkB,OAA4B,EAM5B,IAAY,EAOZ,QAAgB,EAMhB,MAAc,EAMd,MAAc,EAOd,YAAoB;QAhCpB,YAAO,GAAP,OAAO,CAAqB;QAM5B,SAAI,GAAJ,IAAI,CAAQ;QAOZ,aAAQ,GAAR,QAAQ,CAAQ;QAMhB,WAAM,GAAN,MAAM,CAAQ;QAMd,WAAM,GAAN,MAAM,CAAQ;QAOd,iBAAY,GAAZ,YAAY,CAAQ;IACnC,CAAC;IAQG,QAAQ,CAAC,MAAc,EAAE,MAAc;QAC5C,MAAM,UAAU,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QACpF,MAAM,QAAQ,GAAG,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;QACtE,OAAO,IAAI,CAAC,MAAM,GAAG,QAAQ,IAAI,MAAM,GAAG,OAAO,CAAC;IACpD,CAAC;CACF;AArDD,sCAqDC"}
@@ -0,0 +1,13 @@
import type * as msg from '../../messages';
import type * as struct from '../../structs';
export declare class ClientRecord {
readonly principal: string;
readonly verifier: Uint8Array;
readonly clientIdString: Uint8Array;
readonly callback: struct.Nfsv4CbClient;
readonly callbackIdent: number;
readonly setclientidConfirm: Uint8Array;
cache: msg.Nfsv4SetclientidResponse | undefined;
lastRenew: number;
constructor(principal: string, verifier: Uint8Array, clientIdString: Uint8Array, callback: struct.Nfsv4CbClient, callbackIdent: number, setclientidConfirm: Uint8Array, cache?: msg.Nfsv4SetclientidResponse | undefined, lastRenew?: number);
}
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientRecord = void 0;
class ClientRecord {
constructor(principal, verifier, clientIdString, callback, callbackIdent, setclientidConfirm, cache = undefined, lastRenew = Date.now()) {
this.principal = principal;
this.verifier = verifier;
this.clientIdString = clientIdString;
this.callback = callback;
this.callbackIdent = callbackIdent;
this.setclientidConfirm = setclientidConfirm;
this.cache = cache;
this.lastRenew = lastRenew;
}
}
exports.ClientRecord = ClientRecord;
//# sourceMappingURL=ClientRecord.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ClientRecord.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/ClientRecord.ts"],"names":[],"mappings":";;;AAIA,MAAa,YAAY;IACvB,YAIkB,SAAiB,EAQjB,QAAoB,EAOpB,cAA0B,EAO1B,QAA8B,EAO9B,aAAqB,EAWrB,kBAA8B,EAQvC,QAAkD,SAAS,EAO3D,YAAoB,IAAI,CAAC,GAAG,EAAE;QAvDrB,cAAS,GAAT,SAAS,CAAQ;QAQjB,aAAQ,GAAR,QAAQ,CAAY;QAOpB,mBAAc,GAAd,cAAc,CAAY;QAO1B,aAAQ,GAAR,QAAQ,CAAsB;QAO9B,kBAAa,GAAb,aAAa,CAAQ;QAWrB,uBAAkB,GAAlB,kBAAkB,CAAY;QAQvC,UAAK,GAAL,KAAK,CAAsD;QAO3D,cAAS,GAAT,SAAS,CAAqB;IACpC,CAAC;CACL;AA9DD,oCA8DC"}
@@ -0,0 +1,9 @@
export declare class FilesystemStats {
readonly spaceAvail: bigint;
readonly spaceFree: bigint;
readonly spaceTotal: bigint;
readonly filesAvail: bigint;
readonly filesFree: bigint;
readonly filesTotal: bigint;
constructor(spaceAvail: bigint, spaceFree: bigint, spaceTotal: bigint, filesAvail: bigint, filesFree: bigint, filesTotal: bigint);
}
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FilesystemStats = void 0;
class FilesystemStats {
constructor(spaceAvail, spaceFree, spaceTotal, filesAvail, filesFree, filesTotal) {
this.spaceAvail = spaceAvail;
this.spaceFree = spaceFree;
this.spaceTotal = spaceTotal;
this.filesAvail = filesAvail;
this.filesFree = filesFree;
this.filesTotal = filesTotal;
}
}
exports.FilesystemStats = FilesystemStats;
//# sourceMappingURL=FilesystemStats.js.map
@@ -0,0 +1 @@
{"version":3,"file":"FilesystemStats.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/FilesystemStats.ts"],"names":[],"mappings":";;;AAGA,MAAa,eAAe;IAC1B,YAEkB,UAAkB,EAElB,SAAiB,EAEjB,UAAkB,EAElB,UAAkB,EAElB,SAAiB,EAEjB,UAAkB;QAVlB,eAAU,GAAV,UAAU,CAAQ;QAElB,cAAS,GAAT,SAAS,CAAQ;QAEjB,eAAU,GAAV,UAAU,CAAQ;QAElB,eAAU,GAAV,UAAU,CAAQ;QAElB,cAAS,GAAT,SAAS,CAAQ;QAEjB,eAAU,GAAV,UAAU,CAAQ;IACjC,CAAC;CACL;AAfD,0CAeC"}
@@ -0,0 +1,9 @@
export declare class LockOwnerState {
readonly clientid: bigint;
readonly owner: Uint8Array;
seqid: number;
readonly locks: Set<string>;
lastResponse?: any;
lastRequestKey?: string | undefined;
constructor(clientid: bigint, owner: Uint8Array, seqid: number, locks?: Set<string>, lastResponse?: any, lastRequestKey?: string | undefined);
}
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LockOwnerState = void 0;
class LockOwnerState {
constructor(clientid, owner, seqid, locks = new Set(), lastResponse, lastRequestKey) {
this.clientid = clientid;
this.owner = owner;
this.seqid = seqid;
this.locks = locks;
this.lastResponse = lastResponse;
this.lastRequestKey = lastRequestKey;
}
}
exports.LockOwnerState = LockOwnerState;
//# sourceMappingURL=LockOwnerState.js.map
@@ -0,0 +1 @@
{"version":3,"file":"LockOwnerState.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/LockOwnerState.ts"],"names":[],"mappings":";;;AAKA,MAAa,cAAc;IACzB,YAKkB,QAAgB,EAOhB,KAAiB,EAQ1B,KAAa,EAOJ,QAAqB,IAAI,GAAG,EAAE,EAQvC,YAAkB,EAOlB,cAAuB;QArCd,aAAQ,GAAR,QAAQ,CAAQ;QAOhB,UAAK,GAAL,KAAK,CAAY;QAQ1B,UAAK,GAAL,KAAK,CAAQ;QAOJ,UAAK,GAAL,KAAK,CAAyB;QAQvC,iBAAY,GAAZ,YAAY,CAAM;QAOlB,mBAAc,GAAd,cAAc,CAAS;IAC7B,CAAC;CACL;AA7CD,wCA6CC"}
@@ -0,0 +1,10 @@
import * as struct from '../../structs';
export declare class LockStateid {
readonly other: Uint8Array;
seqid: number;
readonly lockOwnerKey: string;
readonly path: string;
constructor(other: Uint8Array, seqid: number, lockOwnerKey: string, path: string);
toStateid(): struct.Nfsv4Stateid;
incrementAndGetStateid(): struct.Nfsv4Stateid;
}
@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LockStateid = void 0;
const tslib_1 = require("tslib");
const struct = tslib_1.__importStar(require("../../structs"));
class LockStateid {
constructor(other, seqid, lockOwnerKey, path) {
this.other = other;
this.seqid = seqid;
this.lockOwnerKey = lockOwnerKey;
this.path = path;
}
toStateid() {
return new struct.Nfsv4Stateid(this.seqid, this.other);
}
incrementAndGetStateid() {
this.seqid = this.seqid === 0xffffffff ? 1 : this.seqid + 1;
return this.toStateid();
}
}
exports.LockStateid = LockStateid;
//# sourceMappingURL=LockStateid.js.map
@@ -0,0 +1 @@
{"version":3,"file":"LockStateid.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/LockStateid.ts"],"names":[],"mappings":";;;;AAAA,8DAAwC;AASxC,MAAa,WAAW;IACtB,YAMkB,KAAiB,EAO1B,KAAa,EAMJ,YAAoB,EAMpB,IAAY;QAnBZ,UAAK,GAAL,KAAK,CAAY;QAO1B,UAAK,GAAL,KAAK,CAAQ;QAMJ,iBAAY,GAAZ,YAAY,CAAQ;QAMpB,SAAI,GAAJ,IAAI,CAAQ;IAC3B,CAAC;IAKJ,SAAS;QACP,OAAO,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;IAMD,sBAAsB;QACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;CACF;AA5CD,kCA4CC"}
@@ -0,0 +1,44 @@
import * as msg from '../../messages';
import type { Nfsv4CompoundProcCtx } from '../Nfsv4CompoundProcCtx';
export type Nfsv4OperationCtx = Pick<Nfsv4CompoundProcCtx, 'cfh' | 'sfh' | 'req' | 'getPrincipal' | 'connection'>;
export type Nfsv4OperationFn<Req extends msg.Nfsv4Request, Res extends msg.Nfsv4Response> = (request: Req, ctx: Nfsv4OperationCtx) => Promise<Res>;
export interface Nfsv4Operations {
ACCESS: Nfsv4OperationFn<msg.Nfsv4AccessRequest, msg.Nfsv4AccessResponse>;
CLOSE: Nfsv4OperationFn<msg.Nfsv4CloseRequest, msg.Nfsv4CloseResponse>;
COMMIT: Nfsv4OperationFn<msg.Nfsv4CommitRequest, msg.Nfsv4CommitResponse>;
CREATE: Nfsv4OperationFn<msg.Nfsv4CreateRequest, msg.Nfsv4CreateResponse>;
DELEGPURGE: Nfsv4OperationFn<msg.Nfsv4DelegpurgeRequest, msg.Nfsv4DelegpurgeResponse>;
DELEGRETURN: Nfsv4OperationFn<msg.Nfsv4DelegreturnRequest, msg.Nfsv4DelegreturnResponse>;
GETATTR: Nfsv4OperationFn<msg.Nfsv4GetattrRequest, msg.Nfsv4GetattrResponse>;
GETFH: Nfsv4OperationFn<msg.Nfsv4GetfhRequest, msg.Nfsv4GetfhResponse>;
LINK: Nfsv4OperationFn<msg.Nfsv4LinkRequest, msg.Nfsv4LinkResponse>;
LOCK: Nfsv4OperationFn<msg.Nfsv4LockRequest, msg.Nfsv4LockResponse>;
LOCKT: Nfsv4OperationFn<msg.Nfsv4LocktRequest, msg.Nfsv4LocktResponse>;
LOCKU: Nfsv4OperationFn<msg.Nfsv4LockuRequest, msg.Nfsv4LockuResponse>;
LOOKUP: Nfsv4OperationFn<msg.Nfsv4LookupRequest, msg.Nfsv4LookupResponse>;
LOOKUPP: Nfsv4OperationFn<msg.Nfsv4LookuppRequest, msg.Nfsv4LookuppResponse>;
NVERIFY: Nfsv4OperationFn<msg.Nfsv4NverifyRequest, msg.Nfsv4NverifyResponse>;
OPEN: Nfsv4OperationFn<msg.Nfsv4OpenRequest, msg.Nfsv4OpenResponse>;
OPENATTR: Nfsv4OperationFn<msg.Nfsv4OpenattrRequest, msg.Nfsv4OpenattrResponse>;
OPEN_CONFIRM: Nfsv4OperationFn<msg.Nfsv4OpenConfirmRequest, msg.Nfsv4OpenConfirmResponse>;
OPEN_DOWNGRADE: Nfsv4OperationFn<msg.Nfsv4OpenDowngradeRequest, msg.Nfsv4OpenDowngradeResponse>;
PUTFH: Nfsv4OperationFn<msg.Nfsv4PutfhRequest, msg.Nfsv4PutfhResponse>;
PUTPUBFH: Nfsv4OperationFn<msg.Nfsv4PutpubfhRequest, msg.Nfsv4PutpubfhResponse>;
PUTROOTFH: Nfsv4OperationFn<msg.Nfsv4PutrootfhRequest, msg.Nfsv4PutrootfhResponse>;
READ: Nfsv4OperationFn<msg.Nfsv4ReadRequest, msg.Nfsv4ReadResponse>;
READDIR: Nfsv4OperationFn<msg.Nfsv4ReaddirRequest, msg.Nfsv4ReaddirResponse>;
READLINK: Nfsv4OperationFn<msg.Nfsv4ReadlinkRequest, msg.Nfsv4ReadlinkResponse>;
REMOVE: Nfsv4OperationFn<msg.Nfsv4RemoveRequest, msg.Nfsv4RemoveResponse>;
RENAME: Nfsv4OperationFn<msg.Nfsv4RenameRequest, msg.Nfsv4RenameResponse>;
RENEW: Nfsv4OperationFn<msg.Nfsv4RenewRequest, msg.Nfsv4RenewResponse>;
RESTOREFH: Nfsv4OperationFn<msg.Nfsv4RestorefhRequest, msg.Nfsv4RestorefhResponse>;
SAVEFH: Nfsv4OperationFn<msg.Nfsv4SavefhRequest, msg.Nfsv4SavefhResponse>;
SECINFO: Nfsv4OperationFn<msg.Nfsv4SecinfoRequest, msg.Nfsv4SecinfoResponse>;
SETATTR: Nfsv4OperationFn<msg.Nfsv4SetattrRequest, msg.Nfsv4SetattrResponse>;
SETCLIENTID: Nfsv4OperationFn<msg.Nfsv4SetclientidRequest, msg.Nfsv4SetclientidResponse>;
SETCLIENTID_CONFIRM: Nfsv4OperationFn<msg.Nfsv4SetclientidConfirmRequest, msg.Nfsv4SetclientidConfirmResponse>;
VERIFY: Nfsv4OperationFn<msg.Nfsv4VerifyRequest, msg.Nfsv4VerifyResponse>;
WRITE: Nfsv4OperationFn<msg.Nfsv4WriteRequest, msg.Nfsv4WriteResponse>;
RELEASE_LOCKOWNER: Nfsv4OperationFn<msg.Nfsv4ReleaseLockOwnerRequest, msg.Nfsv4ReleaseLockOwnerResponse>;
ILLEGAL: Nfsv4OperationFn<msg.Nfsv4IllegalRequest, msg.Nfsv4IllegalResponse>;
}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=Nfsv4Operations.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Nfsv4Operations.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/Nfsv4Operations.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
import * as msg from '../../messages';
import { Nfsv4OperationCtx, Nfsv4Operations } from './Nfsv4Operations';
export declare class Nfsv4OperationsNotImpl implements Nfsv4Operations {
ACCESS(request: msg.Nfsv4AccessRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4AccessResponse>;
CLOSE(request: msg.Nfsv4CloseRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4CloseResponse>;
COMMIT(request: msg.Nfsv4CommitRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4CommitResponse>;
CREATE(request: msg.Nfsv4CreateRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4CreateResponse>;
DELEGPURGE(request: msg.Nfsv4DelegpurgeRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4DelegpurgeResponse>;
DELEGRETURN(request: msg.Nfsv4DelegreturnRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4DelegreturnResponse>;
GETATTR(request: msg.Nfsv4GetattrRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4GetattrResponse>;
GETFH(request: msg.Nfsv4GetfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4GetfhResponse>;
LINK(request: msg.Nfsv4LinkRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LinkResponse>;
LOCK(request: msg.Nfsv4LockRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LockResponse>;
LOCKT(request: msg.Nfsv4LocktRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LocktResponse>;
LOCKU(request: msg.Nfsv4LockuRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LockuResponse>;
LOOKUP(request: msg.Nfsv4LookupRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LookupResponse>;
LOOKUPP(request: msg.Nfsv4LookuppRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LookuppResponse>;
NVERIFY(request: msg.Nfsv4NverifyRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4NverifyResponse>;
OPEN(request: msg.Nfsv4OpenRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenResponse>;
OPENATTR(request: msg.Nfsv4OpenattrRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenattrResponse>;
OPEN_CONFIRM(request: msg.Nfsv4OpenConfirmRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenConfirmResponse>;
OPEN_DOWNGRADE(request: msg.Nfsv4OpenDowngradeRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenDowngradeResponse>;
PUTFH(request: msg.Nfsv4PutfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4PutfhResponse>;
PUTPUBFH(request: msg.Nfsv4PutpubfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4PutpubfhResponse>;
PUTROOTFH(request: msg.Nfsv4PutrootfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4PutrootfhResponse>;
READ(request: msg.Nfsv4ReadRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReadResponse>;
READDIR(request: msg.Nfsv4ReaddirRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReaddirResponse>;
READLINK(request: msg.Nfsv4ReadlinkRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReadlinkResponse>;
REMOVE(request: msg.Nfsv4RemoveRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RemoveResponse>;
RENAME(request: msg.Nfsv4RenameRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RenameResponse>;
RENEW(request: msg.Nfsv4RenewRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RenewResponse>;
RESTOREFH(request: msg.Nfsv4RestorefhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RestorefhResponse>;
SAVEFH(request: msg.Nfsv4SavefhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SavefhResponse>;
SECINFO(request: msg.Nfsv4SecinfoRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SecinfoResponse>;
SETATTR(request: msg.Nfsv4SetattrRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SetattrResponse>;
SETCLIENTID(request: msg.Nfsv4SetclientidRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SetclientidResponse>;
SETCLIENTID_CONFIRM(request: msg.Nfsv4SetclientidConfirmRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SetclientidConfirmResponse>;
VERIFY(request: msg.Nfsv4VerifyRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4VerifyResponse>;
WRITE(request: msg.Nfsv4WriteRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4WriteResponse>;
RELEASE_LOCKOWNER(request: msg.Nfsv4ReleaseLockOwnerRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReleaseLockOwnerResponse>;
ILLEGAL(request: msg.Nfsv4IllegalRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4IllegalResponse>;
}
@@ -0,0 +1,159 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Nfsv4OperationsNotImpl = void 0;
class Nfsv4OperationsNotImpl {
async ACCESS(request, ctx) {
ctx.connection.logger.log('ACCESS', request);
throw new Error('Not implemented');
}
async CLOSE(request, ctx) {
ctx.connection.logger.log('CLOSE', request);
throw new Error('Not implemented');
}
async COMMIT(request, ctx) {
ctx.connection.logger.log('COMMIT', request);
throw new Error('Not implemented');
}
async CREATE(request, ctx) {
ctx.connection.logger.log('CREATE', request);
throw new Error('Not implemented');
}
async DELEGPURGE(request, ctx) {
ctx.connection.logger.log('DELEGPURGE', request);
throw new Error('Not implemented');
}
async DELEGRETURN(request, ctx) {
ctx.connection.logger.log('DELEGRETURN', request);
throw new Error('Not implemented');
}
async GETATTR(request, ctx) {
ctx.connection.logger.log('GETATTR', request);
throw new Error('Not implemented');
}
async GETFH(request, ctx) {
ctx.connection.logger.log('GETFH', request);
throw new Error('Not implemented');
}
async LINK(request, ctx) {
ctx.connection.logger.log('LINK', request);
throw new Error('Not implemented');
}
async LOCK(request, ctx) {
ctx.connection.logger.log('LOCK', request);
throw new Error('Not implemented');
}
async LOCKT(request, ctx) {
ctx.connection.logger.log('LOCKT', request);
throw new Error('Not implemented');
}
async LOCKU(request, ctx) {
ctx.connection.logger.log('LOCKU', request);
throw new Error('Not implemented');
}
async LOOKUP(request, ctx) {
ctx.connection.logger.log('LOOKUP', request);
throw new Error('Not implemented');
}
async LOOKUPP(request, ctx) {
ctx.connection.logger.log('LOOKUPP', request);
throw new Error('Not implemented');
}
async NVERIFY(request, ctx) {
ctx.connection.logger.log('NVERIFY', request);
throw new Error('Not implemented');
}
async OPEN(request, ctx) {
ctx.connection.logger.log('OPEN', request);
throw new Error('Not implemented');
}
async OPENATTR(request, ctx) {
ctx.connection.logger.log('OPENATTR', request);
throw new Error('Not implemented');
}
async OPEN_CONFIRM(request, ctx) {
ctx.connection.logger.log('OPEN_CONFIRM', request);
throw new Error('Not implemented');
}
async OPEN_DOWNGRADE(request, ctx) {
ctx.connection.logger.log('OPEN_DOWNGRADE', request);
throw new Error('Not implemented');
}
async PUTFH(request, ctx) {
ctx.connection.logger.log('PUTFH', request);
throw new Error('Not implemented');
}
async PUTPUBFH(request, ctx) {
ctx.connection.logger.log('PUTPUBFH', request);
throw new Error('Not implemented');
}
async PUTROOTFH(request, ctx) {
ctx.connection.logger.log('PUTROOTFH', request);
throw new Error('Not implemented');
}
async READ(request, ctx) {
ctx.connection.logger.log('READ', request);
throw new Error('Not implemented');
}
async READDIR(request, ctx) {
ctx.connection.logger.log('READDIR', request);
throw new Error('Not implemented');
}
async READLINK(request, ctx) {
ctx.connection.logger.log('READLINK', request);
throw new Error('Not implemented');
}
async REMOVE(request, ctx) {
ctx.connection.logger.log('REMOVE', request);
throw new Error('Not implemented');
}
async RENAME(request, ctx) {
ctx.connection.logger.log('RENAME', request);
throw new Error('Not implemented');
}
async RENEW(request, ctx) {
ctx.connection.logger.log('RENEW', request);
throw new Error('Not implemented');
}
async RESTOREFH(request, ctx) {
ctx.connection.logger.log('RESTOREFH', request);
throw new Error('Not implemented');
}
async SAVEFH(request, ctx) {
ctx.connection.logger.log('SAVEFH', request);
throw new Error('Not implemented');
}
async SECINFO(request, ctx) {
ctx.connection.logger.log('SECINFO', request);
throw new Error('Not implemented');
}
async SETATTR(request, ctx) {
ctx.connection.logger.log('SETATTR', request);
throw new Error('Not implemented');
}
async SETCLIENTID(request, ctx) {
ctx.connection.logger.log('SETCLIENTID', request);
throw new Error('Not implemented');
}
async SETCLIENTID_CONFIRM(request, ctx) {
ctx.connection.logger.log('SETCLIENTID_CONFIRM', request);
throw new Error('Not implemented');
}
async VERIFY(request, ctx) {
ctx.connection.logger.log('VERIFY', request);
throw new Error('Not implemented');
}
async WRITE(request, ctx) {
ctx.connection.logger.log('WRITE', request);
throw new Error('Not implemented');
}
async RELEASE_LOCKOWNER(request, ctx) {
ctx.connection.logger.log('RELEASE_LOCKOWNER', request);
throw new Error('Not implemented');
}
async ILLEGAL(request, ctx) {
ctx.connection.logger.log('ILLEGAL', request);
throw new Error('Not implemented');
}
}
exports.Nfsv4OperationsNotImpl = Nfsv4OperationsNotImpl;
//# sourceMappingURL=Nfsv4OperationsNotImpl.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,14 @@
/// <reference types="node" />
import type * as struct from '../../structs';
import type { FileHandle } from 'node:fs/promises';
export declare class OpenFileState {
readonly stateid: struct.Nfsv4Stateid;
readonly path: string;
readonly fd: FileHandle;
shareAccess: number;
shareDeny: number;
readonly openOwnerKey: string;
seqid: number;
confirmed: boolean;
constructor(stateid: struct.Nfsv4Stateid, path: string, fd: FileHandle, shareAccess: number, shareDeny: number, openOwnerKey: string, seqid: number, confirmed: boolean);
}
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenFileState = void 0;
class OpenFileState {
constructor(stateid, path, fd, shareAccess, shareDeny, openOwnerKey, seqid, confirmed) {
this.stateid = stateid;
this.path = path;
this.fd = fd;
this.shareAccess = shareAccess;
this.shareDeny = shareDeny;
this.openOwnerKey = openOwnerKey;
this.seqid = seqid;
this.confirmed = confirmed;
}
}
exports.OpenFileState = OpenFileState;
//# sourceMappingURL=OpenFileState.js.map
@@ -0,0 +1 @@
{"version":3,"file":"OpenFileState.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/OpenFileState.ts"],"names":[],"mappings":";;;AAQA,MAAa,aAAa;IACxB,YAMkB,OAA4B,EAM5B,IAAY,EAMZ,EAAc,EAOvB,WAAmB,EAOnB,SAAiB,EAOR,YAAoB,EAO7B,KAAa,EAOb,SAAkB;QA/CT,YAAO,GAAP,OAAO,CAAqB;QAM5B,SAAI,GAAJ,IAAI,CAAQ;QAMZ,OAAE,GAAF,EAAE,CAAY;QAOvB,gBAAW,GAAX,WAAW,CAAQ;QAOnB,cAAS,GAAT,SAAS,CAAQ;QAOR,iBAAY,GAAZ,YAAY,CAAQ;QAO7B,UAAK,GAAL,KAAK,CAAQ;QAOb,cAAS,GAAT,SAAS,CAAS;IACxB,CAAC;CACL;AAxDD,sCAwDC"}
@@ -0,0 +1,9 @@
export declare class OpenOwnerState {
readonly clientid: bigint;
readonly owner: Uint8Array;
seqid: number;
readonly opens: Set<string>;
lastResponse?: any;
lastRequestKey?: string | undefined;
constructor(clientid: bigint, owner: Uint8Array, seqid: number, opens?: Set<string>, lastResponse?: any, lastRequestKey?: string | undefined);
}
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenOwnerState = void 0;
class OpenOwnerState {
constructor(clientid, owner, seqid, opens = new Set(), lastResponse, lastRequestKey) {
this.clientid = clientid;
this.owner = owner;
this.seqid = seqid;
this.opens = opens;
this.lastResponse = lastResponse;
this.lastRequestKey = lastRequestKey;
}
}
exports.OpenOwnerState = OpenOwnerState;
//# sourceMappingURL=OpenOwnerState.js.map
@@ -0,0 +1 @@
{"version":3,"file":"OpenOwnerState.js","sourceRoot":"","sources":["../../../../../src/nfs/v4/server/operations/OpenOwnerState.ts"],"names":[],"mappings":";;;AAMA,MAAa,cAAc;IACzB,YAKkB,QAAgB,EAOhB,KAAiB,EAQ1B,KAAa,EAOJ,QAAqB,IAAI,GAAG,EAAE,EAQvC,YAAkB,EAOlB,cAAuB;QArCd,aAAQ,GAAR,QAAQ,CAAQ;QAOhB,UAAK,GAAL,KAAK,CAAY;QAQ1B,UAAK,GAAL,KAAK,CAAQ;QAOJ,UAAK,GAAL,KAAK,CAAyB;QAQvC,iBAAY,GAAZ,YAAY,CAAM;QAOlB,mBAAc,GAAd,cAAc,CAAS;IAC7B,CAAC;CACL;AA7CD,wCA6CC"}
@@ -0,0 +1,99 @@
/// <reference types="node" />
import { Nfsv4OperationCtx, Nfsv4Operations } from '../Nfsv4Operations';
import * as msg from '../../../messages';
import * as struct from '../../../structs';
import { ClientRecord } from '../ClientRecord';
import { OpenFileState } from '../OpenFileState';
import { OpenOwnerState } from '../OpenOwnerState';
import { LockOwnerState } from '../LockOwnerState';
import { ByteRangeLock } from '../ByteRangeLock';
import { LockStateid } from '../LockStateid';
import { FilesystemStats } from '../FilesystemStats';
import { FileHandleMapper } from './fh';
export interface Nfsv4OperationsNodeOpts {
fs: typeof import('node:fs');
dir: string;
maxClients?: number;
maxPendingClients?: number;
fsStats?: () => Promise<FilesystemStats>;
}
export declare class Nfsv4OperationsNode implements Nfsv4Operations {
protected readonly fs: typeof import('node:fs');
protected readonly promises: (typeof import('node:fs'))['promises'];
protected dir: string;
protected readonly leaseTime: number;
protected clients: Map<bigint, ClientRecord>;
protected pendingClients: Map<bigint, ClientRecord>;
protected maxClients: number;
protected maxPendingClients: number;
protected nextClientId: bigint;
protected bootStamp: number;
protected readonly fh: FileHandleMapper;
protected nextStateidSeqid: number;
protected openFiles: Map<string, OpenFileState>;
protected openOwners: Map<string, OpenOwnerState>;
protected locks: Map<string, ByteRangeLock>;
protected lockOwners: Map<string, LockOwnerState>;
protected lockStateids: Map<string, LockStateid>;
protected changeCounter: bigint;
protected fsStats: () => Promise<FilesystemStats>;
constructor(opts: Nfsv4OperationsNodeOpts);
protected defaultFsStats: () => Promise<FilesystemStats>;
protected findClientByIdString(map: Map<bigint, ClientRecord>, clientIdString: Uint8Array): [bigint, ClientRecord] | undefined;
protected enforceClientLimit(): void;
protected enforcePendingClientLimit(): void;
protected makeOpenOwnerKey(clientid: bigint, owner: Uint8Array): string;
protected validateSeqid(requestSeqid: number, ownerSeqid: number): 'valid' | 'replay' | 'invalid';
protected renewClientLease(clientid: bigint): void;
protected makeStateidKey(stateid: struct.Nfsv4Stateid): string;
protected createStateid(): struct.Nfsv4Stateid;
protected canAccessFile(path: string, shareAccess: number, shareDeny: number): boolean;
protected makeLockOwnerKey(clientid: bigint, owner: Uint8Array): string;
protected makeOpenRequestKey(ownerKey: string, currentPath: string, request: msg.Nfsv4OpenRequest): string;
protected makeLockRequestKey(lockOwnerKey: string, filePath: string, locktype: number, offset: bigint, length: bigint, seqid: number): string;
protected makeLockuRequestKey(lockOwnerKey: string, stateid: struct.Nfsv4Stateid, offset: bigint, length: bigint, seqid: number): string;
protected makeLockKey(stateid: struct.Nfsv4Stateid, offset: bigint, length: bigint): string;
protected makeLockStateidKey(lockOwnerKey: string, path: string): string;
protected getOrCreateLockStateid(lockOwnerKey: string, path: string): LockStateid;
protected findLockStateidByOther(other: Uint8Array): LockStateid | undefined;
protected hasConflictingLock(path: string, locktype: number, offset: bigint, length: bigint, ownerKey: string): boolean;
SETCLIENTID(request: msg.Nfsv4SetclientidRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SetclientidResponse>;
SETCLIENTID_CONFIRM(request: msg.Nfsv4SetclientidConfirmRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SetclientidConfirmResponse>;
ILLEGAL(request: msg.Nfsv4IllegalRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4IllegalResponse>;
PUTROOTFH(request: msg.Nfsv4PutrootfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4PutrootfhResponse>;
PUTPUBFH(request: msg.Nfsv4PutpubfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4PutpubfhResponse>;
PUTFH(request: msg.Nfsv4PutfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4PutfhResponse>;
GETFH(request: msg.Nfsv4GetfhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4GetfhResponse>;
RESTOREFH(request: msg.Nfsv4RestorefhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RestorefhResponse>;
SAVEFH(request: msg.Nfsv4SavefhRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SavefhResponse>;
private absolutePath;
LOOKUP(request: msg.Nfsv4LookupRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LookupResponse>;
LOOKUPP(request: msg.Nfsv4LookuppRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LookuppResponse>;
GETATTR(request: msg.Nfsv4GetattrRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4GetattrResponse>;
ACCESS(request: msg.Nfsv4AccessRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4AccessResponse>;
READDIR(request: msg.Nfsv4ReaddirRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReaddirResponse>;
OPEN(request: msg.Nfsv4OpenRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenResponse>;
OPENATTR(request: msg.Nfsv4OpenattrRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenattrResponse>;
OPEN_CONFIRM(request: msg.Nfsv4OpenConfirmRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenConfirmResponse>;
OPEN_DOWNGRADE(request: msg.Nfsv4OpenDowngradeRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4OpenDowngradeResponse>;
CLOSE(request: msg.Nfsv4CloseRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4CloseResponse>;
SECINFO(request: msg.Nfsv4SecinfoRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SecinfoResponse>;
LOCK(request: msg.Nfsv4LockRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LockResponse>;
LOCKT(request: msg.Nfsv4LocktRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LocktResponse>;
LOCKU(request: msg.Nfsv4LockuRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LockuResponse>;
RELEASE_LOCKOWNER(request: msg.Nfsv4ReleaseLockOwnerRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReleaseLockOwnerResponse>;
RENEW(request: msg.Nfsv4RenewRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RenewResponse>;
READ(request: msg.Nfsv4ReadRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReadResponse>;
READLINK(request: msg.Nfsv4ReadlinkRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4ReadlinkResponse>;
REMOVE(request: msg.Nfsv4RemoveRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RemoveResponse>;
RENAME(request: msg.Nfsv4RenameRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4RenameResponse>;
WRITE(request: msg.Nfsv4WriteRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4WriteResponse>;
DELEGPURGE(request: msg.Nfsv4DelegpurgeRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4DelegpurgeResponse>;
DELEGRETURN(request: msg.Nfsv4DelegreturnRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4DelegreturnResponse>;
COMMIT(request: msg.Nfsv4CommitRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4CommitResponse>;
CREATE(request: msg.Nfsv4CreateRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4CreateResponse>;
LINK(request: msg.Nfsv4LinkRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4LinkResponse>;
NVERIFY(request: msg.Nfsv4NverifyRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4NverifyResponse>;
SETATTR(request: msg.Nfsv4SetattrRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4SetattrResponse>;
VERIFY(request: msg.Nfsv4VerifyRequest, ctx: Nfsv4OperationCtx): Promise<msg.Nfsv4VerifyResponse>;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
/// <reference types="node" />
import type { Stats } from 'node:fs';
import * as struct from '../../../structs';
import type { FilesystemStats } from '../FilesystemStats';
export declare const encodeAttrs: (requestedAttrs: struct.Nfsv4Bitmap, stats: Stats | undefined, path: string, fh?: Uint8Array, leaseTime?: number, fsStats?: FilesystemStats) => struct.Nfsv4Fattr;
@@ -0,0 +1,262 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeAttrs = void 0;
const tslib_1 = require("tslib");
const Writer_1 = require("@jsonjoy.com/buffers/lib/Writer");
const XdrEncoder_1 = require("../../../../../xdr/XdrEncoder");
const struct = tslib_1.__importStar(require("../../../structs"));
const attributes_1 = require("../../../attributes");
const encodeAttrs = (requestedAttrs, stats, path, fh, leaseTime, fsStats) => {
const writer = new Writer_1.Writer(512);
const xdr = new XdrEncoder_1.XdrEncoder(writer);
const supportedMask = [];
const requested = requestedAttrs.mask;
for (let i = 0; i < requested.length; i++) {
const word = requested[i];
if (!word)
continue;
const wordIndex = i;
for (let bit = 0; bit < 32; bit++) {
if (!(word & (1 << bit)))
continue;
const attrNum = wordIndex * 32 + bit;
switch (attrNum) {
case 0: {
const implementedAttrs = [];
(0, attributes_1.setBit)(implementedAttrs, 0);
(0, attributes_1.setBit)(implementedAttrs, 1);
(0, attributes_1.setBit)(implementedAttrs, 2);
(0, attributes_1.setBit)(implementedAttrs, 3);
(0, attributes_1.setBit)(implementedAttrs, 4);
(0, attributes_1.setBit)(implementedAttrs, 5);
(0, attributes_1.setBit)(implementedAttrs, 6);
(0, attributes_1.setBit)(implementedAttrs, 7);
(0, attributes_1.setBit)(implementedAttrs, 8);
(0, attributes_1.setBit)(implementedAttrs, 9);
(0, attributes_1.setBit)(implementedAttrs, 10);
(0, attributes_1.setBit)(implementedAttrs, 11);
(0, attributes_1.setBit)(implementedAttrs, 19);
(0, attributes_1.setBit)(implementedAttrs, 20);
(0, attributes_1.setBit)(implementedAttrs, 33);
(0, attributes_1.setBit)(implementedAttrs, 35);
(0, attributes_1.setBit)(implementedAttrs, 45);
(0, attributes_1.setBit)(implementedAttrs, 42);
(0, attributes_1.setBit)(implementedAttrs, 43);
(0, attributes_1.setBit)(implementedAttrs, 44);
(0, attributes_1.setBit)(implementedAttrs, 21);
(0, attributes_1.setBit)(implementedAttrs, 22);
(0, attributes_1.setBit)(implementedAttrs, 23);
(0, attributes_1.setBit)(implementedAttrs, 47);
(0, attributes_1.setBit)(implementedAttrs, 52);
(0, attributes_1.setBit)(implementedAttrs, 53);
xdr.writeUnsignedInt(implementedAttrs.length);
for (let j = 0; j < implementedAttrs.length; j++) {
xdr.writeUnsignedInt(implementedAttrs[j]);
}
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 1: {
if (!stats)
break;
let type;
if (stats.isFile())
type = 1;
else if (stats.isDirectory())
type = 2;
else if (stats.isSymbolicLink())
type = 5;
else if (stats.isBlockDevice())
type = 3;
else if (stats.isCharacterDevice())
type = 4;
else if (stats.isFIFO())
type = 7;
else if (stats.isSocket())
type = 6;
else
type = 1;
xdr.writeUnsignedInt(type);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 4: {
if (!stats)
break;
xdr.writeUnsignedHyper(BigInt(stats.size));
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 20: {
if (!stats)
break;
xdr.writeUnsignedHyper(BigInt(stats.ino));
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 33: {
if (!stats)
break;
xdr.writeUnsignedInt(stats.mode & 0o7777);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 35: {
if (!stats)
break;
xdr.writeUnsignedInt(stats.nlink);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 45: {
if (!stats)
break;
xdr.writeUnsignedHyper(BigInt(stats.blocks * 512));
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 42: {
if (!fsStats)
break;
xdr.writeUnsignedHyper(fsStats.spaceAvail);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 43: {
if (!fsStats)
break;
xdr.writeUnsignedHyper(fsStats.spaceFree);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 44: {
if (!fsStats)
break;
xdr.writeUnsignedHyper(fsStats.spaceTotal);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 21: {
if (!fsStats)
break;
xdr.writeUnsignedHyper(fsStats.filesAvail);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 22: {
if (!fsStats)
break;
xdr.writeUnsignedHyper(fsStats.filesFree);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 23: {
if (!fsStats)
break;
xdr.writeUnsignedHyper(fsStats.filesTotal);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 47: {
if (!stats)
break;
const atime = stats.atimeMs;
const seconds = Math.floor(atime / 1000);
const nseconds = Math.floor((atime % 1000) * 1000000);
xdr.writeHyper(BigInt(seconds));
xdr.writeUnsignedInt(nseconds);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 53: {
if (!stats)
break;
const mtime = stats.mtimeMs;
const seconds = Math.floor(mtime / 1000);
const nseconds = Math.floor((mtime % 1000) * 1000000);
xdr.writeHyper(BigInt(seconds));
xdr.writeUnsignedInt(nseconds);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 52: {
if (!stats)
break;
const ctime = stats.ctimeMs;
const seconds = Math.floor(ctime / 1000);
const nseconds = Math.floor((ctime % 1000) * 1000000);
xdr.writeHyper(BigInt(seconds));
xdr.writeUnsignedInt(nseconds);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 3: {
if (!stats)
break;
const changeTime = BigInt(Math.floor(stats.mtimeMs * 1000000));
xdr.writeUnsignedHyper(changeTime);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 10: {
if (leaseTime !== undefined) {
xdr.writeUnsignedInt(leaseTime);
(0, attributes_1.setBit)(supportedMask, attrNum);
}
break;
}
case 2: {
xdr.writeUnsignedInt(2);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 5: {
xdr.writeUnsignedInt(1);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 6: {
xdr.writeUnsignedInt(1);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 7: {
xdr.writeUnsignedInt(0);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 8: {
xdr.writeUnsignedHyper(BigInt(0));
xdr.writeUnsignedHyper(BigInt(0));
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 9: {
xdr.writeUnsignedInt(1);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 11: {
xdr.writeUnsignedInt(0);
(0, attributes_1.setBit)(supportedMask, attrNum);
break;
}
case 19: {
if (fh) {
xdr.writeVarlenOpaque(fh);
(0, attributes_1.setBit)(supportedMask, attrNum);
}
break;
}
default: {
if (attributes_1.SET_ONLY_ATTRS.has(attrNum))
throw 22;
}
}
}
}
const attrVals = writer.flush();
return new struct.Nfsv4Fattr(new struct.Nfsv4Bitmap(supportedMask), attrVals);
};
exports.encodeAttrs = encodeAttrs;
//# sourceMappingURL=attrs.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,28 @@
import type { Nfsv4OperationCtx } from '../Nfsv4Operations';
export declare const ROOT_FH: Uint8Array;
export declare const enum FH_TYPE {
ROOT = 0,
PATH = 1,
ID = 2
}
export declare const enum FH {
MAX_SIZE = 128
}
export declare const encodePathFh: (absolutePath: string) => Uint8Array | undefined;
export declare const decodePathFh: (fh: Uint8Array) => string | undefined;
export declare class FileHandleMapper {
protected readonly dir: string;
protected readonly stamp: number;
protected idToPath: Map<number, string>;
protected pathToId: Map<string, Uint8Array>;
protected readonly maxFhTableSize = 100000;
constructor(stamp: number, dir: string);
decode(fh: Uint8Array): string;
encode(path: string): Uint8Array;
validate(fh: Uint8Array): boolean;
currentPath(ctx: Nfsv4OperationCtx): string;
savedPath(ctx: Nfsv4OperationCtx): string;
setCfh(ctx: Nfsv4OperationCtx, path: string): void;
remove(path: string): void;
rename(oldPath: string, newPath: string): void;
}
@@ -0,0 +1,147 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileHandleMapper = exports.decodePathFh = exports.encodePathFh = exports.ROOT_FH = void 0;
const encode_1 = require("@jsonjoy.com/buffers/lib/utf8/encode");
const decodeUtf8_1 = require("@jsonjoy.com/buffers/lib/utf8/decodeUtf8");
const node_crypto_1 = require("node:crypto");
exports.ROOT_FH = new Uint8Array([0]);
const encodePathFh = (absolutePath) => {
const utf8Length = Buffer.byteLength(absolutePath, 'utf8');
if (utf8Length + 1 > 128)
return undefined;
const u8 = new Uint8Array(1 + utf8Length);
u8[0] = 1;
(0, encode_1.encode)(u8, absolutePath, 1, utf8Length);
return u8;
};
exports.encodePathFh = encodePathFh;
const decodePathFh = (fh) => {
const length = fh.length;
if (length < 2)
return undefined;
if (fh[0] !== 1)
return undefined;
return (0, decodeUtf8_1.decodeUtf8)(fh, 1, length - 1);
};
exports.decodePathFh = decodePathFh;
class FileHandleMapper {
constructor(stamp, dir) {
this.dir = dir;
this.idToPath = new Map();
this.pathToId = new Map();
this.maxFhTableSize = 100000;
this.stamp = stamp & 0xffff;
}
decode(fh) {
const length = fh.length;
if (fh.length === 0)
return this.dir;
const type = fh[0];
if (type === 0)
return this.dir;
if (type === 1) {
try {
const path = (0, exports.decodePathFh)(fh);
if (!path)
throw 10001;
return path;
}
catch {
throw 10001;
}
}
if (type === 2) {
if (length !== 8)
throw 10001;
const stamp = (fh[1] << 8) | fh[2];
if (stamp !== this.stamp)
throw 10014;
const id = fh[3] * 0x100000000 + fh[4] * 0x1000000 + (fh[5] << 16) + (fh[6] << 8) + fh[7];
const path = this.idToPath.get(id);
if (!path)
throw 10014;
return path;
}
throw 10001;
}
encode(path) {
if (path === this.dir)
return exports.ROOT_FH;
let fh = this.pathToId.get(path);
if (fh)
return fh;
fh = (0, node_crypto_1.randomBytes)(8);
fh[0] = 2;
fh[1] = (this.stamp >> 8) & 0xff;
fh[2] = this.stamp & 0xff;
const id = fh[3] * 0x100000000 + fh[4] * 0x1000000 + (fh[5] << 16) + (fh[6] << 8) + fh[7];
const { idToPath, pathToId, maxFhTableSize } = this;
ENFORCE_FH_TABLE_SIZE_LIMIT: {
if (idToPath.size <= maxFhTableSize)
break ENFORCE_FH_TABLE_SIZE_LIMIT;
const entry = idToPath.entries().next().value;
if (entry) {
const [id, path] = entry;
idToPath.delete(id);
pathToId.delete(path);
}
}
idToPath.set(id, path);
pathToId.set(path, fh);
return fh;
}
validate(fh) {
if (fh.length === 0)
return true;
const type = fh[0];
if (type === 0)
return true;
if (type === 1)
return true;
if (type === 2)
return true;
return false;
}
currentPath(ctx) {
const cfh = ctx.cfh;
if (!cfh)
throw 10020;
return this.decode(cfh);
}
savedPath(ctx) {
const sfh = ctx.sfh;
if (!sfh)
throw 10020;
return this.decode(sfh);
}
setCfh(ctx, path) {
const newFh = this.encode(path);
ctx.cfh = newFh;
}
remove(path) {
const fh = this.pathToId.get(path);
if (!fh)
return;
const type = fh[0];
if (type !== 2)
return;
const id = fh[3] * 0x100000000 + fh[4] * 0x1000000 + (fh[5] << 16) + (fh[6] << 8) + fh[7];
this.pathToId.delete(path);
this.idToPath.delete(id);
}
rename(oldPath, newPath) {
this.remove(newPath);
const fh = this.pathToId.get(oldPath);
if (!fh)
return;
const type = fh[0];
if (type !== 2)
return;
const id = fh[3] * 0x100000000 + fh[4] * 0x1000000 + (fh[5] << 16) + (fh[6] << 8) + fh[7];
this.pathToId.delete(oldPath);
this.pathToId.set(newPath, fh);
this.idToPath.set(id, newPath);
}
}
exports.FileHandleMapper = FileHandleMapper;
//# sourceMappingURL=fh.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
import { Nfsv4Stat } from '../../..';
import type { Logger } from '../../types';
export declare const isErrCode: (code: unknown, error: unknown) => boolean;
export declare const normalizeNodeFsError: (err: unknown, logger: Logger) => Nfsv4Stat;
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeNodeFsError = exports.isErrCode = void 0;
const isErrCode = (code, error) => !!error && typeof error === 'object' && error.code === code;
exports.isErrCode = isErrCode;
const normalizeNodeFsError = (err, logger) => {
if ((0, exports.isErrCode)('ENOENT', err))
return 2;
if ((0, exports.isErrCode)('EACCES', err))
return 13;
if ((0, exports.isErrCode)('EEXIST', err))
return 17;
logger.error('UNEXPECTED_FS_ERROR', err);
return 5;
};
exports.normalizeNodeFsError = normalizeNodeFsError;
//# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../../../../src/nfs/v4/server/operations/node/util.ts"],"names":[],"mappings":";;;AAGO,MAAM,SAAS,GAAG,CAAC,IAAa,EAAE,KAAc,EAAW,EAAE,CAClE,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAAa,CAAC,IAAI,KAAK,IAAI,CAAC;AAD1D,QAAA,SAAS,aACiD;AAEhE,MAAM,oBAAoB,GAAG,CAAC,GAAY,EAAE,MAAc,EAAa,EAAE;IAC9E,IAAI,IAAA,iBAAS,EAAC,QAAQ,EAAE,GAAG,CAAC;QAAE,SAA+B;IAC7D,IAAI,IAAA,iBAAS,EAAC,QAAQ,EAAE,GAAG,CAAC;QAAE,UAAgC;IAC9D,IAAI,IAAA,iBAAS,EAAC,QAAQ,EAAE,GAAG,CAAC;QAAE,UAA+B;IAC7D,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IACzC,SAA4B;AAC9B,CAAC,CAAC;AANW,QAAA,oBAAoB,wBAM/B"}