1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.File = exports.Link = exports.Node = exports.SEP = void 0;
|
4 | const process_1 = require("./process");
|
5 | const buffer_1 = require("./internal/buffer");
|
6 | const constants_1 = require("./constants");
|
7 | const events_1 = require("events");
|
8 | const Stats_1 = require("./Stats");
|
9 | const { S_IFMT, S_IFDIR, S_IFREG, S_IFLNK, O_APPEND } = constants_1.constants;
|
10 | const getuid = () => { var _a, _b; return (_b = (_a = process_1.default.getuid) === null || _a === void 0 ? void 0 : _a.call(process_1.default)) !== null && _b !== void 0 ? _b : 0; };
|
11 | const getgid = () => { var _a, _b; return (_b = (_a = process_1.default.getgid) === null || _a === void 0 ? void 0 : _a.call(process_1.default)) !== null && _b !== void 0 ? _b : 0; };
|
12 | exports.SEP = '/';
|
13 |
|
14 |
|
15 |
|
16 | class Node extends events_1.EventEmitter {
|
17 | constructor(ino, perm = 0o666) {
|
18 | super();
|
19 |
|
20 | this._uid = getuid();
|
21 | this._gid = getgid();
|
22 | this._atime = new Date();
|
23 | this._mtime = new Date();
|
24 | this._ctime = new Date();
|
25 | this._perm = 0o666;
|
26 | this.mode = S_IFREG;
|
27 |
|
28 | this._nlink = 1;
|
29 | this._perm = perm;
|
30 | this.mode |= perm;
|
31 | this.ino = ino;
|
32 | }
|
33 | set ctime(ctime) {
|
34 | this._ctime = ctime;
|
35 | }
|
36 | get ctime() {
|
37 | return this._ctime;
|
38 | }
|
39 | set uid(uid) {
|
40 | this._uid = uid;
|
41 | this.ctime = new Date();
|
42 | }
|
43 | get uid() {
|
44 | return this._uid;
|
45 | }
|
46 | set gid(gid) {
|
47 | this._gid = gid;
|
48 | this.ctime = new Date();
|
49 | }
|
50 | get gid() {
|
51 | return this._gid;
|
52 | }
|
53 | set atime(atime) {
|
54 | this._atime = atime;
|
55 | this.ctime = new Date();
|
56 | }
|
57 | get atime() {
|
58 | return this._atime;
|
59 | }
|
60 | set mtime(mtime) {
|
61 | this._mtime = mtime;
|
62 | this.ctime = new Date();
|
63 | }
|
64 | get mtime() {
|
65 | return this._mtime;
|
66 | }
|
67 | set perm(perm) {
|
68 | this._perm = perm;
|
69 | this.ctime = new Date();
|
70 | }
|
71 | get perm() {
|
72 | return this._perm;
|
73 | }
|
74 | set nlink(nlink) {
|
75 | this._nlink = nlink;
|
76 | this.ctime = new Date();
|
77 | }
|
78 | get nlink() {
|
79 | return this._nlink;
|
80 | }
|
81 | getString(encoding = 'utf8') {
|
82 | this.atime = new Date();
|
83 | return this.getBuffer().toString(encoding);
|
84 | }
|
85 | setString(str) {
|
86 |
|
87 | this.buf = (0, buffer_1.bufferFrom)(str, 'utf8');
|
88 | this.touch();
|
89 | }
|
90 | getBuffer() {
|
91 | this.atime = new Date();
|
92 | if (!this.buf)
|
93 | this.setBuffer((0, buffer_1.bufferAllocUnsafe)(0));
|
94 | return (0, buffer_1.bufferFrom)(this.buf);
|
95 | }
|
96 | setBuffer(buf) {
|
97 | this.buf = (0, buffer_1.bufferFrom)(buf);
|
98 | this.touch();
|
99 | }
|
100 | getSize() {
|
101 | return this.buf ? this.buf.length : 0;
|
102 | }
|
103 | setModeProperty(property) {
|
104 | this.mode = (this.mode & ~S_IFMT) | property;
|
105 | }
|
106 | setIsFile() {
|
107 | this.setModeProperty(S_IFREG);
|
108 | }
|
109 | setIsDirectory() {
|
110 | this.setModeProperty(S_IFDIR);
|
111 | }
|
112 | setIsSymlink() {
|
113 | this.setModeProperty(S_IFLNK);
|
114 | }
|
115 | isFile() {
|
116 | return (this.mode & S_IFMT) === S_IFREG;
|
117 | }
|
118 | isDirectory() {
|
119 | return (this.mode & S_IFMT) === S_IFDIR;
|
120 | }
|
121 | isSymlink() {
|
122 |
|
123 | return (this.mode & S_IFMT) === S_IFLNK;
|
124 | }
|
125 | makeSymlink(steps) {
|
126 | this.symlink = steps;
|
127 | this.setIsSymlink();
|
128 | }
|
129 | write(buf, off = 0, len = buf.length, pos = 0) {
|
130 | if (!this.buf)
|
131 | this.buf = (0, buffer_1.bufferAllocUnsafe)(0);
|
132 | if (pos + len > this.buf.length) {
|
133 | const newBuf = (0, buffer_1.bufferAllocUnsafe)(pos + len);
|
134 | this.buf.copy(newBuf, 0, 0, this.buf.length);
|
135 | this.buf = newBuf;
|
136 | }
|
137 | buf.copy(this.buf, pos, off, off + len);
|
138 | this.touch();
|
139 | return len;
|
140 | }
|
141 |
|
142 | read(buf, off = 0, len = buf.byteLength, pos = 0) {
|
143 | this.atime = new Date();
|
144 | if (!this.buf)
|
145 | this.buf = (0, buffer_1.bufferAllocUnsafe)(0);
|
146 | let actualLen = len;
|
147 | if (actualLen > buf.byteLength) {
|
148 | actualLen = buf.byteLength;
|
149 | }
|
150 | if (actualLen + pos > this.buf.length) {
|
151 | actualLen = this.buf.length - pos;
|
152 | }
|
153 | const buf2 = buf instanceof Buffer ? buf : Buffer.from(buf.buffer);
|
154 | this.buf.copy(buf2, off, pos, pos + actualLen);
|
155 | return actualLen;
|
156 | }
|
157 | truncate(len = 0) {
|
158 | if (!len)
|
159 | this.buf = (0, buffer_1.bufferAllocUnsafe)(0);
|
160 | else {
|
161 | if (!this.buf)
|
162 | this.buf = (0, buffer_1.bufferAllocUnsafe)(0);
|
163 | if (len <= this.buf.length) {
|
164 | this.buf = this.buf.slice(0, len);
|
165 | }
|
166 | else {
|
167 | const buf = (0, buffer_1.bufferAllocUnsafe)(len);
|
168 | this.buf.copy(buf);
|
169 | buf.fill(0, this.buf.length);
|
170 | this.buf = buf;
|
171 | }
|
172 | }
|
173 | this.touch();
|
174 | }
|
175 | chmod(perm) {
|
176 | this.perm = perm;
|
177 | this.mode = (this.mode & ~0o777) | perm;
|
178 | this.touch();
|
179 | }
|
180 | chown(uid, gid) {
|
181 | this.uid = uid;
|
182 | this.gid = gid;
|
183 | this.touch();
|
184 | }
|
185 | touch() {
|
186 | this.mtime = new Date();
|
187 | this.emit('change', this);
|
188 | }
|
189 | canRead(uid = getuid(), gid = getgid()) {
|
190 | if (this.perm & 4 ) {
|
191 | return true;
|
192 | }
|
193 | if (gid === this.gid) {
|
194 | if (this.perm & 32 ) {
|
195 | return true;
|
196 | }
|
197 | }
|
198 | if (uid === this.uid) {
|
199 | if (this.perm & 256 ) {
|
200 | return true;
|
201 | }
|
202 | }
|
203 | return false;
|
204 | }
|
205 | canWrite(uid = getuid(), gid = getgid()) {
|
206 | if (this.perm & 2 ) {
|
207 | return true;
|
208 | }
|
209 | if (gid === this.gid) {
|
210 | if (this.perm & 16 ) {
|
211 | return true;
|
212 | }
|
213 | }
|
214 | if (uid === this.uid) {
|
215 | if (this.perm & 128 ) {
|
216 | return true;
|
217 | }
|
218 | }
|
219 | return false;
|
220 | }
|
221 | del() {
|
222 | this.emit('delete', this);
|
223 | }
|
224 | toJSON() {
|
225 | return {
|
226 | ino: this.ino,
|
227 | uid: this.uid,
|
228 | gid: this.gid,
|
229 | atime: this.atime.getTime(),
|
230 | mtime: this.mtime.getTime(),
|
231 | ctime: this.ctime.getTime(),
|
232 | perm: this.perm,
|
233 | mode: this.mode,
|
234 | nlink: this.nlink,
|
235 | symlink: this.symlink,
|
236 | data: this.getString(),
|
237 | };
|
238 | }
|
239 | }
|
240 | exports.Node = Node;
|
241 |
|
242 |
|
243 |
|
244 | class Link extends events_1.EventEmitter {
|
245 | get steps() {
|
246 | return this._steps;
|
247 | }
|
248 |
|
249 | set steps(val) {
|
250 | this._steps = val;
|
251 | for (const [child, link] of this.children.entries()) {
|
252 | if (child === '.' || child === '..') {
|
253 | continue;
|
254 | }
|
255 | link === null || link === void 0 ? void 0 : link.syncSteps();
|
256 | }
|
257 | }
|
258 | constructor(vol, parent, name) {
|
259 | super();
|
260 | this.children = new Map();
|
261 |
|
262 | this._steps = [];
|
263 |
|
264 | this.ino = 0;
|
265 |
|
266 | this.length = 0;
|
267 | this.vol = vol;
|
268 | this.parent = parent;
|
269 | this.name = name;
|
270 | this.syncSteps();
|
271 | }
|
272 | setNode(node) {
|
273 | this.node = node;
|
274 | this.ino = node.ino;
|
275 | }
|
276 | getNode() {
|
277 | return this.node;
|
278 | }
|
279 | createChild(name, node = this.vol.createNode()) {
|
280 | const link = new Link(this.vol, this, name);
|
281 | link.setNode(node);
|
282 | if (node.isDirectory()) {
|
283 | link.children.set('.', link);
|
284 | link.getNode().nlink++;
|
285 | }
|
286 | this.setChild(name, link);
|
287 | return link;
|
288 | }
|
289 | setChild(name, link = new Link(this.vol, this, name)) {
|
290 | this.children.set(name, link);
|
291 | link.parent = this;
|
292 | this.length++;
|
293 | const node = link.getNode();
|
294 | if (node.isDirectory()) {
|
295 | link.children.set('..', this);
|
296 | this.getNode().nlink++;
|
297 | }
|
298 | this.getNode().mtime = new Date();
|
299 | this.emit('child:add', link, this);
|
300 | return link;
|
301 | }
|
302 | deleteChild(link) {
|
303 | const node = link.getNode();
|
304 | if (node.isDirectory()) {
|
305 | link.children.delete('..');
|
306 | this.getNode().nlink--;
|
307 | }
|
308 | this.children.delete(link.getName());
|
309 | this.length--;
|
310 | this.getNode().mtime = new Date();
|
311 | this.emit('child:delete', link, this);
|
312 | }
|
313 | getChild(name) {
|
314 | this.getNode().mtime = new Date();
|
315 | return this.children.get(name);
|
316 | }
|
317 | getPath() {
|
318 | return this.steps.join(exports.SEP);
|
319 | }
|
320 | getName() {
|
321 | return this.steps[this.steps.length - 1];
|
322 | }
|
323 |
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 | |
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 | walk(steps, stop = steps.length, i = 0) {
|
340 | if (i >= steps.length)
|
341 | return this;
|
342 | if (i >= stop)
|
343 | return this;
|
344 | const step = steps[i];
|
345 | const link = this.getChild(step);
|
346 | if (!link)
|
347 | return null;
|
348 | return link.walk(steps, stop, i + 1);
|
349 | }
|
350 | toJSON() {
|
351 | return {
|
352 | steps: this.steps,
|
353 | ino: this.ino,
|
354 | children: Array.from(this.children.keys()),
|
355 | };
|
356 | }
|
357 | syncSteps() {
|
358 | this.steps = this.parent ? this.parent.steps.concat([this.name]) : [this.name];
|
359 | }
|
360 | }
|
361 | exports.Link = Link;
|
362 |
|
363 |
|
364 |
|
365 | class File {
|
366 | |
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 | constructor(link, node, flags, fd) {
|
375 | this.link = link;
|
376 | this.node = node;
|
377 | this.flags = flags;
|
378 | this.fd = fd;
|
379 | this.position = 0;
|
380 | if (this.flags & O_APPEND)
|
381 | this.position = this.getSize();
|
382 | }
|
383 | getString(encoding = 'utf8') {
|
384 | return this.node.getString();
|
385 | }
|
386 | setString(str) {
|
387 | this.node.setString(str);
|
388 | }
|
389 | getBuffer() {
|
390 | return this.node.getBuffer();
|
391 | }
|
392 | setBuffer(buf) {
|
393 | this.node.setBuffer(buf);
|
394 | }
|
395 | getSize() {
|
396 | return this.node.getSize();
|
397 | }
|
398 | truncate(len) {
|
399 | this.node.truncate(len);
|
400 | }
|
401 | seekTo(position) {
|
402 | this.position = position;
|
403 | }
|
404 | stats() {
|
405 | return Stats_1.default.build(this.node);
|
406 | }
|
407 | write(buf, offset = 0, length = buf.length, position) {
|
408 | if (typeof position !== 'number')
|
409 | position = this.position;
|
410 | const bytes = this.node.write(buf, offset, length, position);
|
411 | this.position = position + bytes;
|
412 | return bytes;
|
413 | }
|
414 | read(buf, offset = 0, length = buf.byteLength, position) {
|
415 | if (typeof position !== 'number')
|
416 | position = this.position;
|
417 | const bytes = this.node.read(buf, offset, length, position);
|
418 | this.position = position + bytes;
|
419 | return bytes;
|
420 | }
|
421 | chmod(perm) {
|
422 | this.node.chmod(perm);
|
423 | }
|
424 | chown(uid, gid) {
|
425 | this.node.chown(uid, gid);
|
426 | }
|
427 | }
|
428 | exports.File = File;
|
429 |
|
\ | No newline at end of file |