Node.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Node = void 0;
  4. const fanout_1 = require("thingies/lib/fanout");
  5. const process_1 = require("./process");
  6. const buffer_1 = require("@jsonjoy.com/fs-node-builtins/lib/internal/buffer");
  7. const fs_node_utils_1 = require("@jsonjoy.com/fs-node-utils");
  8. const { S_IFMT, S_IFDIR, S_IFREG, S_IFLNK, S_IFCHR } = fs_node_utils_1.constants;
  9. const getuid = () => process_1.default.getuid?.() ?? 0;
  10. const getgid = () => process_1.default.getgid?.() ?? 0;
  11. const EMPTY_BUFFER = (0, buffer_1.bufferAllocUnsafe)(0);
  12. /**
  13. * Node in a file system (like i-node, v-node).
  14. */
  15. class Node {
  16. constructor(ino, mode = 0o666, uid = getuid(), gid = getgid()) {
  17. this.changes = new fanout_1.FanOut();
  18. // User ID and group ID.
  19. this._uid = getuid();
  20. this._gid = getgid();
  21. this._atime = new Date();
  22. this._mtime = new Date();
  23. this._ctime = new Date();
  24. this.buf = EMPTY_BUFFER;
  25. /** Total allocated memory capacity for this node. */
  26. this.capacity = 0;
  27. /** Actually used bytes to store content. */
  28. this.size = 0;
  29. this.rdev = 0;
  30. // Number of hard links pointing at this Node.
  31. this._nlink = 1;
  32. this.mode = mode;
  33. this.ino = ino;
  34. this._uid = uid;
  35. this._gid = gid;
  36. }
  37. set ctime(ctime) {
  38. this._ctime = ctime;
  39. }
  40. get ctime() {
  41. return this._ctime;
  42. }
  43. set uid(uid) {
  44. this._uid = uid;
  45. this.ctime = new Date();
  46. }
  47. get uid() {
  48. return this._uid;
  49. }
  50. set gid(gid) {
  51. this._gid = gid;
  52. this.ctime = new Date();
  53. }
  54. get gid() {
  55. return this._gid;
  56. }
  57. set atime(atime) {
  58. this._atime = atime;
  59. }
  60. get atime() {
  61. return this._atime;
  62. }
  63. set mtime(mtime) {
  64. this._mtime = mtime;
  65. this.ctime = new Date();
  66. }
  67. get mtime() {
  68. return this._mtime;
  69. }
  70. get perm() {
  71. return this.mode & ~S_IFMT;
  72. }
  73. set perm(perm) {
  74. this.mode = (this.mode & S_IFMT) | (perm & ~S_IFMT);
  75. this.ctime = new Date();
  76. }
  77. set nlink(nlink) {
  78. this._nlink = nlink;
  79. this.ctime = new Date();
  80. }
  81. get nlink() {
  82. return this._nlink;
  83. }
  84. getString(encoding = 'utf8') {
  85. this.atime = new Date();
  86. return this.getBuffer().toString(encoding);
  87. }
  88. setString(str) {
  89. this._setBuf((0, buffer_1.bufferFrom)(str, 'utf8'));
  90. }
  91. getBuffer() {
  92. this.atime = new Date();
  93. if (!this.buf)
  94. this.buf = (0, buffer_1.bufferAllocUnsafe)(0);
  95. return (0, buffer_1.bufferFrom)(this.buf.subarray(0, this.size)); // Return a copy of used portion.
  96. }
  97. setBuffer(buf) {
  98. const copy = (0, buffer_1.bufferFrom)(buf); // Creates a copy of data.
  99. this._setBuf(copy);
  100. }
  101. _setBuf(buf) {
  102. const size = buf.length;
  103. this.buf = buf;
  104. this.capacity = size;
  105. this.size = size;
  106. this.touch();
  107. }
  108. getSize() {
  109. return this.size;
  110. }
  111. setModeProperty(property) {
  112. this.mode = property;
  113. }
  114. isFile() {
  115. return (this.mode & S_IFMT) === S_IFREG;
  116. }
  117. isDirectory() {
  118. return (this.mode & S_IFMT) === S_IFDIR;
  119. }
  120. isSymlink() {
  121. // return !!this.symlink;
  122. return (this.mode & S_IFMT) === S_IFLNK;
  123. }
  124. isCharacterDevice() {
  125. return (this.mode & S_IFMT) === S_IFCHR;
  126. }
  127. makeSymlink(symlink) {
  128. this.mode = S_IFLNK | 0o666;
  129. this.symlink = symlink;
  130. }
  131. write(buf, off = 0, len = buf.length, pos = 0) {
  132. const bufLength = buf.length;
  133. if (off + len > bufLength)
  134. len = bufLength - off;
  135. if (len <= 0)
  136. return 0;
  137. const requiredSize = pos + len;
  138. if (requiredSize > this.capacity) {
  139. let newCapacity = Math.max(this.capacity * 2, 64);
  140. while (newCapacity < requiredSize)
  141. newCapacity *= 2;
  142. const newBuf = (0, buffer_1.bufferAllocUnsafe)(newCapacity);
  143. if (this.size > 0)
  144. this.buf.copy(newBuf, 0, 0, this.size);
  145. this.buf = newBuf;
  146. this.capacity = newCapacity;
  147. }
  148. if (pos > this.size)
  149. this.buf.fill(0, this.size, pos);
  150. buf.copy(this.buf, pos, off, off + len);
  151. if (requiredSize > this.size)
  152. this.size = requiredSize;
  153. this.touch();
  154. return len;
  155. }
  156. /**
  157. * Read data from the file.
  158. *
  159. * @param buf Buffer to read data into.
  160. * @param off Offset int the `buf` where to start writing data.
  161. * @param len How many bytes to read. Equals to `buf.byteLength` by default.
  162. * @param pos Position offset in file where to start reading. Defaults to `0`.
  163. * @returns Returns the number of bytes read.
  164. */
  165. read(buf, off = 0, len = buf.byteLength, pos = 0) {
  166. this.atime = new Date();
  167. if (pos >= this.size)
  168. return 0;
  169. let actualLen = len;
  170. if (actualLen > buf.byteLength)
  171. actualLen = buf.byteLength;
  172. if (actualLen + pos > this.size)
  173. actualLen = this.size - pos;
  174. if (actualLen <= 0)
  175. return 0;
  176. const buf2 = buf instanceof buffer_1.Buffer ? buf : buffer_1.Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
  177. this.buf.copy(buf2, off, pos, pos + actualLen);
  178. return actualLen;
  179. }
  180. truncate(len = 0) {
  181. if (!len) {
  182. this.buf = EMPTY_BUFFER;
  183. this.capacity = 0;
  184. this.size = 0;
  185. this.touch();
  186. return;
  187. }
  188. if (len <= this.size)
  189. this.size = len;
  190. else {
  191. if (len > this.capacity) {
  192. let newCapacity = Math.max(this.capacity * 2, 64);
  193. while (newCapacity < len)
  194. newCapacity *= 2;
  195. const buf = (0, buffer_1.bufferAllocUnsafe)(newCapacity);
  196. if (this.size > 0)
  197. this.buf.copy(buf, 0, 0, this.size);
  198. buf.fill(0, this.size, len);
  199. this.buf = buf;
  200. this.capacity = newCapacity;
  201. }
  202. else
  203. this.buf.fill(0, this.size, len);
  204. this.size = len;
  205. }
  206. this.touch();
  207. }
  208. chmod(perm) {
  209. this.mode = (this.mode & S_IFMT) | (perm & ~S_IFMT);
  210. this.touch();
  211. }
  212. chown(uid, gid) {
  213. this.uid = uid;
  214. this.gid = gid;
  215. this.touch();
  216. }
  217. touch() {
  218. this.mtime = new Date();
  219. this.changes.emit(['modify']);
  220. }
  221. canRead(uid = getuid(), gid = getgid()) {
  222. if (this.perm & 4 /* S.IROTH */) {
  223. return true;
  224. }
  225. if (gid === this.gid) {
  226. if (this.perm & 32 /* S.IRGRP */) {
  227. return true;
  228. }
  229. }
  230. if (uid === this.uid) {
  231. if (this.perm & 256 /* S.IRUSR */) {
  232. return true;
  233. }
  234. }
  235. return false;
  236. }
  237. canWrite(uid = getuid(), gid = getgid()) {
  238. if (this.perm & 2 /* S.IWOTH */) {
  239. return true;
  240. }
  241. if (gid === this.gid) {
  242. if (this.perm & 16 /* S.IWGRP */) {
  243. return true;
  244. }
  245. }
  246. if (uid === this.uid) {
  247. if (this.perm & 128 /* S.IWUSR */) {
  248. return true;
  249. }
  250. }
  251. return false;
  252. }
  253. canExecute(uid = getuid(), gid = getgid()) {
  254. if (this.perm & 1 /* S.IXOTH */) {
  255. return true;
  256. }
  257. if (gid === this.gid) {
  258. if (this.perm & 8 /* S.IXGRP */) {
  259. return true;
  260. }
  261. }
  262. if (uid === this.uid) {
  263. if (this.perm & 64 /* S.IXUSR */) {
  264. return true;
  265. }
  266. }
  267. return false;
  268. }
  269. del() {
  270. this.changes.emit(['delete']);
  271. }
  272. toJSON() {
  273. return {
  274. ino: this.ino,
  275. uid: this.uid,
  276. gid: this.gid,
  277. atime: this.atime.getTime(),
  278. mtime: this.mtime.getTime(),
  279. ctime: this.ctime.getTime(),
  280. perm: this.perm,
  281. mode: this.mode,
  282. nlink: this.nlink,
  283. symlink: this.symlink,
  284. data: this.getString(),
  285. };
  286. }
  287. }
  288. exports.Node = Node;
  289. //# sourceMappingURL=Node.js.map