Skip to content

Commit

Permalink
Fs: use bigint version of file stats, fixes #366 #365 (#367)
Browse files Browse the repository at this point in the history
Note: only the ino & dev are used as bigint, other numeric inputs are converted as Numbers
so there may be other limitations (length for eg.). But changing length to bigint would
require lots more work so this should be done in another PR.
  • Loading branch information
warpdesign authored Jan 27, 2023
1 parent d30736c commit 1d13e06
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 60 deletions.
6 changes: 3 additions & 3 deletions src/services/Fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export function registerFs(fs: Fs): void {
}

export interface FileID {
ino: number
dev: number
ino: bigint
dev: bigint
}

export interface FileDescriptor {
Expand Down Expand Up @@ -71,7 +71,7 @@ export const ExeMaskUser = 0o0100

export type FileType = 'exe' | 'img' | 'arc' | 'snd' | 'vid' | 'doc' | 'cod' | ''

export function MakeId(stats: { ino: number; dev: number }): FileID {
export function MakeId(stats: { ino: bigint; dev: bigint }): FileID {
return {
ino: stats.ino,
dev: stats.dev,
Expand Down
12 changes: 6 additions & 6 deletions src/services/__tests__/Fs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { MakeId, ExeMaskAll, ExeMaskGroup, ExeMaskUser, filetype, sameID, FileID
describe('makeId', () => {
it('should return FileID from stats', () => {
const stats = {
ino: 123,
dev: 456,
ino: 123n,
dev: 456n,
fullname: 'foo',
}

Expand All @@ -19,13 +19,13 @@ describe('makeId', () => {

describe('sameID', () => {
const id1: FileID = {
dev: 10,
ino: 5,
dev: 10n,
ino: 5n,
}

const id2: FileID = {
dev: 28,
ino: 32,
dev: 28n,
ino: 32n,
}

it('should return true if ino & dev are identical', () => {
Expand Down
24 changes: 12 additions & 12 deletions src/services/__tests__/FsSort.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const files: Array<FileDescriptor> = [
isDir: true,
readonly: false,
id: {
ino: 0,
dev: 1,
ino: 0n,
dev: 1n,
},
isSym: false,
target: '',
Expand All @@ -35,8 +35,8 @@ const files: Array<FileDescriptor> = [
isDir: false,
readonly: false,
id: {
ino: 1,
dev: 1,
ino: 1n,
dev: 1n,
},
isSym: false,
target: '',
Expand All @@ -55,8 +55,8 @@ const files: Array<FileDescriptor> = [
isDir: false,
readonly: false,
id: {
ino: 2,
dev: 1,
ino: 2n,
dev: 1n,
},
isSym: false,
target: '',
Expand All @@ -75,8 +75,8 @@ const files: Array<FileDescriptor> = [
isDir: false,
readonly: false,
id: {
ino: 3,
dev: 1,
ino: 3n,
dev: 1n,
},
isSym: false,
target: '',
Expand All @@ -88,24 +88,24 @@ describe('sorting methods', () => {
it('sort by Name/Asc', () => {
const sortMethod = getSortMethod('name', 'asc')
const sorted_ids = files.sort(sortMethod).map((file) => file.id.ino)
expect(sorted_ids).toEqual([2, 0, 1, 3])
expect(sorted_ids).toEqual([2n, 0n, 1n, 3n])
})

it('sort by Name/Desc', () => {
const sortMethod = getSortMethod('name', 'desc')
const sorted_ids = files.sort(sortMethod).map((file) => file.id.ino)
expect(sorted_ids).toEqual([3, 1, 0, 2])
expect(sorted_ids).toEqual([3n, 1n, 0n, 2n])
})

it('sort by Size/Asc', () => {
const sortMethod = getSortMethod('size', 'asc')
const sorted_ids = files.sort(sortMethod).map((file) => file.id.ino)
expect(sorted_ids).toEqual([1, 0, 3, 2])
expect(sorted_ids).toEqual([1n, 0n, 3n, 2n])
})

it('sort by Size/Asc', () => {
const sortMethod = getSortMethod('size', 'desc')
const sorted_ids = files.sort(sortMethod).map((file) => file.id.ino)
expect(sorted_ids).toEqual([2, 3, 0, 1])
expect(sorted_ids).toEqual([2n, 3n, 0n, 1n])
})
})
4 changes: 2 additions & 2 deletions src/services/plugins/FsFtp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ class Client {
isSym: false,
target: null,
id: {
ino: mDate.getTime(),
dev: new Date().getTime(),
ino: BigInt(mDate.getTime()),
dev: BigInt(new Date().getTime()),
},
}
return file
Expand Down
34 changes: 18 additions & 16 deletions src/services/plugins/FsLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ export class LocalApi implements FsApi {
}

async isDir(path: string, transferId = -1): Promise<boolean> {
const lstat = fs.lstatSync(path)
const stat = fs.statSync(path)
const lstat = fs.lstatSync(path, { bigint: true })
const stat = fs.statSync(path, { bigint: true })
return stat.isDirectory() || lstat.isDirectory()
}

Expand All @@ -208,7 +208,7 @@ export class LocalApi implements FsApi {
async stat(fullPath: string, transferId = -1): Promise<FileDescriptor> {
try {
const format = path.parse(fullPath)
const stats = fs.lstatSync(fullPath)
const stats = fs.lstatSync(fullPath, { bigint: true })
const file: FileDescriptor = {
dir: format.dir,
fullname: format.base,
Expand All @@ -217,12 +217,13 @@ export class LocalApi implements FsApi {
cDate: stats.ctime,
mDate: stats.mtime,
bDate: stats.birthtime,
length: stats.size,
mode: stats.mode,
length: Number(stats.size),
mode: Number(stats.mode),
isDir: stats.isDirectory(),
readonly: false,
type:
(!stats.isDirectory() && filetype(stats.mode, stats.gid, stats.uid, format.ext.toLowerCase())) ||
(!stats.isDirectory() &&
filetype(Number(stats.mode), Number(stats.gid), Number(stats.uid), format.ext.toLowerCase())) ||
'',
isSym: stats.isSymbolicLink(),
target: (stats.isSymbolicLink() && fs.readlinkSync(fullPath)) || null,
Expand Down Expand Up @@ -289,16 +290,16 @@ export class LocalApi implements FsApi {
static fileFromPath(fullPath: string): FileDescriptor {
const format = path.parse(fullPath)
let name = fullPath
let stats: Partial<fs.Stats> = null
let stats: Partial<fs.BigIntStats> = null
let targetStats = null

try {
// do not follow symlinks first
stats = fs.lstatSync(fullPath)
stats = fs.lstatSync(fullPath, { bigint: true })
if (stats.isSymbolicLink()) {
// get link target path first
name = fs.readlinkSync(fullPath)
targetStats = fs.statSync(fullPath)
targetStats = fs.statSync(fullPath, { bigint: true })
}
} catch (err) {
console.warn('error getting stats for', fullPath, err)
Expand All @@ -310,12 +311,12 @@ export class LocalApi implements FsApi {
ctime: new Date(),
mtime: new Date(),
birthtime: new Date(),
size: stats ? stats.size : 0,
size: stats ? stats.size : 0n,
isDirectory: (): boolean => isDir,
mode: -1,
mode: -1n,
isSymbolicLink: (): boolean => isSymLink,
ino: 0,
dev: 0,
ino: 0n,
dev: 0n,
}
}

Expand All @@ -330,12 +331,13 @@ export class LocalApi implements FsApi {
cDate: stats.ctime,
mDate: stats.mtime,
bDate: stats.birthtime,
length: stats.size,
mode: mode,
length: Number(stats.size),
mode: Number(mode),
isDir: targetStats ? targetStats.isDirectory() : stats.isDirectory(),
readonly: false,
type:
(!(targetStats ? targetStats.isDirectory() : stats.isDirectory()) && filetype(mode, 0, 0, extension)) ||
(!(targetStats ? targetStats.isDirectory() : stats.isDirectory()) &&
filetype(Number(mode), 0, 0, extension)) ||
'',
isSym: stats.isSymbolicLink(),
target: (stats.isSymbolicLink() && name) || null,
Expand Down
41 changes: 20 additions & 21 deletions src/services/plugins/FsVirtual.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { fs, vol } from 'memfs'
import type { Stats, ReadStream } from 'fs'
import type { ReadStream, BigIntStats } from 'fs'
import { Transform, TransformCallback } from 'stream'
import * as path from 'path'
// import mkdir = require('mkdirp')
// import del = require('del')

import { FsApi, FileDescriptor, Credentials, Fs, filetype, MakeId } from '$src/services/Fs'
// import { size } from '$src/utils/size'
import { throttle } from '$src/utils/throttle'
import { isWin, HOME_DIR } from '$src/utils/platform'
import { VirtualWatch } from '$src/services/plugins/VirtualWatch'
Expand Down Expand Up @@ -191,8 +188,8 @@ export class VirtualApi implements FsApi {
}

async isDir(path: string, transferId = -1): Promise<boolean> {
const lstat = vol.lstatSync(path)
const stat = vol.statSync(path)
const lstat = vol.lstatSync(path, { bigint: true })
const stat = vol.statSync(path, { bigint: true })
return stat.isDirectory() || lstat.isDirectory()
}

Expand All @@ -212,7 +209,7 @@ export class VirtualApi implements FsApi {
async stat(fullPath: string, transferId = -1): Promise<FileDescriptor> {
try {
const format = path.parse(fullPath)
const stats = vol.lstatSync(fullPath)
const stats = vol.lstatSync(fullPath, { bigint: true })
const file: FileDescriptor = {
dir: format.dir,
fullname: format.base,
Expand All @@ -221,12 +218,13 @@ export class VirtualApi implements FsApi {
cDate: stats.ctime,
mDate: stats.mtime,
bDate: stats.birthtime,
length: stats.size,
mode: stats.mode,
length: Number(stats.size),
mode: Number(stats.mode),
isDir: stats.isDirectory(),
readonly: false,
type:
(!stats.isDirectory() && filetype(stats.mode, stats.gid, stats.uid, format.ext.toLowerCase())) ||
(!stats.isDirectory() &&
filetype(Number(stats.mode), Number(stats.gid), Number(stats.uid), format.ext.toLowerCase())) ||
'',
isSym: stats.isSymbolicLink(),
target: (stats.isSymbolicLink() && vol.readlinkSync(fullPath)) || null,
Expand Down Expand Up @@ -291,16 +289,16 @@ export class VirtualApi implements FsApi {
static fileFromPath(fullPath: string): FileDescriptor {
const format = path.parse(fullPath)
let name = fullPath
let stats: Partial<Stats> = null
let stats: Partial<BigIntStats> = null
let targetStats = null

try {
// do not follow symlinks first
stats = vol.lstatSync(fullPath)
stats = vol.lstatSync(fullPath, { bigint: true })
if (stats.isSymbolicLink()) {
// get link target path first
name = vol.readlinkSync(fullPath) as string
targetStats = vol.statSync(fullPath)
targetStats = vol.statSync(fullPath, { bigint: true })
}
} catch (err) {
console.warn('error getting stats for', fullPath, err)
Expand All @@ -312,12 +310,12 @@ export class VirtualApi implements FsApi {
ctime: new Date(),
mtime: new Date(),
birthtime: new Date(),
size: stats ? stats.size : 0,
size: stats ? stats.size : 0n,
isDirectory: (): boolean => isDir,
mode: -1,
mode: -1n,
isSymbolicLink: (): boolean => isSymLink,
ino: 0,
dev: 0,
ino: 0n,
dev: 0n,
}
}

Expand All @@ -332,12 +330,13 @@ export class VirtualApi implements FsApi {
cDate: stats.ctime,
mDate: stats.mtime,
bDate: stats.birthtime,
length: stats.size,
mode: mode,
length: Number(stats.size),
mode: Number(mode),
isDir: targetStats ? targetStats.isDirectory() : stats.isDirectory(),
readonly: false,
type:
(!(targetStats ? targetStats.isDirectory() : stats.isDirectory()) && filetype(mode, 0, 0, extension)) ||
(!(targetStats ? targetStats.isDirectory() : stats.isDirectory()) &&
filetype(Number(mode), 0, 0, extension)) ||
'',
isSym: stats.isSymbolicLink(),
target: (stats.isSymbolicLink() && name) || null,
Expand Down Expand Up @@ -481,7 +480,7 @@ export class VirtualApi implements FsApi {

export function FolderExists(path: string): boolean {
try {
return vol.existsSync(path) && vol.lstatSync(path).isDirectory()
return vol.existsSync(path) && vol.lstatSync(path, { bigint: true }).isDirectory()
} catch (err) {
return false
}
Expand Down

0 comments on commit 1d13e06

Please sign in to comment.