@componentor/fs 3.0.44 → 3.0.45
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/index.js +125 -25
- package/dist/index.js.map +1 -1
- package/dist/workers/repair.worker.js +125 -25
- package/dist/workers/repair.worker.js.map +1 -1
- package/dist/workers/server.worker.js +125 -25
- package/dist/workers/server.worker.js.map +1 -1
- package/dist/workers/sync-relay.worker.js +125 -25
- package/dist/workers/sync-relay.worker.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +11 -0
package/dist/index.js
CHANGED
|
@@ -4560,14 +4560,23 @@ var VFSEngine = class {
|
|
|
4560
4560
|
growPathTable(needed) {
|
|
4561
4561
|
const newSize = Math.max(this.pathTableSize * 2, needed + INITIAL_PATH_TABLE_SIZE);
|
|
4562
4562
|
const growth = newSize - this.pathTableSize;
|
|
4563
|
-
const dataSize = this.totalBlocks * this.blockSize;
|
|
4564
|
-
const dataBuf = new Uint8Array(dataSize);
|
|
4565
|
-
this.handle.read(dataBuf, { at: this.dataOffset });
|
|
4566
4563
|
const newTotalSize = this.handle.getSize() + growth;
|
|
4567
4564
|
this.handle.truncate(newTotalSize);
|
|
4565
|
+
const dataSize = this.totalBlocks * this.blockSize;
|
|
4566
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
4567
|
+
const scratch = new Uint8Array(Math.min(CHUNK, Math.max(dataSize, 1)));
|
|
4568
|
+
let remaining = dataSize;
|
|
4569
|
+
while (remaining > 0) {
|
|
4570
|
+
const chunk = Math.min(remaining, CHUNK);
|
|
4571
|
+
const srcAt = this.dataOffset + (remaining - chunk);
|
|
4572
|
+
const dstAt = this.dataOffset + growth + (remaining - chunk);
|
|
4573
|
+
const slice = chunk < scratch.length ? scratch.subarray(0, chunk) : scratch;
|
|
4574
|
+
this.handle.read(slice, { at: srcAt });
|
|
4575
|
+
this.handle.write(slice, { at: dstAt });
|
|
4576
|
+
remaining -= chunk;
|
|
4577
|
+
}
|
|
4568
4578
|
const newBitmapOffset = this.bitmapOffset + growth;
|
|
4569
4579
|
const newDataOffset = this.dataOffset + growth;
|
|
4570
|
-
this.handle.write(dataBuf, { at: newDataOffset });
|
|
4571
4580
|
this.handle.write(this.bitmap, { at: newBitmapOffset });
|
|
4572
4581
|
this.pathTableSize = newSize;
|
|
4573
4582
|
this.bitmapOffset = newBitmapOffset;
|
|
@@ -4575,6 +4584,23 @@ var VFSEngine = class {
|
|
|
4575
4584
|
this.superblockDirty = true;
|
|
4576
4585
|
}
|
|
4577
4586
|
// ========== Bitmap I/O ==========
|
|
4587
|
+
// Write `length` zero bytes at absolute file offset `at` via a small
|
|
4588
|
+
// reusable scratch buffer. Used to materialize POSIX "holes" when a
|
|
4589
|
+
// write starts past the current file size — those bytes must read as
|
|
4590
|
+
// zeros rather than whatever stale data happened to live in the
|
|
4591
|
+
// underlying storage blocks.
|
|
4592
|
+
zeroFileRange(at, length) {
|
|
4593
|
+
if (length <= 0) return;
|
|
4594
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
4595
|
+
const zeros = new Uint8Array(Math.min(length, CHUNK));
|
|
4596
|
+
let written = 0;
|
|
4597
|
+
while (written < length) {
|
|
4598
|
+
const n = Math.min(CHUNK, length - written);
|
|
4599
|
+
const slice = n < zeros.length ? zeros.subarray(0, n) : zeros;
|
|
4600
|
+
this.handle.write(slice, { at: at + written });
|
|
4601
|
+
written += n;
|
|
4602
|
+
}
|
|
4603
|
+
}
|
|
4578
4604
|
allocateBlocks(count) {
|
|
4579
4605
|
if (count === 0) return 0;
|
|
4580
4606
|
const bitmap = this.bitmap;
|
|
@@ -4899,17 +4925,28 @@ var VFSEngine = class {
|
|
|
4899
4925
|
}
|
|
4900
4926
|
const inode = this.readInode(existingIdx);
|
|
4901
4927
|
if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };
|
|
4902
|
-
const
|
|
4903
|
-
const
|
|
4904
|
-
combined.set(existing);
|
|
4905
|
-
combined.set(data, existing.byteLength);
|
|
4906
|
-
const neededBlocks = Math.ceil(combined.byteLength / this.blockSize);
|
|
4907
|
-
this.freeBlockRange(inode.firstBlock, inode.blockCount);
|
|
4928
|
+
const combinedSize = inode.size + data.byteLength;
|
|
4929
|
+
const neededBlocks = Math.ceil(combinedSize / this.blockSize);
|
|
4908
4930
|
const newFirst = this.allocateBlocks(neededBlocks);
|
|
4909
|
-
this.
|
|
4931
|
+
const newBase = this.dataOffset + newFirst * this.blockSize;
|
|
4932
|
+
if (inode.size > 0) {
|
|
4933
|
+
const oldBase = this.dataOffset + inode.firstBlock * this.blockSize;
|
|
4934
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
4935
|
+
const scratch = new Uint8Array(Math.min(CHUNK, inode.size));
|
|
4936
|
+
let copied = 0;
|
|
4937
|
+
while (copied < inode.size) {
|
|
4938
|
+
const n = Math.min(CHUNK, inode.size - copied);
|
|
4939
|
+
const slice = n < scratch.length ? scratch.subarray(0, n) : scratch;
|
|
4940
|
+
this.handle.read(slice, { at: oldBase + copied });
|
|
4941
|
+
this.handle.write(slice, { at: newBase + copied });
|
|
4942
|
+
copied += n;
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
this.freeBlockRange(inode.firstBlock, inode.blockCount);
|
|
4946
|
+
this.handle.write(data, { at: newBase + inode.size });
|
|
4910
4947
|
inode.firstBlock = newFirst;
|
|
4911
4948
|
inode.blockCount = neededBlocks;
|
|
4912
|
-
inode.size =
|
|
4949
|
+
inode.size = combinedSize;
|
|
4913
4950
|
inode.mtime = Date.now();
|
|
4914
4951
|
this.writeInode(existingIdx, inode);
|
|
4915
4952
|
this.commitPending();
|
|
@@ -5172,13 +5209,29 @@ var VFSEngine = class {
|
|
|
5172
5209
|
} else if (len > inode.size) {
|
|
5173
5210
|
const neededBlocks = Math.ceil(len / this.blockSize);
|
|
5174
5211
|
if (neededBlocks > inode.blockCount) {
|
|
5175
|
-
const oldData = this.readData(inode.firstBlock, inode.blockCount, inode.size);
|
|
5176
|
-
this.freeBlockRange(inode.firstBlock, inode.blockCount);
|
|
5177
5212
|
const newFirst = this.allocateBlocks(neededBlocks);
|
|
5178
|
-
const
|
|
5179
|
-
|
|
5180
|
-
|
|
5213
|
+
const newBase = this.dataOffset + newFirst * this.blockSize;
|
|
5214
|
+
if (inode.size > 0) {
|
|
5215
|
+
const oldBase = this.dataOffset + inode.firstBlock * this.blockSize;
|
|
5216
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
5217
|
+
const scratch = new Uint8Array(Math.min(CHUNK, inode.size));
|
|
5218
|
+
let copied = 0;
|
|
5219
|
+
while (copied < inode.size) {
|
|
5220
|
+
const n = Math.min(CHUNK, inode.size - copied);
|
|
5221
|
+
const slice = n < scratch.length ? scratch.subarray(0, n) : scratch;
|
|
5222
|
+
this.handle.read(slice, { at: oldBase + copied });
|
|
5223
|
+
this.handle.write(slice, { at: newBase + copied });
|
|
5224
|
+
copied += n;
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
this.freeBlockRange(inode.firstBlock, inode.blockCount);
|
|
5228
|
+
this.zeroFileRange(newBase + inode.size, len - inode.size);
|
|
5181
5229
|
inode.firstBlock = newFirst;
|
|
5230
|
+
} else {
|
|
5231
|
+
this.zeroFileRange(
|
|
5232
|
+
this.dataOffset + inode.firstBlock * this.blockSize + inode.size,
|
|
5233
|
+
len - inode.size
|
|
5234
|
+
);
|
|
5182
5235
|
}
|
|
5183
5236
|
inode.blockCount = neededBlocks;
|
|
5184
5237
|
inode.size = len;
|
|
@@ -5199,8 +5252,36 @@ var VFSEngine = class {
|
|
|
5199
5252
|
if (flags & 1 && this.pathIndex.has(destPath)) {
|
|
5200
5253
|
return { status: CODE_TO_STATUS.EEXIST };
|
|
5201
5254
|
}
|
|
5202
|
-
|
|
5203
|
-
|
|
5255
|
+
if (srcPath === destPath) return { status: 0 };
|
|
5256
|
+
const srcSize = srcInode.size;
|
|
5257
|
+
const srcFirstBlock = srcInode.firstBlock;
|
|
5258
|
+
const emptyStatus = this.write(destPath, new Uint8Array(0));
|
|
5259
|
+
if (emptyStatus.status !== 0) return emptyStatus;
|
|
5260
|
+
if (srcSize === 0) return { status: 0 };
|
|
5261
|
+
const destIdx = this.resolvePathComponents(destPath, true);
|
|
5262
|
+
if (destIdx === void 0) return { status: CODE_TO_STATUS.EIO };
|
|
5263
|
+
const destInode = this.readInode(destIdx);
|
|
5264
|
+
const neededBlocks = Math.ceil(srcSize / this.blockSize);
|
|
5265
|
+
const newFirst = this.allocateBlocks(neededBlocks);
|
|
5266
|
+
const newBase = this.dataOffset + newFirst * this.blockSize;
|
|
5267
|
+
const srcBase = this.dataOffset + srcFirstBlock * this.blockSize;
|
|
5268
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
5269
|
+
const scratch = new Uint8Array(Math.min(CHUNK, srcSize));
|
|
5270
|
+
let copied = 0;
|
|
5271
|
+
while (copied < srcSize) {
|
|
5272
|
+
const n = Math.min(CHUNK, srcSize - copied);
|
|
5273
|
+
const slice = n < scratch.length ? scratch.subarray(0, n) : scratch;
|
|
5274
|
+
this.handle.read(slice, { at: srcBase + copied });
|
|
5275
|
+
this.handle.write(slice, { at: newBase + copied });
|
|
5276
|
+
copied += n;
|
|
5277
|
+
}
|
|
5278
|
+
destInode.firstBlock = newFirst;
|
|
5279
|
+
destInode.blockCount = neededBlocks;
|
|
5280
|
+
destInode.size = srcSize;
|
|
5281
|
+
destInode.mtime = Date.now();
|
|
5282
|
+
this.writeInode(destIdx, destInode);
|
|
5283
|
+
this.commitPending();
|
|
5284
|
+
return { status: 0 };
|
|
5204
5285
|
}
|
|
5205
5286
|
// ---- ACCESS ----
|
|
5206
5287
|
access(path, mode = 0) {
|
|
@@ -5364,16 +5445,35 @@ var VFSEngine = class {
|
|
|
5364
5445
|
if (endPos > inode.size) {
|
|
5365
5446
|
const neededBlocks = Math.ceil(endPos / this.blockSize);
|
|
5366
5447
|
if (neededBlocks > inode.blockCount) {
|
|
5367
|
-
const oldData = inode.size > 0 ? this.readData(inode.firstBlock, inode.blockCount, inode.size) : new Uint8Array(0);
|
|
5368
|
-
this.freeBlockRange(inode.firstBlock, inode.blockCount);
|
|
5369
5448
|
const newFirst = this.allocateBlocks(neededBlocks);
|
|
5370
|
-
const
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5449
|
+
const newBase = this.dataOffset + newFirst * this.blockSize;
|
|
5450
|
+
const oldBase = this.dataOffset + inode.firstBlock * this.blockSize;
|
|
5451
|
+
if (inode.size > 0) {
|
|
5452
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
5453
|
+
const scratch = new Uint8Array(Math.min(CHUNK, inode.size));
|
|
5454
|
+
let copied = 0;
|
|
5455
|
+
while (copied < inode.size) {
|
|
5456
|
+
const n = Math.min(CHUNK, inode.size - copied);
|
|
5457
|
+
const slice = n < scratch.length ? scratch.subarray(0, n) : scratch;
|
|
5458
|
+
this.handle.read(slice, { at: oldBase + copied });
|
|
5459
|
+
this.handle.write(slice, { at: newBase + copied });
|
|
5460
|
+
copied += n;
|
|
5461
|
+
}
|
|
5462
|
+
}
|
|
5463
|
+
this.freeBlockRange(inode.firstBlock, inode.blockCount);
|
|
5464
|
+
if (pos > inode.size) {
|
|
5465
|
+
this.zeroFileRange(newBase + inode.size, pos - inode.size);
|
|
5466
|
+
}
|
|
5467
|
+
this.handle.write(data, { at: newBase + pos });
|
|
5374
5468
|
inode.firstBlock = newFirst;
|
|
5375
5469
|
inode.blockCount = neededBlocks;
|
|
5376
5470
|
} else {
|
|
5471
|
+
if (pos > inode.size) {
|
|
5472
|
+
this.zeroFileRange(
|
|
5473
|
+
this.dataOffset + inode.firstBlock * this.blockSize + inode.size,
|
|
5474
|
+
pos - inode.size
|
|
5475
|
+
);
|
|
5476
|
+
}
|
|
5377
5477
|
const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;
|
|
5378
5478
|
this.handle.write(data, { at: dataOffset });
|
|
5379
5479
|
}
|