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 { Nfsv4Connection } from './Nfsv4Connection';
import * as msg from '../messages';
export declare class Nfsv4CompoundProcCtx {
readonly connection: Nfsv4Connection;
readonly req: msg.Nfsv4CompoundRequest;
cfh: Uint8Array | null;
sfh: Uint8Array | null;
constructor(connection: Nfsv4Connection, req: msg.Nfsv4CompoundRequest);
getPrincipal(): string;
exec(): Promise<msg.Nfsv4CompoundResponse>;
}
@@ -0,0 +1,155 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Nfsv4CompoundProcCtx = void 0;
const tslib_1 = require("tslib");
const msg = tslib_1.__importStar(require("../messages"));
const format_1 = require("../format");
class Nfsv4CompoundProcCtx {
constructor(connection, req) {
this.connection = connection;
this.req = req;
this.cfh = null;
this.sfh = null;
}
getPrincipal() {
return 'none';
}
async exec() {
const { req, connection } = this;
const { ops, debug, logger } = connection;
const { argarray, tag } = req;
const length = argarray.length;
let status = 0;
const resarray = [];
OPS_LOOP: for (let i = 0; i < length; i++) {
const op = argarray[i];
const opReq = op;
let fn = void 0;
let Response = void 0;
if (op instanceof msg.Nfsv4AccessRequest)
(fn = ops.ACCESS), (Response = msg.Nfsv4AccessResponse);
else if (op instanceof msg.Nfsv4PutrootfhRequest)
(fn = ops.PUTROOTFH), (Response = msg.Nfsv4PutrootfhResponse);
else if (op instanceof msg.Nfsv4PutpubfhRequest)
(fn = ops.PUTPUBFH), (Response = msg.Nfsv4PutpubfhResponse);
else if (op instanceof msg.Nfsv4PutfhRequest)
(fn = ops.PUTFH), (Response = msg.Nfsv4PutfhResponse);
else if (op instanceof msg.Nfsv4GetfhRequest)
(fn = ops.GETFH), (Response = msg.Nfsv4GetfhResponse);
else if (op instanceof msg.Nfsv4SavefhRequest)
(fn = ops.SAVEFH), (Response = msg.Nfsv4SavefhResponse);
else if (op instanceof msg.Nfsv4ReadRequest)
(fn = ops.READ), (Response = msg.Nfsv4ReadResponse);
else if (op instanceof msg.Nfsv4ReaddirRequest)
(fn = ops.READDIR), (Response = msg.Nfsv4ReaddirResponse);
else if (op instanceof msg.Nfsv4ReadlinkRequest)
(fn = ops.READLINK), (Response = msg.Nfsv4ReadlinkResponse);
else if (op instanceof msg.Nfsv4WriteRequest)
(fn = ops.WRITE), (Response = msg.Nfsv4WriteResponse);
else if (op instanceof msg.Nfsv4OpenRequest)
(fn = ops.OPEN), (Response = msg.Nfsv4OpenResponse);
else if (op instanceof msg.Nfsv4CloseRequest)
(fn = ops.CLOSE), (Response = msg.Nfsv4CloseResponse);
else if (op instanceof msg.Nfsv4RemoveRequest)
(fn = ops.REMOVE), (Response = msg.Nfsv4RemoveResponse);
else if (op instanceof msg.Nfsv4RenameRequest)
(fn = ops.RENAME), (Response = msg.Nfsv4RenameResponse);
else if (op instanceof msg.Nfsv4OpenattrRequest)
(fn = ops.OPENATTR), (Response = msg.Nfsv4OpenattrResponse);
else if (op instanceof msg.Nfsv4GetattrRequest)
(fn = ops.GETATTR), (Response = msg.Nfsv4GetattrResponse);
else if (op instanceof msg.Nfsv4SetattrRequest)
(fn = ops.SETATTR), (Response = msg.Nfsv4SetattrResponse);
else if (op instanceof msg.Nfsv4CreateRequest)
(fn = ops.CREATE), (Response = msg.Nfsv4CreateResponse);
else if (op instanceof msg.Nfsv4SetclientidRequest)
(fn = ops.SETCLIENTID), (Response = msg.Nfsv4SetclientidResponse);
else if (op instanceof msg.Nfsv4SetclientidConfirmRequest)
(fn = ops.SETCLIENTID_CONFIRM), (Response = msg.Nfsv4SetclientidConfirmResponse);
else if (op instanceof msg.Nfsv4OpenConfirmRequest)
(fn = ops.OPEN_CONFIRM), (Response = msg.Nfsv4OpenConfirmResponse);
else if (op instanceof msg.Nfsv4OpenDowngradeRequest)
(fn = ops.OPEN_DOWNGRADE), (Response = msg.Nfsv4OpenDowngradeResponse);
else if (op instanceof msg.Nfsv4CommitRequest)
(fn = ops.COMMIT), (Response = msg.Nfsv4CommitResponse);
else if (op instanceof msg.Nfsv4LinkRequest)
(fn = ops.LINK), (Response = msg.Nfsv4LinkResponse);
else if (op instanceof msg.Nfsv4RenewRequest)
(fn = ops.RENEW), (Response = msg.Nfsv4RenewResponse);
else if (op instanceof msg.Nfsv4DelegpurgeRequest)
(fn = ops.DELEGPURGE), (Response = msg.Nfsv4DelegpurgeResponse);
else if (op instanceof msg.Nfsv4DelegreturnRequest)
(fn = ops.DELEGRETURN), (Response = msg.Nfsv4DelegreturnResponse);
else if (op instanceof msg.Nfsv4RestorefhRequest)
(fn = ops.RESTOREFH), (Response = msg.Nfsv4RestorefhResponse);
else if (op instanceof msg.Nfsv4SecinfoRequest)
(fn = ops.SECINFO), (Response = msg.Nfsv4SecinfoResponse);
else if (op instanceof msg.Nfsv4VerifyRequest)
(fn = ops.VERIFY), (Response = msg.Nfsv4VerifyResponse);
else if (op instanceof msg.Nfsv4LockRequest)
(fn = ops.LOCK), (Response = msg.Nfsv4LockResponse);
else if (op instanceof msg.Nfsv4LocktRequest)
(fn = ops.LOCKT), (Response = msg.Nfsv4LocktResponse);
else if (op instanceof msg.Nfsv4LockuRequest)
(fn = ops.LOCKU), (Response = msg.Nfsv4LockuResponse);
else if (op instanceof msg.Nfsv4LookupRequest)
(fn = ops.LOOKUP), (Response = msg.Nfsv4LookupResponse);
else if (op instanceof msg.Nfsv4LookuppRequest)
(fn = ops.LOOKUPP), (Response = msg.Nfsv4LookuppResponse);
else if (op instanceof msg.Nfsv4NverifyRequest)
(fn = ops.NVERIFY), (Response = msg.Nfsv4NverifyResponse);
else if (op instanceof msg.Nfsv4ReleaseLockOwnerRequest)
(fn = ops.RELEASE_LOCKOWNER), (Response = msg.Nfsv4ReleaseLockOwnerResponse);
else if (op instanceof msg.Nfsv4IllegalRequest)
(fn = ops.ILLEGAL), (Response = msg.Nfsv4IllegalResponse);
if (!fn || !Response)
return new msg.Nfsv4CompoundResponse(10044, tag, resarray);
EXEC_OP: try {
if (debug)
logger.log((0, format_1.formatNfsv4Request)(opReq));
const opResponse = await fn.call(ops, opReq, this);
if (!(opResponse instanceof Response))
throw new Error('Unexpected response, fn = ' + fn.name);
if (debug)
logger.log(': ' + (0, format_1.formatNfsv4Response)(opResponse));
status = opResponse.status;
resarray.push(opResponse);
}
catch (err) {
if (debug)
logger.error(': ERROR', fn.name, err);
if (err instanceof Response) {
if (err.status !== 0) {
status = err.status;
resarray.push(err);
break EXEC_OP;
}
else {
logger.error('Operation [' + fn.name + '] threw response with NFS4_OK');
err = 10006;
}
}
FIND_STATUS_CODE: {
if (typeof err === 'number') {
if (err > 0 && err <= 16777215) {
status = err;
break FIND_STATUS_CODE;
}
status = 10006;
logger.error('Invalid status [code = ' + err + ', fn = ' + fn.name + ']');
break FIND_STATUS_CODE;
}
status = 10006;
logger.error(fn.name, err);
}
const opResponse = new Response(status);
resarray.push(opResponse);
}
if (status !== 0)
break OPS_LOOP;
}
return new msg.Nfsv4CompoundResponse(status, tag, resarray);
}
}
exports.Nfsv4CompoundProcCtx = Nfsv4CompoundProcCtx;
//# sourceMappingURL=Nfsv4CompoundProcCtx.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,42 @@
/// <reference types="node" />
import { Nfsv4Decoder } from '../Nfsv4Decoder';
import { Nfsv4FullEncoder } from '../Nfsv4FullEncoder';
import { RmRecordDecoder, RmRecordEncoder } from '../../../rm';
import { RpcCallMessage, RpcMessage, RpcMessageDecoder, RpcMessageEncoder } from '../../../rpc';
import type { Duplex } from 'node:stream';
import type { IWriter, IWriterGrowable } from '@jsonjoy.com/buffers/lib/types';
import type { Nfsv4Operations } from './operations/Nfsv4Operations';
export interface Nfsv4ConnectionOpts {
duplex: Duplex;
ops: Nfsv4Operations;
encoder?: Nfsv4FullEncoder;
decoder?: Nfsv4Decoder;
debug?: boolean;
logger?: Pick<typeof console, 'log' | 'error'>;
}
export declare class Nfsv4Connection {
closed: boolean;
maxIncomingMessage: number;
maxBackpressure: number;
protected lastXid: number;
readonly duplex: Duplex;
protected readonly rmDecoder: RmRecordDecoder;
protected readonly rpcDecoder: RpcMessageDecoder;
protected readonly nfsDecoder: Nfsv4Decoder;
protected readonly writer: IWriter & IWriterGrowable;
protected readonly rmEncoder: RmRecordEncoder;
protected readonly rpcEncoder: RpcMessageEncoder;
protected readonly nfsEncoder: Nfsv4FullEncoder;
debug: boolean;
logger: Pick<typeof console, 'log' | 'error'>;
readonly ops: Nfsv4Operations;
constructor(opts: Nfsv4ConnectionOpts);
protected onData(data: Uint8Array): void;
protected onRpcMessage(msg: RpcMessage): void;
protected onRpcCallMessage(procedure: RpcCallMessage): void;
private closeWithError;
close(): void;
private __uncorkTimer;
write(buf: Uint8Array): void;
send(): void;
}
@@ -0,0 +1,160 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Nfsv4Connection = void 0;
const tslib_1 = require("tslib");
const Reader_1 = require("@jsonjoy.com/buffers/lib/Reader");
const Nfsv4Decoder_1 = require("../Nfsv4Decoder");
const Nfsv4FullEncoder_1 = require("../Nfsv4FullEncoder");
const rm_1 = require("../../../rm");
const rpc_1 = require("../../../rpc");
const msg = tslib_1.__importStar(require("../messages"));
const constants_1 = require("../constants");
const Nfsv4CompoundProcCtx_1 = require("./Nfsv4CompoundProcCtx");
const EMPTY_AUTH = new rpc_1.RpcOpaqueAuth(0, constants_1.EMPTY_READER);
class Nfsv4Connection {
constructor(opts) {
this.closed = false;
this.maxIncomingMessage = 2 * 1024 * 1024;
this.maxBackpressure = 2 * 1024 * 1024;
this.lastXid = 0;
this.__uncorkTimer = null;
this.debug = !!opts.debug;
this.logger = opts.logger || console;
const duplex = (this.duplex = opts.duplex);
this.ops = opts.ops;
this.rmDecoder = new rm_1.RmRecordDecoder();
this.rpcDecoder = new rpc_1.RpcMessageDecoder();
this.nfsDecoder = new Nfsv4Decoder_1.Nfsv4Decoder();
const nfsEncoder = (this.nfsEncoder = new Nfsv4FullEncoder_1.Nfsv4FullEncoder());
this.writer = nfsEncoder.writer;
this.rmEncoder = nfsEncoder.rmEncoder;
this.rpcEncoder = nfsEncoder.rpcEncoder;
duplex.on('data', this.onData.bind(this));
duplex.on('timeout', () => this.close());
duplex.on('close', (hadError) => {
this.close();
});
duplex.on('error', (err) => {
this.logger.error('SOCKET ERROR:', err);
this.close();
});
}
onData(data) {
const { rmDecoder, rpcDecoder } = this;
rmDecoder.push(data);
let record = rmDecoder.readRecord();
while (record) {
if (record.size()) {
const rpcMessage = rpcDecoder.decodeMessage(record);
if (rpcMessage)
this.onRpcMessage(rpcMessage);
else {
this.close();
return;
}
}
record = rmDecoder.readRecord();
}
}
onRpcMessage(msg) {
if (msg instanceof rpc_1.RpcCallMessage) {
this.lastXid = msg.xid;
this.onRpcCallMessage(msg);
}
else if (msg instanceof rpc_1.RpcAcceptedReplyMessage) {
throw new Error('Not implemented RpcAcceptedReplyMessage');
}
else if (msg instanceof rpc_1.RpcRejectedReplyMessage) {
throw new Error('Not implemented RpcRejectedReplyMessage');
}
}
onRpcCallMessage(procedure) {
const { debug, logger, writer, rmEncoder } = this;
const { xid, proc } = procedure;
switch (proc) {
case 1: {
if (debug)
logger.log(`\n<COMPOUND{${xid}}>`);
if (!(procedure.params instanceof Reader_1.Reader))
return;
const compound = this.nfsDecoder.decodeCompoundRequest(procedure.params);
if (compound instanceof msg.Nfsv4CompoundRequest) {
new Nfsv4CompoundProcCtx_1.Nfsv4CompoundProcCtx(this, compound)
.exec()
.then((procResponse) => {
if (debug)
logger.log(`</COMPOUND{${xid}}>`);
this.nfsEncoder.writeAcceptedCompoundReply(xid, EMPTY_AUTH, procResponse);
this.write(writer.flush());
})
.catch((err) => {
logger.error('NFS COMPOUND error:', xid, err);
this.nfsEncoder.writeRejectedReply(xid, 10006);
});
}
else
this.closeWithError(4);
break;
}
case 0: {
if (debug)
logger.log('NULL', procedure);
const state = rmEncoder.startRecord();
this.rpcEncoder.writeAcceptedReply(xid, EMPTY_AUTH, 0);
rmEncoder.endRecord(state);
this.write(writer.flush());
break;
}
default: {
if (debug)
logger.error(`Unknown procedure: ${proc}`);
}
}
}
closeWithError(error) {
if (this.debug)
this.logger.log(`Closing with error: RpcAcceptStat = ${error}, xid = ${this.lastXid}`);
const xid = this.lastXid;
if (xid) {
const state = this.rmEncoder.startRecord();
const verify = new rpc_1.RpcOpaqueAuth(0, constants_1.EMPTY_READER);
this.rpcEncoder.writeAcceptedReply(xid, verify, error);
this.rmEncoder.endRecord(state);
const bin = this.writer.flush();
this.duplex.write(bin);
}
this.close();
}
close() {
if (this.closed)
return;
this.closed = true;
clearImmediate(this.__uncorkTimer);
this.__uncorkTimer = null;
const duplex = this.duplex;
duplex.removeAllListeners();
if (!duplex.destroyed)
duplex.destroy();
}
write(buf) {
if (this.closed)
return;
const duplex = this.duplex;
if (duplex.writableLength > this.maxBackpressure) {
this.closeWithError(5);
return;
}
const __uncorkTimer = this.__uncorkTimer;
if (!__uncorkTimer)
duplex.cork();
duplex.write(buf);
if (!__uncorkTimer)
this.__uncorkTimer = setImmediate(() => {
this.__uncorkTimer = null;
duplex.uncork();
});
}
send() { }
}
exports.Nfsv4Connection = Nfsv4Connection;
//# sourceMappingURL=Nfsv4Connection.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,26 @@
/// <reference types="node" />
import * as net from 'net';
import { Logger } from './types';
import { Nfsv4Operations } from './operations/Nfsv4Operations';
export interface Nfsv4TcpServerOpts {
ops: Nfsv4Operations;
port?: number;
host?: string;
debug?: boolean;
logger?: Logger;
onError?: (err: Error) => void;
stopOnSigint?: boolean;
}
export declare class Nfsv4TcpServer {
static start(opts: Nfsv4TcpServerOpts): void;
readonly server: net.Server;
port: number;
host: string;
debug: boolean;
logger: Logger;
private sigintHandler?;
constructor(opts: Nfsv4TcpServerOpts);
private cleanup;
stop(): Promise<void>;
start(port?: number, host?: string): Promise<void>;
}
@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Nfsv4TcpServer = void 0;
const tslib_1 = require("tslib");
const net = tslib_1.__importStar(require("net"));
const Nfsv4Connection_1 = require("./Nfsv4Connection");
const PORT = Number(process.env.NFS_PORT) || Number(process.env.PORT) || 2049;
const HOST = process.env.NFS_HOST
? String(process.env.NFS_HOST)
: process.env.HOST
? String(process.env.HOST)
: '127.0.0.1';
class Nfsv4TcpServer {
static start(opts) {
const server = new Nfsv4TcpServer(opts);
server.start().catch(console.error);
}
constructor(opts) {
this.port = PORT;
this.host = HOST;
this.debug = false;
this.port = opts.port ?? PORT;
this.host = opts.host ?? HOST;
this.debug = opts.debug ?? false;
this.logger = opts.logger ?? console;
const ops = opts.ops;
const server = (this.server = new net.Server());
server.on('connection', (socket) => {
if (this.debug)
this.logger.log('New connection from', socket.remoteAddress, 'port', socket.remotePort);
new Nfsv4Connection_1.Nfsv4Connection({
duplex: socket,
ops,
debug: this.debug,
logger: this.logger,
});
});
server.on('error', opts.onError ??
((err) => {
if (this.debug)
this.logger.error('Server error:', err.message);
process.exit(1);
}));
if (opts.stopOnSigint ?? true) {
this.sigintHandler = () => {
if (this.debug)
this.logger.log('\nShutting down NFSv4 server...');
this.cleanup();
process.exit(0);
};
process.on('SIGINT', this.sigintHandler);
}
}
cleanup() {
if (this.sigintHandler) {
process.off('SIGINT', this.sigintHandler);
this.sigintHandler = undefined;
}
this.server.close((err) => {
if (this.debug && err)
this.logger.error('Error closing server:', err);
});
}
stop() {
return new Promise((resolve) => {
this.cleanup();
this.server.close(() => {
if (this.debug)
this.logger.log('NFSv4 server closed');
resolve();
});
});
}
start(port = this.port, host = this.host) {
if (this.debug)
this.logger.log(`Starting NFSv4 TCP server on ${host}:${port}...`);
return new Promise((resolve, reject) => {
const onError = (err) => reject(err);
const server = this.server;
server.on('error', onError);
server.listen(port, host, () => {
if (this.debug)
this.logger.log(`NFSv4 TCP server listening on ${host}:${port}`);
server.off('error', onError);
resolve();
});
});
}
}
exports.Nfsv4TcpServer = Nfsv4TcpServer;
//# sourceMappingURL=Nfsv4TcpServer.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Nfsv4TcpServer.js","sourceRoot":"","sources":["../../../../src/nfs/v4/server/Nfsv4TcpServer.ts"],"names":[],"mappings":"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"}
@@ -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"}
+4
View File
@@ -0,0 +1,4 @@
export interface Logger {
log(...args: unknown[]): void;
error(...args: unknown[]): void;
}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/nfs/v4/server/types.ts"],"names":[],"mappings":""}
+6
View File
@@ -0,0 +1,6 @@
/// <reference types="node" />
import * as msg from '../messages';
export declare const toHex: (buffer: Uint8Array | Buffer) => string;
export declare const getProcName: (proc: number) => string;
export declare const getOpName: (op: number) => string;
export declare const getOpNameFromRequest: (op: msg.Nfsv4Request | unknown) => string;
+184
View File
@@ -0,0 +1,184 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOpNameFromRequest = exports.getOpName = exports.getProcName = exports.toHex = void 0;
const tslib_1 = require("tslib");
const msg = tslib_1.__importStar(require("../messages"));
const toHex = (buffer) => {
return Array.from(buffer)
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('');
};
exports.toHex = toHex;
const getProcName = (proc) => {
switch (proc) {
case 0:
return 'NULL';
case 1:
return 'COMPOUND';
}
return 'UNKNOWN(' + proc + ')';
};
exports.getProcName = getProcName;
const getOpName = (op) => {
switch (op) {
case 3:
return 'ACCESS';
case 4:
return 'CLOSE';
case 5:
return 'COMMIT';
case 6:
return 'CREATE';
case 7:
return 'DELEGPURGE';
case 8:
return 'DELEGRETURN';
case 9:
return 'GETATTR';
case 10:
return 'GETFH';
case 11:
return 'LINK';
case 12:
return 'LOCK';
case 13:
return 'LOCKT';
case 14:
return 'LOCKU';
case 15:
return 'LOOKUP';
case 16:
return 'LOOKUPP';
case 17:
return 'NVERIFY';
case 18:
return 'OPEN';
case 19:
return 'OPENATTR';
case 20:
return 'OPEN_CONFIRM';
case 21:
return 'OPEN_DOWNGRADE';
case 22:
return 'PUTFH';
case 23:
return 'PUTPUBFH';
case 24:
return 'PUTROOTFH';
case 25:
return 'READ';
case 26:
return 'READDIR';
case 27:
return 'READLINK';
case 28:
return 'REMOVE';
case 29:
return 'RENAME';
case 30:
return 'RENEW';
case 31:
return 'RESTOREFH';
case 32:
return 'SAVEFH';
case 33:
return 'SECINFO';
case 34:
return 'SETATTR';
case 35:
return 'SETCLIENTID';
case 36:
return 'SETCLIENTID_CONFIRM';
case 37:
return 'VERIFY';
case 38:
return 'WRITE';
case 39:
return 'RELEASE_LOCKOWNER';
case 10044:
return 'ILLEGAL';
}
return 'UNKNOWN(' + op + ')';
};
exports.getOpName = getOpName;
const getOpNameFromRequest = (op) => {
if (op instanceof msg.Nfsv4AccessRequest)
return 'ACCESS';
if (op instanceof msg.Nfsv4CloseRequest)
return 'CLOSE';
if (op instanceof msg.Nfsv4CommitRequest)
return 'COMMIT';
if (op instanceof msg.Nfsv4CreateRequest)
return 'CREATE';
if (op instanceof msg.Nfsv4DelegpurgeRequest)
return 'DELEGPURGE';
if (op instanceof msg.Nfsv4DelegreturnRequest)
return 'DELEGRETURN';
if (op instanceof msg.Nfsv4GetattrRequest)
return 'GETATTR';
if (op instanceof msg.Nfsv4GetfhRequest)
return 'GETFH';
if (op instanceof msg.Nfsv4LinkRequest)
return 'LINK';
if (op instanceof msg.Nfsv4LockRequest)
return 'LOCK';
if (op instanceof msg.Nfsv4LocktRequest)
return 'LOCKT';
if (op instanceof msg.Nfsv4LockuRequest)
return 'LOCKU';
if (op instanceof msg.Nfsv4LookupRequest)
return 'LOOKUP';
if (op instanceof msg.Nfsv4LookuppRequest)
return 'LOOKUPP';
if (op instanceof msg.Nfsv4NverifyRequest)
return 'NVERIFY';
if (op instanceof msg.Nfsv4OpenRequest)
return 'OPEN';
if (op instanceof msg.Nfsv4OpenattrRequest)
return 'OPENATTR';
if (op instanceof msg.Nfsv4OpenConfirmRequest)
return 'OPEN_CONFIRM';
if (op instanceof msg.Nfsv4OpenDowngradeRequest)
return 'OPEN_DOWNGRADE';
if (op instanceof msg.Nfsv4PutfhRequest)
return 'PUTFH';
if (op instanceof msg.Nfsv4PutpubfhRequest)
return 'PUTPUBFH';
if (op instanceof msg.Nfsv4PutrootfhRequest)
return 'PUTROOTFH';
if (op instanceof msg.Nfsv4ReadRequest)
return 'READ';
if (op instanceof msg.Nfsv4ReaddirRequest)
return 'READDIR';
if (op instanceof msg.Nfsv4ReadlinkRequest)
return 'READLINK';
if (op instanceof msg.Nfsv4RemoveRequest)
return 'REMOVE';
if (op instanceof msg.Nfsv4RenameRequest)
return 'RENAME';
if (op instanceof msg.Nfsv4RenewRequest)
return 'RENEW';
if (op instanceof msg.Nfsv4RestorefhRequest)
return 'RESTOREFH';
if (op instanceof msg.Nfsv4SavefhRequest)
return 'SAVEFH';
if (op instanceof msg.Nfsv4SecinfoRequest)
return 'SECINFO';
if (op instanceof msg.Nfsv4SetattrRequest)
return 'SETATTR';
if (op instanceof msg.Nfsv4SetclientidRequest)
return 'SETCLIENTID';
if (op instanceof msg.Nfsv4SetclientidConfirmRequest)
return 'SETCLIENTID_CONFIRM';
if (op instanceof msg.Nfsv4VerifyRequest)
return 'VERIFY';
if (op instanceof msg.Nfsv4WriteRequest)
return 'WRITE';
if (op instanceof msg.Nfsv4ReleaseLockOwnerRequest)
return 'RELEASE_LOCKOWNER';
if (op instanceof msg.Nfsv4IllegalRequest)
return 'ILLEGAL';
return 'UNKNOWN';
};
exports.getOpNameFromRequest = getOpNameFromRequest;
//# sourceMappingURL=util.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../../src/nfs/v4/server/util.ts"],"names":[],"mappings":"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"}