@zenfs/core
Advanced tools
Comparing version 1.2.9 to 1.2.10
@@ -67,3 +67,3 @@ import { Buffer } from 'buffer'; | ||
* @option mode Defaults to `0644`. | ||
* @option flag Defaults to `'a'`. | ||
* @option flag Defaults to `'a+'`. | ||
*/ | ||
@@ -70,0 +70,0 @@ export declare function appendFileSync(filename: fs.PathOrFileDescriptor, data: FileContents, _options?: fs.WriteFileOptions): void; |
@@ -275,3 +275,3 @@ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) { | ||
* @option mode Defaults to `0644`. | ||
* @option flag Defaults to `'a'`. | ||
* @option flag Defaults to `'a+'`. | ||
*/ | ||
@@ -281,3 +281,3 @@ export function appendFileSync(filename, data, _options = {}) { | ||
try { | ||
const options = normalizeOptions(_options, 'utf8', 'a', 0o644); | ||
const options = normalizeOptions(_options, 'utf8', 'a+', 0o644); | ||
const flag = parseFlag(options.flag); | ||
@@ -284,0 +284,0 @@ if (!isAppendable(flag)) { |
@@ -0,3 +1,3 @@ | ||
import { config } from './emulation/config.js'; | ||
import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT, size_max } from './emulation/constants.js'; | ||
import { config } from './emulation/config.js'; | ||
import { Errno, ErrnoError } from './error.js'; | ||
@@ -4,0 +4,0 @@ import './polyfills.js'; |
@@ -39,4 +39,4 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { | ||
}; | ||
import { deserialize, serialize, sizeof, struct, types as t } from 'utilium'; | ||
import { Stats } from './stats.js'; | ||
import { types as t, struct, sizeof, serialize, deserialize } from 'utilium'; | ||
/** | ||
@@ -166,4 +166,4 @@ * Room inode | ||
} | ||
if (this.uid !== stats.uid) { | ||
this.uid = stats.uid; | ||
if (this.gid !== stats.gid) { | ||
this.gid = stats.gid; | ||
hasChanged = true; | ||
@@ -170,0 +170,0 @@ } |
import { credentials } from './credentials.js'; | ||
import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU, size_max } from './emulation/constants.js'; | ||
import { R_OK, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR, size_max, W_OK, X_OK, } from './emulation/constants.js'; | ||
/** | ||
@@ -113,8 +113,33 @@ * Provides information about a particular entry in the file system. | ||
if (credentials.euid === 0 || credentials.egid === 0) { | ||
//Running as root | ||
// Running as root | ||
return true; | ||
} | ||
// Mask for | ||
const adjusted = (credentials.uid == this.uid ? S_IRWXU : 0) | (credentials.gid == this.gid ? S_IRWXG : 0) | S_IRWXO; | ||
return (mode & this.mode & adjusted) == mode; | ||
let perm = 0; | ||
// Owner permissions | ||
if (credentials.uid === this.uid) { | ||
if (this.mode & S_IRUSR) | ||
perm |= R_OK; | ||
if (this.mode & S_IWUSR) | ||
perm |= W_OK; | ||
if (this.mode & S_IXUSR) | ||
perm |= X_OK; | ||
} | ||
// Group permissions | ||
if (credentials.gid === this.gid) { | ||
if (this.mode & S_IRGRP) | ||
perm |= R_OK; | ||
if (this.mode & S_IWGRP) | ||
perm |= W_OK; | ||
if (this.mode & S_IXGRP) | ||
perm |= X_OK; | ||
} | ||
// Others permissions | ||
if (this.mode & S_IROTH) | ||
perm |= R_OK; | ||
if (this.mode & S_IWOTH) | ||
perm |= W_OK; | ||
if (this.mode & S_IXOTH) | ||
perm |= X_OK; | ||
// Perform the access check | ||
return (perm & mode) === mode; | ||
} | ||
@@ -121,0 +146,0 @@ /** |
{ | ||
"name": "@zenfs/core", | ||
"version": "1.2.9", | ||
"version": "1.2.10", | ||
"description": "A filesystem, anywhere", | ||
@@ -5,0 +5,0 @@ "funding": { |
@@ -246,6 +246,6 @@ import { Buffer } from 'buffer'; | ||
* @option mode Defaults to `0644`. | ||
* @option flag Defaults to `'a'`. | ||
* @option flag Defaults to `'a+'`. | ||
*/ | ||
export function appendFileSync(filename: fs.PathOrFileDescriptor, data: FileContents, _options: fs.WriteFileOptions = {}): void { | ||
const options = normalizeOptions(_options, 'utf8', 'a', 0o644); | ||
const options = normalizeOptions(_options, 'utf8', 'a+', 0o644); | ||
const flag = parseFlag(options.flag); | ||
@@ -252,0 +252,0 @@ if (!isAppendable(flag)) { |
import type { FileReadResult } from 'node:fs/promises'; | ||
import { config } from './emulation/config.js'; | ||
import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT, size_max } from './emulation/constants.js'; | ||
import { config } from './emulation/config.js'; | ||
import { Errno, ErrnoError } from './error.js'; | ||
@@ -5,0 +5,0 @@ import type { FileSystem } from './filesystem.js'; |
@@ -0,3 +1,3 @@ | ||
import { deserialize, serialize, sizeof, struct, types as t } from 'utilium'; | ||
import { Stats, type StatsLike } from './stats.js'; | ||
import { types as t, struct, sizeof, serialize, deserialize } from 'utilium'; | ||
@@ -111,4 +111,4 @@ /** | ||
if (this.uid !== stats.uid) { | ||
this.uid = stats.uid; | ||
if (this.gid !== stats.gid) { | ||
this.gid = stats.gid; | ||
hasChanged = true; | ||
@@ -115,0 +115,0 @@ } |
import type * as Node from 'node:fs'; | ||
import { credentials, type Credentials } from './credentials.js'; | ||
import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU, size_max } from './emulation/constants.js'; | ||
import { | ||
R_OK, | ||
S_IFBLK, | ||
S_IFCHR, | ||
S_IFDIR, | ||
S_IFIFO, | ||
S_IFLNK, | ||
S_IFMT, | ||
S_IFREG, | ||
S_IFSOCK, | ||
S_IRGRP, | ||
S_IROTH, | ||
S_IRUSR, | ||
S_IWGRP, | ||
S_IWOTH, | ||
S_IWUSR, | ||
S_IXGRP, | ||
S_IXOTH, | ||
S_IXUSR, | ||
size_max, | ||
W_OK, | ||
X_OK, | ||
} from './emulation/constants.js'; | ||
@@ -225,9 +247,29 @@ /** | ||
if (credentials.euid === 0 || credentials.egid === 0) { | ||
//Running as root | ||
// Running as root | ||
return true; | ||
} | ||
// Mask for | ||
const adjusted = (credentials.uid == this.uid ? S_IRWXU : 0) | (credentials.gid == this.gid ? S_IRWXG : 0) | S_IRWXO; | ||
return (mode & this.mode & adjusted) == mode; | ||
let perm = 0; | ||
// Owner permissions | ||
if (credentials.uid === this.uid) { | ||
if (this.mode & S_IRUSR) perm |= R_OK; | ||
if (this.mode & S_IWUSR) perm |= W_OK; | ||
if (this.mode & S_IXUSR) perm |= X_OK; | ||
} | ||
// Group permissions | ||
if (credentials.gid === this.gid) { | ||
if (this.mode & S_IRGRP) perm |= R_OK; | ||
if (this.mode & S_IWGRP) perm |= W_OK; | ||
if (this.mode & S_IXGRP) perm |= X_OK; | ||
} | ||
// Others permissions | ||
if (this.mode & S_IROTH) perm |= R_OK; | ||
if (this.mode & S_IWOTH) perm |= W_OK; | ||
if (this.mode & S_IXOTH) perm |= X_OK; | ||
// Perform the access check | ||
return (perm & mode) === mode; | ||
} | ||
@@ -234,0 +276,0 @@ |
import assert from 'node:assert'; | ||
import { suite, test } from 'node:test'; | ||
import { credentials } from '../../dist/credentials.js'; | ||
import { Stats } from '../../dist/stats.js'; | ||
@@ -37,2 +38,43 @@ import { fs } from '../common.js'; | ||
test('hasAccess for non-root access', () => { | ||
const newFile = 'new.txt'; | ||
fs.writeFileSync(newFile, 'hello', { | ||
mode: 0o640, // allow group access | ||
}); | ||
const prevCredentials = { | ||
...credentials, | ||
}; | ||
const uid = 33; | ||
const nonRootCredentials = { | ||
uid, | ||
gid: uid, | ||
euid: uid, | ||
egid: uid, | ||
suid: uid, | ||
sgid: uid, | ||
}; | ||
fs.chownSync(newFile, 0, nonRootCredentials.gid); // creating with root-user so that non-root user can access | ||
Object.assign(credentials, nonRootCredentials); | ||
const stat = fs.statSync(newFile); | ||
assert.equal(stat.gid, nonRootCredentials.gid); | ||
assert.equal(stat.uid, 0); | ||
assert.equal(stat.hasAccess(fs.constants.R_OK), true); | ||
assert.equal(stat.hasAccess(fs.constants.W_OK), false); | ||
assert.equal(stat.hasAccess(fs.constants.X_OK), false); | ||
// changing group | ||
Object.assign(credentials, { ...nonRootCredentials, gid: 44 }); | ||
assert.equal(stat.hasAccess(fs.constants.R_OK), false); | ||
assert.equal(stat.hasAccess(fs.constants.W_OK), false); | ||
assert.equal(stat.hasAccess(fs.constants.X_OK), false); | ||
Object.assign(credentials, prevCredentials); | ||
}); | ||
test('stat file', async () => { | ||
@@ -39,0 +81,0 @@ const stats = await fs.promises.stat(existing_file); |
@@ -8,10 +8,10 @@ import assert from 'node:assert'; | ||
const path = 'x.txt'; | ||
suite('times', () => { | ||
const path = 'x.txt'; | ||
function expect_assert(resource: string | number, atime: Date | number, mtime: Date | number) { | ||
const stats = typeof resource == 'string' ? fs.statSync(resource) : fs.fstatSync(resource); | ||
// check up to single-second precision since sub-second precision is OS and fs dependent | ||
assert(_toUnixTimestamp(atime) == _toUnixTimestamp(stats.atime)); | ||
assert(_toUnixTimestamp(mtime) == _toUnixTimestamp(stats.mtime)); | ||
assert.equal(_toUnixTimestamp(atime), _toUnixTimestamp(stats.atime)); | ||
assert.equal(_toUnixTimestamp(mtime), _toUnixTimestamp(stats.mtime)); | ||
} | ||
@@ -28,4 +28,3 @@ | ||
// don't close this fd | ||
const handle = await fs.promises.open(path, 'r'); | ||
await using handle = await fs.promises.open(path, 'r'); | ||
@@ -38,13 +37,3 @@ await handle.utimes(atime, mtime); | ||
// some systems don't have futimes | ||
// if there's an error, it be ENOSYS | ||
try { | ||
fs.futimesSync(handle.fd, atime, mtime); | ||
expect_assert(handle.fd, atime, mtime); | ||
} catch (error: any) { | ||
assert(error instanceof ErrnoError); | ||
assert.strictEqual(error.code, 'ENOSYS'); | ||
} | ||
try { | ||
fs.utimesSync('foobarbaz', atime, mtime); | ||
@@ -65,7 +54,7 @@ } catch (error: any) { | ||
test('utimes works', async () => { | ||
await runTest(new Date('1982/09/10 13:37:00'), new Date('1982/09/10 13:37:00')); | ||
await runTest(new Date(), new Date()); | ||
await runTest(123456.789, 123456.789); | ||
await test('new Date(...)', () => runTest(new Date('1982/09/10 13:37:00'), new Date('1982/09/10 13:37:00'))); | ||
await test('new Date()', () => runTest(new Date(), new Date())); | ||
await test('number', () => runTest(123456.789, 123456.789)); | ||
const stats = fs.statSync(path); | ||
await runTest(stats.atime, stats.mtime); | ||
await test('from stats', () => runTest(stats.atime, stats.mtime)); | ||
}); | ||
@@ -72,0 +61,0 @@ |
876334
23354