UNPKG

@zenfs/core

Version:

A filesystem, anywhere

243 lines (242 loc) 6.53 kB
import { pick } from 'utilium'; import { _inode_fields, hasAccess } from '../internal/inode.js'; import * as c from '../constants.js'; const n1000 = BigInt(1000); /** * Provides information about a particular entry in the file system. * Common code used by both Stats and BigIntStats. */ export class StatsCommon { _convert(arg) { return (this._isBigint ? BigInt(arg) : Number(arg)); } get blocks() { return this._convert(Math.ceil(Number(this.size) / 512)); } set blocks(value) { } /** * Unix-style file mode (e.g. 0o644) that includes the type of the item. */ mode; /** * ID of device containing file */ dev = this._convert(0); /** * Inode number */ ino = this._convert(0); /** * Device ID (if special file) */ rdev = this._convert(0); /** * Number of hard links */ nlink = this._convert(1); /** * Block size for file system I/O */ blksize = this._convert(4096); /** * User ID of owner */ uid = this._convert(0); /** * Group ID of owner */ gid = this._convert(0); /** * Time of last access, since epoch */ atimeMs; get atime() { return new Date(Number(this.atimeMs)); } set atime(value) { this.atimeMs = this._convert(value.getTime()); } /** * Time of last modification, since epoch */ mtimeMs; get mtime() { return new Date(Number(this.mtimeMs)); } set mtime(value) { this.mtimeMs = this._convert(value.getTime()); } /** * Time of last time file status was changed, since epoch */ ctimeMs; get ctime() { return new Date(Number(this.ctimeMs)); } set ctime(value) { this.ctimeMs = this._convert(value.getTime()); } /** * Time of file creation, since epoch */ birthtimeMs; get birthtime() { return new Date(Number(this.birthtimeMs)); } set birthtime(value) { this.birthtimeMs = this._convert(value.getTime()); } /** * Size of the item in bytes. * For directories/symlinks, this is normally the size of the struct that represents the item. */ size; /** * @internal Used by inodes */ data; /** * @internal Used by inodes */ flags; /** * @internal Used by inodes */ version; /** * Creates a new stats instance from a stats-like object. Can be used to copy stats (note) */ constructor({ atimeMs, mtimeMs, ctimeMs, birthtimeMs, uid, gid, size, mode, ino, ...rest } = {}) { const now = Date.now(); this.atimeMs = this._convert(atimeMs ?? now); this.mtimeMs = this._convert(mtimeMs ?? now); this.ctimeMs = this._convert(ctimeMs ?? now); this.birthtimeMs = this._convert(birthtimeMs ?? now); this.uid = this._convert(uid ?? 0); this.gid = this._convert(gid ?? 0); this.size = this._convert(size ?? 0); this.ino = this._convert(ino ?? 0); this.mode = this._convert(mode ?? 0o644 & c.S_IFREG); if ((this.mode & c.S_IFMT) == 0) { this.mode = (this.mode | this._convert(c.S_IFREG)); } Object.assign(this, rest); } isFile() { return (this.mode & c.S_IFMT) === c.S_IFREG; } isDirectory() { return (this.mode & c.S_IFMT) === c.S_IFDIR; } isSymbolicLink() { return (this.mode & c.S_IFMT) === c.S_IFLNK; } isSocket() { return (this.mode & c.S_IFMT) === c.S_IFSOCK; } isBlockDevice() { return (this.mode & c.S_IFMT) === c.S_IFBLK; } isCharacterDevice() { return (this.mode & c.S_IFMT) === c.S_IFCHR; } isFIFO() { return (this.mode & c.S_IFMT) === c.S_IFIFO; } toJSON() { return pick(this, _inode_fields); } /** * Checks if a given user/group has access to this item * @param mode The requested access, combination of W_OK, R_OK, and X_OK * @returns True if the request has access, false if the request does not * @internal */ hasAccess(mode, context) { return hasAccess(context, this._isBigint ? new Stats(this) : this, mode); } get atimeNs() { return BigInt(this.atimeMs) * n1000; } get mtimeNs() { return BigInt(this.mtimeMs) * n1000; } get ctimeNs() { return BigInt(this.ctimeMs) * n1000; } get birthtimeNs() { return BigInt(this.birthtimeMs) * n1000; } } /** * Implementation of Node's `Stats`. * * Attribute descriptions are from `man 2 stat' * @see http://nodejs.org/api/fs.html#fs_class_fs_stats * @see http://man7.org/linux/man-pages/man2/stat.2.html */ export class Stats extends StatsCommon { _isBigint = false; } Stats; /** * Stats with bigint */ export class BigIntStats extends StatsCommon { _isBigint = true; } /** * Determines if the file stats have changed by comparing relevant properties. * * @param left The previous stats. * @param right The current stats. * @returns `true` if stats have changed; otherwise, `false`. * @internal */ export function isStatsEqual(left, right) { return (left.size == right.size && +left.atime == +right.atime && +left.mtime == +right.mtime && +left.ctime == +right.ctime && left.mode == right.mode); } /** @internal */ export const ZenFsType = 0x7a656e6673; // 'z' 'e' 'n' 'f' 's' /** * @hidden */ export class StatsFs { /** Type of file system. */ type = 0x7a656e6673; /** Optimal transfer block size. */ bsize = 4096; /** Total data blocks in file system. */ blocks = 0; /** Free blocks in file system. */ bfree = 0; /** Available blocks for unprivileged users */ bavail = 0; /** Total file nodes in file system. */ files = c.size_max; /** Free file nodes in file system. */ ffree = c.size_max; } /** * @hidden */ export class BigIntStatsFs { /** Type of file system. */ type = BigInt('0x7a656e6673'); /** Optimal transfer block size. */ bsize = BigInt(4096); /** Total data blocks in file system. */ blocks = BigInt(0); /** Free blocks in file system. */ bfree = BigInt(0); /** Available blocks for unprivileged users */ bavail = BigInt(0); /** Total file nodes in file system. */ files = BigInt(c.size_max); /** Free file nodes in file system. */ ffree = BigInt(c.size_max); }