@zenfs/dom 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/IndexedDB.d.ts +1 -1
- package/dist/IndexedDB.js +3 -4
- package/dist/access.d.ts +7 -28
- package/dist/access.js +31 -126
- package/dist/devices/dsp.js +2 -2
- package/dist/devices/framebuffer.js +2 -2
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +6 -5
- package/dist/utils.js +2 -1
- package/dist/xml.d.ts +8 -8
- package/dist/xml.js +29 -33
- package/package.json +3 -3
package/dist/IndexedDB.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ declare const _IndexedDB: {
|
|
|
52
52
|
readonly required: false;
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
|
-
readonly isAvailable: (idbFactory
|
|
55
|
+
readonly isAvailable: ({ idbFactory }: IndexedDBOptions) => Promise<boolean>;
|
|
56
56
|
readonly create: (options: IndexedDBOptions & Partial<SharedConfig>) => Promise<StoreFS<IndexedDBStore>>;
|
|
57
57
|
};
|
|
58
58
|
type _IndexedDB = typeof _IndexedDB;
|
package/dist/IndexedDB.js
CHANGED
|
@@ -89,11 +89,10 @@ const _IndexedDB = {
|
|
|
89
89
|
storeName: { type: 'string', required: false },
|
|
90
90
|
idbFactory: { type: 'object', required: false },
|
|
91
91
|
},
|
|
92
|
-
async isAvailable(idbFactory = globalThis.indexedDB) {
|
|
92
|
+
async isAvailable({ idbFactory = globalThis.indexedDB }) {
|
|
93
93
|
try {
|
|
94
|
-
if (!(idbFactory instanceof IDBFactory))
|
|
94
|
+
if (!(idbFactory instanceof IDBFactory))
|
|
95
95
|
return false;
|
|
96
|
-
}
|
|
97
96
|
const req = idbFactory.open('__zenfs_test');
|
|
98
97
|
await wrap(req);
|
|
99
98
|
return true;
|
|
@@ -102,7 +101,7 @@ const _IndexedDB = {
|
|
|
102
101
|
return false;
|
|
103
102
|
}
|
|
104
103
|
finally {
|
|
105
|
-
idbFactory
|
|
104
|
+
idbFactory?.deleteDatabase('__zenfs_test');
|
|
106
105
|
}
|
|
107
106
|
},
|
|
108
107
|
async create(options) {
|
package/dist/access.d.ts
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import type { CreationOptions,
|
|
2
|
-
import {
|
|
1
|
+
import type { CreationOptions, FileSystem, InodeLike } from '@zenfs/core';
|
|
2
|
+
import { IndexFS } from '@zenfs/core';
|
|
3
3
|
export interface WebAccessOptions {
|
|
4
4
|
handle: FileSystemDirectoryHandle;
|
|
5
5
|
metadata?: string;
|
|
6
6
|
}
|
|
7
7
|
type HKindToType<T extends FileSystemHandleKind> = T extends 'directory' ? FileSystemDirectoryHandle : T extends 'file' ? FileSystemFileHandle : FileSystemHandle;
|
|
8
|
-
declare const WebAccessFS_base: import("@zenfs/core").Mixin<typeof
|
|
8
|
+
declare const WebAccessFS_base: import("@zenfs/core").Mixin<typeof IndexFS, import("@zenfs/core").AsyncMixin>;
|
|
9
9
|
export declare class WebAccessFS extends WebAccessFS_base {
|
|
10
|
-
/**
|
|
11
|
-
* Disables index optimizations,
|
|
12
|
-
* like using the index for `readdir`
|
|
13
|
-
*/
|
|
14
|
-
private readonly disableIndexOptimizations;
|
|
15
|
-
protected index: Index;
|
|
16
10
|
protected _handles: Map<string, FileSystemHandle>;
|
|
17
11
|
/**
|
|
18
12
|
* Loads all of the handles.
|
|
@@ -28,14 +22,9 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
28
22
|
* @hidden
|
|
29
23
|
*/
|
|
30
24
|
_sync: FileSystem;
|
|
31
|
-
constructor(handle: FileSystemDirectoryHandle
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* like using the index for `readdir`
|
|
35
|
-
*/
|
|
36
|
-
disableIndexOptimizations?: boolean);
|
|
37
|
-
rename(oldPath: string, newPath: string): Promise<void>;
|
|
38
|
-
unlink(path: string): Promise<void>;
|
|
25
|
+
constructor(handle: FileSystemDirectoryHandle);
|
|
26
|
+
remove(path: string): Promise<void>;
|
|
27
|
+
protected removeSync(path: string): void;
|
|
39
28
|
read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
40
29
|
write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
|
|
41
30
|
/**
|
|
@@ -43,17 +32,7 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
43
32
|
* @deprecated @internal @hidden
|
|
44
33
|
*/
|
|
45
34
|
writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
46
|
-
|
|
47
|
-
createFile(path: string, flag: string, mode: number, options: CreationOptions): Promise<File>;
|
|
48
|
-
openFile(path: string, flag: string): Promise<File>;
|
|
49
|
-
/**
|
|
50
|
-
* @todo Implement
|
|
51
|
-
*/
|
|
52
|
-
link(srcpath: string): Promise<void>;
|
|
53
|
-
sync(path: string, data?: Uint8Array, stats?: Readonly<Partial<InodeLike>>): Promise<void>;
|
|
54
|
-
rmdir(path: string): Promise<void>;
|
|
55
|
-
mkdir(path: string, mode: number, options: CreationOptions): Promise<void>;
|
|
56
|
-
readdir(path: string): Promise<string[]>;
|
|
35
|
+
mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
|
|
57
36
|
protected get<const T extends FileSystemHandleKind | null>(kind: T | undefined, path: string, syscall?: string): T extends FileSystemHandleKind ? HKindToType<T> : FileSystemHandle;
|
|
58
37
|
}
|
|
59
38
|
declare const _WebAccess: {
|
package/dist/access.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Async, constants, Errno, ErrnoError,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { Async, constants, Errno, ErrnoError, IndexFS, InMemory, Inode, log } from '@zenfs/core';
|
|
2
|
+
import { basename, dirname, join } from '@zenfs/core/path.js';
|
|
3
|
+
import { S_IFDIR, S_IFMT } from '@zenfs/core/vfs/constants.js';
|
|
4
4
|
import { _throw } from 'utilium';
|
|
5
5
|
import { convertException } from './utils.js';
|
|
6
6
|
function isResizable(buffer) {
|
|
@@ -16,7 +16,7 @@ function isResizable(buffer) {
|
|
|
16
16
|
function isKind(handle, kind) {
|
|
17
17
|
return handle.kind == kind;
|
|
18
18
|
}
|
|
19
|
-
export class WebAccessFS extends Async(
|
|
19
|
+
export class WebAccessFS extends Async(IndexFS) {
|
|
20
20
|
/**
|
|
21
21
|
* Loads all of the handles.
|
|
22
22
|
* @internal @hidden
|
|
@@ -53,59 +53,22 @@ export class WebAccessFS extends Async(FileSystem) {
|
|
|
53
53
|
this.index.set(path, new Inode({ mode: 0o777 | constants.S_IFDIR, size: 0 }));
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
constructor(handle
|
|
57
|
-
/**
|
|
58
|
-
* Disables index optimizations,
|
|
59
|
-
* like using the index for `readdir`
|
|
60
|
-
*/
|
|
61
|
-
disableIndexOptimizations = false) {
|
|
56
|
+
constructor(handle) {
|
|
62
57
|
super(0x77656261, 'webaccessfs');
|
|
63
|
-
this.disableIndexOptimizations = disableIndexOptimizations;
|
|
64
|
-
this.index = new Index();
|
|
65
58
|
this._handles = new Map();
|
|
66
59
|
/**
|
|
67
60
|
* @hidden
|
|
68
61
|
*/
|
|
69
|
-
this._sync = InMemory.create({
|
|
62
|
+
this._sync = InMemory.create({ label: 'accessfs-cache' });
|
|
70
63
|
this.attributes.set('no_buffer_resize');
|
|
71
|
-
this.attributes.set('setid');
|
|
72
64
|
this._handles.set('/', handle);
|
|
73
65
|
}
|
|
74
|
-
async
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (newPath.startsWith(oldPath + '/'))
|
|
78
|
-
throw ErrnoError.With('EBUSY', oldPath, 'rename');
|
|
79
|
-
const handle = this.get(null, oldPath, 'rename');
|
|
80
|
-
if (isKind(handle, 'directory')) {
|
|
81
|
-
const files = await this.readdir(oldPath);
|
|
82
|
-
const stats = await this.stat(oldPath);
|
|
83
|
-
await this.mkdir(newPath, stats.mode, stats);
|
|
84
|
-
for (const file of files)
|
|
85
|
-
await this.rename(join(oldPath, file), join(newPath, file));
|
|
86
|
-
await this.rmdir(oldPath);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (!isKind(handle, 'file')) {
|
|
90
|
-
throw new ErrnoError(Errno.ENOTSUP, 'Not a file or directory handle', oldPath, 'rename');
|
|
91
|
-
}
|
|
92
|
-
const oldFile = await handle.getFile().catch(ex => _throw(convertException(ex, oldPath, 'rename')));
|
|
93
|
-
const destFolder = this.get('directory', dirname(newPath), 'rename');
|
|
94
|
-
const newFile = await destFolder
|
|
95
|
-
.getFileHandle(basename(newPath), { create: true })
|
|
96
|
-
.catch((ex) => _throw(ex.name == 'TypeMismatchError' ? ErrnoError.With('EISDIR', newPath, 'rename') : convertException(ex, newPath, 'rename')));
|
|
97
|
-
const writable = await newFile.createWritable();
|
|
98
|
-
await writable.write(await oldFile.arrayBuffer());
|
|
99
|
-
await writable.close();
|
|
100
|
-
await this.unlink(oldPath);
|
|
101
|
-
this._handles.set(newPath, newFile);
|
|
66
|
+
async remove(path) {
|
|
67
|
+
const handle = this.get('directory', dirname(path));
|
|
68
|
+
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path)));
|
|
102
69
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
throw ErrnoError.With('EBUSY', '/', 'unlink');
|
|
106
|
-
const handle = this.get('directory', dirname(path), 'unlink');
|
|
107
|
-
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path, 'unlink')));
|
|
108
|
-
this.index.delete(path);
|
|
70
|
+
removeSync(path) {
|
|
71
|
+
throw log.crit(ErrnoError.With('ENOSYS', path));
|
|
109
72
|
}
|
|
110
73
|
async read(path, buffer, offset, end) {
|
|
111
74
|
if (end <= offset)
|
|
@@ -126,7 +89,22 @@ export class WebAccessFS extends Async(FileSystem) {
|
|
|
126
89
|
const inode = this.index.get(path);
|
|
127
90
|
if (!inode)
|
|
128
91
|
throw ErrnoError.With('ENOENT', path, 'write');
|
|
129
|
-
const
|
|
92
|
+
const isDir = (inode.mode & S_IFMT) == S_IFDIR;
|
|
93
|
+
let handle;
|
|
94
|
+
try {
|
|
95
|
+
handle = this.get(isDir ? 'directory' : 'file', path, 'write');
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
const parent = this.get('directory', dirname(path), 'write');
|
|
99
|
+
handle = await parent[isDir ? 'getDirectoryHandle' : 'getFileHandle'](basename(path), { create: true }).catch((ex) => _throw(convertException(ex, path)));
|
|
100
|
+
this._handles.set(path, handle);
|
|
101
|
+
}
|
|
102
|
+
if (isDir)
|
|
103
|
+
return;
|
|
104
|
+
if (isKind(handle, 'directory')) {
|
|
105
|
+
log.crit(new ErrnoError(Errno.EIO, 'Mismatch in entry kind on write', path, 'write'));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
130
108
|
const writable = await handle.createWritable();
|
|
131
109
|
try {
|
|
132
110
|
await writable.seek(offset);
|
|
@@ -147,85 +125,12 @@ export class WebAccessFS extends Async(FileSystem) {
|
|
|
147
125
|
async writeFile(path, data) {
|
|
148
126
|
return this.write(path, data, 0);
|
|
149
127
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const inode = this.index.get(path);
|
|
153
|
-
if (!inode)
|
|
154
|
-
throw ErrnoError.With('ENOENT', path, 'stat');
|
|
155
|
-
return inode.toStats();
|
|
156
|
-
}
|
|
157
|
-
async createFile(path, flag, mode, options) {
|
|
158
|
-
const handle = this.get('directory', dirname(path), 'createFile');
|
|
159
|
-
if (this.index.has(path))
|
|
160
|
-
throw ErrnoError.With('EEXIST', path, 'createFile');
|
|
161
|
-
const file = await handle.getFileHandle(basename(path), { create: true });
|
|
162
|
-
// Race condition bypass
|
|
163
|
-
const inode = this.index.get(path) ?? new Inode({ ...options, mode: mode | S_IFREG });
|
|
164
|
-
this.index.set(path, inode);
|
|
165
|
-
this._handles.set(path, file);
|
|
166
|
-
return new LazyFile(this, path, flag, inode);
|
|
167
|
-
}
|
|
168
|
-
async openFile(path, flag) {
|
|
169
|
-
const inode = this.index.get(path);
|
|
170
|
-
if (!inode)
|
|
171
|
-
throw ErrnoError.With('ENOENT', path, 'stat');
|
|
172
|
-
return new LazyFile(this, path, flag, inode.toStats());
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* @todo Implement
|
|
176
|
-
*/
|
|
177
|
-
async link(srcpath) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
async sync(path, data, stats) {
|
|
181
|
-
const inode = this.index.get(path) ?? new Inode();
|
|
182
|
-
inode.update(stats);
|
|
183
|
-
this.index.set(path, inode);
|
|
184
|
-
if (!data)
|
|
185
|
-
return;
|
|
186
|
-
const handle = this.get('file', path, 'write');
|
|
187
|
-
const writable = await handle.createWritable();
|
|
188
|
-
try {
|
|
189
|
-
await writable.seek(0);
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
await writable.write({ type: 'seek', position: 0 });
|
|
193
|
-
}
|
|
194
|
-
await writable.write(data);
|
|
195
|
-
await writable.close();
|
|
196
|
-
}
|
|
197
|
-
async rmdir(path) {
|
|
198
|
-
if ((await this.readdir(path)).length)
|
|
199
|
-
throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
|
|
200
|
-
if (path == '/')
|
|
201
|
-
throw ErrnoError.With('EBUSY', '/', 'rmdir');
|
|
202
|
-
const handle = this.get('directory', dirname(path), 'rmdir');
|
|
203
|
-
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path, 'rmdir')));
|
|
204
|
-
this.index.delete(path);
|
|
205
|
-
}
|
|
206
|
-
async mkdir(path, mode, options) {
|
|
207
|
-
if (this.index.has(path))
|
|
208
|
-
throw ErrnoError.With('EEXIST', path, 'mkdir');
|
|
128
|
+
async mkdir(path, options) {
|
|
129
|
+
const inode = await super.mkdir(path, options);
|
|
209
130
|
const handle = this.get('directory', dirname(path), 'mkdir');
|
|
210
|
-
const dir = await handle.getDirectoryHandle(basename(path), { create: true });
|
|
131
|
+
const dir = await handle.getDirectoryHandle(basename(path), { create: true }).catch((ex) => _throw(convertException(ex, path)));
|
|
211
132
|
this._handles.set(path, dir);
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
async readdir(path) {
|
|
215
|
-
if (!this.disableIndexOptimizations) {
|
|
216
|
-
if (!this.index.has(path))
|
|
217
|
-
throw ErrnoError.With('ENOENT', path, 'readdir');
|
|
218
|
-
const entries = this.index.directoryEntries(path);
|
|
219
|
-
if (!entries)
|
|
220
|
-
throw ErrnoError.With('ENOTDIR', path, 'readdir');
|
|
221
|
-
return Object.keys(entries);
|
|
222
|
-
}
|
|
223
|
-
const handle = this.get('directory', path, 'readdir');
|
|
224
|
-
const entries = [];
|
|
225
|
-
for await (const k of handle.keys()) {
|
|
226
|
-
entries.push(k);
|
|
227
|
-
}
|
|
228
|
-
return entries;
|
|
133
|
+
return inode;
|
|
229
134
|
}
|
|
230
135
|
get(kind = null, path, syscall) {
|
|
231
136
|
const handle = this._handles.get(path);
|
package/dist/devices/dsp.js
CHANGED
|
@@ -44,10 +44,10 @@ export async function dsp(options = {}) {
|
|
|
44
44
|
init(ino, options) {
|
|
45
45
|
return { data: dsp, major: 14, minor: 3 };
|
|
46
46
|
},
|
|
47
|
-
|
|
47
|
+
read() {
|
|
48
48
|
return;
|
|
49
49
|
},
|
|
50
|
-
|
|
50
|
+
write(device, buffer, offset) {
|
|
51
51
|
device.data.port.postMessage(buffer.buffer);
|
|
52
52
|
},
|
|
53
53
|
};
|
|
@@ -27,8 +27,8 @@ export const framebuffer = {
|
|
|
27
27
|
name: 'fb',
|
|
28
28
|
};
|
|
29
29
|
},
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
read() { },
|
|
31
|
+
write({ data: { image, context } }, buffer, offset) {
|
|
32
32
|
image.data.set(buffer, offset);
|
|
33
33
|
context.putImageData(image, 0, 0);
|
|
34
34
|
return buffer.byteLength;
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Store, SyncMapStore } from '@zenfs/core';
|
|
2
2
|
import { StoreFS, SyncMapTransaction } from '@zenfs/core';
|
|
3
3
|
/**
|
|
4
4
|
* A synchronous key-value store backed by Storage.
|
|
@@ -39,7 +39,7 @@ declare const _WebStorage: {
|
|
|
39
39
|
/**
|
|
40
40
|
* @todo Consider replacing `instanceof` with a duck-typing check?
|
|
41
41
|
*/
|
|
42
|
-
readonly isAvailable: (
|
|
42
|
+
readonly isAvailable: (config?: WebStorageOptions) => boolean;
|
|
43
43
|
readonly create: ({ storage }: WebStorageOptions) => StoreFS<WebStorageStore>;
|
|
44
44
|
};
|
|
45
45
|
type _WebStorage = typeof _WebStorage;
|
package/dist/storage.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Errno, ErrnoError, StoreFS, SyncMapTransaction } from '@zenfs/core';
|
|
2
|
+
import { decodeASCII, encodeASCII } from 'utilium';
|
|
2
3
|
/**
|
|
3
4
|
* A synchronous key-value store backed by Storage.
|
|
4
5
|
*/
|
|
@@ -28,11 +29,11 @@ export class WebStorageStore {
|
|
|
28
29
|
if (typeof data != 'string') {
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
|
-
return
|
|
32
|
+
return encodeASCII(data);
|
|
32
33
|
}
|
|
33
34
|
set(key, data) {
|
|
34
35
|
try {
|
|
35
|
-
this.storage.setItem(key.toString(),
|
|
36
|
+
this.storage.setItem(key.toString(), decodeASCII(data));
|
|
36
37
|
}
|
|
37
38
|
catch {
|
|
38
39
|
throw new ErrnoError(Errno.ENOSPC, 'Storage is full.');
|
|
@@ -58,8 +59,8 @@ const _WebStorage = {
|
|
|
58
59
|
/**
|
|
59
60
|
* @todo Consider replacing `instanceof` with a duck-typing check?
|
|
60
61
|
*/
|
|
61
|
-
isAvailable(
|
|
62
|
-
return storage instanceof globalThis.Storage;
|
|
62
|
+
isAvailable(config) {
|
|
63
|
+
return (config?.storage ?? globalThis.localStorage) instanceof globalThis.Storage;
|
|
63
64
|
},
|
|
64
65
|
create({ storage = globalThis.localStorage }) {
|
|
65
66
|
return new StoreFS(new WebStorageStore(storage));
|
package/dist/utils.js
CHANGED
|
@@ -5,13 +5,14 @@ import { ErrnoError, Errno } from '@zenfs/core';
|
|
|
5
5
|
*/
|
|
6
6
|
function errnoForDOMException(ex) {
|
|
7
7
|
switch (ex.name) {
|
|
8
|
+
case 'TypeMismatchError':
|
|
9
|
+
return 'EPERM';
|
|
8
10
|
case 'IndexSizeError':
|
|
9
11
|
case 'HierarchyRequestError':
|
|
10
12
|
case 'InvalidCharacterError':
|
|
11
13
|
case 'InvalidStateError':
|
|
12
14
|
case 'SyntaxError':
|
|
13
15
|
case 'NamespaceError':
|
|
14
|
-
case 'TypeMismatchError':
|
|
15
16
|
case 'ConstraintError':
|
|
16
17
|
case 'VersionError':
|
|
17
18
|
case 'URLMismatchError':
|
package/dist/xml.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { CreationOptions,
|
|
2
|
-
import { FileSystem,
|
|
1
|
+
import type { CreationOptions, InodeLike, StatsLike } from '@zenfs/core';
|
|
2
|
+
import { FileSystem, Inode } from '@zenfs/core';
|
|
3
3
|
export interface XMLOptions {
|
|
4
4
|
/**
|
|
5
5
|
* The root `fs` element
|
|
@@ -18,15 +18,15 @@ export declare class XMLFS extends XMLFS_base {
|
|
|
18
18
|
*/
|
|
19
19
|
root?: Element);
|
|
20
20
|
renameSync(oldPath: string, newPath: string): void;
|
|
21
|
-
statSync(path: string):
|
|
22
|
-
|
|
23
|
-
createFileSync(path: string, flag: string, mode: number, { uid, gid }: CreationOptions): File;
|
|
21
|
+
statSync(path: string): Inode;
|
|
22
|
+
createFileSync(path: string, options: CreationOptions): Inode;
|
|
24
23
|
unlinkSync(path: string): void;
|
|
25
24
|
rmdirSync(path: string): void;
|
|
26
|
-
mkdirSync(path: string,
|
|
25
|
+
mkdirSync(path: string, options: CreationOptions): InodeLike;
|
|
27
26
|
readdirSync(path: string): string[];
|
|
28
27
|
linkSync(target: string, link: string): void;
|
|
29
|
-
|
|
28
|
+
touchSync(path: string, metadata: Partial<InodeLike>): void;
|
|
29
|
+
syncSync(): void;
|
|
30
30
|
readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
|
|
31
31
|
writeSync(path: string, buffer: Uint8Array, offset: number): void;
|
|
32
32
|
toString(): string;
|
|
@@ -39,7 +39,7 @@ declare const _XML: {
|
|
|
39
39
|
name: string;
|
|
40
40
|
options: {
|
|
41
41
|
root: {
|
|
42
|
-
type:
|
|
42
|
+
type: string;
|
|
43
43
|
required: false;
|
|
44
44
|
};
|
|
45
45
|
};
|
package/dist/xml.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { _inode_fields, constants,
|
|
2
|
-
import { basename, dirname } from '@zenfs/core/
|
|
1
|
+
import { _inode_fields, constants, Errno, ErrnoError, FileSystem, Inode, Sync } from '@zenfs/core';
|
|
2
|
+
import { basename, dirname } from '@zenfs/core/path.js';
|
|
3
|
+
import { decodeASCII, encodeASCII } from 'utilium';
|
|
3
4
|
function get_stats(node) {
|
|
4
5
|
const stats = {};
|
|
5
6
|
for (const key of _inode_fields) {
|
|
@@ -7,7 +8,7 @@ function get_stats(node) {
|
|
|
7
8
|
if (value !== null && value !== undefined)
|
|
8
9
|
stats[key] = parseInt(value, 16);
|
|
9
10
|
}
|
|
10
|
-
return new
|
|
11
|
+
return new Inode(stats);
|
|
11
12
|
}
|
|
12
13
|
function set_stats(node, stats) {
|
|
13
14
|
for (const key of Object.keys(stats)) {
|
|
@@ -35,9 +36,8 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
35
36
|
root = new DOMParser().parseFromString('<fs></fs>', 'application/xml').documentElement) {
|
|
36
37
|
super(0x20786d6c, 'xmltmpfs');
|
|
37
38
|
this.root = root;
|
|
38
|
-
this.attributes.set('setid');
|
|
39
39
|
try {
|
|
40
|
-
this.mkdirSync('/',
|
|
40
|
+
this.mkdirSync('/', { uid: 0, gid: 0, mode: 0o777 });
|
|
41
41
|
}
|
|
42
42
|
catch (e) {
|
|
43
43
|
const error = e;
|
|
@@ -53,23 +53,19 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
53
53
|
statSync(path) {
|
|
54
54
|
return get_stats(this.get('stat', path));
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
const node = this.get('openFile', path);
|
|
58
|
-
return new LazyFile(this, path, flag, get_stats(node));
|
|
59
|
-
}
|
|
60
|
-
createFileSync(path, flag, mode, { uid, gid }) {
|
|
56
|
+
createFileSync(path, options) {
|
|
61
57
|
const parent = this.statSync(dirname(path));
|
|
62
|
-
const
|
|
63
|
-
mode: mode | constants.S_IFREG,
|
|
64
|
-
uid: parent.mode & constants.S_ISUID ? parent.uid : uid,
|
|
65
|
-
gid: parent.mode & constants.S_ISGID ? parent.gid : gid,
|
|
58
|
+
const inode = new Inode({
|
|
59
|
+
mode: options.mode | constants.S_IFREG,
|
|
60
|
+
uid: parent.mode & constants.S_ISUID ? parent.uid : options.uid,
|
|
61
|
+
gid: parent.mode & constants.S_ISGID ? parent.gid : options.gid,
|
|
66
62
|
});
|
|
67
|
-
this.create('createFile', path,
|
|
68
|
-
return
|
|
63
|
+
this.create('createFile', path, inode);
|
|
64
|
+
return inode;
|
|
69
65
|
}
|
|
70
66
|
unlinkSync(path) {
|
|
71
67
|
const node = this.get('unlink', path);
|
|
72
|
-
if (get_stats(node).
|
|
68
|
+
if (get_stats(node).mode & constants.S_IFDIR)
|
|
73
69
|
throw ErrnoError.With('EISDIR', path, 'unlink');
|
|
74
70
|
this.remove('unlink', node, path);
|
|
75
71
|
}
|
|
@@ -77,22 +73,23 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
77
73
|
const node = this.get('rmdir', path);
|
|
78
74
|
if (node.textContent?.length)
|
|
79
75
|
throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
|
|
80
|
-
if (!get_stats(node).
|
|
76
|
+
if (!(get_stats(node).mode & constants.S_IFDIR))
|
|
81
77
|
throw ErrnoError.With('ENOTDIR', path, 'rmdir');
|
|
82
78
|
this.remove('rmdir', node, path);
|
|
83
79
|
}
|
|
84
|
-
mkdirSync(path,
|
|
80
|
+
mkdirSync(path, options) {
|
|
85
81
|
const parent = this.statSync(dirname(path));
|
|
86
|
-
const
|
|
87
|
-
mode: mode | constants.S_IFDIR,
|
|
88
|
-
uid: parent.mode & constants.S_ISUID ? parent.uid : uid,
|
|
89
|
-
gid: parent.mode & constants.S_ISGID ? parent.gid : gid,
|
|
82
|
+
const inode = new Inode({
|
|
83
|
+
mode: options.mode | constants.S_IFDIR,
|
|
84
|
+
uid: parent.mode & constants.S_ISUID ? parent.uid : options.uid,
|
|
85
|
+
gid: parent.mode & constants.S_ISGID ? parent.gid : options.gid,
|
|
90
86
|
});
|
|
91
|
-
|
|
87
|
+
this.create('mkdir', path, inode).textContent = '[]';
|
|
88
|
+
return inode;
|
|
92
89
|
}
|
|
93
90
|
readdirSync(path) {
|
|
94
91
|
const node = this.get('readdir', path);
|
|
95
|
-
if (!get_stats(node).
|
|
92
|
+
if (!(get_stats(node).mode & constants.S_IFDIR))
|
|
96
93
|
throw ErrnoError.With('ENOTDIR', path, 'rmdir');
|
|
97
94
|
try {
|
|
98
95
|
return JSON.parse(node.textContent);
|
|
@@ -105,20 +102,19 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
105
102
|
const node = this.get('link', target);
|
|
106
103
|
this.add('link', node, link);
|
|
107
104
|
}
|
|
108
|
-
|
|
109
|
-
const node = this.get('
|
|
110
|
-
|
|
111
|
-
node.textContent = decodeRaw(data);
|
|
112
|
-
set_stats(node, stats);
|
|
105
|
+
touchSync(path, metadata) {
|
|
106
|
+
const node = this.get('touch', path);
|
|
107
|
+
set_stats(node, metadata);
|
|
113
108
|
}
|
|
109
|
+
syncSync() { }
|
|
114
110
|
readSync(path, buffer, offset, end) {
|
|
115
111
|
const node = this.get('read', path);
|
|
116
|
-
const raw =
|
|
112
|
+
const raw = encodeASCII(node.textContent.slice(offset, end));
|
|
117
113
|
buffer.set(raw);
|
|
118
114
|
}
|
|
119
115
|
writeSync(path, buffer, offset) {
|
|
120
116
|
const node = this.get('write', path);
|
|
121
|
-
const data =
|
|
117
|
+
const data = decodeASCII(buffer);
|
|
122
118
|
const after = node.textContent.slice(offset + data.length);
|
|
123
119
|
node.textContent = node.textContent.slice(0, offset) + data + after;
|
|
124
120
|
}
|
|
@@ -140,7 +136,7 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
140
136
|
throw ErrnoError.With('EEXIST', path, syscall);
|
|
141
137
|
const node = document.createElement('file');
|
|
142
138
|
this.add(syscall, node, path);
|
|
143
|
-
set_stats(node, new
|
|
139
|
+
set_stats(node, new Inode({
|
|
144
140
|
...stats,
|
|
145
141
|
uid: stats.mode,
|
|
146
142
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/dom",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "DOM backends for ZenFS",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"typescript-eslint": "^8.8.1"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@zenfs/core": "^
|
|
65
|
-
"utilium": "^1.
|
|
64
|
+
"@zenfs/core": "^2.0.0",
|
|
65
|
+
"utilium": "^1.9.0"
|
|
66
66
|
},
|
|
67
67
|
"keywords": [
|
|
68
68
|
"filesystem",
|