190 lines
7.4 KiB
JavaScript
190 lines
7.4 KiB
JavaScript
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.FsaNodeCore = void 0;
|
||
|
const util_1 = require("../node/util");
|
||
|
const util_2 = require("./util");
|
||
|
const constants_1 = require("../node/constants");
|
||
|
const FsaNodeFsOpenFile_1 = require("./FsaNodeFsOpenFile");
|
||
|
const util = require("../node/util");
|
||
|
class FsaNodeCore {
|
||
|
constructor(root, syncAdapter) {
|
||
|
this.root = root;
|
||
|
this.syncAdapter = syncAdapter;
|
||
|
this.fds = new Map();
|
||
|
/**
|
||
|
* A list of reusable (opened and closed) file descriptors, that should be
|
||
|
* used first before creating a new file descriptor.
|
||
|
*/
|
||
|
this.releasedFds = [];
|
||
|
if (root instanceof Promise) {
|
||
|
root
|
||
|
.then(root => {
|
||
|
this.root = root;
|
||
|
})
|
||
|
.catch(error => { });
|
||
|
}
|
||
|
}
|
||
|
getSyncAdapter() {
|
||
|
const adapter = this.syncAdapter;
|
||
|
if (!adapter)
|
||
|
throw new Error('No sync adapter');
|
||
|
return adapter;
|
||
|
}
|
||
|
newFdNumber() {
|
||
|
const releasedFd = this.releasedFds.pop();
|
||
|
return typeof releasedFd === 'number' ? releasedFd : FsaNodeCore.fd--;
|
||
|
}
|
||
|
/**
|
||
|
* @param path Path from root to the new folder.
|
||
|
* @param create Whether to create the folders if they don't exist.
|
||
|
*/
|
||
|
async getDir(path, create, funcName) {
|
||
|
let curr = await this.root;
|
||
|
const options = { create };
|
||
|
try {
|
||
|
for (const name of path) {
|
||
|
curr = await curr.getDirectoryHandle(name, options);
|
||
|
}
|
||
|
}
|
||
|
catch (error) {
|
||
|
if (error && typeof error === 'object') {
|
||
|
switch (error.name) {
|
||
|
case 'TypeMismatchError':
|
||
|
throw (0, util_1.createError)('ENOTDIR', funcName, path.join("/" /* FsaToNodeConstants.Separator */));
|
||
|
case 'NotFoundError':
|
||
|
throw (0, util_1.createError)('ENOENT', funcName, path.join("/" /* FsaToNodeConstants.Separator */));
|
||
|
}
|
||
|
}
|
||
|
throw error;
|
||
|
}
|
||
|
return curr;
|
||
|
}
|
||
|
async getFile(path, name, funcName, create) {
|
||
|
const dir = await this.getDir(path, false, funcName);
|
||
|
const file = await dir.getFileHandle(name, { create });
|
||
|
return file;
|
||
|
}
|
||
|
async getFileOrDir(path, name, funcName) {
|
||
|
const dir = await this.getDir(path, false, funcName);
|
||
|
if (!name)
|
||
|
return dir;
|
||
|
try {
|
||
|
const file = await dir.getFileHandle(name);
|
||
|
return file;
|
||
|
}
|
||
|
catch (error) {
|
||
|
if (error && typeof error === 'object') {
|
||
|
switch (error.name) {
|
||
|
case 'TypeMismatchError':
|
||
|
try {
|
||
|
return await dir.getDirectoryHandle(name);
|
||
|
}
|
||
|
catch (error2) {
|
||
|
if (error2 && typeof error2 === 'object') {
|
||
|
switch (error2.name) {
|
||
|
case 'TypeMismatchError':
|
||
|
throw (0, util_1.createError)('ENOTDIR', funcName, path.join("/" /* FsaToNodeConstants.Separator */));
|
||
|
case 'NotFoundError':
|
||
|
throw (0, util_1.createError)('ENOENT', funcName, path.join("/" /* FsaToNodeConstants.Separator */));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
case 'NotFoundError':
|
||
|
throw (0, util_1.createError)('ENOENT', funcName, path.join("/" /* FsaToNodeConstants.Separator */));
|
||
|
}
|
||
|
}
|
||
|
throw error;
|
||
|
}
|
||
|
}
|
||
|
getFileByFd(fd, funcName) {
|
||
|
if (!(0, util_1.isFd)(fd))
|
||
|
throw TypeError(constants_1.ERRSTR.FD);
|
||
|
const file = this.fds.get(fd);
|
||
|
if (!file)
|
||
|
throw (0, util_1.createError)('EBADF', funcName);
|
||
|
return file;
|
||
|
}
|
||
|
async getFileByFdAsync(fd, funcName) {
|
||
|
return this.getFileByFd(fd, funcName);
|
||
|
}
|
||
|
async __getFileById(id, funcName) {
|
||
|
if (typeof id === 'number')
|
||
|
return (await this.getFileByFd(id, funcName)).file;
|
||
|
const filename = (0, util_1.pathToFilename)(id);
|
||
|
const [folder, name] = (0, util_2.pathToLocation)(filename);
|
||
|
return await this.getFile(folder, name, funcName);
|
||
|
}
|
||
|
async getFileByIdOrCreate(id, funcName) {
|
||
|
if (typeof id === 'number')
|
||
|
return (await this.getFileByFd(id, funcName)).file;
|
||
|
const filename = (0, util_1.pathToFilename)(id);
|
||
|
const [folder, name] = (0, util_2.pathToLocation)(filename);
|
||
|
const dir = await this.getDir(folder, false, funcName);
|
||
|
return await dir.getFileHandle(name, { create: true });
|
||
|
}
|
||
|
async __open(filename, flags, mode) {
|
||
|
const [folder, name] = (0, util_2.pathToLocation)(filename);
|
||
|
const throwIfExists = !!(flags & 128 /* FLAG.O_EXCL */);
|
||
|
if (throwIfExists) {
|
||
|
try {
|
||
|
await this.getFile(folder, name, 'open', false);
|
||
|
throw util.createError('EEXIST', 'writeFile');
|
||
|
}
|
||
|
catch (error) {
|
||
|
const file404 = error && typeof error === 'object' && (error.code === 'ENOENT' || error.name === 'NotFoundError');
|
||
|
if (!file404) {
|
||
|
if (error && typeof error === 'object') {
|
||
|
switch (error.name) {
|
||
|
case 'TypeMismatchError':
|
||
|
throw (0, util_1.createError)('ENOTDIR', 'open', filename);
|
||
|
case 'NotFoundError':
|
||
|
throw (0, util_1.createError)('ENOENT', 'open', filename);
|
||
|
}
|
||
|
}
|
||
|
throw error;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
try {
|
||
|
const createIfMissing = !!(flags & 64 /* FLAG.O_CREAT */);
|
||
|
const fsaFile = await this.getFile(folder, name, 'open', createIfMissing);
|
||
|
return this.__open2(fsaFile, filename, flags, mode);
|
||
|
}
|
||
|
catch (error) {
|
||
|
if (error && typeof error === 'object') {
|
||
|
switch (error.name) {
|
||
|
case 'TypeMismatchError':
|
||
|
throw (0, util_1.createError)('ENOTDIR', 'open', filename);
|
||
|
case 'NotFoundError':
|
||
|
throw (0, util_1.createError)('ENOENT', 'open', filename);
|
||
|
}
|
||
|
}
|
||
|
throw error;
|
||
|
}
|
||
|
}
|
||
|
__open2(fsaFile, filename, flags, mode) {
|
||
|
const fd = this.newFdNumber();
|
||
|
const file = new FsaNodeFsOpenFile_1.FsaNodeFsOpenFile(fd, mode, flags, fsaFile, filename);
|
||
|
this.fds.set(fd, file);
|
||
|
return file;
|
||
|
}
|
||
|
async __close(fd) {
|
||
|
const openFile = await this.getFileByFdAsync(fd, 'close');
|
||
|
await openFile.close();
|
||
|
const deleted = this.fds.delete(fd);
|
||
|
if (deleted)
|
||
|
this.releasedFds.push(fd);
|
||
|
}
|
||
|
getFileName(id) {
|
||
|
if (typeof id === 'number') {
|
||
|
const openFile = this.fds.get(id);
|
||
|
if (!openFile)
|
||
|
throw (0, util_1.createError)('EBADF', 'readFile');
|
||
|
return openFile.filename;
|
||
|
}
|
||
|
return (0, util_1.pathToFilename)(id);
|
||
|
}
|
||
|
}
|
||
|
exports.FsaNodeCore = FsaNodeCore;
|
||
|
FsaNodeCore.fd = 0x7fffffff;
|
||
|
//# sourceMappingURL=FsaNodeCore.js.map
|