├── .gitattributes ├── .prettierrc ├── binding.js ├── test └── fixtures │ └── .gitignore ├── .gitignore ├── CMakeLists.txt ├── lib ├── errors.d.ts ├── constants.d.ts ├── errors.js └── constants.js ├── .clang-format ├── README.md ├── NOTICE ├── .github └── workflows │ ├── test.yml │ └── prebuild.yml ├── package.json ├── promises.js ├── promises.d.ts ├── LICENSE ├── test.js ├── index.d.ts ├── index.js └── binding.c /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | "prettier-config-holepunch" 2 | -------------------------------------------------------------------------------- /binding.js: -------------------------------------------------------------------------------- 1 | module.exports = require.addon() 2 | -------------------------------------------------------------------------------- /test/fixtures/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | sandbox.js 3 | sandbox 4 | coverage 5 | build 6 | prebuilds 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 4.0) 2 | 3 | find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare) 4 | 5 | project(bare_fs C) 6 | 7 | add_bare_module(bare_fs) 8 | 9 | target_sources( 10 | ${bare_fs} 11 | PRIVATE 12 | binding.c 13 | ) 14 | -------------------------------------------------------------------------------- /lib/errors.d.ts: -------------------------------------------------------------------------------- 1 | declare class FileError extends Error { 2 | private constructor(msg: string) 3 | 4 | readonly code: string 5 | readonly operation?: string 6 | readonly path?: string 7 | readonly destination?: string 8 | readonly fd?: number 9 | } 10 | 11 | export = FileError 12 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | AlignAfterOpenBracket: BlockIndent 2 | AlignConsecutiveMacros: Consecutive 3 | AlignEscapedNewlines: DontAlign 4 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 5 | AlwaysBreakAfterReturnType: All 6 | BinPackArguments: false 7 | BinPackParameters: false 8 | ContinuationIndentWidth: 2 9 | ColumnLimit: 0 10 | SpaceAfterCStyleCast: true 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bare-fs 2 | 3 | Native file system operations for Javascript. 4 | 5 | ``` 6 | npm i bare-fs 7 | ``` 8 | 9 | ## Usage 10 | 11 | ```js 12 | const fs = require('bare-fs') 13 | 14 | const fd = await fs.open('hello.txt') 15 | 16 | const buffer = Buffer.alloc(1024) 17 | 18 | try { 19 | const length = await fs.read(fd, buffer) 20 | 21 | console.log('Read', length, 'bytes') 22 | } finally { 23 | await fs.close(fd) 24 | } 25 | ``` 26 | 27 | ## License 28 | 29 | Apache-2.0 30 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Holepunch Inc 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | jobs: 10 | test: 11 | strategy: 12 | matrix: 13 | include: 14 | - os: ubuntu-latest 15 | platform: linux 16 | arch: x64 17 | - os: macos-latest 18 | platform: darwin 19 | arch: arm64 20 | - os: windows-latest 21 | platform: win32 22 | arch: x64 23 | runs-on: ${{ matrix.os }} 24 | name: ${{ matrix.platform }}-${{ matrix.arch }} 25 | steps: 26 | - uses: actions/checkout@v4 27 | - uses: actions/setup-node@v4 28 | with: 29 | node-version: lts/* 30 | - run: npm install -g bare-runtime bare-make 31 | - run: npm install 32 | - run: bare-make generate --platform ${{ matrix.platform }} --arch ${{ matrix.arch }} --debug 33 | - run: bare-make build 34 | - run: bare-make install 35 | - run: npm test 36 | -------------------------------------------------------------------------------- /lib/constants.d.ts: -------------------------------------------------------------------------------- 1 | declare const constants: { 2 | O_RDWR: number 3 | O_RDONLY: number 4 | O_WRONLY: number 5 | O_CREAT: number 6 | O_TRUNC: number 7 | O_APPEND: number 8 | 9 | F_OK: number 10 | R_OK: number 11 | W_OK: number 12 | X_OK: number 13 | 14 | S_IFMT: number 15 | S_IFREG: number 16 | S_IFDIR: number 17 | S_IFCHR: number 18 | S_IFLNK: number 19 | S_IFBLK: number 20 | S_IFIFO: number 21 | S_IFSOCK: number 22 | 23 | S_IRUSR: number 24 | S_IWUSR: number 25 | S_IXUSR: number 26 | S_IRGRP: number 27 | S_IWGRP: number 28 | S_IXGRP: number 29 | S_IROTH: number 30 | S_IWOTH: number 31 | S_IXOTH: number 32 | 33 | UV_DIRENT_UNKNOWN: number 34 | UV_DIRENT_FILE: number 35 | UV_DIRENT_DIR: number 36 | UV_DIRENT_LINK: number 37 | UV_DIRENT_FIFO: number 38 | UV_DIRENT_SOCKET: number 39 | UV_DIRENT_CHAR: number 40 | UV_DIRENT_BLOCK: number 41 | 42 | COPYFILE_EXCL: number 43 | COPYFILE_FICLONE: number 44 | COPYFILE_FICLONE_FORCE: number 45 | UV_FS_SYMLINK_DIR: number 46 | UV_FS_SYMLINK_JUNCTION: number 47 | } 48 | 49 | export = constants 50 | -------------------------------------------------------------------------------- /lib/errors.js: -------------------------------------------------------------------------------- 1 | const os = require('bare-os') 2 | 3 | module.exports = class FileError extends Error { 4 | constructor(msg, opts = {}) { 5 | const { code, operation = null, path = null, destination = null, fd = -1 } = opts 6 | 7 | if (operation !== null) msg += describe(operation, opts) 8 | 9 | super(`${code}: ${msg}`) 10 | 11 | this.code = code 12 | 13 | if (operation !== null) this.operation = operation 14 | if (path !== null) this.path = path 15 | if (destination !== null) this.destination = destination 16 | if (fd !== -1) this.fd = fd 17 | } 18 | 19 | get name() { 20 | return 'FileError' 21 | } 22 | 23 | // For Node.js compatibility 24 | get errno() { 25 | return os.constants.errnos[this.code] 26 | } 27 | 28 | // For Node.js compatibility 29 | get syscall() { 30 | return this.operation 31 | } 32 | 33 | // For Node.js compatibility 34 | get dest() { 35 | return this.destination 36 | } 37 | } 38 | 39 | function describe(operation, opts) { 40 | const { path = null, destination = null, fd = -1 } = opts 41 | 42 | let result = `, ${operation}` 43 | 44 | if (path !== null) { 45 | result += ` ${JSON.stringify(path)}` 46 | 47 | if (destination !== null) { 48 | result += ` -> ${JSON.stringify(destination)}` 49 | } 50 | } else if (fd !== -1) { 51 | result += ` ${fd}` 52 | } 53 | 54 | return result 55 | } 56 | -------------------------------------------------------------------------------- /lib/constants.js: -------------------------------------------------------------------------------- 1 | const binding = require('../binding') 2 | 3 | module.exports = { 4 | O_RDWR: binding.O_RDWR, 5 | O_RDONLY: binding.O_RDONLY, 6 | O_WRONLY: binding.O_WRONLY, 7 | O_CREAT: binding.O_CREAT, 8 | O_TRUNC: binding.O_TRUNC, 9 | O_APPEND: binding.O_APPEND, 10 | 11 | F_OK: binding.F_OK || 0, 12 | R_OK: binding.R_OK || 0, 13 | W_OK: binding.W_OK || 0, 14 | X_OK: binding.X_OK || 0, 15 | 16 | S_IFMT: binding.S_IFMT, 17 | S_IFREG: binding.S_IFREG, 18 | S_IFDIR: binding.S_IFDIR, 19 | S_IFCHR: binding.S_IFCHR, 20 | S_IFLNK: binding.S_IFLNK, 21 | S_IFBLK: binding.S_IFBLK || 0, 22 | S_IFIFO: binding.S_IFIFO || 0, 23 | S_IFSOCK: binding.S_IFSOCK || 0, 24 | 25 | S_IRUSR: binding.S_IRUSR || 0, 26 | S_IWUSR: binding.S_IWUSR || 0, 27 | S_IXUSR: binding.S_IXUSR || 0, 28 | S_IRGRP: binding.S_IRGRP || 0, 29 | S_IWGRP: binding.S_IWGRP || 0, 30 | S_IXGRP: binding.S_IXGRP || 0, 31 | S_IROTH: binding.S_IROTH || 0, 32 | S_IWOTH: binding.S_IWOTH || 0, 33 | S_IXOTH: binding.S_IXOTH || 0, 34 | 35 | UV_DIRENT_UNKNOWN: binding.UV_DIRENT_UNKNOWN, 36 | UV_DIRENT_FILE: binding.UV_DIRENT_FILE, 37 | UV_DIRENT_DIR: binding.UV_DIRENT_DIR, 38 | UV_DIRENT_LINK: binding.UV_DIRENT_LINK, 39 | UV_DIRENT_FIFO: binding.UV_DIRENT_FIFO, 40 | UV_DIRENT_SOCKET: binding.UV_DIRENT_SOCKET, 41 | UV_DIRENT_CHAR: binding.UV_DIRENT_CHAR, 42 | UV_DIRENT_BLOCK: binding.UV_DIRENT_BLOCK, 43 | 44 | COPYFILE_EXCL: binding.UV_FS_COPYFILE_EXCL, 45 | COPYFILE_FICLONE: binding.UV_FS_COPYFILE_FICLONE, 46 | COPYFILE_FICLONE_FORCE: binding.UV_FS_COPYFILE_FICLONE_FORCE, 47 | UV_FS_SYMLINK_DIR: binding.UV_FS_SYMLINK_DIR, 48 | UV_FS_SYMLINK_JUNCTION: binding.UV_FS_SYMLINK_JUNCTION 49 | } 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bare-fs", 3 | "version": "4.5.2", 4 | "description": "Native file system operations for Javascript", 5 | "exports": { 6 | "./package": "./package.json", 7 | ".": { 8 | "types": "./index.d.ts", 9 | "default": "./index.js" 10 | }, 11 | "./promises": { 12 | "types": "./promises.d.ts", 13 | "default": "./promises.js" 14 | }, 15 | "./constants": { 16 | "types": "./lib/constants.d.ts", 17 | "default": "./lib/constants.js" 18 | } 19 | }, 20 | "files": [ 21 | "index.js", 22 | "index.d.ts", 23 | "promises.js", 24 | "promises.d.ts", 25 | "binding.c", 26 | "binding.js", 27 | "CMakeLists.txt", 28 | "lib", 29 | "prebuilds" 30 | ], 31 | "addon": true, 32 | "scripts": { 33 | "test": "prettier . --check && bare test.js" 34 | }, 35 | "repository": { 36 | "type": "git", 37 | "url": "git+https://github.com/holepunchto/bare-fs.git" 38 | }, 39 | "author": "Holepunch", 40 | "license": "Apache-2.0", 41 | "bugs": { 42 | "url": "https://github.com/holepunchto/bare-fs/issues" 43 | }, 44 | "homepage": "https://github.com/holepunchto/bare-fs#readme", 45 | "engines": { 46 | "bare": ">=1.16.0" 47 | }, 48 | "dependencies": { 49 | "bare-events": "^2.5.4", 50 | "bare-path": "^3.0.0", 51 | "bare-stream": "^2.6.4", 52 | "bare-url": "^2.2.2", 53 | "fast-fifo": "^1.3.2" 54 | }, 55 | "devDependencies": { 56 | "bare-buffer": "^3.0.2", 57 | "bare-crypto": "^1.11.2", 58 | "brittle": "^3.1.1", 59 | "cmake-bare": "^1.1.7", 60 | "prettier": "^3.4.1", 61 | "prettier-config-holepunch": "^2.0.0" 62 | }, 63 | "peerDependencies": { 64 | "bare-buffer": "*" 65 | }, 66 | "peerDependenciesMeta": { 67 | "bare-buffer": { 68 | "optional": true 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /promises.js: -------------------------------------------------------------------------------- 1 | const EventEmitter = require('bare-events') 2 | const fs = require('.') 3 | 4 | class FileHandle extends EventEmitter { 5 | constructor(fd) { 6 | this.fd = fd 7 | } 8 | 9 | async close() { 10 | await fs.close(fd) 11 | 12 | this.fd = -1 13 | this.emit('close') 14 | } 15 | 16 | async read(buffer, ...args) { 17 | return { 18 | bytesRead: await fs.read(this.fd, buffer, ...args), 19 | buffer 20 | } 21 | } 22 | 23 | async readv(buffers, ...args) { 24 | return { 25 | bytesRead: await fs.readv(this.fd, buffers, ...args), 26 | buffers 27 | } 28 | } 29 | 30 | async write(buffer, ...args) { 31 | return { 32 | bytesWritten: await fs.write(this.fd, buffer, ...args), 33 | buffer 34 | } 35 | } 36 | 37 | async writev(buffers, ...args) { 38 | return { 39 | bytesWritten: await fs.writev(this.fd, buffers, ...args), 40 | buffers 41 | } 42 | } 43 | 44 | async stat() { 45 | return fs.fstat(this.fd) 46 | } 47 | 48 | async chmod(mode) { 49 | await fs.fchmod(this.fd, mode) 50 | } 51 | 52 | createReadStream(opts) { 53 | return fs.createReadStream(null, { ...opts, fd: this.fd }) 54 | } 55 | 56 | createWriteStream(opts) { 57 | return fs.createWriteStream(null, { ...opts, fd: this.fd }) 58 | } 59 | 60 | async [Symbol.asyncDispose]() { 61 | await this.close() 62 | } 63 | } 64 | 65 | exports.open = async function open(filepath, flags, mode) { 66 | return new FileHandle(await fs.open(filepath, flags, mode)) 67 | } 68 | 69 | exports.access = fs.access 70 | exports.appendFile = fs.appendFile 71 | exports.chmod = fs.chmod 72 | exports.constants = fs.constants 73 | exports.copyFile = fs.copyFile 74 | exports.cp = fs.cp 75 | exports.lstat = fs.lstat 76 | exports.mkdir = fs.mkdir 77 | exports.opendir = fs.opendir 78 | exports.readFile = fs.readFile 79 | exports.readdir = fs.readdir 80 | exports.readlink = fs.readlink 81 | exports.realpath = fs.realpath 82 | exports.rename = fs.rename 83 | exports.rm = fs.rm 84 | exports.rmdir = fs.rmdir 85 | exports.stat = fs.stat 86 | exports.symlink = fs.symlink 87 | exports.unlink = fs.unlink 88 | exports.utimes = fs.utimes 89 | exports.watch = fs.watch 90 | exports.writeFile = fs.writeFile 91 | -------------------------------------------------------------------------------- /.github/workflows/prebuild.yml: -------------------------------------------------------------------------------- 1 | name: Prebuild 2 | on: 3 | workflow_dispatch: 4 | jobs: 5 | prebuild: 6 | strategy: 7 | matrix: 8 | include: 9 | - os: ubuntu-22.04 10 | platform: linux 11 | arch: x64 12 | - os: ubuntu-22.04-arm 13 | platform: linux 14 | arch: arm64 15 | - os: ubuntu-24.04 16 | platform: android 17 | arch: x64 18 | - os: ubuntu-24.04 19 | platform: android 20 | arch: ia32 21 | - os: ubuntu-24.04 22 | platform: android 23 | arch: arm64 24 | - os: ubuntu-24.04 25 | platform: android 26 | arch: arm 27 | - os: macos-14 28 | platform: darwin 29 | arch: x64 30 | - os: macos-14 31 | platform: darwin 32 | arch: arm64 33 | - os: macos-14 34 | platform: ios 35 | arch: arm64 36 | - os: macos-14 37 | platform: ios 38 | arch: arm64 39 | tags: -simulator 40 | flags: --simulator 41 | - os: macos-14 42 | platform: ios 43 | arch: x64 44 | tags: -simulator 45 | flags: --simulator 46 | - os: windows-2022 47 | platform: win32 48 | arch: x64 49 | - os: windows-2022 50 | platform: win32 51 | arch: arm64 52 | runs-on: ${{ matrix.os }} 53 | name: ${{ matrix.platform }}-${{ matrix.arch }}${{ matrix.tags }} 54 | steps: 55 | - uses: actions/checkout@v4 56 | - uses: actions/setup-node@v4 57 | with: 58 | node-version: lts/* 59 | - run: npm install -g bare-runtime bare-make 60 | - run: npm install 61 | - run: bare-make generate --platform ${{ matrix.platform }} --arch ${{ matrix.arch }} ${{ matrix.flags }} 62 | - run: bare-make build 63 | - run: bare-make install 64 | - uses: actions/upload-artifact@v4 65 | with: 66 | name: ${{ matrix.platform }}-${{ matrix.arch }}${{ matrix.tags }} 67 | path: prebuilds/* 68 | merge: 69 | runs-on: ubuntu-latest 70 | needs: prebuild 71 | steps: 72 | - uses: actions/download-artifact@v4 73 | with: 74 | path: prebuilds 75 | merge-multiple: true 76 | - uses: actions/upload-artifact@v4 77 | with: 78 | name: prebuilds 79 | path: prebuilds 80 | -------------------------------------------------------------------------------- /promises.d.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter, { EventMap } from 'bare-events' 2 | import Buffer, { BufferEncoding } from 'bare-buffer' 3 | import { 4 | constants, 5 | AppendFileOptions, 6 | CpOptions, 7 | Dir, 8 | MkdirOptions, 9 | OpendirOptions, 10 | Path, 11 | ReadFileOptions, 12 | ReadStream, 13 | ReadStreamOptions, 14 | ReaddirOptions, 15 | ReadlinkOptions, 16 | RealpathOptions, 17 | RmOptions, 18 | Stats, 19 | Watcher, 20 | WatcherOptions, 21 | WriteFileOptions, 22 | WriteStream, 23 | WriteStreamOptions 24 | } from '.' 25 | 26 | export { constants } 27 | 28 | interface FileHandleEvents extends EventMap { 29 | close: [] 30 | } 31 | 32 | interface FileHandle extends EventEmitter, AsyncDisposable { 33 | close(): Promise 34 | 35 | read( 36 | buffer: Buffer | ArrayBufferView, 37 | offset?: number, 38 | len?: number, 39 | pos?: number 40 | ): Promise 41 | 42 | readv(buffers: ArrayBufferView[], position?: number): Promise 43 | 44 | write( 45 | data: Buffer | ArrayBufferView, 46 | offset?: number, 47 | len?: number, 48 | pos?: number 49 | ): Promise 50 | 51 | write(data: string, pos?: number, encoding?: BufferEncoding): Promise 52 | 53 | stat(): Promise 54 | 55 | chmod(mode: string | number): Promise 56 | 57 | createReadStream(opts?: ReadStreamOptions): ReadStream 58 | 59 | createWriteStream(opts?: WriteStreamOptions): WriteStream 60 | } 61 | 62 | declare class FileHandle { 63 | private constructor(fd: number) 64 | } 65 | 66 | export function open( 67 | filepath: Path, 68 | flags?: Flag | number, 69 | mode?: string | number 70 | ): Promise 71 | 72 | export function access(filepath: Path, mode?: number): Promise 73 | 74 | export function appendFile( 75 | filepath: Path, 76 | data: string | Buffer | ArrayBufferView, 77 | opts?: AppendFileOptions 78 | ): Promise 79 | 80 | export function appendFile( 81 | filepath: Path, 82 | data: string | Buffer | ArrayBufferView, 83 | encoding: BufferEncoding 84 | ): Promise 85 | 86 | export function chmod(filepath: Path, mode: string | number): Promise 87 | 88 | export function copyFile(src: Path, dst: Path, mode?: number): Promise 89 | 90 | export function cp(src: Path, dst: Path, opts?: CpOptions): Promise 91 | 92 | export function lstat(filepath: Path): Promise 93 | 94 | export function mkdir(filepath: Path, opts?: MkdirOptions): Promise 95 | 96 | export function mkdir(filepath: Path, mode: number): Promise 97 | 98 | export function opendir( 99 | filepath: Path, 100 | opts: OpendirOptions & { encoding?: BufferEncoding } 101 | ): Promise> 102 | 103 | export function opendir( 104 | filepath: Path, 105 | opts: OpendirOptions & { encoding: 'buffer' } 106 | ): Promise> 107 | 108 | export function opendir(filepath: Path, opts: OpendirOptions): Promise 109 | 110 | export function opendir(filepath: Path, encoding: BufferEncoding): Promise> 111 | 112 | export function opendir(filepath: Path, encoding: 'buffer'): Promise> 113 | 114 | export function opendir(filepath: Path, encoding: BufferEncoding | 'buffer'): Promise 115 | 116 | export function opendir(filepath: Path): Promise> 117 | 118 | export function readFile( 119 | filepath: Path, 120 | opts: ReadFileOptions & { encoding: BufferEncoding } 121 | ): Promise 122 | 123 | export function readFile( 124 | filepath: Path, 125 | opts: ReadFileOptions & { encoding?: 'buffer' } 126 | ): Promise 127 | 128 | export function readFile(filepath: Path, opts: ReadFileOptions): Promise 129 | 130 | export function readFile(filepath: Path, encoding: BufferEncoding): Promise 131 | 132 | export function readFile(filepath: Path, encoding: 'buffer'): Promise 133 | 134 | export function readFile( 135 | filepath: Path, 136 | encoding?: BufferEncoding | 'buffer' 137 | ): Promise 138 | 139 | export function readFile(filepath: Path): Promise 140 | 141 | export function readdir( 142 | filepath: Path, 143 | opts: ReaddirOptions & { encoding?: BufferEncoding } 144 | ): Promise[] | string[]> 145 | 146 | export function readdir( 147 | filepath: Path, 148 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true } 149 | ): Promise[]> 150 | 151 | export function readdir( 152 | filepath: Path, 153 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false } 154 | ): Promise 155 | 156 | export function readdir( 157 | filepath: Path, 158 | opts: ReaddirOptions & { encoding: 'buffer' } 159 | ): Promise[] | Buffer[]> 160 | 161 | export function readdir( 162 | filepath: Path, 163 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true } 164 | ): Promise[]> 165 | 166 | export function readdir( 167 | filepath: Path, 168 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false } 169 | ): Promise 170 | 171 | export function readdir( 172 | filepath: Path, 173 | opts: ReaddirOptions & { withFileTypes: true } 174 | ): Promise[]> 175 | 176 | export function readdir( 177 | filepath: Path, 178 | opts: ReaddirOptions & { withFileTypes?: false } 179 | ): Promise 180 | 181 | export function readdir(filepath: Path, opts: ReaddirOptions): Promise 182 | 183 | export function readdir(filepath: Path, encoding: BufferEncoding): Promise 184 | 185 | export function readdir(filepath: Path, encoding: 'buffer'): Promise 186 | 187 | export function readdir( 188 | filepath: Path, 189 | encoding: BufferEncoding | 'buffer' 190 | ): Promise 191 | 192 | export function readdir(filepath: Path): Promise 193 | 194 | export function readlink( 195 | filepath: Path, 196 | opts: ReadlinkOptions & { encoding?: BufferEncoding } 197 | ): Promise 198 | 199 | export function readlink( 200 | filepath: Path, 201 | opts: ReadlinkOptions & { encoding: 'buffer' } 202 | ): Promise 203 | 204 | export function readlink(filepath: Path, opts: ReadlinkOptions): Promise 205 | 206 | export function readlink(filepath: Path, encoding: BufferEncoding): Promise 207 | 208 | export function readlink(filepath: Path, encoding: 'buffer'): Promise 209 | 210 | export function readlink( 211 | filepath: Path, 212 | encoding: BufferEncoding | 'buffer' 213 | ): Promise 214 | 215 | export function readlink(filepath: Path): Promise 216 | 217 | export function realpath( 218 | filepath: Path, 219 | opts: RealpathOptions & { encoding?: BufferEncoding } 220 | ): Promise 221 | 222 | export function realpath( 223 | filepath: Path, 224 | opts: RealpathOptions & { encoding: 'buffer' } 225 | ): Promise 226 | 227 | export function realpath(filepath: Path, opts: RealpathOptions): Promise 228 | 229 | export function realpath(filepath: Path, encoding: BufferEncoding): Promise 230 | 231 | export function realpath(filepath: Path, encoding: 'buffer'): Promise 232 | 233 | export function realpath( 234 | filepath: Path, 235 | encoding: BufferEncoding | 'buffer' 236 | ): Promise 237 | 238 | export function realpath(filepath: Path): Promise 239 | 240 | export function rename(src: Path, dst: Path): Promise 241 | 242 | export function rm(filepath: Path, opts?: RmOptions): Promise 243 | 244 | export function rmdir(filepath: Path): Promise 245 | 246 | export function stat(filepath: Path): Promise 247 | 248 | export function symlink(target: Path, filepath: Path, type?: string | number): Promise 249 | 250 | export function unlink(filepath: Path): Promise 251 | 252 | export function watch( 253 | filepath: Path, 254 | opts: WatcherOptions & { encoding?: BufferEncoding } 255 | ): Watcher 256 | 257 | export function watch( 258 | filepath: Path, 259 | opts: WatcherOptions & { encoding: 'buffer' } 260 | ): Watcher 261 | 262 | export function watch(filepath: Path, opts: WatcherOptions): Watcher 263 | 264 | export function watch(filepath: Path, encoding: BufferEncoding): Watcher 265 | 266 | export function watch(filepath: Path, encoding: 'buffer'): Watcher 267 | 268 | export function watch(filepath: Path, encoding: BufferEncoding | 'buffer'): Watcher 269 | 270 | export function watch(filepath: Path): Watcher 271 | 272 | export function writeFile( 273 | filepath: Path, 274 | data: string | Buffer | ArrayBufferView, 275 | opts?: WriteFileOptions 276 | ): Promise 277 | 278 | export function writeFile( 279 | filepath: Path, 280 | data: string | Buffer | ArrayBufferView, 281 | encoding: BufferEncoding 282 | ): Promise 283 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const test = require('brittle') 2 | const path = require('bare-path') 3 | const crypto = require('bare-crypto') 4 | const fs = require('.') 5 | 6 | const isWindows = Bare.platform === 'win32' 7 | 8 | test('open + close', async (t) => { 9 | t.plan(2) 10 | 11 | const file = await withFile(t, 'test/fixtures/foo.txt') 12 | 13 | fs.open(file, (err, fd) => { 14 | t.absent(err, 'opened') 15 | 16 | fs.close(fd, (err) => { 17 | t.absent(err, 'closed') 18 | }) 19 | }) 20 | }) 21 | 22 | test('open + close, long path', async (t) => { 23 | t.plan(2) 24 | 25 | const dir = await withDir( 26 | t, 27 | `test/fixtures/${'a'.repeat(128)}/${'b'.repeat(128)}/${'c'.repeat(128)}` 28 | ) 29 | 30 | const file = await withFile(t, `${dir}/${'d'.repeat(128)}.txt`) 31 | 32 | fs.open(file, (err, fd) => { 33 | t.absent(err, 'opened') 34 | 35 | fs.close(fd, (err) => { 36 | t.absent(err, 'closed') 37 | }) 38 | }) 39 | }) 40 | 41 | test('open + close sync', async (t) => { 42 | const file = await withFile(t, 'test/fixtures/foo.txt') 43 | 44 | const fd = fs.openSync(file) 45 | 46 | fs.closeSync(fd) 47 | 48 | t.pass() 49 | }) 50 | 51 | test('access', async (t) => { 52 | t.plan(1) 53 | 54 | const file = await withFile(t, 'test/fixtures/foo.txt') 55 | 56 | fs.access(file, (err) => { 57 | t.absent(err, 'accessed') 58 | }) 59 | }) 60 | 61 | test('access, file missing', async (t) => { 62 | t.plan(1) 63 | 64 | fs.access('test/fixtures/foo.txt', (err) => { 65 | t.ok(err, 'file missing') 66 | }) 67 | }) 68 | 69 | test('access, is executable', { skip: isWindows }, async (t) => { 70 | t.plan(1) 71 | 72 | const file = await withFile(t, 'test/fixtures/foo.txt', Buffer.alloc(0), { 73 | mode: 0o755 74 | }) 75 | 76 | fs.access(file, fs.constants.X_OK, (err) => { 77 | t.absent(err) 78 | }) 79 | }) 80 | 81 | test('access, is not executable', { skip: isWindows }, async (t) => { 82 | t.plan(1) 83 | 84 | const file = await withFile(t, 'test/fixtures/foo.txt') 85 | 86 | fs.access(file, fs.constants.X_OK, (err) => { 87 | t.ok(err) 88 | }) 89 | }) 90 | 91 | test('access sync', async (t) => { 92 | const file = await withFile(t, 'test/fixtures/foo.txt') 93 | 94 | fs.accessSync(file) 95 | }) 96 | 97 | test('access async, file missing', async (t) => { 98 | try { 99 | fs.accessSync('test/fixtures/foo.txt') 100 | 101 | t.fail('should fail') 102 | } catch { 103 | t.pass('file missing') 104 | } 105 | }) 106 | 107 | test('read', async (t) => { 108 | t.plan(5) 109 | 110 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 111 | 112 | fs.open(file, (err, fd) => { 113 | t.absent(err, 'opened') 114 | 115 | const data = Buffer.alloc(4) 116 | 117 | fs.read(fd, data, 0, 4, 0, (err, len) => { 118 | t.absent(err) 119 | t.is(len, 4) 120 | t.alike(data, Buffer.from('foo\n')) 121 | 122 | fs.close(fd, (err) => { 123 | t.absent(err, 'closed') 124 | }) 125 | }) 126 | }) 127 | }) 128 | 129 | test('read + offset', async (t) => { 130 | t.plan(5) 131 | 132 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 133 | 134 | fs.open(file, (err, fd) => { 135 | t.absent(err, 'opened') 136 | 137 | const data = Buffer.alloc(4) 138 | 139 | fs.read(fd, data, 2, 2, 0, (err, len) => { 140 | t.absent(err) 141 | t.is(len, 2) 142 | t.alike(data, Buffer.from('\x00\x00fo')) 143 | 144 | fs.close(fd, (err) => { 145 | t.absent(err, 'closed') 146 | }) 147 | }) 148 | }) 149 | }) 150 | 151 | test('read + position', async (t) => { 152 | t.plan(5) 153 | 154 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 155 | 156 | fs.open(file, (err, fd) => { 157 | t.absent(err, 'opened') 158 | 159 | const data = Buffer.alloc(2) 160 | 161 | fs.read(fd, data, 0, 2, 2, (err, len) => { 162 | t.absent(err) 163 | t.is(len, 2) 164 | t.alike(data, Buffer.from('o\n')) 165 | 166 | fs.close(fd, (err) => { 167 | t.absent(err, 'closed') 168 | }) 169 | }) 170 | }) 171 | }) 172 | 173 | test('read + current position', async (t) => { 174 | t.plan(8) 175 | 176 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 177 | 178 | fs.open(file, (err, fd) => { 179 | t.absent(err, 'opened') 180 | 181 | const data = Buffer.alloc(2) 182 | 183 | fs.read(fd, data, 0, 2, -1, (err, len) => { 184 | t.absent(err) 185 | t.is(len, 2) 186 | t.alike(data, Buffer.from('fo')) 187 | 188 | fs.read(fd, data, 0, 2, -1, (err, len) => { 189 | t.absent(err) 190 | t.is(len, 2) 191 | t.alike(data, Buffer.from('o\n')) 192 | 193 | fs.close(fd, (err) => { 194 | t.absent(err, 'closed') 195 | }) 196 | }) 197 | }) 198 | }) 199 | }) 200 | 201 | test('read out of buffer bounds', async (t) => { 202 | t.plan(6) 203 | 204 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 205 | 206 | fs.open(file, (err, fd) => { 207 | t.absent(err, 'opened') 208 | 209 | const data = Buffer.alloc(4) 210 | 211 | fs.read(fd, data, 0, 4, 0, (err, len) => { 212 | t.absent(err) 213 | t.is(len, 4) 214 | 215 | fs.read(fd, data, 6, 4, 0, (err, len) => { 216 | t.absent(err) 217 | t.is(len, 0) 218 | 219 | fs.close(fd, (err) => { 220 | t.absent(err, 'closed') 221 | }) 222 | }) 223 | }) 224 | }) 225 | }) 226 | 227 | test('read sync', async (t) => { 228 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 229 | 230 | const fd = fs.openSync(file) 231 | 232 | const data = Buffer.alloc(4) 233 | const len = fs.readSync(fd, data, 0, 4, 0) 234 | t.is(len, 4) 235 | t.alike(data, Buffer.from('foo\n')) 236 | 237 | fs.closeSync(fd) 238 | }) 239 | 240 | test('write', async (t) => { 241 | t.plan(7) 242 | 243 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 244 | 245 | fs.open(file, 'w+', (err, fd) => { 246 | t.absent(err, 'opened') 247 | 248 | const data = Buffer.from('foo\n') 249 | 250 | fs.write(fd, data, 0, 4, 0, (err, len) => { 251 | t.absent(err) 252 | t.is(len, 4) 253 | 254 | const data = Buffer.alloc(4) 255 | 256 | fs.read(fd, data, 0, 4, 0, (err, len) => { 257 | t.absent(err) 258 | t.is(len, 4) 259 | t.alike(data, Buffer.from('foo\n')) 260 | 261 | fs.close(fd, (err) => { 262 | t.absent(err, 'closed') 263 | }) 264 | }) 265 | }) 266 | }) 267 | }) 268 | 269 | test('write + offset', async (t) => { 270 | t.plan(7) 271 | 272 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 273 | 274 | fs.open(file, 'w+', (err, fd) => { 275 | t.absent(err, 'opened') 276 | 277 | const data = Buffer.from('foo\n') 278 | 279 | fs.write(fd, data, 2, 2, 2, (err, len) => { 280 | t.absent(err) 281 | t.is(len, 2) 282 | 283 | const data = Buffer.alloc(4) 284 | 285 | fs.read(fd, data, 0, 4, 0, (err, len) => { 286 | t.absent(err) 287 | t.is(len, 4) 288 | t.alike(data, Buffer.from('\x00\x00o\n')) 289 | 290 | fs.close(fd, (err) => { 291 | t.absent(err, 'closed') 292 | }) 293 | }) 294 | }) 295 | }) 296 | }) 297 | 298 | test('write + position', async (t) => { 299 | t.plan(7) 300 | 301 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 302 | 303 | fs.open(file, 'w+', (err, fd) => { 304 | t.absent(err, 'opened') 305 | 306 | const data = Buffer.from('o\n') 307 | 308 | fs.write(fd, data, 0, 2, 2, (err, len) => { 309 | t.absent(err) 310 | t.is(len, 2) 311 | 312 | const data = Buffer.alloc(4) 313 | 314 | fs.read(fd, data, 0, 4, 0, (err, len) => { 315 | t.absent(err) 316 | t.is(len, 4) 317 | t.alike(data, Buffer.from('\x00\x00o\n')) 318 | 319 | fs.close(fd, (err) => { 320 | t.absent(err, 'closed') 321 | }) 322 | }) 323 | }) 324 | }) 325 | }) 326 | 327 | test('write + current position', async (t) => { 328 | t.plan(9) 329 | 330 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 331 | 332 | fs.open(file, 'w+', (err, fd) => { 333 | t.absent(err, 'opened') 334 | 335 | const data = Buffer.from('foo\n') 336 | 337 | fs.write(fd, data, 0, 2, -1, (err, len) => { 338 | t.absent(err) 339 | t.is(len, 2) 340 | 341 | fs.write(fd, data, 2, 2, -1, (err, len) => { 342 | t.absent(err) 343 | t.is(len, 2) 344 | 345 | const data = Buffer.alloc(4) 346 | 347 | fs.read(fd, data, 0, 4, 0, (err, len) => { 348 | t.absent(err) 349 | t.is(len, 4) 350 | t.alike(data, Buffer.from('foo\n')) 351 | 352 | fs.close(fd, (err) => { 353 | t.absent(err, 'closed') 354 | }) 355 | }) 356 | }) 357 | }) 358 | }) 359 | }) 360 | 361 | test('write out of buffer bounds', async (t) => { 362 | t.plan(6) 363 | 364 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 365 | 366 | fs.open(file, 'w+', (err, fd) => { 367 | t.absent(err, 'opened') 368 | 369 | const data = Buffer.from('foo\n') 370 | 371 | fs.write(fd, data, 0, 6, 0, (err, len) => { 372 | t.absent(err) 373 | t.is(len, 4) 374 | 375 | fs.write(fd, data, 6, 4, 0, (err, len) => { 376 | t.absent(err) 377 | t.is(len, 0) 378 | 379 | fs.close(fd, (err) => { 380 | t.absent(err, 'closed') 381 | }) 382 | }) 383 | }) 384 | }) 385 | }) 386 | 387 | test('write string', async (t) => { 388 | t.plan(4) 389 | 390 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 391 | 392 | fs.open(file, 'w+', (err, fd) => { 393 | t.absent(err, 'opened') 394 | 395 | const data = 'foo\n' 396 | 397 | fs.write(fd, data, (err, len) => { 398 | t.absent(err) 399 | t.is(len, 4) 400 | 401 | fs.close(fd, (err) => { 402 | t.absent(err, 'closed') 403 | }) 404 | }) 405 | }) 406 | }) 407 | 408 | test('write sync', async (t) => { 409 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 410 | 411 | const fd = fs.openSync(file, 'w+') 412 | 413 | let data 414 | let len 415 | 416 | data = Buffer.from('foo\n') 417 | len = fs.writeSync(fd, data, 0, 4, 0) 418 | t.is(len, 4) 419 | 420 | data = Buffer.alloc(4) 421 | len = fs.readSync(fd, data, 0, 4, 0) 422 | t.is(len, 4) 423 | t.alike(data, Buffer.from('foo\n')) 424 | 425 | fs.closeSync(fd) 426 | }) 427 | 428 | test('stat', async (t) => { 429 | t.plan(2) 430 | 431 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 432 | 433 | fs.stat(file, (err, st) => { 434 | t.absent(err, 'stat') 435 | for (const [key, value] of Object.entries(st)) t.comment(key, value) 436 | t.ok(st) 437 | }) 438 | }) 439 | 440 | test('stat sync', async (t) => { 441 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 442 | 443 | const st = fs.statSync(file) 444 | 445 | for (const [key, value] of Object.entries(st)) t.comment(key, value) 446 | t.ok(st) 447 | }) 448 | 449 | test('fstat', async (t) => { 450 | t.plan(4) 451 | 452 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 453 | 454 | fs.open(file, (err, fd) => { 455 | t.absent(err, 'opened') 456 | 457 | fs.fstat(fd, (err, st) => { 458 | t.absent(err, 'stat') 459 | for (const [key, value] of Object.entries(st)) t.comment(key, value) 460 | t.ok(st) 461 | 462 | fs.close(fd, (err) => { 463 | t.absent(err, 'closed') 464 | }) 465 | }) 466 | }) 467 | }) 468 | 469 | test('fstat sync', async (t) => { 470 | const file = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 471 | 472 | const fd = fs.openSync(file) 473 | 474 | const st = fs.fstatSync(fd) 475 | 476 | for (const [key, value] of Object.entries(st)) t.comment(key, value) 477 | t.ok(st) 478 | 479 | fs.closeSync(fd) 480 | }) 481 | 482 | test('lstat', async (t) => { 483 | t.plan(3) 484 | 485 | const target = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 486 | const link = await withSymlink(t, 'test/fixtures/foo-link.txt', target) 487 | 488 | fs.lstat(link, (err, st) => { 489 | t.absent(err, 'stat') 490 | t.ok(st.isSymbolicLink()) 491 | for (const [key, value] of Object.entries(st)) t.comment(key, value) 492 | t.ok(st) 493 | }) 494 | }) 495 | 496 | test('lstat sync', async (t) => { 497 | const target = await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 498 | const link = await withSymlink(t, 'test/fixtures/foo-link.txt', target) 499 | 500 | const st = fs.lstatSync(link) 501 | 502 | t.ok(st.isSymbolicLink()) 503 | for (const [key, value] of Object.entries(st)) t.comment(key, value) 504 | t.ok(st) 505 | }) 506 | 507 | test('utimes', async (t) => { 508 | t.plan(3) 509 | 510 | const file = await withFile(t, 'test/fixtures/foo.txt') 511 | 512 | const oldStat = fs.statSync(file) 513 | 514 | const future = new Date(Date.now() + 1000) 515 | fs.utimes(file, future, future, (err) => { 516 | t.absent(err) 517 | 518 | const newStat = fs.statSync(file) 519 | 520 | t.ok(oldStat.atimeMs < newStat.atimeMs) 521 | t.ok(oldStat.mtimeMs < newStat.mtimeMs) 522 | }) 523 | }) 524 | 525 | test('utimes sync', async (t) => { 526 | const file = await withFile(t, 'test/fixtures/foo.txt') 527 | 528 | const oldStat = fs.statSync(file) 529 | 530 | const future = Date.now() / 1000 + 1000 531 | fs.utimesSync(file, future, future) 532 | 533 | const newStat = fs.statSync(file) 534 | 535 | t.ok(oldStat.atimeMs < newStat.atimeMs) 536 | t.ok(oldStat.mtimeMs < newStat.mtimeMs) 537 | }) 538 | 539 | test('opendir + close', async (t) => { 540 | t.plan(2) 541 | 542 | await withDir(t, 'test/fixtures/dir') 543 | 544 | fs.opendir('test/fixtures/dir', (err, dir) => { 545 | t.absent(err, 'opened') 546 | 547 | dir.close((err) => { 548 | t.absent(err, 'closed') 549 | }) 550 | }) 551 | }) 552 | 553 | test('opendirSync + closeSync', async (t) => { 554 | await withDir(t, 'test/fixtures/dir') 555 | 556 | const dir = fs.opendirSync('test/fixtures/dir') 557 | 558 | dir.closeSync() 559 | }) 560 | 561 | test('opendir + asyncIterator', async (t) => { 562 | t.plan(2) 563 | 564 | await withDir(t, 'test/fixtures/dir') 565 | await withFile(t, 'test/fixtures/dir/foo.txt', 'hello\n') 566 | 567 | fs.opendir('test/fixtures/dir', async (err, dir) => { 568 | t.absent(err, 'opened') 569 | 570 | for await (const entry of dir) { 571 | t.comment(entry) 572 | } 573 | 574 | t.pass('iterated') 575 | }) 576 | }) 577 | 578 | test('opendirSync + iterator', async (t) => { 579 | await withDir(t, 'test/fixtures/dir') 580 | await withFile(t, 'test/fixtures/dir/foo.txt', 'hello\n') 581 | 582 | const dir = fs.opendirSync('test/fixtures/dir') 583 | 584 | for (const entry of dir) { 585 | t.comment(entry) 586 | } 587 | 588 | t.pass('iterated') 589 | }) 590 | 591 | test('readdir', async (t) => { 592 | t.plan(2) 593 | 594 | await withDir(t, 'test/fixtures/dir') 595 | await withFile(t, 'test/fixtures/dir/foo.txt', 'hello\n') 596 | 597 | fs.readdir('test/fixtures/dir', (err, files) => { 598 | t.absent(err, 'read') 599 | 600 | for (const entry of files) { 601 | t.comment(entry) 602 | } 603 | 604 | t.pass('iterated') 605 | }) 606 | }) 607 | 608 | test('readdir + withFileTypes: true', async (t) => { 609 | t.plan(2) 610 | 611 | await withDir(t, 'test/fixtures/dir') 612 | await withFile(t, 'test/fixtures/dir/foo.txt', 'hello\n') 613 | 614 | fs.readdir('test/fixtures/dir', { withFileTypes: true }, (err, files) => { 615 | t.absent(err, 'read') 616 | 617 | for (const entry of files) { 618 | t.comment(entry) 619 | } 620 | 621 | t.pass('iterated') 622 | }) 623 | }) 624 | 625 | test('readdirSync', async (t) => { 626 | await withDir(t, 'test/fixtures/dir') 627 | await withFile(t, 'test/fixtures/dir/foo.txt', 'hello\n') 628 | 629 | const files = fs.readdirSync('test/fixtures/dir') 630 | 631 | for (const entry of files) { 632 | t.comment(entry) 633 | } 634 | 635 | t.pass('iterated') 636 | }) 637 | 638 | test('readdirSync + withFileTypes: true', async (t) => { 639 | await withDir(t, 'test/fixtures/dir') 640 | await withFile(t, 'test/fixtures/dir/foo.txt', 'hello\n') 641 | 642 | const files = fs.readdirSync('test/fixtures/dir', { withFileTypes: true }) 643 | 644 | for (const entry of files) { 645 | t.comment(entry) 646 | } 647 | 648 | t.pass('iterated') 649 | }) 650 | 651 | test('readFile, file missing', async (t) => { 652 | t.plan(1) 653 | 654 | fs.readFile('test/fixtures/foo.txt', (err) => { 655 | t.ok(err, 'file missing') 656 | }) 657 | }) 658 | 659 | test('writeFile + readFile', async (t) => { 660 | t.plan(3) 661 | 662 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 663 | 664 | fs.writeFile(file, Buffer.from('foo\n'), (err) => { 665 | t.absent(err) 666 | 667 | fs.readFile(file, (err, data) => { 668 | t.absent(err) 669 | t.alike(data, Buffer.from('foo\n')) 670 | }) 671 | }) 672 | }) 673 | 674 | test('appendFile + readFile', async (t) => { 675 | t.plan(4) 676 | 677 | const file = await withFile(t, 'test/fixtures/foo.txt', false) 678 | 679 | fs.appendFile(file, Buffer.from('foo\n'), (err) => { 680 | t.absent(err) 681 | 682 | fs.appendFile(file, Buffer.from('bar\n'), (err) => { 683 | t.absent(err) 684 | 685 | fs.readFile(file, (err, data) => { 686 | t.absent(err) 687 | t.alike(data, Buffer.from('foo\nbar\n')) 688 | }) 689 | }) 690 | }) 691 | }) 692 | 693 | test('mkdir', async (t) => { 694 | t.plan(3) 695 | 696 | const dir = await withDir(t, 'test/fixtures/foo', false) 697 | 698 | fs.mkdir(dir, (err) => { 699 | if (err) t.pass('dir exists') 700 | else t.pass('made dir') 701 | 702 | fs.stat(dir, (err, st) => { 703 | t.absent(err, 'stat') 704 | t.ok(st.isDirectory(), 'is dir') 705 | }) 706 | }) 707 | }) 708 | 709 | test('mkdir recursive', async (t) => { 710 | t.plan(3) 711 | 712 | await withDir(t, 'test/fixtures/foo', false) 713 | const dir = await withDir(t, 'test/fixtures/foo/bar/baz', false) 714 | 715 | fs.mkdir(dir, { recursive: true }, (err) => { 716 | t.absent(err, 'made dir') 717 | 718 | fs.stat(dir, (err, st) => { 719 | t.absent(err, 'stat') 720 | t.ok(st.isDirectory(), 'is dir') 721 | }) 722 | }) 723 | }) 724 | 725 | test('copyFile', async (t) => { 726 | t.plan(11) 727 | 728 | await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 729 | 730 | fs.copyFile('test/fixtures/foo.txt', 'test/fixtures/bar.txt', (err) => { 731 | t.absent(err, 'file copied') 732 | 733 | fs.open('test/fixtures/foo.txt', (err, fd) => { 734 | t.absent(err, 'original copy opened') 735 | 736 | const data = Buffer.alloc(4) 737 | 738 | fs.read(fd, data, 0, 4, 0, (err, len) => { 739 | t.absent(err, 'read original copy') 740 | t.is(len, 4) 741 | t.alike(data, Buffer.from('foo\n'), 'check original copy content') 742 | 743 | fs.close(fd, (err) => { 744 | t.absent(err, 'original copy closed') 745 | }) 746 | }) 747 | }) 748 | 749 | fs.open('test/fixtures/bar.txt', (err, fd) => { 750 | t.absent(err, 'new copy opened') 751 | 752 | const data = Buffer.alloc(4) 753 | 754 | fs.read(fd, data, 0, 4, 0, (err, len) => { 755 | t.absent(err, 'read new copy') 756 | t.is(len, 4) 757 | t.alike(data, Buffer.from('foo\n'), 'check new copy content') 758 | 759 | fs.close(fd, (err) => { 760 | t.absent(err, 'new copy closed') 761 | }) 762 | }) 763 | }) 764 | }) 765 | }) 766 | 767 | test('copyFileSync', async (t) => { 768 | t.plan(10) 769 | 770 | await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 771 | 772 | fs.copyFileSync('test/fixtures/foo.txt', 'test/fixtures/bar.txt') 773 | 774 | fs.open('test/fixtures/foo.txt', (err, fd) => { 775 | t.absent(err, 'original copy opened') 776 | 777 | const data = Buffer.alloc(4) 778 | 779 | fs.read(fd, data, 0, 4, 0, (err, len) => { 780 | t.absent(err, 'read original copy') 781 | t.is(len, 4) 782 | t.alike(data, Buffer.from('foo\n'), 'check original copy content') 783 | 784 | fs.close(fd, (err) => { 785 | t.absent(err, 'original copy closed') 786 | }) 787 | }) 788 | }) 789 | 790 | fs.open('test/fixtures/bar.txt', (err, fd) => { 791 | t.absent(err, 'new copy opened') 792 | 793 | const data = Buffer.alloc(4) 794 | 795 | fs.read(fd, data, 0, 4, 0, (err, len) => { 796 | t.absent(err, 'read new copy') 797 | t.is(len, 4) 798 | t.alike(data, Buffer.from('foo\n'), 'check new copy content') 799 | 800 | fs.close(fd, (err) => { 801 | t.absent(err, 'new copy closed') 802 | }) 803 | }) 804 | }) 805 | }) 806 | 807 | test('copyFile with COPYFILE_EXCL', async (t) => { 808 | t.plan(2) 809 | 810 | await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 811 | await withFile(t, 'test/fixtures/bar.txt', 'bar\n') 812 | 813 | fs.copyFile( 814 | 'test/fixtures/foo.txt', 815 | 'test/fixtures/bar.txt', 816 | fs.constants.COPYFILE_EXCL, 817 | (err) => { 818 | t.ok(err) 819 | t.is(err.code, 'EEXIST') 820 | } 821 | ) 822 | }) 823 | 824 | test('copyFileSync with COPYFILE_EXCL', async (t) => { 825 | t.plan(1) 826 | 827 | await withFile(t, 'test/fixtures/foo.txt', 'foo\n') 828 | await withFile(t, 'test/fixtures/bar.txt', 'bar\n') 829 | 830 | t.exception( 831 | () => 832 | fs.copyFileSync('test/fixtures/foo.txt', 'test/fixtures/bar.txt', fs.constants.COPYFILE_EXCL), 833 | /file already exists/ 834 | ) 835 | }) 836 | 837 | test('cp', async (t) => { 838 | t.plan(11) 839 | 840 | await withDir(t, 'test/fixtures/dir/foo/bar/baz') 841 | await withFile(t, 'test/fixtures/dir/foo/bar/baz/foo.txt', 'foo\n') 842 | 843 | await withDir(t, 'test/fixtures/dir2', false) 844 | 845 | fs.cp('test/fixtures/dir', 'test/fixtures/dir2', { recursive: true }, (err) => { 846 | t.absent(err, 'directory copied') 847 | 848 | fs.open('test/fixtures/dir/foo/bar/baz/foo.txt', (err, fd) => { 849 | t.absent(err, 'original copy opened') 850 | 851 | const data = Buffer.alloc(4) 852 | 853 | fs.read(fd, data, 0, 4, 0, (err, len) => { 854 | t.absent(err, 'read original copy') 855 | t.is(len, 4) 856 | t.alike(data, Buffer.from('foo\n'), 'check original copy content') 857 | 858 | fs.close(fd, (err) => { 859 | t.absent(err, 'original copy closed') 860 | }) 861 | }) 862 | }) 863 | 864 | fs.open('test/fixtures/dir2/foo/bar/baz/foo.txt', (err, fd) => { 865 | t.absent(err, 'new copy opened') 866 | 867 | const data = Buffer.alloc(4) 868 | 869 | fs.read(fd, data, 0, 4, 0, (err, len) => { 870 | t.absent(err, 'read new copy') 871 | t.is(len, 4) 872 | t.alike(data, Buffer.from('foo\n'), 'check new copy content') 873 | 874 | fs.close(fd, (err) => { 875 | t.absent(err, 'new copy closed') 876 | }) 877 | }) 878 | }) 879 | }) 880 | }) 881 | 882 | test('realpath', async (t) => { 883 | t.plan(2) 884 | 885 | await withDir(t, 'test/fixtures/foo') 886 | const link = await withSymlink(t, 'test/fixtures/foo-link', 'foo') 887 | 888 | fs.realpath(link, (err, link) => { 889 | t.absent(err) 890 | t.is(link, path.resolve('test/fixtures/foo')) 891 | }) 892 | }) 893 | 894 | test('realpath sync', async (t) => { 895 | await withDir(t, 'test/fixtures/foo') 896 | const link = await withSymlink(t, 'test/fixtures/foo-link', 'foo') 897 | 898 | t.is(fs.realpathSync(link), path.resolve('test/fixtures/foo')) 899 | }) 900 | 901 | test('readlink', async (t) => { 902 | t.plan(2) 903 | 904 | const target = await withDir(t, 'test/fixtures/foo') 905 | const link = await withSymlink(t, 'test/fixtures/foo-link', 'foo') 906 | 907 | fs.readlink(link, (err, link) => { 908 | t.absent(err) 909 | t.is(link, isWindows ? path.resolve(target) : 'foo') 910 | }) 911 | }) 912 | 913 | test('readlink sync', async (t) => { 914 | const target = await withDir(t, 'test/fixtures/foo') 915 | const link = await withSymlink(t, 'test/fixtures/foo-link', 'foo') 916 | 917 | t.is(fs.readlinkSync(link), isWindows ? path.resolve(target) : 'foo') 918 | }) 919 | 920 | test('symlink', async (t) => { 921 | t.plan(3) 922 | 923 | const target = await withDir(t, 'test/fixtures/foo') 924 | const link = await withSymlink(t, 'test/fixtures/foo-link') 925 | 926 | fs.symlink('foo', link, (err) => { 927 | t.absent(err) 928 | 929 | fs.readlink(link, (err, link) => { 930 | t.absent(err) 931 | t.is(link, isWindows ? path.resolve(target) : 'foo') 932 | }) 933 | }) 934 | }) 935 | 936 | test('symlink sync', async (t) => { 937 | const target = await withDir(t, 'test/fixtures/foo') 938 | const link = await withSymlink(t, 'test/fixtures/foo-link') 939 | 940 | fs.symlinkSync('foo', link) 941 | 942 | t.is(fs.readlinkSync(link), isWindows ? path.resolve(target) : 'foo') 943 | }) 944 | 945 | test('createReadStream', async (t) => { 946 | t.plan(1) 947 | 948 | const expected = crypto.randomBytes(1024 * 16 /* 16 KiB */) 949 | 950 | const file = await withFile(t, 'test/fixtures/foo', expected) 951 | 952 | const stream = fs.createReadStream(file) 953 | const read = [] 954 | 955 | stream 956 | .on('data', (data) => read.push(data)) 957 | .on('end', () => t.alike(Buffer.concat(read), expected)) 958 | }) 959 | 960 | test('createReadStream, large file', async (t) => { 961 | t.plan(1) 962 | 963 | const expected = crypto.randomBytes(1024 * 512 /* 512 KiB */) 964 | 965 | const file = await withFile(t, 'test/fixtures/foo', expected) 966 | 967 | const stream = fs.createReadStream(file) 968 | const read = [] 969 | 970 | stream 971 | .on('data', (data) => read.push(data)) 972 | .on('end', () => t.alike(Buffer.concat(read), expected)) 973 | }) 974 | 975 | test('createWriteStream', async (t) => { 976 | t.plan(2) 977 | 978 | const file = await withFile(t, 'test/fixtures/foo') 979 | 980 | const stream = fs.createWriteStream(file) 981 | 982 | stream.on('close', () => 983 | fs.readFile(file, (err, data) => { 984 | t.absent(err) 985 | t.alike(data, Buffer.from('hello world')) 986 | }) 987 | ) 988 | 989 | stream.write('hello') 990 | stream.end(' world') 991 | }) 992 | 993 | async function withFile(t, path, data = Buffer.alloc(0), opts = {}) { 994 | if (data) await fs.promises.writeFile(path, data, opts) 995 | 996 | t.teardown(() => fs.promises.rm(path, { force: true })) 997 | 998 | return path 999 | } 1000 | 1001 | async function withSymlink(t, path, target = false) { 1002 | if (target) { 1003 | try { 1004 | await fs.promises.rm(path) 1005 | } catch {} 1006 | 1007 | await fs.promises.symlink(target, path) 1008 | } 1009 | 1010 | t.teardown(() => fs.promises.rm(path, { force: true })) 1011 | 1012 | return path 1013 | } 1014 | 1015 | async function withDir(t, path, create = true) { 1016 | if (create) await fs.promises.mkdir(path, { recursive: true }) 1017 | 1018 | t.teardown(() => fs.promises.rm(path, { force: true, recursive: true })) 1019 | 1020 | return path 1021 | } 1022 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter, { EventMap } from 'bare-events' 2 | import Buffer, { BufferEncoding } from 'bare-buffer' 3 | import URL from 'bare-url' 4 | import { Readable, Writable } from 'bare-stream' 5 | import promises from './promises' 6 | import constants from './lib/constants' 7 | 8 | export { promises, constants } 9 | 10 | type Path = string | Buffer | URL 11 | 12 | type Flag = 13 | | 'a' 14 | | 'a+' 15 | | 'as' 16 | | 'as+' 17 | | 'ax' 18 | | 'ax+' 19 | | 'r' 20 | | 'r+' 21 | | 'rs' 22 | | 'rs+' 23 | | 'sa' 24 | | 'sa+' 25 | | 'sr' 26 | | 'sr+' 27 | | 'w' 28 | | 'w+' 29 | | 'wx' 30 | | 'wx+' 31 | | 'xa' 32 | | 'xa+' 33 | | 'xw' 34 | | 'xw+' 35 | 36 | interface Callback { 37 | (err: Error | null, ...args: A): void 38 | } 39 | 40 | export interface Dir 41 | extends Iterable, AsyncIterable { 42 | readonly path: string 43 | 44 | read(): Promise | null> 45 | read(cb: Callback<[dirent: Dirent | null]>): void 46 | readSync(): Dirent | null 47 | 48 | close(): Promise 49 | close(cb: Callback): void 50 | closeSync(): void 51 | } 52 | 53 | export class Dir { 54 | private constructor(path: string, handle: ArrayBuffer, opts?: OpendirOptions) 55 | } 56 | 57 | export interface Dirent { 58 | readonly path: string 59 | readonly name: T 60 | readonly type: number 61 | 62 | isFile(): boolean 63 | isDirectory(): boolean 64 | isSymbolicLink(): boolean 65 | isFIFO(): boolean 66 | isSocket(): boolean 67 | isCharacterDevice(): boolean 68 | isBlockDevice(): boolean 69 | } 70 | 71 | export class Dirent { 72 | private constructor(path: string, name: T, type: number) 73 | } 74 | 75 | export interface Stats { 76 | readonly dev: number 77 | readonly mode: number 78 | readonly nlink: number 79 | readonly uid: number 80 | readonly gid: number 81 | readonly rdev: number 82 | readonly blksize: number 83 | readonly ino: number 84 | readonly size: number 85 | readonly blocks: number 86 | readonly atimeMs: Date 87 | readonly mtimeMs: Date 88 | readonly ctimeMs: Date 89 | readonly birthtimeMs: Date 90 | 91 | isDirectory(): boolean 92 | isFile(): boolean 93 | isBlockDevice(): boolean 94 | isCharacterDevice(): boolean 95 | isFIFO(): boolean 96 | isSymbolicLink(): boolean 97 | isSocket(): boolean 98 | } 99 | 100 | export class Stats { 101 | private constructor( 102 | dev: number, 103 | mode: number, 104 | nlink: number, 105 | uid: number, 106 | gid: number, 107 | rdev: number, 108 | blksize: number, 109 | ino: number, 110 | size: number, 111 | blocks: number, 112 | atimeMs: number, 113 | mtimeMs: number, 114 | ctimeMs: number, 115 | birthtimeMs: number 116 | ) 117 | } 118 | 119 | export interface ReadStreamOptions { 120 | fd?: number 121 | flags?: Flag 122 | mode?: number 123 | start?: number 124 | end?: number 125 | } 126 | 127 | export interface ReadStream extends Readable { 128 | readonly path: string | null 129 | readonly fd: number 130 | readonly flags: Flag 131 | readonly mode: number 132 | } 133 | 134 | export class ReadStream { 135 | private constructor(path: Path | null, opts?: WriteStreamOptions) 136 | } 137 | 138 | export function createReadStream(path: Path | null, opts?: ReadStreamOptions): ReadStream 139 | 140 | export interface WriteStreamOptions { 141 | fd?: number 142 | flags?: Flag 143 | mode?: number 144 | } 145 | 146 | export interface WriteStream extends Writable { 147 | readonly path: string | null 148 | readonly fd: number 149 | readonly flags: Flag 150 | readonly mode: number 151 | } 152 | 153 | export class WriteStream { 154 | private constructor(path: Path | null, opts?: WriteStreamOptions) 155 | } 156 | 157 | export function createWriteStream(path: Path | null, opts?: WriteStreamOptions): WriteStream 158 | 159 | export interface WatcherOptions { 160 | persistent?: boolean 161 | recursive?: boolean 162 | encoding?: BufferEncoding | 'buffer' 163 | } 164 | 165 | export type WatcherEventType = 'rename' | 'change' 166 | 167 | export interface WatcherEvents extends EventMap { 168 | error: [err: Error] 169 | change: [eventType: WatcherEventType, filename: T] 170 | close: [] 171 | } 172 | 173 | export interface Watcher 174 | extends 175 | EventEmitter>, 176 | AsyncIterable<{ eventType: WatcherEventType; filename: T }> { 177 | close(): void 178 | ref(): void 179 | unref(): void 180 | } 181 | 182 | export class Watcher { 183 | private constructor(path: Path, opts: WatcherOptions) 184 | } 185 | 186 | export function access(filepath: Path, mode?: number): Promise 187 | 188 | export function access(filepath: Path, mode: number, cb: Callback): void 189 | 190 | export function access(filepath: Path, cb: Callback): void 191 | 192 | export function accessSync(filepath: Path, mode?: number): void 193 | 194 | export interface AppendFileOptions { 195 | encoding?: BufferEncoding 196 | flag?: string 197 | mode?: number 198 | } 199 | 200 | export function appendFile( 201 | filepath: Path, 202 | data: string | Buffer | ArrayBufferView, 203 | opts?: AppendFileOptions 204 | ): Promise 205 | 206 | export function appendFile( 207 | filepath: Path, 208 | data: string | Buffer | ArrayBufferView, 209 | encoding: BufferEncoding 210 | ): Promise 211 | 212 | export function appendFile( 213 | filepath: Path, 214 | data: string | Buffer | ArrayBufferView, 215 | opts: AppendFileOptions, 216 | cb: Callback 217 | ): void 218 | 219 | export function appendFile( 220 | filepath: Path, 221 | data: string | Buffer | ArrayBufferView, 222 | encoding: BufferEncoding, 223 | cb: Callback 224 | ): void 225 | 226 | export function appendFile( 227 | filepath: Path, 228 | data: string | Buffer | ArrayBufferView, 229 | cb: Callback 230 | ): void 231 | 232 | export function appendFileSync( 233 | filepath: Path, 234 | data: string | Buffer | ArrayBufferView, 235 | opts?: AppendFileOptions 236 | ): void 237 | 238 | export function appendFileSync( 239 | filepath: Path, 240 | data: string | Buffer | ArrayBufferView, 241 | encoding: BufferEncoding 242 | ): void 243 | 244 | export function chmod(filepath: Path, mode: string | number): Promise 245 | 246 | export function chmod(filepath: Path, mode: string | number, cb: Callback): void 247 | 248 | export function chmodSync(filepath: Path, mode: string | number): void 249 | 250 | export function close(fd: number): Promise 251 | 252 | export function close(fd: number, cb: Callback): void 253 | 254 | export function closeSync(fd: number): void 255 | 256 | export function copyFile(src: Path, dst: Path, mode?: number): Promise 257 | 258 | export function copyFile(src: Path, dst: Path, mode: number, cb: Callback): void 259 | 260 | export function copyFile(src: Path, dst: Path, cb: Callback): void 261 | 262 | export function copyFileSync(src: Path, dst: Path, mode?: number): void 263 | 264 | export interface CpOptions { 265 | recursive?: boolean 266 | } 267 | 268 | export function cp(src: Path, dst: Path, opts?: CpOptions): Promise 269 | 270 | export function cp(src: Path, dst: Path, opts: CpOptions, cb: Callback): void 271 | 272 | export function cp(src: Path, dst: Path, cb: Callback): void 273 | 274 | export function exists(filepath: Path): Promise 275 | 276 | export function exists(filepath: Path, cb: (exists: boolean) => void): void 277 | 278 | export function existsSync(filepath: Path): boolean 279 | 280 | export function fchmod(fd: number, mode: string | number): Promise 281 | 282 | export function fchmod(fd: number, mode: string | number, cb: Callback): void 283 | 284 | export function fchmodSync(fd: number, mode: string | number): void 285 | 286 | export function fstat(fd: number): Promise 287 | 288 | export function fstat(fd: number, cb: Callback<[stats: Stats | null]>): void 289 | 290 | export function fstatSync(fd: number): Stats 291 | 292 | export function ftruncate(fd: number, len?: number): Promise 293 | 294 | export function ftruncate(fd: number, len: number, cb: Callback): void 295 | 296 | export function ftruncate(fd: number, cb: Callback): void 297 | 298 | export function ftruncateSync(fd: number, len?: number): void 299 | 300 | export function lstat(filepath: Path): Promise 301 | 302 | export function lstat(filepath: Path, cb: Callback<[stats: Stats | null]>): void 303 | 304 | export function lstatSync(filepath: Path): Stats 305 | 306 | export interface MkdirOptions { 307 | mode?: number 308 | recursive?: boolean 309 | } 310 | 311 | export function mkdir(filepath: Path, opts?: MkdirOptions): Promise 312 | 313 | export function mkdir(filepath: Path, mode: number): Promise 314 | 315 | export function mkdir(filepath: Path, opts: MkdirOptions, cb: Callback): void 316 | 317 | export function mkdir(filepath: Path, mode: number, cb: Callback): void 318 | 319 | export function mkdir(filepath: Path, cb: Callback): void 320 | 321 | export function mkdirSync(filepath: Path, opts?: MkdirOptions): void 322 | 323 | export function mkdirSync(filepath: Path, mode: number): void 324 | 325 | export function open(filepath: Path, flags?: Flag | number, mode?: string | number): Promise 326 | 327 | export function open( 328 | filepath: Path, 329 | flags: Flag | number, 330 | mode: string | number, 331 | cb: Callback<[fd: number]> 332 | ): void 333 | 334 | export function open(filepath: Path, flags: Flag | number, cb: Callback<[fd: number]>): void 335 | 336 | export function open(filepath: Path, cb: Callback<[fd: number]>): void 337 | 338 | export function openSync(filepath: Path, flags?: Flag | number, mode?: string | number): number 339 | 340 | export interface OpendirOptions { 341 | encoding?: BufferEncoding | 'buffer' 342 | bufferSize?: number 343 | } 344 | 345 | export function opendir( 346 | filepath: Path, 347 | opts: OpendirOptions & { encoding?: BufferEncoding } 348 | ): Promise> 349 | 350 | export function opendir( 351 | filepath: Path, 352 | opts: OpendirOptions & { encoding: 'buffer' } 353 | ): Promise> 354 | 355 | export function opendir(filepath: Path, opts: OpendirOptions): Promise 356 | 357 | export function opendir(filepath: Path, encoding: BufferEncoding): Promise> 358 | 359 | export function opendir(filepath: Path, encoding: 'buffer'): Promise> 360 | 361 | export function opendir(filepath: Path, encoding: BufferEncoding | 'buffer'): Promise 362 | 363 | export function opendir(filepath: Path): Promise> 364 | 365 | export function opendir( 366 | filepath: Path, 367 | opts: OpendirOptions & { encoding?: BufferEncoding }, 368 | cb: Callback<[dir: Dir | null]> 369 | ): void 370 | 371 | export function opendir( 372 | filepath: Path, 373 | opts: OpendirOptions & { encoding: 'buffer' }, 374 | cb: Callback<[dir: Dir | null]> 375 | ): void 376 | 377 | export function opendir(filepath: Path, opts: OpendirOptions, cb: Callback<[dir: Dir | null]>): void 378 | 379 | export function opendir( 380 | filepath: Path, 381 | encoding: BufferEncoding, 382 | cb: Callback<[dir: Dir | null]> 383 | ): void 384 | 385 | export function opendir( 386 | filepath: Path, 387 | encoding: 'buffer', 388 | cb: Callback<[dir: Dir | null]> 389 | ): void 390 | 391 | export function opendir( 392 | filepath: Path, 393 | encoding: BufferEncoding | 'buffer', 394 | cb: Callback<[dir: Dir | null]> 395 | ): void 396 | 397 | export function opendir(filepath: Path, cb: Callback<[dir: Dir | null]>): void 398 | 399 | export function opendirSync( 400 | filepath: Path, 401 | opts: OpendirOptions & { encoding?: BufferEncoding } 402 | ): Dir 403 | 404 | export function opendirSync( 405 | filepath: Path, 406 | opts: OpendirOptions & { encoding: 'buffer' } 407 | ): Dir 408 | 409 | export function opendirSync(filepath: Path, opts: OpendirOptions): Dir 410 | 411 | export function opendirSync(filepath: Path, encoding: BufferEncoding): Dir 412 | 413 | export function opendirSync(filepath: Path, encoding: 'buffer'): Dir 414 | 415 | export function opendirSync(filepath: Path, encoding: BufferEncoding | 'buffer'): Dir 416 | 417 | export function opendirSync(filepath: Path): Dir 418 | 419 | export function read( 420 | fd: number, 421 | buffer: Buffer | ArrayBufferView, 422 | offset?: number, 423 | len?: number, 424 | pos?: number 425 | ): Promise 426 | 427 | export function read( 428 | fd: number, 429 | buffer: Buffer | ArrayBufferView, 430 | offset: number, 431 | len: number, 432 | pos: number, 433 | cb: Callback<[len: number]> 434 | ): void 435 | 436 | export function read( 437 | fd: number, 438 | buffer: Buffer | ArrayBufferView, 439 | offset: number, 440 | len: number, 441 | cb: Callback<[len: number]> 442 | ): void 443 | 444 | export function read( 445 | fd: number, 446 | buffer: Buffer | ArrayBufferView, 447 | offset: number, 448 | cb: Callback<[len: number]> 449 | ): void 450 | 451 | export function read( 452 | fd: number, 453 | buffer: Buffer | ArrayBufferView, 454 | cb: Callback<[len: number]> 455 | ): void 456 | 457 | export function readSync( 458 | fd: number, 459 | buffer: Buffer | ArrayBufferView, 460 | offset?: number, 461 | len?: number, 462 | pos?: number 463 | ): number 464 | 465 | export interface ReadFileOptions { 466 | encoding?: BufferEncoding | 'buffer' 467 | flag?: Flag 468 | } 469 | 470 | export function readFile( 471 | filepath: Path, 472 | opts: ReadFileOptions & { encoding: BufferEncoding } 473 | ): Promise 474 | 475 | export function readFile( 476 | filepath: Path, 477 | opts: ReadFileOptions & { encoding?: 'buffer' } 478 | ): Promise 479 | 480 | export function readFile(filepath: Path, opts: ReadFileOptions): Promise 481 | 482 | export function readFile(filepath: Path, encoding: BufferEncoding): Promise 483 | 484 | export function readFile(filepath: Path, encoding: 'buffer'): Promise 485 | 486 | export function readFile( 487 | filepath: Path, 488 | encoding?: BufferEncoding | 'buffer' 489 | ): Promise 490 | 491 | export function readFile(filepath: Path): Promise 492 | 493 | export function readFile( 494 | filepath: Path, 495 | opts: ReadFileOptions & { encoding: BufferEncoding }, 496 | cb: Callback<[buffer?: string]> 497 | ): void 498 | 499 | export function readFile( 500 | filepath: Path, 501 | opts: ReadFileOptions & { encoding?: 'buffer' }, 502 | cb: Callback<[buffer?: Buffer]> 503 | ): void 504 | 505 | export function readFile( 506 | filepath: Path, 507 | opts: ReadFileOptions, 508 | cb: Callback<[buffer?: string | Buffer]> 509 | ): void 510 | 511 | export function readFile( 512 | filepath: Path, 513 | encoding: BufferEncoding, 514 | cb: Callback<[buffer?: string]> 515 | ): void 516 | 517 | export function readFile(filepath: Path, encoding: 'buffer', cb: Callback<[buffer?: Buffer]>): void 518 | 519 | export function readFile( 520 | filepath: Path, 521 | encoding: BufferEncoding | 'buffer', 522 | cb: Callback<[buffer?: string | Buffer]> 523 | ): void 524 | 525 | export function readFile(filepath: Path, cb: Callback<[buffer?: Buffer]>): void 526 | 527 | export function readFileSync( 528 | filepath: Path, 529 | opts: ReadFileOptions & { encoding: BufferEncoding } 530 | ): string 531 | 532 | export function readFileSync( 533 | filepath: Path, 534 | opts: ReadFileOptions & { encoding?: 'buffer' } 535 | ): Buffer 536 | 537 | export function readFileSync(filepath: Path, opts: ReadFileOptions): string | Buffer 538 | 539 | export function readFileSync(filepath: Path, encoding: BufferEncoding): string 540 | 541 | export function readFileSync(filepath: Path, encoding: 'buffer'): Buffer 542 | 543 | export function readFileSync(filepath: Path, encoding?: BufferEncoding | 'buffer'): string | Buffer 544 | 545 | export function readFileSync(filepath: Path): Buffer 546 | 547 | export interface ReaddirOptions extends OpendirOptions { 548 | withFileTypes?: boolean 549 | } 550 | export function readdir( 551 | filepath: Path, 552 | opts: ReaddirOptions & { encoding?: BufferEncoding } 553 | ): Promise[] | string[]> 554 | 555 | export function readdir( 556 | filepath: Path, 557 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true } 558 | ): Promise[]> 559 | 560 | export function readdir( 561 | filepath: Path, 562 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false } 563 | ): Promise 564 | 565 | export function readdir( 566 | filepath: Path, 567 | opts: ReaddirOptions & { encoding: 'buffer' } 568 | ): Promise[] | Buffer[]> 569 | 570 | export function readdir( 571 | filepath: Path, 572 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true } 573 | ): Promise[]> 574 | 575 | export function readdir( 576 | filepath: Path, 577 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false } 578 | ): Promise 579 | 580 | export function readdir( 581 | filepath: Path, 582 | opts: ReaddirOptions & { withFileTypes: true } 583 | ): Promise[]> 584 | 585 | export function readdir( 586 | filepath: Path, 587 | opts: ReaddirOptions & { withFileTypes?: false } 588 | ): Promise 589 | 590 | export function readdir(filepath: Path, opts: ReaddirOptions): Promise 591 | 592 | export function readdir(filepath: Path, encoding: BufferEncoding): Promise 593 | 594 | export function readdir(filepath: Path, encoding: 'buffer'): Promise 595 | 596 | export function readdir( 597 | filepath: Path, 598 | encoding: BufferEncoding | 'buffer' 599 | ): Promise 600 | 601 | export function readdir(filepath: Path): Promise 602 | 603 | export function readdir( 604 | filepath: Path, 605 | opts: ReaddirOptions & { encoding?: BufferEncoding }, 606 | cb: Callback<[entries: Dir[] | string[] | null]> 607 | ): void 608 | 609 | export function readdir( 610 | filepath: Path, 611 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true }, 612 | cb: Callback<[entries: Dir[] | null]> 613 | ): void 614 | 615 | export function readdir( 616 | filepath: Path, 617 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false }, 618 | cb: Callback<[entries: string[] | null]> 619 | ): void 620 | 621 | export function readdir( 622 | filepath: Path, 623 | opts: ReaddirOptions & { encoding: 'buffer' }, 624 | cb: Callback<[entries: Dir[] | Buffer[] | null]> 625 | ): void 626 | 627 | export function readdir( 628 | filepath: Path, 629 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true }, 630 | cb: Callback<[entries: Dir[] | null]> 631 | ): void 632 | 633 | export function readdir( 634 | filepath: Path, 635 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false }, 636 | cb: Callback<[entries: Buffer[] | null]> 637 | ): void 638 | 639 | export function readdir( 640 | filepath: Path, 641 | opts: ReaddirOptions & { withFileTypes: true }, 642 | cb: Callback<[entries: Dir[] | null]> 643 | ): void 644 | 645 | export function readdir( 646 | filepath: Path, 647 | opts: ReaddirOptions & { withFileTypes?: false }, 648 | cb: Callback<[entries: string[] | Buffer[] | null]> 649 | ): void 650 | 651 | export function readdir( 652 | filepath: Path, 653 | opts: ReaddirOptions, 654 | cb: Callback<[entries: Dir[] | string[] | Buffer[] | null]> 655 | ): void 656 | 657 | export function readdir( 658 | filepath: Path, 659 | encoding: BufferEncoding, 660 | cb: Callback<[entries: string[] | null]> 661 | ): void 662 | 663 | export function readdir( 664 | filepath: Path, 665 | encoding: 'buffer', 666 | cb: Callback<[entries: Buffer[] | null]> 667 | ): void 668 | 669 | export function readdir( 670 | filepath: Path, 671 | encoding: BufferEncoding | 'buffer', 672 | cb: Callback<[entries: string[] | Buffer[] | null]> 673 | ): void 674 | 675 | export function readdir(filepath: Path, cb: Callback<[entries: string[] | null]>): void 676 | 677 | export function readdirSync( 678 | filepath: Path, 679 | opts: ReaddirOptions & { encoding?: BufferEncoding } 680 | ): Dir[] | string[] 681 | 682 | export function readdirSync( 683 | filepath: Path, 684 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes: true } 685 | ): Dir[] 686 | 687 | export function readdirSync( 688 | filepath: Path, 689 | opts: ReaddirOptions & { encoding?: BufferEncoding; withFileTypes?: false } 690 | ): string[] 691 | 692 | export function readdirSync( 693 | filepath: Path, 694 | opts: ReaddirOptions & { encoding: 'buffer' } 695 | ): Dir[] | Buffer[] 696 | 697 | export function readdirSync( 698 | filepath: Path, 699 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes: true } 700 | ): Dir[] 701 | 702 | export function readdirSync( 703 | filepath: Path, 704 | opts: ReaddirOptions & { encoding: 'buffer'; withFileTypes?: false } 705 | ): Buffer[] 706 | 707 | export function readdirSync( 708 | filepath: Path, 709 | opts: ReaddirOptions & { withFileTypes: true } 710 | ): Dir[] 711 | 712 | export function readdirSync( 713 | filepath: Path, 714 | opts: ReaddirOptions & { withFileTypes?: false } 715 | ): string[] | Buffer[] 716 | 717 | export function readdirSync(filepath: Path, opts: ReaddirOptions): Dir[] | string[] | Buffer[] 718 | 719 | export function readdirSync(filepath: Path, encoding: BufferEncoding): string[] 720 | 721 | export function readdirSync(filepath: Path, encoding: 'buffer'): Buffer[] 722 | 723 | export function readdirSync( 724 | filepath: Path, 725 | encoding: BufferEncoding | 'buffer' 726 | ): string[] | Buffer[] 727 | 728 | export function readdirSync(filepath: Path): string[] 729 | 730 | export interface ReadlinkOptions { 731 | encoding?: BufferEncoding | 'buffer' 732 | } 733 | 734 | export function readlink( 735 | filepath: Path, 736 | opts: ReadlinkOptions & { encoding?: BufferEncoding } 737 | ): Promise 738 | 739 | export function readlink( 740 | filepath: Path, 741 | opts: ReadlinkOptions & { encoding: 'buffer' } 742 | ): Promise 743 | 744 | export function readlink(filepath: Path, opts: ReadlinkOptions): Promise 745 | 746 | export function readlink(filepath: Path, encoding: BufferEncoding): Promise 747 | 748 | export function readlink(filepath: Path, encoding: 'buffer'): Promise 749 | 750 | export function readlink( 751 | filepath: Path, 752 | encoding: BufferEncoding | 'buffer' 753 | ): Promise 754 | 755 | export function readlink(filepath: Path): Promise 756 | 757 | export function readlink( 758 | filepath: Path, 759 | opts: ReadlinkOptions & { encoding?: BufferEncoding }, 760 | cb: Callback<[link: string | null]> 761 | ): void 762 | 763 | export function readlink( 764 | filepath: Path, 765 | opts: ReadlinkOptions & { encoding: 'buffer' }, 766 | cb: Callback<[link: Buffer | null]> 767 | ): void 768 | 769 | export function readlink( 770 | filepath: Path, 771 | opts: ReadlinkOptions, 772 | cb: Callback<[link: string | Buffer | null]> 773 | ): void 774 | 775 | export function readlink( 776 | filepath: Path, 777 | encoding: BufferEncoding, 778 | cb: Callback<[link: string | null]> 779 | ): void 780 | 781 | export function readlink( 782 | filepath: Path, 783 | encoding: 'buffer', 784 | cb: Callback<[link: Buffer | null]> 785 | ): void 786 | 787 | export function readlink( 788 | filepath: Path, 789 | encoding: BufferEncoding | 'buffer', 790 | cb: Callback<[link: string | Buffer | null]> 791 | ): void 792 | 793 | export function readlink(filepath: Path, cb: Callback<[link: string | null]>): void 794 | 795 | export function readlinkSync( 796 | filepath: Path, 797 | opts: ReadlinkOptions & { encoding?: BufferEncoding } 798 | ): string 799 | 800 | export function readlinkSync(filepath: Path, opts: ReadlinkOptions & { encoding: 'buffer' }): Buffer 801 | 802 | export function readlinkSync(filepath: Path, opts: ReadlinkOptions): string | Buffer 803 | 804 | export function readlinkSync(filepath: Path, encoding: BufferEncoding): string 805 | 806 | export function readlinkSync(filepath: Path, encoding: 'buffer'): Buffer 807 | 808 | export function readlinkSync(filepath: Path, encoding: BufferEncoding | 'buffer'): string | Buffer 809 | 810 | export function readlinkSync(filepath: Path): string 811 | 812 | export function readv(fd: number, buffers: ArrayBufferView[], position?: number): Promise 813 | 814 | export function readv( 815 | fd: number, 816 | buffers: ArrayBufferView[], 817 | position: number, 818 | cb: Callback<[len: number]> 819 | ): void 820 | 821 | export function readv(fd: number, buffers: ArrayBufferView[], cb: Callback<[len: number]>): void 822 | 823 | export function readvSync(fd: number, buffers: ArrayBufferView[], position?: number): number 824 | 825 | export interface RealpathOptions { 826 | encoding?: BufferEncoding | 'buffer' 827 | } 828 | 829 | export function realpath( 830 | filepath: Path, 831 | opts: RealpathOptions & { encoding?: BufferEncoding } 832 | ): Promise 833 | 834 | export function realpath( 835 | filepath: Path, 836 | opts: RealpathOptions & { encoding: 'buffer' } 837 | ): Promise 838 | 839 | export function realpath(filepath: Path, opts: RealpathOptions): Promise 840 | 841 | export function realpath(filepath: Path, encoding: BufferEncoding): Promise 842 | 843 | export function realpath(filepath: Path, encoding: 'buffer'): Promise 844 | 845 | export function realpath( 846 | filepath: Path, 847 | encoding: BufferEncoding | 'buffer' 848 | ): Promise 849 | 850 | export function realpath(filepath: Path): Promise 851 | 852 | export function realpath( 853 | filepath: Path, 854 | opts: RealpathOptions & { encoding?: BufferEncoding }, 855 | cb: Callback<[path: string | null]> 856 | ): void 857 | 858 | export function realpath( 859 | filepath: Path, 860 | opts: RealpathOptions & { encoding: 'buffer' }, 861 | cb: Callback<[path: Buffer | null]> 862 | ): void 863 | 864 | export function realpath( 865 | filepath: Path, 866 | opts: RealpathOptions, 867 | cb: Callback<[path: string | Buffer | null]> 868 | ): void 869 | 870 | export function realpath( 871 | filepath: Path, 872 | encoding: BufferEncoding, 873 | cb: Callback<[path: string | null]> 874 | ): void 875 | 876 | export function realpath( 877 | filepath: Path, 878 | encoding: 'buffer', 879 | cb: Callback<[path: Buffer | null]> 880 | ): void 881 | 882 | export function realpath( 883 | filepath: Path, 884 | encoding: BufferEncoding | 'buffer', 885 | cb: Callback<[path: string | Buffer | null]> 886 | ): void 887 | 888 | export function realpath(filepath: Path, cb: Callback<[path: string | null]>): void 889 | 890 | export function realpathSync( 891 | filepath: Path, 892 | opts: RealpathOptions & { encoding?: BufferEncoding } 893 | ): string 894 | 895 | export function realpathSync(filepath: Path, opts: RealpathOptions & { encoding: 'buffer' }): Buffer 896 | 897 | export function realpathSync(filepath: Path, opts: RealpathOptions): string | Buffer 898 | 899 | export function realpathSync(filepath: Path, encoding: BufferEncoding): string 900 | 901 | export function realpathSync(filepath: Path, encoding: 'buffer'): Buffer 902 | 903 | export function realpathSync(filepath: Path, encoding: BufferEncoding | 'buffer'): string | Buffer 904 | 905 | export function realpathSync(filepath: Path): string 906 | 907 | export function rename(src: string, dst: string): Promise 908 | 909 | export function rename(src: string, dst: string, cb: Callback): void 910 | 911 | export function renameSync(src: string, dst: string): void 912 | 913 | export interface RmOptions { 914 | force?: boolean 915 | recursive?: boolean 916 | } 917 | 918 | export function rm(filepath: Path, opts?: RmOptions): Promise 919 | 920 | export function rm(filepath: Path, opts: RmOptions, cb: Callback): void 921 | 922 | export function rm(filepath: Path, cb: Callback): void 923 | 924 | export function rmSync(filepath: Path, opts?: RmOptions): void 925 | 926 | export function rmdir(filepath: Path, cb: Callback): void 927 | 928 | export function rmdirSync(filepath: Path): void 929 | 930 | export function stat(filepath: Path): Promise 931 | 932 | export function stat(filepath: Path, cb: Callback<[stats: Stats | null]>): void 933 | 934 | export function statSync(filepath: Path): Stats 935 | 936 | export function symlink(target: Path, filepath: Path, type?: string | number): Promise 937 | 938 | export function symlink(target: Path, filepath: Path, type: string | number, cb: Callback): void 939 | 940 | export function symlink(target: string, filepath: Path, cb: Callback): void 941 | 942 | export function symlinkSync(target: string, filepath: Path, type?: string | number): void 943 | 944 | export function unlink(filepath: Path): Promise 945 | 946 | export function unlink(filepath: Path, cb: Callback): void 947 | 948 | export function unlinkSync(filepath: Path): void 949 | 950 | export function watch( 951 | filepath: Path, 952 | opts: WatcherOptions & { encoding?: BufferEncoding }, 953 | cb: (eventType: WatcherEventType, filename: string) => void 954 | ): Watcher 955 | 956 | export function watch( 957 | filepath: Path, 958 | opts: WatcherOptions & { encoding: 'buffer' }, 959 | cb: (eventType: WatcherEventType, filename: Buffer) => void 960 | ): Watcher 961 | 962 | export function watch( 963 | filepath: Path, 964 | opts: WatcherOptions, 965 | cb: (eventType: WatcherEventType, filename: string | Buffer) => void 966 | ): Watcher 967 | 968 | export function watch( 969 | filepath: Path, 970 | encoding: BufferEncoding, 971 | cb: (evenType: WatcherEventType, filename: string) => void 972 | ): Watcher 973 | 974 | export function watch( 975 | filepath: Path, 976 | encoding: 'buffer', 977 | cb: (evenType: WatcherEventType, filename: Buffer) => void 978 | ): Watcher 979 | 980 | export function watch( 981 | filepath: Path, 982 | encoding: BufferEncoding | 'buffer', 983 | cb: (evenType: WatcherEventType, filename: string | Buffer) => void 984 | ): Watcher 985 | 986 | export function watch( 987 | filepath: Path, 988 | cb: (eventType: WatcherEventType, filename: string) => void 989 | ): Watcher 990 | 991 | export function write( 992 | fd: number, 993 | data: Buffer | ArrayBufferView, 994 | offset?: number, 995 | len?: number, 996 | pos?: number 997 | ): Promise 998 | 999 | export function write( 1000 | fd: number, 1001 | data: string, 1002 | pos?: number, 1003 | encoding?: BufferEncoding 1004 | ): Promise 1005 | 1006 | export function write( 1007 | fd: number, 1008 | data: Buffer | ArrayBufferView, 1009 | offset: number, 1010 | len: number, 1011 | pos: number, 1012 | cb: Callback<[len: number]> 1013 | ): void 1014 | 1015 | export function write( 1016 | fd: number, 1017 | data: Buffer | ArrayBufferView, 1018 | offset: number, 1019 | len: number, 1020 | cb: Callback<[len: number]> 1021 | ): void 1022 | 1023 | export function write( 1024 | fd: number, 1025 | data: string, 1026 | pos: number, 1027 | encoding: BufferEncoding, 1028 | cb: Callback<[len: number]> 1029 | ): void 1030 | 1031 | export function write( 1032 | fd: number, 1033 | data: Buffer | ArrayBufferView, 1034 | offset: number, 1035 | cb: Callback<[len: number]> 1036 | ): void 1037 | 1038 | export function write(fd: number, data: string, pos: number, cb: Callback<[len: number]>): void 1039 | 1040 | export function write(fd: number, data: Buffer | ArrayBufferView, cb: Callback<[len: number]>): void 1041 | 1042 | export function write(fd: number, data: string, cb: Callback<[len: number]>): void 1043 | 1044 | export function writeSync( 1045 | fd: number, 1046 | data: Buffer | ArrayBufferView, 1047 | offset?: number, 1048 | len?: number, 1049 | pos?: number 1050 | ): number 1051 | 1052 | export function writeSync(fd: number, data: string, pos?: number, encoding?: BufferEncoding): number 1053 | 1054 | export interface WriteFileOptions { 1055 | encoding?: BufferEncoding 1056 | flag?: Flag 1057 | mode?: number 1058 | } 1059 | 1060 | export function writeFile( 1061 | filepath: Path, 1062 | data: string | Buffer | ArrayBufferView, 1063 | opts?: WriteFileOptions 1064 | ): Promise 1065 | 1066 | export function writeFile( 1067 | filepath: Path, 1068 | data: string | Buffer | ArrayBufferView, 1069 | encoding: BufferEncoding 1070 | ): Promise 1071 | 1072 | export function writeFile( 1073 | filepath: Path, 1074 | data: string | Buffer | ArrayBufferView, 1075 | opts: WriteFileOptions, 1076 | cb: Callback 1077 | ): void 1078 | 1079 | export function writeFile( 1080 | filepath: Path, 1081 | data: string | Buffer | ArrayBufferView, 1082 | encoding: BufferEncoding, 1083 | cb: Callback 1084 | ): void 1085 | 1086 | export function writeFile( 1087 | filepath: Path, 1088 | data: string | Buffer | ArrayBufferView, 1089 | cb: Callback 1090 | ): void 1091 | 1092 | export function writeFileSync( 1093 | filepath: Path, 1094 | data: string | Buffer | ArrayBufferView, 1095 | opts?: WriteFileOptions 1096 | ): void 1097 | 1098 | export function writeFileSync( 1099 | filepath: Path, 1100 | data: string | Buffer | ArrayBufferView, 1101 | encoding: BufferEncoding 1102 | ): void 1103 | 1104 | export function writev(fd: number, buffers: ArrayBufferView[], pos?: number): Promise 1105 | 1106 | export function writev( 1107 | fd: number, 1108 | buffers: ArrayBufferView[], 1109 | pos: number, 1110 | cb: Callback<[len: number]> 1111 | ): void 1112 | 1113 | export function writev(fd: number, buffers: ArrayBufferView[], cb: Callback<[len: number]>): void 1114 | 1115 | export function writevSync(fd: number, buffers: ArrayBufferView[], pos?: number): number 1116 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const FIFO = require('fast-fifo') 2 | const EventEmitter = require('bare-events') 3 | const path = require('bare-path') 4 | const { fileURLToPath } = require('bare-url') 5 | const { Readable, Writable } = require('bare-stream') 6 | const binding = require('./binding') 7 | const constants = require('./lib/constants') 8 | const FileError = require('./lib/errors') 9 | 10 | const isWindows = Bare.platform === 'win32' 11 | 12 | exports.constants = constants 13 | 14 | class FileRequest { 15 | static _free = [] 16 | 17 | static borrow() { 18 | if (this._free.length > 0) return this._free.pop() 19 | return new FileRequest() 20 | } 21 | 22 | static return(req) { 23 | if (this._free.length < 32) this._free.push(req.reset()) 24 | else req.destroy() 25 | } 26 | 27 | constructor() { 28 | this._reset() 29 | this._handle = binding.requestInit(this, this._onresult) 30 | } 31 | 32 | get handle() { 33 | return this._handle 34 | } 35 | 36 | retain(value) { 37 | this._retain = value // Tie the lifetime of `value` to the lifetime of `this` 38 | } 39 | 40 | reset() { 41 | if (this._handle === null) return this 42 | 43 | binding.requestReset(this._handle) 44 | 45 | this._reset() 46 | 47 | return this 48 | } 49 | 50 | destroy() { 51 | if (this._handle === null) return this 52 | 53 | binding.requestDestroy(this._handle) 54 | 55 | this._reset() 56 | this._handle = null 57 | 58 | return this 59 | } 60 | 61 | then(resolve, reject) { 62 | return this._promise.then(resolve, reject) 63 | } 64 | 65 | return() { 66 | if (this._handle === null) return this 67 | 68 | FileRequest.return(this) 69 | 70 | return this 71 | } 72 | 73 | [Symbol.dispose]() { 74 | this.return() 75 | } 76 | 77 | _reset() { 78 | const { promise, resolve, reject } = Promise.withResolvers() 79 | 80 | this._promise = promise 81 | this._resolve = resolve 82 | this._reject = reject 83 | this._retain = null 84 | } 85 | 86 | _onresult(err, status) { 87 | if (err) this._reject(err) 88 | else this._resolve(status) 89 | } 90 | } 91 | 92 | function ok(result, cb) { 93 | if (typeof result === 'function') { 94 | cb = result 95 | result = undefined 96 | } 97 | 98 | if (cb) cb(null, result) 99 | else return result 100 | } 101 | 102 | function fail(err, cb) { 103 | if (cb) cb(err) 104 | else throw err 105 | } 106 | 107 | function done(err, result, cb) { 108 | if (typeof result === 'function') { 109 | cb = result 110 | result = undefined 111 | } 112 | 113 | if (err) fail(err, cb) 114 | else return ok(result, cb) 115 | } 116 | 117 | async function open(filepath, flags = 'r', mode = 0o666, cb) { 118 | if (typeof flags === 'function') { 119 | cb = flags 120 | flags = 'r' 121 | mode = 0o666 122 | } else if (typeof mode === 'function') { 123 | cb = mode 124 | mode = 0o666 125 | } 126 | 127 | if (typeof flags === 'string') flags = toFlags(flags) 128 | if (typeof mode === 'string') mode = toMode(mode) 129 | 130 | filepath = toNamespacedPath(filepath) 131 | 132 | using req = FileRequest.borrow() 133 | 134 | let fd 135 | let err = null 136 | try { 137 | binding.open(req.handle, filepath, flags, mode) 138 | 139 | fd = await req 140 | } catch (e) { 141 | err = new FileError(e.message, { 142 | operation: 'open', 143 | code: e.code, 144 | path: filepath 145 | }) 146 | } 147 | 148 | return done(err, fd, cb) 149 | } 150 | 151 | function openSync(filepath, flags = 'r', mode = 0o666) { 152 | if (typeof flags === 'string') flags = toFlags(flags) 153 | if (typeof mode === 'string') mode = toMode(mode) 154 | 155 | filepath = toNamespacedPath(filepath) 156 | 157 | using req = FileRequest.borrow() 158 | 159 | try { 160 | return binding.openSync(req.handle, filepath, flags, mode) 161 | } catch (e) { 162 | throw new FileError(e.message, { 163 | operation: 'open', 164 | code: e.code, 165 | path: filepath 166 | }) 167 | } 168 | } 169 | 170 | async function close(fd, cb) { 171 | using req = FileRequest.borrow() 172 | 173 | let err = null 174 | try { 175 | binding.close(req.handle, fd) 176 | 177 | await req 178 | } catch (e) { 179 | err = new FileError(e.message, { operation: 'close', code: e.code, fd }) 180 | } 181 | 182 | return done(err, cb) 183 | } 184 | 185 | function closeSync(fd) { 186 | using req = FileRequest.borrow() 187 | 188 | try { 189 | binding.closeSync(req.handle, fd) 190 | } catch (e) { 191 | throw new FileError(e.message, { operation: 'close', code: e.code, fd }) 192 | } 193 | } 194 | 195 | async function access(filepath, mode = constants.F_OK, cb) { 196 | if (typeof mode === 'function') { 197 | cb = mode 198 | mode = constants.F_OK 199 | } 200 | 201 | filepath = toNamespacedPath(filepath) 202 | 203 | using req = FileRequest.borrow() 204 | 205 | let err = null 206 | try { 207 | binding.access(req.handle, filepath, mode) 208 | 209 | await req 210 | } catch (e) { 211 | err = new FileError(e.message, { 212 | operation: 'access', 213 | code: e.code, 214 | path: filepath 215 | }) 216 | } 217 | 218 | return done(err, cb) 219 | } 220 | 221 | function accessSync(filepath, mode = constants.F_OK) { 222 | filepath = toNamespacedPath(filepath) 223 | 224 | using req = FileRequest.borrow() 225 | 226 | try { 227 | binding.accessSync(req.handle, filepath, mode) 228 | } catch (e) { 229 | throw new FileError(e.message, { 230 | operation: 'access', 231 | code: e.code, 232 | path: filepath 233 | }) 234 | } 235 | } 236 | 237 | async function exists(filepath, cb) { 238 | let ok = true 239 | try { 240 | await access(filepath) 241 | } catch { 242 | ok = false 243 | } 244 | 245 | return done(null, ok, cb) 246 | } 247 | 248 | function existsSync(filepath) { 249 | try { 250 | accessSync(filepath) 251 | } catch { 252 | return false 253 | } 254 | 255 | return true 256 | } 257 | 258 | async function read(fd, buffer, offset = 0, len = buffer.byteLength - offset, pos = -1, cb) { 259 | if (typeof offset === 'function') { 260 | cb = offset 261 | offset = 0 262 | len = buffer.byteLength 263 | pos = -1 264 | } else if (typeof len === 'function') { 265 | cb = len 266 | len = buffer.byteLength - offset 267 | pos = -1 268 | } else if (typeof pos === 'function') { 269 | cb = pos 270 | pos = -1 271 | } 272 | 273 | if (typeof pos !== 'number') pos = -1 274 | 275 | using req = FileRequest.borrow() 276 | 277 | let bytes 278 | let err = null 279 | try { 280 | binding.read(req.handle, fd, buffer, offset, len, pos) 281 | 282 | bytes = await req 283 | } catch (e) { 284 | err = new FileError(e.message, { operation: 'read', code: e.code, fd }) 285 | } 286 | 287 | return done(err, bytes, cb) 288 | } 289 | 290 | function readSync(fd, buffer, offset = 0, len = buffer.byteLength - offset, pos = -1) { 291 | using req = FileRequest.borrow() 292 | 293 | try { 294 | return binding.readSync(req.handle, fd, buffer, offset, len, pos) 295 | } catch (e) { 296 | throw new FileError(e.message, { operation: 'read', code: e.code, fd }) 297 | } 298 | } 299 | 300 | async function readv(fd, buffers, pos = -1, cb) { 301 | if (typeof pos === 'function') { 302 | cb = pos 303 | pos = -1 304 | } 305 | 306 | if (typeof pos !== 'number') pos = -1 307 | 308 | using req = FileRequest.borrow() 309 | 310 | let bytes 311 | let err = null 312 | try { 313 | binding.readv(req.handle, fd, buffers, pos) 314 | 315 | bytes = await req 316 | } catch (e) { 317 | err = new FileError(e.message, { operation: 'readv', code: e.code, fd }) 318 | } 319 | 320 | return done(err, bytes, cb) 321 | } 322 | 323 | function readvSync(fd, buffers, pos = -1) { 324 | if (typeof pos !== 'number') pos = -1 325 | 326 | using req = FileRequest.borrow() 327 | 328 | try { 329 | return binding.readvSync(req.handle, fd, buffers, pos) 330 | } catch (e) { 331 | throw new FileError(e.message, { operation: 'readv', code: e.code, fd }) 332 | } 333 | } 334 | 335 | async function write(fd, data, offset = 0, len, pos = -1, cb) { 336 | if (typeof data === 'string') { 337 | let encoding = len 338 | cb = pos 339 | pos = offset 340 | 341 | if (typeof pos === 'function') { 342 | cb = pos 343 | pos = -1 344 | encoding = 'utf8' 345 | } else if (typeof encoding === 'function') { 346 | cb = encoding 347 | encoding = 'utf8' 348 | } 349 | 350 | if (typeof pos === 'string') { 351 | encoding = pos 352 | pos = -1 353 | } 354 | 355 | data = Buffer.from(data, encoding) 356 | offset = 0 357 | len = data.byteLength 358 | } else if (typeof offset === 'function') { 359 | cb = offset 360 | offset = 0 361 | len = data.byteLength 362 | pos = -1 363 | } else if (typeof len === 'function') { 364 | cb = len 365 | len = data.byteLength - offset 366 | pos = -1 367 | } else if (typeof pos === 'function') { 368 | cb = pos 369 | pos = -1 370 | } 371 | 372 | if (typeof len !== 'number') len = data.byteLength - offset 373 | if (typeof pos !== 'number') pos = -1 374 | 375 | using req = FileRequest.borrow() 376 | 377 | let bytes 378 | let err = null 379 | try { 380 | binding.write(req.handle, fd, data, offset, len, pos) 381 | 382 | bytes = await req 383 | } catch (e) { 384 | err = new FileError(e.message, { operation: 'write', code: e.code, fd }) 385 | } 386 | 387 | return done(err, bytes, cb) 388 | } 389 | 390 | function writeSync(fd, data, offset = 0, len, pos = -1) { 391 | if (typeof data === 'string') { 392 | let encoding = len 393 | pos = offset 394 | 395 | if (typeof pos === 'string') { 396 | encoding = pos 397 | pos = -1 398 | } 399 | 400 | data = Buffer.from(data, encoding) 401 | offset = 0 402 | len = data.byteLength 403 | } 404 | 405 | if (typeof len !== 'number') len = data.byteLength - offset 406 | if (typeof pos !== 'number') pos = -1 407 | 408 | using req = FileRequest.borrow() 409 | 410 | try { 411 | return binding.writeSync(req.handle, fd, data, offset, len, pos) 412 | } catch (e) { 413 | throw new FileError(e.message, { operation: 'write', code: e.code, fd }) 414 | } 415 | } 416 | 417 | async function writev(fd, buffers, pos = -1, cb) { 418 | if (typeof pos === 'function') { 419 | cb = pos 420 | pos = -1 421 | } 422 | 423 | if (typeof pos !== 'number') pos = -1 424 | 425 | using req = FileRequest.borrow() 426 | 427 | let bytes 428 | let err = null 429 | try { 430 | binding.writev(req.handle, fd, buffers, pos) 431 | 432 | bytes = await req 433 | } catch (e) { 434 | err = new FileError(e.message, { operation: 'writev', code: e.code, fd }) 435 | } 436 | 437 | return done(err, bytes, cb) 438 | } 439 | 440 | function writevSync(fd, buffers, pos = -1) { 441 | if (typeof pos !== 'number') pos = -1 442 | 443 | using req = FileRequest.borrow() 444 | 445 | try { 446 | return binding.writevSync(req.handle, fd, buffers, pos) 447 | } catch (e) { 448 | throw new FileError(e.message, { operation: 'writev', code: e.code, fd }) 449 | } 450 | } 451 | 452 | async function stat(filepath, cb) { 453 | filepath = toNamespacedPath(filepath) 454 | 455 | using req = FileRequest.borrow() 456 | 457 | let st 458 | let err = null 459 | try { 460 | binding.stat(req.handle, filepath) 461 | 462 | await req 463 | 464 | st = new Stats(...binding.requestResultStat(req.handle)) 465 | } catch (e) { 466 | err = new FileError(e.message, { 467 | operation: 'stat', 468 | code: e.code, 469 | path: filepath 470 | }) 471 | } 472 | 473 | return done(err, st, cb) 474 | } 475 | 476 | function statSync(filepath) { 477 | filepath = toNamespacedPath(filepath) 478 | 479 | using req = FileRequest.borrow() 480 | 481 | try { 482 | binding.statSync(req.handle, filepath) 483 | 484 | return new Stats(...binding.requestResultStat(req.handle)) 485 | } catch (e) { 486 | throw new FileError(e.message, { 487 | operation: 'stat', 488 | code: e.code, 489 | path: filepath 490 | }) 491 | } 492 | } 493 | 494 | async function lstat(filepath, cb) { 495 | filepath = toNamespacedPath(filepath) 496 | 497 | using req = FileRequest.borrow() 498 | 499 | let st 500 | let err = null 501 | try { 502 | binding.lstat(req.handle, filepath) 503 | 504 | await req 505 | 506 | st = new Stats(...binding.requestResultStat(req.handle)) 507 | } catch (e) { 508 | err = new FileError(e.message, { 509 | operation: 'lstat', 510 | code: e.code, 511 | path: filepath 512 | }) 513 | } 514 | 515 | return done(err, st, cb) 516 | } 517 | 518 | function lstatSync(filepath) { 519 | filepath = toNamespacedPath(filepath) 520 | 521 | using req = FileRequest.borrow() 522 | 523 | try { 524 | binding.lstatSync(req.handle, filepath) 525 | 526 | return new Stats(...binding.requestResultStat(req.handle)) 527 | } catch (e) { 528 | throw new FileError(e.message, { 529 | operation: 'lstat', 530 | code: e.code, 531 | path: filepath 532 | }) 533 | } 534 | } 535 | 536 | async function fstat(fd, cb) { 537 | using req = FileRequest.borrow() 538 | 539 | let st 540 | let err = null 541 | try { 542 | binding.fstat(req.handle, fd) 543 | 544 | await req 545 | 546 | st = new Stats(...binding.requestResultStat(req.handle)) 547 | } catch (e) { 548 | err = new FileError(e.message, { operation: 'fstat', code: e.code, fd }) 549 | } 550 | 551 | return done(err, st, cb) 552 | } 553 | 554 | function fstatSync(fd) { 555 | using req = FileRequest.borrow() 556 | 557 | try { 558 | binding.fstatSync(req.handle, fd) 559 | 560 | return new Stats(...binding.requestResultStat(req.handle)) 561 | } catch (e) { 562 | throw new FileError(e.message, { operation: 'fstat', code: e.code, fd }) 563 | } 564 | } 565 | 566 | async function ftruncate(fd, len = 0, cb) { 567 | if (typeof len === 'function') { 568 | cb = len 569 | len = 0 570 | } 571 | 572 | if (typeof len !== 'number') len = 0 573 | 574 | using req = FileRequest.borrow() 575 | 576 | let err = null 577 | try { 578 | binding.ftruncate(req.handle, fd, len) 579 | 580 | await req 581 | } catch (e) { 582 | err = new FileError(e.message, { operation: 'ftruncate', code: e.code, fd }) 583 | } 584 | 585 | return done(err, cb) 586 | } 587 | 588 | function ftruncateSync(fd, len = 0) { 589 | if (typeof len !== 'number') len = 0 590 | 591 | using req = FileRequest.borrow() 592 | 593 | try { 594 | binding.ftruncateSync(req.handle, fd, len) 595 | } catch (e) { 596 | throw new FileError(e.message, { operation: 'ftruncate', code: e.code, fd }) 597 | } 598 | } 599 | 600 | async function chmod(filepath, mode, cb) { 601 | if (typeof mode === 'string') mode = toMode(mode) 602 | 603 | filepath = toNamespacedPath(filepath) 604 | 605 | using req = FileRequest.borrow() 606 | 607 | let err = null 608 | try { 609 | binding.chmod(req.handle, filepath, mode) 610 | 611 | await req 612 | } catch (e) { 613 | err = new FileError(e.message, { 614 | operation: 'chmod', 615 | code: e.code, 616 | path: filepath 617 | }) 618 | } 619 | 620 | return done(err, cb) 621 | } 622 | 623 | function chmodSync(filepath, mode) { 624 | if (typeof mode === 'string') mode = toMode(mode) 625 | 626 | filepath = toNamespacedPath(filepath) 627 | 628 | using req = FileRequest.borrow() 629 | 630 | try { 631 | binding.chmodSync(req.handle, filepath, mode) 632 | } catch (e) { 633 | throw new FileError(e.message, { 634 | operation: 'chmod', 635 | code: e.code, 636 | path: filepath 637 | }) 638 | } 639 | } 640 | 641 | async function fchmod(fd, mode, cb) { 642 | if (typeof mode === 'string') mode = toMode(mode) 643 | 644 | using req = FileRequest.borrow() 645 | 646 | let err = null 647 | try { 648 | binding.fchmod(req.handle, fd, mode) 649 | 650 | await req 651 | } catch (e) { 652 | err = new FileError(e.message, { operation: 'fchmod', code: e.code, fd }) 653 | } 654 | 655 | return done(err, cb) 656 | } 657 | 658 | function fchmodSync(fd, mode) { 659 | if (typeof mode === 'string') mode = toMode(mode) 660 | 661 | using req = FileRequest.borrow() 662 | 663 | try { 664 | binding.fchmodSync(req.handle, fd, mode) 665 | } catch (e) { 666 | throw new FileError(e.message, { operation: 'fchmod', code: e.code, fd }) 667 | } 668 | } 669 | 670 | async function utimes(filepath, atime, mtime, cb) { 671 | if (typeof atime !== 'number') atime = atime.getTime() / 1000 672 | if (typeof mtime !== 'number') mtime = mtime.getTime() / 1000 673 | 674 | filepath = toNamespacedPath(filepath) 675 | 676 | using req = FileRequest.borrow() 677 | 678 | let err = null 679 | try { 680 | binding.utimes(req.handle, filepath, atime, mtime) 681 | 682 | await req 683 | } catch (e) { 684 | err = new FileError(e.message, { 685 | operation: 'utimes', 686 | code: e.code, 687 | path: filepath 688 | }) 689 | } 690 | 691 | return done(err, cb) 692 | } 693 | 694 | function utimesSync(filepath, atime, mtime) { 695 | if (typeof atime !== 'number') atime = atime.getTime() / 1000 696 | if (typeof mtime !== 'number') mtime = mtime.getTime() / 1000 697 | 698 | filepath = toNamespacedPath(filepath) 699 | 700 | using req = FileRequest.borrow() 701 | 702 | try { 703 | binding.utimesSync(req.handle, filepath, atime, mtime) 704 | } catch (e) { 705 | throw new FileError(e.message, { 706 | operation: 'utimes', 707 | code: e.code, 708 | path: filepath 709 | }) 710 | } 711 | } 712 | 713 | async function mkdir(filepath, opts, cb) { 714 | if (typeof opts === 'function') { 715 | cb = opts 716 | opts = { mode: 0o777 } 717 | } 718 | 719 | if (typeof opts === 'number') opts = { mode: opts } 720 | else if (!opts) opts = {} 721 | 722 | const mode = typeof opts.mode === 'number' ? opts.mode : 0o777 723 | 724 | filepath = toNamespacedPath(filepath) 725 | 726 | if (opts.recursive) { 727 | let err = null 728 | try { 729 | try { 730 | await mkdir(filepath, { mode }) 731 | } catch (err) { 732 | if (err.code !== 'ENOENT') { 733 | if (!(await stat(filepath)).isDirectory()) throw err 734 | } else { 735 | while (filepath.endsWith(path.sep)) filepath = filepath.slice(0, -1) 736 | const i = filepath.lastIndexOf(path.sep) 737 | if (i <= 0) throw err 738 | 739 | await mkdir(filepath.slice(0, i), { mode, recursive: true }) 740 | 741 | try { 742 | await mkdir(filepath, { mode }) 743 | } catch (err) { 744 | if (!(await stat(filepath)).isDirectory()) throw err 745 | } 746 | } 747 | } 748 | } catch (e) { 749 | err = e 750 | } 751 | 752 | return done(err, cb) 753 | } 754 | 755 | using req = FileRequest.borrow() 756 | 757 | let err = null 758 | try { 759 | binding.mkdir(req.handle, filepath, mode) 760 | 761 | await req 762 | } catch (e) { 763 | err = new FileError(e.message, { 764 | operation: 'mkdir', 765 | code: e.code, 766 | path: filepath 767 | }) 768 | } 769 | 770 | return done(err, cb) 771 | } 772 | 773 | function mkdirSync(filepath, opts) { 774 | if (typeof opts === 'number') opts = { mode: opts } 775 | else if (!opts) opts = {} 776 | 777 | const mode = typeof opts.mode === 'number' ? opts.mode : 0o777 778 | 779 | filepath = toNamespacedPath(filepath) 780 | 781 | if (opts.recursive) { 782 | try { 783 | mkdirSync(filepath, { mode }) 784 | } catch (err) { 785 | if (err.code !== 'ENOENT') { 786 | if (!statSync(filepath).isDirectory()) throw err 787 | } else { 788 | while (filepath.endsWith(path.sep)) filepath = filepath.slice(0, -1) 789 | const i = filepath.lastIndexOf(path.sep) 790 | if (i <= 0) throw err 791 | 792 | mkdirSync(filepath.slice(0, i), { mode, recursive: true }) 793 | 794 | try { 795 | mkdirSync(filepath, { mode }) 796 | } catch (err) { 797 | if (!statSync(filepath).isDirectory()) throw err 798 | } 799 | } 800 | } 801 | 802 | return 803 | } 804 | 805 | using req = FileRequest.borrow() 806 | 807 | try { 808 | binding.mkdirSync(req.handle, filepath, mode) 809 | } catch (e) { 810 | throw new FileError(e.message, { 811 | operation: 'mkdir', 812 | code: e.code, 813 | path: filepath 814 | }) 815 | } 816 | } 817 | 818 | async function rmdir(filepath, cb) { 819 | filepath = toNamespacedPath(filepath) 820 | 821 | using req = FileRequest.borrow() 822 | 823 | let err = null 824 | try { 825 | binding.rmdir(req.handle, filepath) 826 | 827 | await req 828 | } catch (e) { 829 | err = new FileError(e.message, { 830 | operation: 'rmdir', 831 | code: e.code, 832 | path: filepath 833 | }) 834 | } 835 | 836 | return done(err, cb) 837 | } 838 | 839 | function rmdirSync(filepath) { 840 | filepath = toNamespacedPath(filepath) 841 | 842 | using req = FileRequest.borrow() 843 | 844 | try { 845 | binding.rmdirSync(req.handle, filepath) 846 | } catch (e) { 847 | throw new FileError(e.message, { 848 | operation: 'rmdir', 849 | code: e.code, 850 | path: filepath 851 | }) 852 | } 853 | } 854 | 855 | async function rm(filepath, opts, cb) { 856 | if (typeof opts === 'function') { 857 | cb = opts 858 | opts = {} 859 | } 860 | 861 | if (!opts) opts = {} 862 | 863 | filepath = toNamespacedPath(filepath) 864 | 865 | let err = null 866 | try { 867 | const st = await lstat(filepath) 868 | 869 | if (st.isDirectory()) { 870 | if (opts.recursive) { 871 | try { 872 | await rmdir(filepath) 873 | } catch (err) { 874 | if (err.code !== 'ENOTEMPTY') throw err 875 | 876 | const files = await readdir(filepath) 877 | 878 | for (const file of files) { 879 | await rm(filepath + path.sep + file, opts) 880 | } 881 | 882 | await rmdir(filepath) 883 | } 884 | } else { 885 | throw new FileError('is a directory', { 886 | operation: 'rm', 887 | code: 'EISDIR', 888 | path: filepath 889 | }) 890 | } 891 | } else { 892 | await unlink(filepath) 893 | } 894 | } catch (e) { 895 | if (e.code !== 'ENOENT' || !opts.force) err = e 896 | } 897 | 898 | return done(err, cb) 899 | } 900 | 901 | function rmSync(filepath, opts) { 902 | if (!opts) opts = {} 903 | 904 | filepath = toNamespacedPath(filepath) 905 | 906 | try { 907 | const st = lstatSync(filepath) 908 | 909 | if (st.isDirectory()) { 910 | if (opts.recursive) { 911 | try { 912 | rmdirSync(filepath) 913 | } catch (err) { 914 | if (err.code !== 'ENOTEMPTY') throw err 915 | 916 | const files = readdirSync(filepath) 917 | 918 | for (const file of files) { 919 | rmSync(filepath + path.sep + file, opts) 920 | } 921 | 922 | rmdirSync(filepath) 923 | } 924 | } else { 925 | throw new FileError('is a directory', { 926 | operation: 'rm', 927 | code: 'EISDIR', 928 | path: filepath 929 | }) 930 | } 931 | } else { 932 | unlinkSync(filepath) 933 | } 934 | } catch (err) { 935 | if (err.code !== 'ENOENT' || !opts.force) throw err 936 | } 937 | } 938 | 939 | async function unlink(filepath, cb) { 940 | filepath = toNamespacedPath(filepath) 941 | 942 | using req = FileRequest.borrow() 943 | 944 | let err = null 945 | try { 946 | binding.unlink(req.handle, filepath) 947 | 948 | await req 949 | } catch (e) { 950 | err = new FileError(e.message, { 951 | operation: 'unlink', 952 | code: e.code, 953 | path: filepath 954 | }) 955 | } 956 | 957 | return done(err, cb) 958 | } 959 | 960 | function unlinkSync(filepath) { 961 | filepath = toNamespacedPath(filepath) 962 | 963 | using req = FileRequest.borrow() 964 | 965 | try { 966 | binding.unlinkSync(req.handle, filepath) 967 | } catch (e) { 968 | throw new FileError(e.message, { 969 | operation: 'unlink', 970 | code: e.code, 971 | path: filepath 972 | }) 973 | } 974 | } 975 | 976 | async function rename(src, dst, cb) { 977 | src = toNamespacedPath(src) 978 | dst = toNamespacedPath(dst) 979 | 980 | using req = FileRequest.borrow() 981 | 982 | let err = null 983 | try { 984 | binding.rename(req.handle, src, dst) 985 | 986 | await req 987 | } catch (e) { 988 | err = new FileError(e.message, { 989 | operation: 'rename', 990 | code: e.code, 991 | path: src, 992 | destination: dst 993 | }) 994 | } 995 | 996 | return done(err, cb) 997 | } 998 | 999 | function renameSync(src, dst) { 1000 | src = toNamespacedPath(src) 1001 | dst = toNamespacedPath(dst) 1002 | 1003 | using req = FileRequest.borrow() 1004 | 1005 | try { 1006 | binding.renameSync(req.handle, src, dst) 1007 | } catch (e) { 1008 | throw new FileError(e.message, { 1009 | operation: 'rename', 1010 | code: e.code, 1011 | path: src, 1012 | destination: dst 1013 | }) 1014 | } 1015 | } 1016 | 1017 | async function copyFile(src, dst, mode = 0, cb) { 1018 | if (typeof mode === 'function') { 1019 | cb = mode 1020 | mode = 0 1021 | } 1022 | 1023 | src = toNamespacedPath(src) 1024 | dst = toNamespacedPath(dst) 1025 | 1026 | using req = FileRequest.borrow() 1027 | 1028 | let err = null 1029 | try { 1030 | binding.copyfile(req.handle, src, dst, mode) 1031 | 1032 | await req 1033 | } catch (e) { 1034 | err = new FileError(e.message, { 1035 | operation: 'copyfile', 1036 | code: e.code, 1037 | path: src, 1038 | destination: dst 1039 | }) 1040 | } 1041 | 1042 | return done(err, cb) 1043 | } 1044 | 1045 | function copyFileSync(src, dst, mode = 0) { 1046 | src = toNamespacedPath(src) 1047 | dst = toNamespacedPath(dst) 1048 | 1049 | using req = FileRequest.borrow() 1050 | 1051 | try { 1052 | binding.copyfileSync(req.handle, src, dst, mode) 1053 | } catch (e) { 1054 | throw new FileError(e.message, { 1055 | operation: 'copyfile', 1056 | code: e.code, 1057 | path: src, 1058 | destination: dst 1059 | }) 1060 | } 1061 | } 1062 | 1063 | async function cp(src, dst, opts, cb) { 1064 | if (typeof opts === 'function') { 1065 | cb = opts 1066 | opts = {} 1067 | } 1068 | 1069 | if (!opts) opts = {} 1070 | 1071 | src = toNamespacedPath(src) 1072 | dst = toNamespacedPath(dst) 1073 | 1074 | let err = null 1075 | try { 1076 | const st = await lstat(src) 1077 | 1078 | if (st.isDirectory()) { 1079 | if (opts.recursive !== true) { 1080 | throw new FileError('is a directory', { 1081 | operation: 'cp', 1082 | code: 'EISDIR', 1083 | path: src 1084 | }) 1085 | } 1086 | 1087 | try { 1088 | await lstat(dst) 1089 | } catch (e) { 1090 | if (e.code === 'ENOENT') { 1091 | await mkdir(dst, { mode: st.mode, recursive: true }) 1092 | } else { 1093 | throw e 1094 | } 1095 | } 1096 | 1097 | const dir = await opendir(src) 1098 | for await (const { name } of dir) { 1099 | await cp(path.join(src, name), path.join(dst, name), opts) 1100 | } 1101 | } else if (st.isFile()) { 1102 | await copyFile(src, dst) 1103 | await chmod(dst, st.mode) 1104 | } 1105 | } catch (e) { 1106 | err = e 1107 | } 1108 | 1109 | return done(err, cb) 1110 | } 1111 | 1112 | async function realpath(filepath, opts, cb) { 1113 | if (typeof opts === 'function') { 1114 | cb = opts 1115 | opts = {} 1116 | } 1117 | 1118 | if (typeof opts === 'string') opts = { encoding: opts } 1119 | else if (!opts) opts = {} 1120 | 1121 | const { encoding = 'utf8' } = opts 1122 | 1123 | filepath = toNamespacedPath(filepath) 1124 | 1125 | using req = FileRequest.borrow() 1126 | 1127 | let res 1128 | let err = null 1129 | try { 1130 | binding.realpath(req.handle, filepath) 1131 | 1132 | await req 1133 | 1134 | res = Buffer.from(binding.requestResultString(req.handle)) 1135 | 1136 | if (encoding !== 'buffer') res = res.toString(encoding) 1137 | } catch (e) { 1138 | err = new FileError(e.message, { 1139 | operation: 'realpath', 1140 | code: e.code, 1141 | path: filepath 1142 | }) 1143 | } 1144 | 1145 | return done(err, res, cb) 1146 | } 1147 | 1148 | function realpathSync(filepath, opts) { 1149 | if (typeof opts === 'string') opts = { encoding: opts } 1150 | else if (!opts) opts = {} 1151 | 1152 | const { encoding = 'utf8' } = opts 1153 | 1154 | filepath = toNamespacedPath(filepath) 1155 | 1156 | using req = FileRequest.borrow() 1157 | 1158 | try { 1159 | binding.realpathSync(req.handle, filepath) 1160 | 1161 | let res = Buffer.from(binding.requestResultString(req.handle)) 1162 | 1163 | if (encoding !== 'buffer') res = res.toString(encoding) 1164 | 1165 | return res 1166 | } catch (e) { 1167 | throw new FileError(e.message, { 1168 | operation: 'realpath', 1169 | code: e.code, 1170 | path: filepath 1171 | }) 1172 | } 1173 | } 1174 | 1175 | async function readlink(filepath, opts, cb) { 1176 | if (typeof opts === 'function') { 1177 | cb = opts 1178 | opts = {} 1179 | } 1180 | 1181 | if (typeof opts === 'string') opts = { encoding: opts } 1182 | else if (!opts) opts = {} 1183 | 1184 | const { encoding = 'utf8' } = opts 1185 | 1186 | filepath = toNamespacedPath(filepath) 1187 | 1188 | using req = FileRequest.borrow() 1189 | 1190 | let res 1191 | let err = null 1192 | try { 1193 | binding.readlink(req.handle, filepath) 1194 | 1195 | await req 1196 | 1197 | res = Buffer.from(binding.requestResultString(req.handle)) 1198 | 1199 | if (encoding !== 'buffer') res = res.toString(encoding) 1200 | } catch (e) { 1201 | err = new FileError(e.message, { 1202 | operation: 'readlink', 1203 | code: e.code, 1204 | path: filepath 1205 | }) 1206 | } 1207 | 1208 | return done(err, res, cb) 1209 | } 1210 | 1211 | function readlinkSync(filepath, opts) { 1212 | if (typeof opts === 'string') opts = { encoding: opts } 1213 | else if (!opts) opts = {} 1214 | 1215 | const { encoding = 'utf8' } = opts 1216 | 1217 | filepath = toNamespacedPath(filepath) 1218 | 1219 | using req = FileRequest.borrow() 1220 | 1221 | try { 1222 | binding.readlinkSync(req.handle, filepath) 1223 | 1224 | let res = Buffer.from(binding.requestResultString(req.handle)) 1225 | 1226 | if (encoding !== 'buffer') res = res.toString(encoding) 1227 | 1228 | return res 1229 | } catch (e) { 1230 | throw new FileError(e.message, { 1231 | operation: 'readlink', 1232 | code: e.code, 1233 | path: filepath 1234 | }) 1235 | } 1236 | } 1237 | 1238 | function normalizeSymlinkTarget(target, type, filepath) { 1239 | if (isWindows) { 1240 | if (type === 'junction') target = path.resolve(filepath, '..', target) 1241 | 1242 | if (path.isAbsolute(target)) return path.toNamespacedPath(target) 1243 | 1244 | return target.replace(/\//g, path.sep) 1245 | } 1246 | 1247 | return target 1248 | } 1249 | 1250 | async function symlink(target, filepath, type, cb) { 1251 | if (typeof type === 'function') { 1252 | cb = type 1253 | type = null 1254 | } 1255 | 1256 | filepath = toNamespacedPath(filepath) 1257 | 1258 | if (typeof type === 'string') { 1259 | switch (type) { 1260 | case 'file': 1261 | default: 1262 | type = 0 1263 | break 1264 | case 'dir': 1265 | type = constants.UV_FS_SYMLINK_DIR 1266 | break 1267 | case 'junction': 1268 | type = constants.UV_FS_SYMLINK_JUNCTION 1269 | break 1270 | } 1271 | } else if (typeof type !== 'number') { 1272 | if (isWindows) { 1273 | target = path.resolve(filepath, '..', target) 1274 | 1275 | try { 1276 | type = (await stat(target)).isDirectory() 1277 | ? constants.UV_FS_SYMLINK_DIR 1278 | : constants.UV_FS_SYMLINK_JUNCTION 1279 | } catch { 1280 | type = 0 1281 | } 1282 | } else { 1283 | type = 0 1284 | } 1285 | } 1286 | 1287 | target = normalizeSymlinkTarget(target) 1288 | 1289 | using req = FileRequest.borrow() 1290 | 1291 | let err = null 1292 | try { 1293 | binding.symlink(req.handle, target, filepath, type) 1294 | 1295 | await req 1296 | } catch (e) { 1297 | err = new FileError(e.message, { 1298 | operation: 'symlink', 1299 | code: e.code, 1300 | path: target, 1301 | destination: filepath 1302 | }) 1303 | } 1304 | 1305 | return done(err, cb) 1306 | } 1307 | 1308 | function symlinkSync(target, filepath, type) { 1309 | filepath = toNamespacedPath(filepath) 1310 | 1311 | if (typeof type === 'string') { 1312 | switch (type) { 1313 | case 'file': 1314 | default: 1315 | type = 0 1316 | break 1317 | case 'dir': 1318 | type = constants.UV_FS_SYMLINK_DIR 1319 | break 1320 | case 'junction': 1321 | type = constants.UV_FS_SYMLINK_JUNCTION 1322 | break 1323 | } 1324 | } else if (typeof type !== 'number') { 1325 | if (isWindows) { 1326 | target = path.resolve(filepath, '..', target) 1327 | 1328 | try { 1329 | type = statSync(target).isDirectory() 1330 | ? constants.UV_FS_SYMLINK_DIR 1331 | : constants.UV_FS_SYMLINK_JUNCTION 1332 | } catch { 1333 | type = 0 1334 | } 1335 | } else { 1336 | type = 0 1337 | } 1338 | } 1339 | 1340 | target = normalizeSymlinkTarget(target) 1341 | 1342 | using req = FileRequest.borrow() 1343 | 1344 | try { 1345 | binding.symlinkSync(req.handle, target, filepath, type) 1346 | } catch (e) { 1347 | throw new FileError(e.message, { 1348 | operation: 'symlink', 1349 | code: e.code, 1350 | path: target, 1351 | destination: filepath 1352 | }) 1353 | } 1354 | } 1355 | 1356 | async function opendir(filepath, opts, cb) { 1357 | if (typeof opts === 'function') { 1358 | cb = opts 1359 | opts = {} 1360 | } 1361 | 1362 | if (typeof opts === 'string') opts = { encoding: opts } 1363 | else if (!opts) opts = {} 1364 | 1365 | filepath = toNamespacedPath(filepath) 1366 | 1367 | using req = FileRequest.borrow() 1368 | 1369 | let dir 1370 | let err = null 1371 | try { 1372 | binding.opendir(req.handle, filepath) 1373 | 1374 | await req 1375 | 1376 | dir = new Dir(filepath, binding.requestResultDir(req.handle), opts) 1377 | } catch (e) { 1378 | err = new FileError(e.message, { 1379 | operation: 'opendir', 1380 | code: e.code, 1381 | path: filepath 1382 | }) 1383 | } 1384 | 1385 | return done(err, dir, cb) 1386 | } 1387 | 1388 | function opendirSync(filepath, opts) { 1389 | if (typeof opts === 'string') opts = { encoding: opts } 1390 | else if (!opts) opts = {} 1391 | 1392 | filepath = toNamespacedPath(filepath) 1393 | 1394 | using req = FileRequest.borrow() 1395 | 1396 | try { 1397 | binding.opendirSync(req.handle, filepath) 1398 | 1399 | return new Dir(filepath, binding.requestResultDir(req.handle), opts) 1400 | } catch (e) { 1401 | throw new FileError(e.message, { 1402 | operation: 'opendir', 1403 | code: e.code, 1404 | path: filepath 1405 | }) 1406 | } 1407 | } 1408 | 1409 | async function readdir(filepath, opts, cb) { 1410 | if (typeof opts === 'function') { 1411 | cb = opts 1412 | opts = {} 1413 | } 1414 | 1415 | if (typeof opts === 'string') opts = { encoding: opts } 1416 | else if (!opts) opts = {} 1417 | 1418 | const { withFileTypes = false } = opts 1419 | 1420 | filepath = toNamespacedPath(filepath) 1421 | 1422 | let result = [] 1423 | let err = null 1424 | try { 1425 | const dir = await opendir(filepath) 1426 | 1427 | for await (const entry of dir) { 1428 | result.push(withFileTypes ? entry : entry.name) 1429 | } 1430 | } catch (e) { 1431 | result = [] 1432 | err = e 1433 | } 1434 | 1435 | return done(err, result, cb) 1436 | } 1437 | 1438 | function readdirSync(filepath, opts) { 1439 | if (typeof opts === 'string') opts = { encoding: opts } 1440 | else if (!opts) opts = {} 1441 | 1442 | const { withFileTypes = false } = opts 1443 | 1444 | filepath = toNamespacedPath(filepath) 1445 | 1446 | const dir = opendirSync(filepath, opts) 1447 | const result = [] 1448 | 1449 | for (const entry of dir) { 1450 | result.push(withFileTypes ? entry : entry.name) 1451 | } 1452 | 1453 | return result 1454 | } 1455 | 1456 | async function readFile(filepath, opts, cb) { 1457 | if (typeof opts === 'function') { 1458 | cb = opts 1459 | opts = {} 1460 | } 1461 | 1462 | if (typeof opts === 'string') opts = { encoding: opts } 1463 | else if (!opts) opts = {} 1464 | 1465 | const { encoding = 'buffer' } = opts 1466 | 1467 | let fd = -1 1468 | let buffer = null 1469 | let err = null 1470 | try { 1471 | fd = await open(filepath, opts.flag || 'r') 1472 | 1473 | const st = await fstat(fd) 1474 | 1475 | let len = 0 1476 | 1477 | if (st.size === 0) { 1478 | const buffers = [] 1479 | 1480 | while (true) { 1481 | buffer = Buffer.allocUnsafe(8192) 1482 | const r = await read(fd, buffer) 1483 | len += r 1484 | if (r === 0) break 1485 | buffers.push(buffer.subarray(0, r)) 1486 | } 1487 | 1488 | buffer = Buffer.concat(buffers) 1489 | } else { 1490 | buffer = Buffer.allocUnsafe(st.size) 1491 | 1492 | while (true) { 1493 | const r = await read(fd, len ? buffer.subarray(len) : buffer) 1494 | len += r 1495 | if (r === 0 || len === buffer.byteLength) break 1496 | } 1497 | 1498 | if (len !== buffer.byteLength) buffer = buffer.subarray(0, len) 1499 | } 1500 | 1501 | if (encoding !== 'buffer') buffer = buffer.toString(encoding) 1502 | } catch (e) { 1503 | err = e 1504 | } finally { 1505 | if (fd !== -1) await close(fd) 1506 | } 1507 | 1508 | return done(err, buffer, cb) 1509 | } 1510 | 1511 | function readFileSync(filepath, opts) { 1512 | if (typeof opts === 'string') opts = { encoding: opts } 1513 | else if (!opts) opts = {} 1514 | 1515 | const { encoding = 'buffer' } = opts 1516 | 1517 | let fd = -1 1518 | try { 1519 | fd = openSync(filepath, opts.flag || 'r') 1520 | 1521 | const st = fstatSync(fd) 1522 | 1523 | let buffer 1524 | let len = 0 1525 | 1526 | if (st.size === 0) { 1527 | const buffers = [] 1528 | 1529 | while (true) { 1530 | buffer = Buffer.allocUnsafe(8192) 1531 | const r = readSync(fd, buffer) 1532 | len += r 1533 | if (r === 0) break 1534 | buffers.push(buffer.subarray(0, r)) 1535 | } 1536 | 1537 | buffer = Buffer.concat(buffers) 1538 | } else { 1539 | buffer = Buffer.allocUnsafe(st.size) 1540 | 1541 | while (true) { 1542 | const r = readSync(fd, len ? buffer.subarray(len) : buffer) 1543 | len += r 1544 | if (r === 0 || len === buffer.byteLength) break 1545 | } 1546 | 1547 | if (len !== buffer.byteLength) buffer = buffer.subarray(0, len) 1548 | } 1549 | 1550 | if (encoding !== 'buffer') buffer = buffer.toString(encoding) 1551 | 1552 | return buffer 1553 | } finally { 1554 | if (fd !== -1) closeSync(fd) 1555 | } 1556 | } 1557 | 1558 | async function writeFile(filepath, data, opts, cb) { 1559 | if (typeof opts === 'function') { 1560 | cb = opts 1561 | opts = {} 1562 | } 1563 | 1564 | if (typeof opts === 'string') opts = { encoding: opts } 1565 | else if (!opts) opts = {} 1566 | 1567 | if (typeof data === 'string') data = Buffer.from(data, opts.encoding) 1568 | 1569 | let fd = -1 1570 | let len = 0 1571 | let err = null 1572 | try { 1573 | fd = await open(filepath, opts.flag || 'w', opts.mode || 0o666) 1574 | 1575 | while (true) { 1576 | len += await write(fd, len ? data.subarray(len) : data) 1577 | if (len === data.byteLength) break 1578 | } 1579 | } catch (e) { 1580 | err = e 1581 | } finally { 1582 | if (fd !== -1) await close(fd) 1583 | } 1584 | 1585 | return done(err, len, cb) 1586 | } 1587 | 1588 | function writeFileSync(filepath, data, opts) { 1589 | if (typeof opts === 'string') opts = { encoding: opts } 1590 | else if (!opts) opts = {} 1591 | 1592 | if (typeof data === 'string') data = Buffer.from(data, opts.encoding) 1593 | 1594 | let fd = -1 1595 | try { 1596 | fd = openSync(filepath, opts.flag || 'w', opts.mode || 0o666) 1597 | 1598 | let len = 0 1599 | 1600 | while (true) { 1601 | len += writeSync(fd, len ? data.subarray(len) : data) 1602 | if (len === data.byteLength) break 1603 | } 1604 | } finally { 1605 | if (fd !== -1) closeSync(fd) 1606 | } 1607 | } 1608 | 1609 | function appendFile(filepath, data, opts, cb) { 1610 | if (typeof opts === 'function') { 1611 | cb = opts 1612 | opts = {} 1613 | } 1614 | 1615 | if (typeof opts === 'string') opts = { encoding: opts } 1616 | else if (!opts) opts = {} 1617 | 1618 | if (!opts.flag) opts = { ...opts, flag: 'a' } 1619 | 1620 | return writeFile(filepath, data, opts, cb) 1621 | } 1622 | 1623 | function appendFileSync(filepath, data, opts) { 1624 | if (typeof opts === 'string') opts = { encoding: opts } 1625 | else if (!opts) opts = {} 1626 | 1627 | if (!opts.flag) opts = { ...opts, flag: 'a' } 1628 | 1629 | return writeFileSync(filepath, data, opts) 1630 | } 1631 | 1632 | function watch(filepath, opts, cb) { 1633 | if (typeof opts === 'function') { 1634 | cb = opts 1635 | opts = {} 1636 | } 1637 | 1638 | if (typeof opts === 'string') opts = { encoding: opts } 1639 | else if (!opts) opts = {} 1640 | 1641 | filepath = toNamespacedPath(filepath) 1642 | 1643 | return new Watcher(filepath, opts, cb) 1644 | } 1645 | 1646 | class Stats { 1647 | constructor( 1648 | dev, 1649 | mode, 1650 | nlink, 1651 | uid, 1652 | gid, 1653 | rdev, 1654 | blksize, 1655 | ino, 1656 | size, 1657 | blocks, 1658 | atimeMs, 1659 | mtimeMs, 1660 | ctimeMs, 1661 | birthtimeMs 1662 | ) { 1663 | this.dev = dev 1664 | this.mode = mode 1665 | this.nlink = nlink 1666 | this.uid = uid 1667 | this.gid = gid 1668 | this.rdev = rdev 1669 | this.blksize = blksize 1670 | this.ino = ino 1671 | this.size = size 1672 | this.blocks = blocks 1673 | this.atimeMs = atimeMs 1674 | this.mtimeMs = mtimeMs 1675 | this.ctimeMs = ctimeMs 1676 | this.birthtimeMs = birthtimeMs 1677 | this.atime = new Date(atimeMs) 1678 | this.mtime = new Date(mtimeMs) 1679 | this.ctime = new Date(ctimeMs) 1680 | this.birthtime = new Date(birthtimeMs) 1681 | } 1682 | 1683 | isDirectory() { 1684 | return (this.mode & constants.S_IFMT) === constants.S_IFDIR 1685 | } 1686 | 1687 | isFile() { 1688 | return (this.mode & constants.S_IFMT) === constants.S_IFREG 1689 | } 1690 | 1691 | isBlockDevice() { 1692 | return (this.mode & constants.S_IFMT) === constants.S_IFBLK 1693 | } 1694 | 1695 | isCharacterDevice() { 1696 | return (this.mode & constants.S_IFCHR) === constants.S_IFCHR 1697 | } 1698 | 1699 | isFIFO() { 1700 | return (this.mode & constants.S_IFMT) === constants.S_IFIFO 1701 | } 1702 | 1703 | isSymbolicLink() { 1704 | return (this.mode & constants.S_IFMT) === constants.S_IFLNK 1705 | } 1706 | 1707 | isSocket() { 1708 | return (this.mode & constants.S_IFMT) === constants.S_IFSOCK 1709 | } 1710 | } 1711 | 1712 | class Dir { 1713 | constructor(path, handle, opts = {}) { 1714 | const { encoding = 'utf8', bufferSize = 32 } = opts 1715 | 1716 | this.path = path 1717 | 1718 | this._encoding = encoding 1719 | this._capacity = bufferSize 1720 | this._buffer = new FIFO() 1721 | this._ended = false 1722 | this._handle = handle 1723 | } 1724 | 1725 | async read(cb) { 1726 | if (this._buffer.length) return ok(this._buffer.shift(), cb) 1727 | if (this._ended) return ok(null, cb) 1728 | 1729 | using req = FileRequest.borrow() 1730 | 1731 | let entries 1732 | let err = null 1733 | try { 1734 | req.retain(binding.readdir(req.handle, this._handle, this._capacity)) 1735 | 1736 | await req 1737 | 1738 | entries = binding.requestResultDirents(req.handle) 1739 | } catch (e) { 1740 | err = new FileError(e.message, { 1741 | operation: 'readdir', 1742 | code: e.code, 1743 | path: this.path 1744 | }) 1745 | } 1746 | 1747 | if (err) return fail(err, cb) 1748 | 1749 | if (entries.length === 0) { 1750 | this._ended = true 1751 | 1752 | return ok(null, cb) 1753 | } 1754 | 1755 | for (const entry of entries) { 1756 | let name = Buffer.from(entry.name) 1757 | 1758 | if (this._encoding !== 'buffer') name = name.toString(this._encoding) 1759 | 1760 | this._buffer.push(new Dirent(this.path, name, entry.type)) 1761 | } 1762 | 1763 | return ok(this._buffer.shift(), cb) 1764 | } 1765 | 1766 | readSync() { 1767 | if (this._buffer.length) return this._buffer.shift() 1768 | if (this._ended) return null 1769 | 1770 | using req = FileRequest.borrow() 1771 | 1772 | let entries 1773 | try { 1774 | req.retain(binding.readdirSync(req.handle, this._handle, this._capacity)) 1775 | 1776 | entries = binding.requestResultDirents(req.handle) 1777 | } catch (e) { 1778 | throw new FileError(e.message, { 1779 | operation: 'readdir', 1780 | code: e.code, 1781 | path: this.path 1782 | }) 1783 | } 1784 | 1785 | if (entries.length === 0) { 1786 | this._ended = true 1787 | 1788 | return null 1789 | } 1790 | 1791 | for (const entry of entries) { 1792 | let name = Buffer.from(entry.name) 1793 | 1794 | if (this._encoding !== 'buffer') name = name.toString(this._encoding) 1795 | 1796 | this._buffer.push(new Dirent(this.path, name, entry.type)) 1797 | } 1798 | 1799 | return this._buffer.shift() 1800 | } 1801 | 1802 | async close(cb) { 1803 | using req = FileRequest.borrow() 1804 | 1805 | let err = null 1806 | try { 1807 | binding.closedir(req.handle, this._handle) 1808 | 1809 | await req 1810 | } catch (e) { 1811 | err = new FileError(e.message, { 1812 | operation: 'closedir', 1813 | code: e.code, 1814 | path: this.path 1815 | }) 1816 | } 1817 | 1818 | this._handle = null 1819 | 1820 | return done(err, cb) 1821 | } 1822 | 1823 | closeSync() { 1824 | using req = FileRequest.borrow() 1825 | 1826 | try { 1827 | binding.closedirSync(req.handle, this._handle) 1828 | } catch (e) { 1829 | throw new FileError(e.message, { 1830 | operation: 'closedir', 1831 | code: e.code, 1832 | path: this.path 1833 | }) 1834 | } 1835 | 1836 | this._handle = null 1837 | } 1838 | 1839 | [Symbol.dispose]() { 1840 | this.closeSync() 1841 | } 1842 | 1843 | async [Symbol.asyncDispose]() { 1844 | await this.close() 1845 | } 1846 | 1847 | *[Symbol.iterator]() { 1848 | while (true) { 1849 | const entry = this.readSync() 1850 | if (entry === null) break 1851 | yield entry 1852 | } 1853 | 1854 | this.closeSync() 1855 | } 1856 | 1857 | async *[Symbol.asyncIterator]() { 1858 | while (true) { 1859 | const entry = await this.read() 1860 | if (entry === null) break 1861 | yield entry 1862 | } 1863 | 1864 | await this.close() 1865 | } 1866 | } 1867 | 1868 | class Dirent { 1869 | constructor(parentPath, name, type) { 1870 | this.parentPath = parentPath 1871 | this.name = name 1872 | this.type = type 1873 | } 1874 | 1875 | isFile() { 1876 | return this.type === constants.UV_DIRENT_FILE 1877 | } 1878 | 1879 | isDirectory() { 1880 | return this.type === constants.UV_DIRENT_DIR 1881 | } 1882 | 1883 | isSymbolicLink() { 1884 | return this.type === constants.UV_DIRENT_LINK 1885 | } 1886 | 1887 | isFIFO() { 1888 | return this.type === constants.UV_DIRENT_FIFO 1889 | } 1890 | 1891 | isSocket() { 1892 | return this.type === constants.UV_DIRENT_SOCKET 1893 | } 1894 | 1895 | isCharacterDevice() { 1896 | return this.type === constants.UV_DIRENT_CHAR 1897 | } 1898 | 1899 | isBlockDevice() { 1900 | return this.type === constants.UV_DIRENT_BLOCK 1901 | } 1902 | } 1903 | 1904 | class FileReadStream extends Readable { 1905 | constructor(path, opts = {}) { 1906 | const { eagerOpen = true } = opts 1907 | 1908 | super({ eagerOpen, ...opts }) 1909 | 1910 | this.path = path 1911 | this.fd = typeof opts.fd === 'number' ? opts.fd : -1 1912 | this.flags = opts.flags || 'r' 1913 | this.mode = opts.mode || 0o666 1914 | 1915 | this._offset = opts.start || 0 1916 | this._missing = 0 1917 | 1918 | if (opts.length) { 1919 | this._missing = opts.length 1920 | } else if (typeof opts.end === 'number') { 1921 | this._missing = opts.end - this._offset + 1 1922 | } else { 1923 | this._missing = -1 1924 | } 1925 | } 1926 | 1927 | async _open(cb) { 1928 | let err 1929 | 1930 | if (this.fd === -1) { 1931 | err = null 1932 | try { 1933 | this.fd = await open(this.path, this.flags, this.mode) 1934 | } catch (e) { 1935 | err = e 1936 | } 1937 | 1938 | if (err) return cb(err) 1939 | } 1940 | 1941 | let st 1942 | err = null 1943 | try { 1944 | st = await fstat(this.fd) 1945 | } catch (e) { 1946 | err = e 1947 | } 1948 | 1949 | if (err) return cb(err) 1950 | 1951 | if (this._missing === -1) this._missing = st.size 1952 | 1953 | if (st.size < this._offset) { 1954 | this._offset = st.size 1955 | this._missing = 0 1956 | } else if (st.size < this._offset + this._missing) { 1957 | this._missing = st.size - this._offset 1958 | } 1959 | 1960 | cb(null) 1961 | } 1962 | 1963 | async _read(size) { 1964 | if (this._missing <= 0) return this.push(null) 1965 | 1966 | const data = Buffer.allocUnsafe(Math.min(this._missing, size)) 1967 | 1968 | let len 1969 | let err = null 1970 | try { 1971 | len = await read(this.fd, data, 0, data.byteLength, this._offset) 1972 | } catch (e) { 1973 | err = e 1974 | } 1975 | 1976 | if (err) return this.destroy(err) 1977 | 1978 | if (len === 0) return this.push(null) 1979 | 1980 | if (this._missing < len) len = this._missing 1981 | 1982 | this._missing -= len 1983 | this._offset += len 1984 | 1985 | this.push(data.subarray(0, len)) 1986 | } 1987 | 1988 | async _destroy(err, cb) { 1989 | if (this.fd === -1) return cb(err) 1990 | 1991 | err = null 1992 | try { 1993 | await close(this.fd) 1994 | } catch (e) { 1995 | err = e 1996 | } 1997 | 1998 | cb(err) 1999 | } 2000 | } 2001 | 2002 | class FileWriteStream extends Writable { 2003 | constructor(path, opts = {}) { 2004 | const { eagerOpen = true } = opts 2005 | 2006 | super({ eagerOpen, ...opts }) 2007 | 2008 | this.path = path 2009 | this.fd = typeof opts.fd === 'number' ? opts.fd : -1 2010 | this.flags = opts.flags || 'w' 2011 | this.mode = opts.mode || 0o666 2012 | } 2013 | 2014 | async _open(cb) { 2015 | if (this.fd !== -1) return cb(null) 2016 | 2017 | let err = null 2018 | try { 2019 | this.fd = await open(this.path, this.flags, this.mode) 2020 | } catch (e) { 2021 | err = e 2022 | } 2023 | 2024 | cb(err) 2025 | } 2026 | 2027 | async _writev(batch, cb) { 2028 | let err = null 2029 | try { 2030 | await writev( 2031 | this.fd, 2032 | batch.map(({ chunk }) => chunk) 2033 | ) 2034 | } catch (e) { 2035 | err = e 2036 | } 2037 | 2038 | cb(err) 2039 | } 2040 | 2041 | async _destroy(err, cb) { 2042 | if (this.fd === -1) return cb(err) 2043 | 2044 | err = null 2045 | try { 2046 | await close(this.fd) 2047 | } catch (e) { 2048 | err = e 2049 | } 2050 | 2051 | cb(err) 2052 | } 2053 | } 2054 | 2055 | class Watcher extends EventEmitter { 2056 | constructor(path, opts, onchange) { 2057 | if (typeof opts === 'function') { 2058 | onchange = opts 2059 | opts = {} 2060 | } 2061 | 2062 | if (!opts) opts = {} 2063 | 2064 | const { persistent = true, recursive = false, encoding = 'utf8' } = opts 2065 | 2066 | super() 2067 | 2068 | this._closed = false 2069 | this._encoding = encoding 2070 | this._handle = binding.watcherInit(path, recursive, this, this._onevent, this._onclose) 2071 | 2072 | if (!persistent) this.unref() 2073 | 2074 | if (onchange) this.on('change', onchange) 2075 | } 2076 | 2077 | close() { 2078 | if (this._closed) return 2079 | this._closed = true 2080 | 2081 | binding.watcherClose(this._handle) 2082 | } 2083 | 2084 | ref() { 2085 | if (this._handle) binding.watcherRef(this._handle) 2086 | return this 2087 | } 2088 | 2089 | unref() { 2090 | if (this._handle) binding.watcherUnref(this._handle) 2091 | return this 2092 | } 2093 | 2094 | [Symbol.asyncIterator]() { 2095 | const buffer = [] 2096 | let done = false 2097 | let error = null 2098 | let next = null 2099 | 2100 | this.on('change', (eventType, filename) => { 2101 | if (next) { 2102 | next.resolve({ done: false, value: { eventType, filename } }) 2103 | next = null 2104 | } else { 2105 | buffer.push({ eventType, filename }) 2106 | } 2107 | }) 2108 | .on('error', (err) => { 2109 | done = true 2110 | error = err 2111 | 2112 | if (next) { 2113 | next.reject(error) 2114 | next = null 2115 | } 2116 | }) 2117 | .on('close', () => { 2118 | done = true 2119 | 2120 | if (next) { 2121 | next.resolve({ done }) 2122 | next = null 2123 | } 2124 | }) 2125 | 2126 | return { 2127 | next: () => 2128 | new Promise((resolve, reject) => { 2129 | if (error) return reject(error) 2130 | 2131 | if (buffer.length) return resolve({ done: false, value: buffer.shift() }) 2132 | 2133 | if (done) return resolve({ done }) 2134 | 2135 | next = { resolve, reject } 2136 | }) 2137 | } 2138 | } 2139 | 2140 | _onevent(err, events, filename) { 2141 | if (err) { 2142 | this.close() 2143 | this.emit('error', err) 2144 | } else { 2145 | const path = 2146 | this._encoding === 'buffer' 2147 | ? Buffer.from(filename) 2148 | : Buffer.from(filename).toString(this._encoding) 2149 | 2150 | if (events & binding.UV_RENAME) { 2151 | this.emit('change', 'rename', path) 2152 | } 2153 | 2154 | if (events & binding.UV_CHANGE) { 2155 | this.emit('change', 'change', path) 2156 | } 2157 | } 2158 | } 2159 | 2160 | _onclose() { 2161 | this._handle = null 2162 | 2163 | this.emit('close') 2164 | } 2165 | } 2166 | 2167 | exports.access = access 2168 | exports.appendFile = appendFile 2169 | exports.chmod = chmod 2170 | // exports.chown = chown TODO 2171 | exports.close = close 2172 | exports.copyFile = copyFile 2173 | exports.cp = cp 2174 | exports.exists = exists 2175 | exports.fchmod = fchmod 2176 | // exports.fchown = fchown TODO 2177 | // exports.fdatasync = fdatasync TODO 2178 | exports.fstat = fstat 2179 | // exports.fsync = fsync TODO 2180 | exports.ftruncate = ftruncate 2181 | // exports.futimes = futimes TODO 2182 | // exports.lchmod = lchmod TODO 2183 | // exports.lchown = lchown TODO 2184 | // exports.lutimes = lutimes TODO 2185 | // exports.link = link TODO 2186 | exports.lstat = lstat 2187 | exports.mkdir = mkdir 2188 | // exports.mkdtemp = mkdtemp TODO 2189 | exports.open = open 2190 | exports.opendir = opendir 2191 | exports.read = read 2192 | exports.readFile = readFile 2193 | exports.readdir = readdir 2194 | exports.readlink = readlink 2195 | exports.readv = readv 2196 | exports.realpath = realpath 2197 | exports.rename = rename 2198 | exports.rm = rm 2199 | exports.rmdir = rmdir 2200 | exports.stat = stat 2201 | // exports.statfs = statfs TODO 2202 | exports.symlink = symlink 2203 | // exports.truncate = truncate TODO 2204 | exports.unlink = unlink 2205 | exports.utimes = utimes 2206 | exports.watch = watch 2207 | exports.write = write 2208 | exports.writeFile = writeFile 2209 | exports.writev = writev 2210 | 2211 | exports.accessSync = accessSync 2212 | exports.appendFileSync = appendFileSync 2213 | exports.chmodSync = chmodSync 2214 | // exports.chownSync = chownSync TODO 2215 | exports.closeSync = closeSync 2216 | exports.copyFileSync = copyFileSync 2217 | exports.existsSync = existsSync 2218 | exports.fchmodSync = fchmodSync 2219 | // exports.fchownSync = fchownSync TODO 2220 | // exports.fdatasyncSync = fdatasyncSync TODO 2221 | exports.fstatSync = fstatSync 2222 | // exports.fsyncSync = fsyncSync TODO 2223 | exports.ftruncateSync = ftruncateSync 2224 | // exports.futimesSync = futimesSync TODO 2225 | // exports.lchmodSync = lchmodSync TODO 2226 | // exports.lchownSync = lchownSync TODO 2227 | // exports.lutimesSync = lutimesSync TODO 2228 | // exports.linkSync = linkSync TODO 2229 | exports.lstatSync = lstatSync 2230 | exports.mkdirSync = mkdirSync 2231 | // exports.mkdtempSync = mkdtempSync TODO 2232 | exports.openSync = openSync 2233 | exports.opendirSync = opendirSync 2234 | exports.readFileSync = readFileSync 2235 | exports.readSync = readSync 2236 | exports.readdirSync = readdirSync 2237 | exports.readlinkSync = readlinkSync 2238 | exports.readvSync = readvSync 2239 | exports.realpathSync = realpathSync 2240 | exports.renameSync = renameSync 2241 | exports.rmSync = rmSync 2242 | exports.rmdirSync = rmdirSync 2243 | exports.statSync = statSync 2244 | // exports.statfsSync = statfsSync TODO 2245 | exports.symlinkSync = symlinkSync 2246 | // exports.truncateSync = truncateSync TODO 2247 | exports.unlinkSync = unlinkSync 2248 | exports.utimesSync = utimesSync 2249 | exports.writeFileSync = writeFileSync 2250 | exports.writeSync = writeSync 2251 | exports.writevSync = writevSync 2252 | 2253 | exports.promises = require('./promises') 2254 | 2255 | exports.Stats = Stats 2256 | exports.Dir = Dir 2257 | exports.Dirent = Dirent 2258 | exports.Watcher = Watcher 2259 | 2260 | exports.ReadStream = FileReadStream 2261 | 2262 | exports.createReadStream = function createReadStream(path, opts) { 2263 | return new FileReadStream(path, opts) 2264 | } 2265 | 2266 | exports.WriteStream = FileWriteStream 2267 | 2268 | exports.createWriteStream = function createWriteStream(path, opts) { 2269 | return new FileWriteStream(path, opts) 2270 | } 2271 | 2272 | function toNamespacedPath(filepath) { 2273 | if (typeof filepath !== 'string') { 2274 | if (URL.isURL(filepath)) filepath = fileURLToPath(filepath) 2275 | else filepath = filepath.toString() 2276 | } 2277 | 2278 | return path.toNamespacedPath(filepath) 2279 | } 2280 | 2281 | function toFlags(flags) { 2282 | switch (flags) { 2283 | case 'r': 2284 | return constants.O_RDONLY 2285 | case 'rs': // Fall through. 2286 | case 'sr': 2287 | return constants.O_RDONLY | constants.O_SYNC 2288 | case 'r+': 2289 | return constants.O_RDWR 2290 | case 'rs+': // Fall through. 2291 | case 'sr+': 2292 | return constants.O_RDWR | constants.O_SYNC 2293 | 2294 | case 'w': 2295 | return constants.O_TRUNC | constants.O_CREAT | constants.O_WRONLY 2296 | case 'wx': // Fall through. 2297 | case 'xw': 2298 | return constants.O_TRUNC | constants.O_CREAT | constants.O_WRONLY | constants.O_EXCL 2299 | 2300 | case 'w+': 2301 | return constants.O_TRUNC | constants.O_CREAT | constants.O_RDWR 2302 | case 'wx+': // Fall through. 2303 | case 'xw+': 2304 | return constants.O_TRUNC | constants.O_CREAT | constants.O_RDWR | constants.O_EXCL 2305 | 2306 | case 'a': 2307 | return constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY 2308 | case 'ax': // Fall through. 2309 | case 'xa': 2310 | return constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY | constants.O_EXCL 2311 | case 'as': // Fall through. 2312 | case 'sa': 2313 | return constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY | constants.O_SYNC 2314 | 2315 | case 'a+': 2316 | return constants.O_APPEND | constants.O_CREAT | constants.O_RDWR 2317 | case 'ax+': // Fall through. 2318 | case 'xa+': 2319 | return constants.O_APPEND | constants.O_CREAT | constants.O_RDWR | constants.O_EXCL 2320 | case 'as+': // Fall through. 2321 | case 'sa+': 2322 | return constants.O_APPEND | constants.O_CREAT | constants.O_RDWR | constants.O_SYNC 2323 | default: 2324 | return 0 2325 | } 2326 | } 2327 | 2328 | function toMode(mode) { 2329 | return parseInt(mode, 8) 2330 | } 2331 | -------------------------------------------------------------------------------- /binding.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #ifndef _MSC_VER 12 | #include 13 | #endif 14 | 15 | typedef struct { 16 | uv_fs_t handle; 17 | 18 | js_env_t *env; 19 | js_ref_t *ctx; 20 | js_ref_t *on_result; 21 | 22 | bool exiting; 23 | bool inflight; 24 | 25 | js_deferred_teardown_t *teardown; 26 | } bare_fs_req_t; 27 | 28 | typedef utf8_t bare_fs_path_t[4096 + 1 /* NULL */]; 29 | 30 | typedef struct { 31 | uv_dir_t *handle; 32 | } bare_fs_dir_t; 33 | 34 | typedef struct { 35 | uv_fs_event_t handle; 36 | 37 | js_env_t *env; 38 | js_ref_t *ctx; 39 | js_ref_t *on_event; 40 | js_ref_t *on_close; 41 | 42 | bool exiting; 43 | bool closing; 44 | 45 | js_deferred_teardown_t *teardown; 46 | } bare_fs_watcher_t; 47 | 48 | typedef uv_dirent_t bare_fs_dirent_t; 49 | 50 | enum { 51 | bare_fs_async = true, 52 | bare_fs_sync = false 53 | }; 54 | 55 | static inline void 56 | bare_fs__request_destroy(bare_fs_req_t *req) { 57 | int err; 58 | 59 | js_env_t *env = req->env; 60 | 61 | js_deferred_teardown_t *teardown = req->teardown; 62 | 63 | uv_fs_req_cleanup(&req->handle); 64 | 65 | err = js_delete_reference(env, req->on_result); 66 | assert(err == 0); 67 | 68 | err = js_delete_reference(env, req->ctx); 69 | assert(err == 0); 70 | 71 | err = js_finish_deferred_teardown_callback(teardown); 72 | assert(err == 0); 73 | } 74 | 75 | static void 76 | bare_fs__on_request_teardown(js_deferred_teardown_t *handle, void *data) { 77 | int err; 78 | 79 | bare_fs_req_t *req = (bare_fs_req_t *) data; 80 | 81 | req->exiting = true; 82 | 83 | if (req->inflight) { 84 | err = uv_cancel((uv_req_t *) &req->handle); 85 | if (err < 0) return; 86 | } 87 | 88 | bare_fs__request_destroy(req); 89 | } 90 | 91 | static inline void 92 | bare_fs__on_request_result(uv_fs_t *handle) { 93 | int err; 94 | 95 | bare_fs_req_t *req = (bare_fs_req_t *) handle; 96 | 97 | req->inflight = false; 98 | 99 | if (req->exiting) return bare_fs__request_destroy(req); 100 | 101 | js_env_t *env = req->env; 102 | 103 | js_handle_scope_t *scope; 104 | err = js_open_handle_scope(env, &scope); 105 | assert(err == 0); 106 | 107 | js_value_t *ctx; 108 | err = js_get_reference_value(env, req->ctx, &ctx); 109 | assert(err == 0); 110 | 111 | js_value_t *on_result; 112 | err = js_get_reference_value(env, req->on_result, &on_result); 113 | assert(err == 0); 114 | 115 | int status = handle->result; 116 | 117 | js_value_t *args[2]; 118 | 119 | if (status < 0) { 120 | js_value_t *code; 121 | err = js_create_string_utf8(env, (utf8_t *) uv_err_name(status), -1, &code); 122 | assert(err == 0); 123 | 124 | js_value_t *message; 125 | err = js_create_string_utf8(env, (utf8_t *) uv_strerror(status), -1, &message); 126 | assert(err == 0); 127 | 128 | err = js_create_error(env, code, message, &args[0]); 129 | assert(err == 0); 130 | } else { 131 | err = js_get_null(env, &args[0]); 132 | assert(err == 0); 133 | } 134 | 135 | err = js_create_int32(env, status, &args[1]); 136 | assert(err == 0); 137 | 138 | err = js_call_function(env, ctx, on_result, 2, args, NULL); 139 | (void) err; 140 | 141 | err = js_close_handle_scope(env, scope); 142 | assert(err == 0); 143 | } 144 | 145 | static inline int 146 | bare_fs__request_pending(js_env_t *env, bare_fs_req_t *req, bool async, int *result) { 147 | int err; 148 | 149 | if (async) { 150 | req->inflight = true; 151 | 152 | return 0; 153 | } 154 | 155 | int status = req->handle.result; 156 | 157 | if (status < 0) { 158 | err = js_throw_error(env, uv_err_name(status), uv_strerror(status)); 159 | assert(err == 0); 160 | 161 | return -1; 162 | } 163 | 164 | if (result) *result = status; 165 | 166 | return 1; 167 | } 168 | 169 | static js_value_t * 170 | bare_fs_request_init(js_env_t *env, js_callback_info_t *info) { 171 | int err; 172 | 173 | size_t argc = 2; 174 | js_value_t *argv[2]; 175 | 176 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 177 | assert(err == 0); 178 | 179 | assert(argc == 2); 180 | 181 | js_value_t *handle; 182 | 183 | bare_fs_req_t *req; 184 | err = js_create_arraybuffer(env, sizeof(bare_fs_req_t), (void **) &req, &handle); 185 | assert(err == 0); 186 | 187 | req->env = env; 188 | req->exiting = false; 189 | req->inflight = false; 190 | 191 | err = js_create_reference(env, argv[0], 1, &req->ctx); 192 | assert(err == 0); 193 | 194 | err = js_create_reference(env, argv[1], 1, &req->on_result); 195 | assert(err == 0); 196 | 197 | err = js_add_deferred_teardown_callback(env, bare_fs__on_request_teardown, (void *) req, &req->teardown); 198 | assert(err == 0); 199 | 200 | return handle; 201 | } 202 | 203 | static js_value_t * 204 | bare_fs_request_destroy(js_env_t *env, js_callback_info_t *info) { 205 | int err; 206 | 207 | size_t argc = 1; 208 | js_value_t *argv[1]; 209 | 210 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 211 | assert(err == 0); 212 | 213 | assert(argc == 1); 214 | 215 | bare_fs_req_t *req; 216 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 217 | assert(err == 0); 218 | 219 | bare_fs__request_destroy(req); 220 | 221 | return NULL; 222 | } 223 | 224 | static js_value_t * 225 | bare_fs_request_reset(js_env_t *env, js_callback_info_t *info) { 226 | int err; 227 | 228 | size_t argc = 1; 229 | js_value_t *argv[1]; 230 | 231 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 232 | assert(err == 0); 233 | 234 | assert(argc == 1); 235 | 236 | bare_fs_req_t *req; 237 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 238 | assert(err == 0); 239 | 240 | uv_fs_req_cleanup(&req->handle); 241 | 242 | return NULL; 243 | } 244 | 245 | static js_value_t * 246 | bare_fs_request_result_stat(js_env_t *env, js_callback_info_t *info) { 247 | int err; 248 | 249 | size_t argc = 1; 250 | js_value_t *argv[1]; 251 | 252 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 253 | assert(err == 0); 254 | 255 | assert(argc == 1); 256 | 257 | bare_fs_req_t *req; 258 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 259 | assert(err == 0); 260 | 261 | js_value_t *result; 262 | err = js_create_array_with_length(env, 14, &result); 263 | assert(err == 0); 264 | 265 | uint32_t i = 0; 266 | 267 | #define V(property) \ 268 | { \ 269 | js_value_t *value; \ 270 | err = js_create_int64(env, req->handle.statbuf.st_##property, &value); \ 271 | assert(err == 0); \ 272 | \ 273 | err = js_set_element(env, result, i++, value); \ 274 | assert(err == 0); \ 275 | } 276 | V(dev) 277 | V(mode) 278 | V(nlink) 279 | V(uid) 280 | V(gid) 281 | V(rdev) 282 | V(blksize) 283 | V(ino) 284 | V(size) 285 | V(blocks) 286 | #undef V 287 | 288 | #define V(property) \ 289 | { \ 290 | uv_timespec_t time = req->handle.statbuf.st_##property; \ 291 | \ 292 | js_value_t *value; \ 293 | err = js_create_int64(env, time.tv_sec * 1e3 + time.tv_nsec / 1e6, &value); \ 294 | assert(err == 0); \ 295 | \ 296 | err = js_set_element(env, result, i++, value); \ 297 | assert(err == 0); \ 298 | } 299 | V(atim) 300 | V(mtim) 301 | V(ctim) 302 | V(birthtim) 303 | #undef V 304 | 305 | return result; 306 | } 307 | 308 | static js_value_t * 309 | bare_fs_request_result_string(js_env_t *env, js_callback_info_t *info) { 310 | int err; 311 | 312 | size_t argc = 1; 313 | js_value_t *argv[1]; 314 | 315 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 316 | assert(err == 0); 317 | 318 | assert(argc == 1); 319 | 320 | bare_fs_req_t *req; 321 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 322 | assert(err == 0); 323 | 324 | size_t len = strlen(req->handle.ptr); 325 | 326 | js_value_t *result; 327 | 328 | void *data; 329 | err = js_create_arraybuffer(env, len, (void *) &data, &result); 330 | assert(err == 0); 331 | 332 | strncpy(data, req->handle.ptr, len); 333 | 334 | return result; 335 | } 336 | 337 | static js_value_t * 338 | bare_fs_request_result_dir(js_env_t *env, js_callback_info_t *info) { 339 | int err; 340 | 341 | size_t argc = 1; 342 | js_value_t *argv[1]; 343 | 344 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 345 | assert(err == 0); 346 | 347 | assert(argc == 1); 348 | 349 | bare_fs_req_t *req; 350 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 351 | assert(err == 0); 352 | 353 | js_value_t *result; 354 | 355 | bare_fs_dir_t *dir; 356 | err = js_create_arraybuffer(env, sizeof(bare_fs_dir_t), (void **) &dir, &result); 357 | assert(err == 0); 358 | 359 | dir->handle = req->handle.ptr; 360 | 361 | return result; 362 | } 363 | 364 | static js_value_t * 365 | bare_fs_request_result_dirents(js_env_t *env, js_callback_info_t *info) { 366 | int err; 367 | 368 | size_t argc = 1; 369 | js_value_t *argv[1]; 370 | 371 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 372 | assert(err == 0); 373 | 374 | assert(argc == 1); 375 | 376 | bare_fs_req_t *req; 377 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 378 | assert(err == 0); 379 | 380 | size_t len = req->handle.result; 381 | 382 | js_value_t *result; 383 | err = js_create_array_with_length(env, len, &result); 384 | assert(err == 0); 385 | 386 | uv_dir_t *dir = req->handle.ptr; 387 | 388 | for (uint32_t i = 0; i < len; i++) { 389 | uv_dirent_t *dirent = &dir->dirents[i]; 390 | 391 | js_value_t *entry; 392 | err = js_create_object(env, &entry); 393 | assert(err == 0); 394 | 395 | err = js_set_element(env, result, i, entry); 396 | assert(err == 0); 397 | 398 | size_t name_len = strlen(dirent->name); 399 | 400 | js_value_t *name; 401 | 402 | void *data; 403 | err = js_create_arraybuffer(env, name_len, &data, &name); 404 | assert(err == 0); 405 | 406 | memcpy(data, dirent->name, name_len); 407 | 408 | err = js_set_named_property(env, entry, "name", name); 409 | assert(err == 0); 410 | 411 | js_value_t *type; 412 | err = js_create_uint32(env, dirent->type, &type); 413 | assert(err == 0); 414 | 415 | err = js_set_named_property(env, entry, "type", type); 416 | assert(err == 0); 417 | } 418 | 419 | return result; 420 | } 421 | 422 | static void 423 | bare_fs__on_open(uv_fs_t *handle) { 424 | int err; 425 | 426 | bare_fs_req_t *req = (bare_fs_req_t *) handle; 427 | 428 | int status = handle->result; 429 | 430 | if (req->exiting && status >= 0) { 431 | int fd = status; 432 | 433 | uv_fs_req_cleanup(handle); 434 | 435 | err = uv_fs_close(handle->loop, handle, fd, NULL); 436 | assert(err == 0); 437 | } 438 | 439 | bare_fs__on_request_result(handle); 440 | } 441 | 442 | static inline js_value_t * 443 | bare_fs__open(js_env_t *env, js_callback_info_t *info, bool async) { 444 | int err; 445 | 446 | size_t argc = 4; 447 | js_value_t *argv[4]; 448 | 449 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 450 | assert(err == 0); 451 | 452 | assert(argc == 4); 453 | 454 | bare_fs_req_t *req; 455 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 456 | assert(err == 0); 457 | 458 | bare_fs_path_t path; 459 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 460 | assert(err == 0); 461 | 462 | int32_t flags; 463 | err = js_get_value_int32(env, argv[2], &flags); 464 | assert(err == 0); 465 | 466 | int32_t mode; 467 | err = js_get_value_int32(env, argv[3], &mode); 468 | assert(err == 0); 469 | 470 | uv_loop_t *loop; 471 | err = js_get_env_loop(env, &loop); 472 | assert(err == 0); 473 | 474 | err = uv_fs_open(loop, &req->handle, (char *) path, flags, mode, async ? bare_fs__on_open : NULL); 475 | (void) err; 476 | 477 | int status; 478 | err = bare_fs__request_pending(env, req, async, &status); 479 | if (err != 1) return NULL; 480 | 481 | js_value_t *result; 482 | err = js_create_int32(env, status, &result); 483 | assert(err == 0); 484 | 485 | return result; 486 | } 487 | 488 | static js_value_t * 489 | bare_fs_open(js_env_t *env, js_callback_info_t *info) { 490 | return bare_fs__open(env, info, bare_fs_async); 491 | } 492 | 493 | static js_value_t * 494 | bare_fs_open_sync(js_env_t *env, js_callback_info_t *info) { 495 | return bare_fs__open(env, info, bare_fs_sync); 496 | } 497 | 498 | static void 499 | bare_fs__on_close(uv_fs_t *handle) { 500 | bare_fs__on_request_result(handle); 501 | } 502 | 503 | static inline js_value_t * 504 | bare_fs__close(js_env_t *env, js_callback_info_t *info, bool async) { 505 | int err; 506 | 507 | size_t argc = 2; 508 | js_value_t *argv[2]; 509 | 510 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 511 | assert(err == 0); 512 | 513 | assert(argc == 2); 514 | 515 | bare_fs_req_t *req; 516 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 517 | assert(err == 0); 518 | 519 | uint32_t fd; 520 | err = js_get_value_uint32(env, argv[1], &fd); 521 | assert(err == 0); 522 | 523 | uv_loop_t *loop; 524 | err = js_get_env_loop(env, &loop); 525 | assert(err == 0); 526 | 527 | err = uv_fs_close(loop, &req->handle, fd, async ? bare_fs__on_close : NULL); 528 | (void) err; 529 | 530 | err = bare_fs__request_pending(env, req, async, NULL); 531 | (void) err; 532 | 533 | return NULL; 534 | } 535 | 536 | static js_value_t * 537 | bare_fs_close(js_env_t *env, js_callback_info_t *info) { 538 | return bare_fs__close(env, info, bare_fs_async); 539 | } 540 | 541 | static js_value_t * 542 | bare_fs_close_sync(js_env_t *env, js_callback_info_t *info) { 543 | return bare_fs__close(env, info, bare_fs_sync); 544 | } 545 | 546 | static void 547 | bare_fs__on_access(uv_fs_t *handle) { 548 | bare_fs__on_request_result(handle); 549 | } 550 | 551 | static inline js_value_t * 552 | bare_fs__access(js_env_t *env, js_callback_info_t *info, bool async) { 553 | int err; 554 | 555 | size_t argc = 3; 556 | js_value_t *argv[3]; 557 | 558 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 559 | assert(err == 0); 560 | 561 | assert(argc == 3); 562 | 563 | bare_fs_req_t *req; 564 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 565 | assert(err == 0); 566 | 567 | bare_fs_path_t path; 568 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 569 | assert(err == 0); 570 | 571 | int32_t mode; 572 | err = js_get_value_int32(env, argv[2], &mode); 573 | assert(err == 0); 574 | 575 | uv_loop_t *loop; 576 | err = js_get_env_loop(env, &loop); 577 | assert(err == 0); 578 | 579 | err = uv_fs_access(loop, &req->handle, (char *) path, mode, async ? bare_fs__on_access : NULL); 580 | (void) err; 581 | 582 | err = bare_fs__request_pending(env, req, async, NULL); 583 | (void) err; 584 | 585 | return NULL; 586 | } 587 | 588 | static js_value_t * 589 | bare_fs_access(js_env_t *env, js_callback_info_t *info) { 590 | return bare_fs__access(env, info, bare_fs_async); 591 | } 592 | 593 | static js_value_t * 594 | bare_fs_access_sync(js_env_t *env, js_callback_info_t *info) { 595 | return bare_fs__access(env, info, bare_fs_sync); 596 | } 597 | 598 | static void 599 | bare_fs__on_read(uv_fs_t *handle) { 600 | bare_fs__on_request_result(handle); 601 | } 602 | 603 | static inline js_value_t * 604 | bare_fs__read(js_env_t *env, js_callback_info_t *info, bool async) { 605 | int err; 606 | 607 | size_t argc = 6; 608 | js_value_t *argv[6]; 609 | 610 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 611 | assert(err == 0); 612 | 613 | assert(argc == 6); 614 | 615 | bare_fs_req_t *req; 616 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 617 | assert(err == 0); 618 | 619 | uint32_t fd; 620 | err = js_get_value_uint32(env, argv[1], &fd); 621 | assert(err == 0); 622 | 623 | uint8_t *data; 624 | size_t data_len; 625 | err = js_get_typedarray_info(env, argv[2], NULL, (void **) &data, &data_len, NULL, NULL); 626 | assert(err == 0); 627 | 628 | uint32_t offset; 629 | err = js_get_value_uint32(env, argv[3], &offset); 630 | assert(err == 0); 631 | 632 | uint32_t len; 633 | err = js_get_value_uint32(env, argv[4], &len); 634 | assert(err == 0); 635 | 636 | if (offset >= data_len) len = 0; 637 | else if (offset + len >= data_len) len = data_len - offset; 638 | 639 | int64_t pos; 640 | err = js_get_value_int64(env, argv[5], &pos); 641 | assert(err == 0); 642 | 643 | uv_loop_t *loop; 644 | err = js_get_env_loop(env, &loop); 645 | assert(err == 0); 646 | 647 | uv_buf_t buf = uv_buf_init((void *) (data + offset), len); 648 | 649 | err = uv_fs_read(loop, &req->handle, fd, &buf, 1, pos, async ? bare_fs__on_read : NULL); 650 | (void) err; 651 | 652 | int status; 653 | err = bare_fs__request_pending(env, req, async, &status); 654 | if (err != 1) return NULL; 655 | 656 | js_value_t *result; 657 | err = js_create_int32(env, status, &result); 658 | assert(err == 0); 659 | 660 | return result; 661 | } 662 | 663 | static js_value_t * 664 | bare_fs_read(js_env_t *env, js_callback_info_t *info) { 665 | return bare_fs__read(env, info, bare_fs_async); 666 | } 667 | 668 | static js_value_t * 669 | bare_fs_read_sync(js_env_t *env, js_callback_info_t *info) { 670 | return bare_fs__read(env, info, bare_fs_sync); 671 | } 672 | 673 | static void 674 | bare_fs__on_readv(uv_fs_t *handle) { 675 | bare_fs__on_request_result(handle); 676 | } 677 | 678 | static inline js_value_t * 679 | bare_fs__readv(js_env_t *env, js_callback_info_t *info, bool async) { 680 | int err; 681 | 682 | size_t argc = 4; 683 | js_value_t *argv[4]; 684 | 685 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 686 | assert(err == 0); 687 | 688 | assert(argc == 4); 689 | 690 | bare_fs_req_t *req; 691 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 692 | assert(err == 0); 693 | 694 | uint32_t fd; 695 | err = js_get_value_uint32(env, argv[1], &fd); 696 | assert(err == 0); 697 | 698 | int64_t pos; 699 | err = js_get_value_int64(env, argv[3], &pos); 700 | assert(err == 0); 701 | 702 | uv_loop_t *loop; 703 | err = js_get_env_loop(env, &loop); 704 | assert(err == 0); 705 | 706 | js_value_t *arr = argv[2]; 707 | 708 | uint32_t bufs_len; 709 | err = js_get_array_length(env, arr, &bufs_len); 710 | assert(err == 0); 711 | 712 | uv_buf_t *bufs = malloc(sizeof(uv_buf_t) * bufs_len); 713 | 714 | js_value_t **elements = malloc(bufs_len * sizeof(js_value_t *)); 715 | err = js_get_array_elements(env, arr, elements, bufs_len, 0, NULL); 716 | assert(err == 0); 717 | 718 | for (uint32_t i = 0; i < bufs_len; i++) { 719 | js_value_t *item = elements[i]; 720 | 721 | uv_buf_t *buf = &bufs[i]; 722 | err = js_get_typedarray_info(env, item, NULL, (void **) &buf->base, (size_t *) &buf->len, NULL, NULL); 723 | assert(err == 0); 724 | } 725 | 726 | err = uv_fs_read(loop, &req->handle, fd, bufs, bufs_len, pos, async ? bare_fs__on_readv : NULL); 727 | (void) err; 728 | 729 | free(elements); 730 | free(bufs); 731 | 732 | int status; 733 | err = bare_fs__request_pending(env, req, async, &status); 734 | if (err != 1) return NULL; 735 | 736 | js_value_t *result; 737 | err = js_create_int32(env, status, &result); 738 | assert(err == 0); 739 | 740 | return result; 741 | } 742 | 743 | static js_value_t * 744 | bare_fs_readv(js_env_t *env, js_callback_info_t *info) { 745 | return bare_fs__readv(env, info, bare_fs_async); 746 | } 747 | 748 | static js_value_t * 749 | bare_fs_readv_sync(js_env_t *env, js_callback_info_t *info) { 750 | return bare_fs__readv(env, info, bare_fs_sync); 751 | } 752 | 753 | static void 754 | bare_fs__on_write(uv_fs_t *handle) { 755 | bare_fs__on_request_result(handle); 756 | } 757 | 758 | static inline js_value_t * 759 | bare_fs__write(js_env_t *env, js_callback_info_t *info, bool async) { 760 | int err; 761 | 762 | size_t argc = 6; 763 | js_value_t *argv[6]; 764 | 765 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 766 | assert(err == 0); 767 | 768 | assert(argc == 6); 769 | 770 | bare_fs_req_t *req; 771 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 772 | assert(err == 0); 773 | 774 | uint32_t fd; 775 | err = js_get_value_uint32(env, argv[1], &fd); 776 | assert(err == 0); 777 | 778 | uint8_t *data; 779 | size_t data_len; 780 | err = js_get_typedarray_info(env, argv[2], NULL, (void **) &data, &data_len, NULL, NULL); 781 | assert(err == 0); 782 | 783 | uint32_t offset; 784 | err = js_get_value_uint32(env, argv[3], &offset); 785 | assert(err == 0); 786 | 787 | uint32_t len; 788 | err = js_get_value_uint32(env, argv[4], &len); 789 | assert(err == 0); 790 | 791 | if (offset >= data_len) len = 0; 792 | else if (offset + len >= data_len) len = data_len - offset; 793 | 794 | int64_t pos; 795 | err = js_get_value_int64(env, argv[5], &pos); 796 | assert(err == 0); 797 | 798 | uv_loop_t *loop; 799 | err = js_get_env_loop(env, &loop); 800 | assert(err == 0); 801 | 802 | uv_buf_t buf = uv_buf_init((void *) (data + offset), len); 803 | 804 | err = uv_fs_write(loop, &req->handle, fd, &buf, 1, pos, async ? bare_fs__on_write : NULL); 805 | (void) err; 806 | 807 | int status; 808 | err = bare_fs__request_pending(env, req, async, &status); 809 | if (err != 1) return NULL; 810 | 811 | js_value_t *result; 812 | err = js_create_int32(env, status, &result); 813 | assert(err == 0); 814 | 815 | return result; 816 | } 817 | 818 | static js_value_t * 819 | bare_fs_write(js_env_t *env, js_callback_info_t *info) { 820 | return bare_fs__write(env, info, bare_fs_async); 821 | } 822 | 823 | static js_value_t * 824 | bare_fs_write_sync(js_env_t *env, js_callback_info_t *info) { 825 | return bare_fs__write(env, info, bare_fs_sync); 826 | } 827 | 828 | static void 829 | bare_fs__on_writev(uv_fs_t *handle) { 830 | bare_fs__on_request_result(handle); 831 | } 832 | 833 | static inline js_value_t * 834 | bare_fs__writev(js_env_t *env, js_callback_info_t *info, bool async) { 835 | int err; 836 | 837 | size_t argc = 4; 838 | js_value_t *argv[4]; 839 | 840 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 841 | assert(err == 0); 842 | 843 | assert(argc == 4); 844 | 845 | bare_fs_req_t *req; 846 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 847 | assert(err == 0); 848 | 849 | uint32_t fd; 850 | err = js_get_value_uint32(env, argv[1], &fd); 851 | assert(err == 0); 852 | 853 | int64_t pos; 854 | err = js_get_value_int64(env, argv[3], &pos); 855 | assert(err == 0); 856 | 857 | uv_loop_t *loop; 858 | err = js_get_env_loop(env, &loop); 859 | assert(err == 0); 860 | 861 | js_value_t *arr = argv[2]; 862 | 863 | uint32_t bufs_len; 864 | err = js_get_array_length(env, arr, &bufs_len); 865 | assert(err == 0); 866 | 867 | uv_buf_t *bufs = malloc(sizeof(uv_buf_t) * bufs_len); 868 | 869 | js_value_t **elements = malloc(bufs_len * sizeof(js_value_t *)); 870 | 871 | err = js_get_array_elements(env, arr, elements, bufs_len, 0, NULL); 872 | assert(err == 0); 873 | 874 | for (uint32_t i = 0; i < bufs_len; i++) { 875 | js_value_t *item = elements[i]; 876 | 877 | uv_buf_t *buf = &bufs[i]; 878 | err = js_get_typedarray_info(env, item, NULL, (void **) &buf->base, (size_t *) &buf->len, NULL, NULL); 879 | assert(err == 0); 880 | } 881 | 882 | err = uv_fs_write(loop, &req->handle, fd, bufs, bufs_len, pos, async ? bare_fs__on_writev : NULL); 883 | (void) err; 884 | 885 | free(elements); 886 | free(bufs); 887 | 888 | int status; 889 | err = bare_fs__request_pending(env, req, async, &status); 890 | if (err != 1) return NULL; 891 | 892 | js_value_t *result; 893 | err = js_create_int32(env, status, &result); 894 | assert(err == 0); 895 | 896 | return result; 897 | } 898 | 899 | static js_value_t * 900 | bare_fs_writev(js_env_t *env, js_callback_info_t *info) { 901 | return bare_fs__writev(env, info, bare_fs_async); 902 | } 903 | 904 | static js_value_t * 905 | bare_fs_writev_sync(js_env_t *env, js_callback_info_t *info) { 906 | return bare_fs__writev(env, info, bare_fs_sync); 907 | } 908 | 909 | static void 910 | bare_fs__on_ftruncate(uv_fs_t *handle) { 911 | bare_fs__on_request_result(handle); 912 | } 913 | 914 | static inline js_value_t * 915 | bare_fs__ftruncate(js_env_t *env, js_callback_info_t *info, bool async) { 916 | int err; 917 | 918 | size_t argc = 3; 919 | js_value_t *argv[3]; 920 | 921 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 922 | assert(err == 0); 923 | 924 | assert(argc == 3); 925 | 926 | bare_fs_req_t *req; 927 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 928 | assert(err == 0); 929 | 930 | uint32_t fd; 931 | err = js_get_value_uint32(env, argv[1], &fd); 932 | assert(err == 0); 933 | 934 | int64_t len; 935 | err = js_get_value_int64(env, argv[2], &len); 936 | assert(err == 0); 937 | 938 | uv_loop_t *loop; 939 | err = js_get_env_loop(env, &loop); 940 | assert(err == 0); 941 | 942 | err = uv_fs_ftruncate(loop, &req->handle, fd, len, async ? bare_fs__on_ftruncate : NULL); 943 | (void) err; 944 | 945 | err = bare_fs__request_pending(env, req, async, NULL); 946 | (void) err; 947 | 948 | return NULL; 949 | } 950 | 951 | static js_value_t * 952 | bare_fs_ftruncate(js_env_t *env, js_callback_info_t *info) { 953 | return bare_fs__ftruncate(env, info, bare_fs_async); 954 | } 955 | 956 | static js_value_t * 957 | bare_fs_ftruncate_sync(js_env_t *env, js_callback_info_t *info) { 958 | return bare_fs__ftruncate(env, info, bare_fs_sync); 959 | } 960 | 961 | static void 962 | bare_fs__on_chmod(uv_fs_t *handle) { 963 | bare_fs__on_request_result(handle); 964 | } 965 | 966 | static inline js_value_t * 967 | bare_fs__chmod(js_env_t *env, js_callback_info_t *info, bool async) { 968 | int err; 969 | 970 | size_t argc = 3; 971 | js_value_t *argv[3]; 972 | 973 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 974 | assert(err == 0); 975 | 976 | assert(argc == 3); 977 | 978 | bare_fs_req_t *req; 979 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 980 | assert(err == 0); 981 | 982 | bare_fs_path_t path; 983 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 984 | assert(err == 0); 985 | 986 | int32_t mode; 987 | err = js_get_value_int32(env, argv[2], &mode); 988 | assert(err == 0); 989 | 990 | uv_loop_t *loop; 991 | err = js_get_env_loop(env, &loop); 992 | assert(err == 0); 993 | 994 | err = uv_fs_chmod(loop, &req->handle, (char *) path, mode, async ? bare_fs__on_chmod : NULL); 995 | (void) err; 996 | 997 | err = bare_fs__request_pending(env, req, async, NULL); 998 | (void) err; 999 | 1000 | return NULL; 1001 | } 1002 | 1003 | static js_value_t * 1004 | bare_fs_chmod(js_env_t *env, js_callback_info_t *info) { 1005 | return bare_fs__chmod(env, info, bare_fs_async); 1006 | } 1007 | 1008 | static js_value_t * 1009 | bare_fs_chmod_sync(js_env_t *env, js_callback_info_t *info) { 1010 | return bare_fs__chmod(env, info, bare_fs_sync); 1011 | } 1012 | 1013 | static void 1014 | bare_fs__on_fchmod(uv_fs_t *handle) { 1015 | bare_fs__on_request_result(handle); 1016 | } 1017 | 1018 | static inline js_value_t * 1019 | bare_fs__fchmod(js_env_t *env, js_callback_info_t *info, bool async) { 1020 | int err; 1021 | 1022 | size_t argc = 3; 1023 | js_value_t *argv[3]; 1024 | 1025 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1026 | assert(err == 0); 1027 | 1028 | assert(argc == 3); 1029 | 1030 | bare_fs_req_t *req; 1031 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1032 | assert(err == 0); 1033 | 1034 | uint32_t fd; 1035 | err = js_get_value_uint32(env, argv[1], &fd); 1036 | assert(err == 0); 1037 | 1038 | int32_t mode; 1039 | err = js_get_value_int32(env, argv[2], &mode); 1040 | assert(err == 0); 1041 | 1042 | uv_loop_t *loop; 1043 | err = js_get_env_loop(env, &loop); 1044 | assert(err == 0); 1045 | 1046 | err = uv_fs_fchmod(loop, &req->handle, fd, mode, async ? bare_fs__on_fchmod : NULL); 1047 | (void) err; 1048 | 1049 | err = bare_fs__request_pending(env, req, async, NULL); 1050 | (void) err; 1051 | 1052 | return NULL; 1053 | } 1054 | 1055 | static js_value_t * 1056 | bare_fs_fchmod(js_env_t *env, js_callback_info_t *info) { 1057 | return bare_fs__fchmod(env, info, bare_fs_async); 1058 | } 1059 | 1060 | static js_value_t * 1061 | bare_fs_fchmod_sync(js_env_t *env, js_callback_info_t *info) { 1062 | return bare_fs__fchmod(env, info, bare_fs_sync); 1063 | } 1064 | 1065 | static void 1066 | bare_fs__on_utimes(uv_fs_t *handle) { 1067 | bare_fs__on_request_result(handle); 1068 | } 1069 | 1070 | static inline js_value_t * 1071 | bare_fs__utimes(js_env_t *env, js_callback_info_t *info, bool async) { 1072 | int err; 1073 | 1074 | size_t argc = 4; 1075 | js_value_t *argv[4]; 1076 | 1077 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1078 | assert(err == 0); 1079 | 1080 | assert(argc == 4); 1081 | 1082 | bare_fs_req_t *req; 1083 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1084 | assert(err == 0); 1085 | 1086 | bare_fs_path_t path; 1087 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1088 | assert(err == 0); 1089 | 1090 | double atime; 1091 | err = js_get_value_double(env, argv[2], &atime); 1092 | assert(err == 0); 1093 | 1094 | double mtime; 1095 | err = js_get_value_double(env, argv[3], &mtime); 1096 | assert(err == 0); 1097 | 1098 | uv_loop_t *loop; 1099 | err = js_get_env_loop(env, &loop); 1100 | assert(err == 0); 1101 | 1102 | err = uv_fs_utime(loop, &req->handle, (char *) path, atime, mtime, async ? bare_fs__on_utimes : NULL); 1103 | (void) err; 1104 | 1105 | err = bare_fs__request_pending(env, req, async, NULL); 1106 | (void) err; 1107 | 1108 | return NULL; 1109 | } 1110 | 1111 | static js_value_t * 1112 | bare_fs_utimes(js_env_t *env, js_callback_info_t *info) { 1113 | return bare_fs__utimes(env, info, bare_fs_async); 1114 | } 1115 | 1116 | static js_value_t * 1117 | bare_fs_utimes_sync(js_env_t *env, js_callback_info_t *info) { 1118 | return bare_fs__utimes(env, info, bare_fs_sync); 1119 | } 1120 | 1121 | static void 1122 | bare_fs__on_rename(uv_fs_t *handle) { 1123 | bare_fs__on_request_result(handle); 1124 | } 1125 | 1126 | static inline js_value_t * 1127 | bare_fs__rename(js_env_t *env, js_callback_info_t *info, bool async) { 1128 | int err; 1129 | 1130 | size_t argc = 3; 1131 | js_value_t *argv[3]; 1132 | 1133 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1134 | assert(err == 0); 1135 | 1136 | assert(argc == 3); 1137 | 1138 | bare_fs_req_t *req; 1139 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1140 | assert(err == 0); 1141 | 1142 | bare_fs_path_t src; 1143 | err = js_get_value_string_utf8(env, argv[1], src, sizeof(bare_fs_path_t), NULL); 1144 | assert(err == 0); 1145 | 1146 | bare_fs_path_t dst; 1147 | err = js_get_value_string_utf8(env, argv[2], dst, sizeof(bare_fs_path_t), NULL); 1148 | assert(err == 0); 1149 | 1150 | uv_loop_t *loop; 1151 | err = js_get_env_loop(env, &loop); 1152 | assert(err == 0); 1153 | 1154 | err = uv_fs_rename(loop, &req->handle, (char *) src, (char *) dst, async ? bare_fs__on_rename : NULL); 1155 | (void) err; 1156 | 1157 | err = bare_fs__request_pending(env, req, async, NULL); 1158 | (void) err; 1159 | 1160 | return NULL; 1161 | } 1162 | 1163 | static js_value_t * 1164 | bare_fs_rename(js_env_t *env, js_callback_info_t *info) { 1165 | return bare_fs__rename(env, info, bare_fs_async); 1166 | } 1167 | 1168 | static js_value_t * 1169 | bare_fs_rename_sync(js_env_t *env, js_callback_info_t *info) { 1170 | return bare_fs__rename(env, info, bare_fs_sync); 1171 | } 1172 | 1173 | static void 1174 | bare_fs__on_copyfile(uv_fs_t *handle) { 1175 | bare_fs__on_request_result(handle); 1176 | } 1177 | 1178 | static inline js_value_t * 1179 | bare_fs__copyfile(js_env_t *env, js_callback_info_t *info, bool async) { 1180 | int err; 1181 | 1182 | size_t argc = 4; 1183 | js_value_t *argv[4]; 1184 | 1185 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1186 | assert(err == 0); 1187 | 1188 | assert(argc == 4); 1189 | 1190 | bare_fs_req_t *req; 1191 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1192 | assert(err == 0); 1193 | 1194 | bare_fs_path_t src; 1195 | err = js_get_value_string_utf8(env, argv[1], src, sizeof(bare_fs_path_t), NULL); 1196 | assert(err == 0); 1197 | 1198 | bare_fs_path_t dst; 1199 | err = js_get_value_string_utf8(env, argv[2], dst, sizeof(bare_fs_path_t), NULL); 1200 | assert(err == 0); 1201 | 1202 | int32_t mode; 1203 | err = js_get_value_int32(env, argv[3], &mode); 1204 | assert(err == 0); 1205 | 1206 | uv_loop_t *loop; 1207 | err = js_get_env_loop(env, &loop); 1208 | assert(err == 0); 1209 | 1210 | err = uv_fs_copyfile(loop, &req->handle, (char *) src, (char *) dst, mode, async ? bare_fs__on_copyfile : NULL); 1211 | (void) err; 1212 | 1213 | err = bare_fs__request_pending(env, req, async, NULL); 1214 | (void) err; 1215 | 1216 | return NULL; 1217 | } 1218 | 1219 | static js_value_t * 1220 | bare_fs_copyfile(js_env_t *env, js_callback_info_t *info) { 1221 | return bare_fs__copyfile(env, info, bare_fs_async); 1222 | } 1223 | 1224 | static js_value_t * 1225 | bare_fs_copyfile_sync(js_env_t *env, js_callback_info_t *info) { 1226 | return bare_fs__copyfile(env, info, bare_fs_sync); 1227 | } 1228 | 1229 | static void 1230 | bare_fs__on_mkdir(uv_fs_t *handle) { 1231 | bare_fs__on_request_result(handle); 1232 | } 1233 | 1234 | static inline js_value_t * 1235 | bare_fs__mkdir(js_env_t *env, js_callback_info_t *info, bool async) { 1236 | int err; 1237 | 1238 | size_t argc = 3; 1239 | js_value_t *argv[3]; 1240 | 1241 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1242 | assert(err == 0); 1243 | 1244 | assert(argc == 3); 1245 | 1246 | bare_fs_req_t *req; 1247 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1248 | assert(err == 0); 1249 | 1250 | bare_fs_path_t path; 1251 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1252 | assert(err == 0); 1253 | 1254 | int32_t mode; 1255 | err = js_get_value_int32(env, argv[2], &mode); 1256 | assert(err == 0); 1257 | 1258 | uv_loop_t *loop; 1259 | err = js_get_env_loop(env, &loop); 1260 | assert(err == 0); 1261 | 1262 | err = uv_fs_mkdir(loop, &req->handle, (char *) path, mode, async ? bare_fs__on_mkdir : NULL); 1263 | (void) err; 1264 | 1265 | err = bare_fs__request_pending(env, req, async, NULL); 1266 | (void) err; 1267 | 1268 | return NULL; 1269 | } 1270 | 1271 | static js_value_t * 1272 | bare_fs_mkdir(js_env_t *env, js_callback_info_t *info) { 1273 | return bare_fs__mkdir(env, info, bare_fs_async); 1274 | } 1275 | 1276 | static js_value_t * 1277 | bare_fs_mkdir_sync(js_env_t *env, js_callback_info_t *info) { 1278 | return bare_fs__mkdir(env, info, bare_fs_sync); 1279 | } 1280 | 1281 | static void 1282 | bare_fs__on_rmdir(uv_fs_t *handle) { 1283 | bare_fs__on_request_result(handle); 1284 | } 1285 | 1286 | static inline js_value_t * 1287 | bare_fs__rmdir(js_env_t *env, js_callback_info_t *info, bool async) { 1288 | int err; 1289 | 1290 | size_t argc = 2; 1291 | js_value_t *argv[2]; 1292 | 1293 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1294 | assert(err == 0); 1295 | 1296 | assert(argc == 2); 1297 | 1298 | bare_fs_req_t *req; 1299 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1300 | assert(err == 0); 1301 | 1302 | bare_fs_path_t path; 1303 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1304 | assert(err == 0); 1305 | 1306 | uv_loop_t *loop; 1307 | err = js_get_env_loop(env, &loop); 1308 | assert(err == 0); 1309 | 1310 | err = uv_fs_rmdir(loop, &req->handle, (char *) path, async ? bare_fs__on_rmdir : NULL); 1311 | (void) err; 1312 | 1313 | err = bare_fs__request_pending(env, req, async, NULL); 1314 | (void) err; 1315 | 1316 | return NULL; 1317 | } 1318 | 1319 | static js_value_t * 1320 | bare_fs_rmdir(js_env_t *env, js_callback_info_t *info) { 1321 | return bare_fs__rmdir(env, info, bare_fs_async); 1322 | } 1323 | 1324 | static js_value_t * 1325 | bare_fs_rmdir_sync(js_env_t *env, js_callback_info_t *info) { 1326 | return bare_fs__rmdir(env, info, bare_fs_sync); 1327 | } 1328 | 1329 | static void 1330 | bare_fs__on_stat(uv_fs_t *handle) { 1331 | bare_fs__on_request_result(handle); 1332 | } 1333 | 1334 | static inline js_value_t * 1335 | bare_fs__stat(js_env_t *env, js_callback_info_t *info, bool async) { 1336 | int err; 1337 | 1338 | size_t argc = 2; 1339 | js_value_t *argv[2]; 1340 | 1341 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1342 | assert(err == 0); 1343 | 1344 | assert(argc == 2); 1345 | 1346 | bare_fs_req_t *req; 1347 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1348 | assert(err == 0); 1349 | 1350 | bare_fs_path_t path; 1351 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1352 | assert(err == 0); 1353 | 1354 | uv_loop_t *loop; 1355 | err = js_get_env_loop(env, &loop); 1356 | assert(err == 0); 1357 | 1358 | err = uv_fs_stat(loop, &req->handle, (char *) path, async ? bare_fs__on_stat : NULL); 1359 | (void) err; 1360 | 1361 | err = bare_fs__request_pending(env, req, async, NULL); 1362 | (void) err; 1363 | 1364 | return NULL; 1365 | } 1366 | 1367 | static js_value_t * 1368 | bare_fs_stat(js_env_t *env, js_callback_info_t *info) { 1369 | return bare_fs__stat(env, info, bare_fs_async); 1370 | } 1371 | 1372 | static js_value_t * 1373 | bare_fs_stat_sync(js_env_t *env, js_callback_info_t *info) { 1374 | return bare_fs__stat(env, info, bare_fs_sync); 1375 | } 1376 | 1377 | static void 1378 | bare_fs__on_lstat(uv_fs_t *handle) { 1379 | bare_fs__on_request_result(handle); 1380 | } 1381 | 1382 | static inline js_value_t * 1383 | bare_fs__lstat(js_env_t *env, js_callback_info_t *info, bool async) { 1384 | int err; 1385 | 1386 | size_t argc = 2; 1387 | js_value_t *argv[2]; 1388 | 1389 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1390 | assert(err == 0); 1391 | 1392 | assert(argc == 2); 1393 | 1394 | bare_fs_req_t *req; 1395 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1396 | assert(err == 0); 1397 | 1398 | bare_fs_path_t path; 1399 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1400 | assert(err == 0); 1401 | 1402 | uv_loop_t *loop; 1403 | err = js_get_env_loop(env, &loop); 1404 | assert(err == 0); 1405 | 1406 | err = uv_fs_lstat(loop, &req->handle, (char *) path, async ? bare_fs__on_lstat : NULL); 1407 | (void) err; 1408 | 1409 | err = bare_fs__request_pending(env, req, async, NULL); 1410 | (void) err; 1411 | 1412 | return NULL; 1413 | } 1414 | 1415 | static js_value_t * 1416 | bare_fs_lstat(js_env_t *env, js_callback_info_t *info) { 1417 | return bare_fs__lstat(env, info, bare_fs_async); 1418 | } 1419 | 1420 | static js_value_t * 1421 | bare_fs_lstat_sync(js_env_t *env, js_callback_info_t *info) { 1422 | return bare_fs__lstat(env, info, bare_fs_sync); 1423 | } 1424 | 1425 | static void 1426 | bare_fs__on_fstat(uv_fs_t *handle) { 1427 | bare_fs__on_request_result(handle); 1428 | } 1429 | 1430 | static inline js_value_t * 1431 | bare_fs__fstat(js_env_t *env, js_callback_info_t *info, bool async) { 1432 | int err; 1433 | 1434 | size_t argc = 2; 1435 | js_value_t *argv[2]; 1436 | 1437 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1438 | assert(err == 0); 1439 | 1440 | assert(argc == 2); 1441 | 1442 | bare_fs_req_t *req; 1443 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1444 | assert(err == 0); 1445 | 1446 | uint32_t fd; 1447 | err = js_get_value_uint32(env, argv[1], &fd); 1448 | assert(err == 0); 1449 | 1450 | uv_loop_t *loop; 1451 | err = js_get_env_loop(env, &loop); 1452 | assert(err == 0); 1453 | 1454 | err = uv_fs_fstat(loop, &req->handle, fd, async ? bare_fs__on_fstat : NULL); 1455 | (void) err; 1456 | 1457 | err = bare_fs__request_pending(env, req, async, NULL); 1458 | (void) err; 1459 | 1460 | return NULL; 1461 | } 1462 | 1463 | static js_value_t * 1464 | bare_fs_fstat(js_env_t *env, js_callback_info_t *info) { 1465 | return bare_fs__fstat(env, info, bare_fs_async); 1466 | } 1467 | 1468 | static js_value_t * 1469 | bare_fs_fstat_sync(js_env_t *env, js_callback_info_t *info) { 1470 | return bare_fs__fstat(env, info, bare_fs_sync); 1471 | } 1472 | 1473 | static void 1474 | bare_fs__on_unlink(uv_fs_t *handle) { 1475 | bare_fs__on_request_result(handle); 1476 | } 1477 | 1478 | static inline js_value_t * 1479 | bare_fs__unlink(js_env_t *env, js_callback_info_t *info, bool async) { 1480 | int err; 1481 | 1482 | size_t argc = 2; 1483 | js_value_t *argv[2]; 1484 | 1485 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1486 | assert(err == 0); 1487 | 1488 | assert(argc == 2); 1489 | 1490 | bare_fs_req_t *req; 1491 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1492 | assert(err == 0); 1493 | 1494 | bare_fs_path_t path; 1495 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1496 | assert(err == 0); 1497 | 1498 | uv_loop_t *loop; 1499 | err = js_get_env_loop(env, &loop); 1500 | assert(err == 0); 1501 | 1502 | err = uv_fs_unlink(loop, &req->handle, (char *) path, async ? bare_fs__on_unlink : NULL); 1503 | (void) err; 1504 | 1505 | err = bare_fs__request_pending(env, req, async, NULL); 1506 | (void) err; 1507 | 1508 | return NULL; 1509 | } 1510 | 1511 | static js_value_t * 1512 | bare_fs_unlink(js_env_t *env, js_callback_info_t *info) { 1513 | return bare_fs__unlink(env, info, bare_fs_async); 1514 | } 1515 | 1516 | static js_value_t * 1517 | bare_fs_unlink_sync(js_env_t *env, js_callback_info_t *info) { 1518 | return bare_fs__unlink(env, info, bare_fs_sync); 1519 | } 1520 | 1521 | static void 1522 | bare_fs__on_realpath(uv_fs_t *handle) { 1523 | bare_fs__on_request_result(handle); 1524 | } 1525 | 1526 | static inline js_value_t * 1527 | bare_fs__realpath(js_env_t *env, js_callback_info_t *info, bool async) { 1528 | int err; 1529 | 1530 | size_t argc = 2; 1531 | js_value_t *argv[2]; 1532 | 1533 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1534 | assert(err == 0); 1535 | 1536 | assert(argc == 2); 1537 | 1538 | bare_fs_req_t *req; 1539 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1540 | assert(err == 0); 1541 | 1542 | bare_fs_path_t path; 1543 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1544 | assert(err == 0); 1545 | 1546 | uv_loop_t *loop; 1547 | err = js_get_env_loop(env, &loop); 1548 | assert(err == 0); 1549 | 1550 | err = uv_fs_realpath(loop, &req->handle, (char *) path, async ? bare_fs__on_realpath : NULL); 1551 | (void) err; 1552 | 1553 | err = bare_fs__request_pending(env, req, async, NULL); 1554 | (void) err; 1555 | 1556 | return NULL; 1557 | } 1558 | 1559 | static js_value_t * 1560 | bare_fs_realpath(js_env_t *env, js_callback_info_t *info) { 1561 | return bare_fs__realpath(env, info, bare_fs_async); 1562 | } 1563 | 1564 | static js_value_t * 1565 | bare_fs_realpath_sync(js_env_t *env, js_callback_info_t *info) { 1566 | return bare_fs__realpath(env, info, bare_fs_sync); 1567 | } 1568 | 1569 | static void 1570 | bare_fs__on_readlink(uv_fs_t *handle) { 1571 | bare_fs__on_request_result(handle); 1572 | } 1573 | 1574 | static inline js_value_t * 1575 | bare_fs__readlink(js_env_t *env, js_callback_info_t *info, bool async) { 1576 | int err; 1577 | 1578 | size_t argc = 2; 1579 | js_value_t *argv[2]; 1580 | 1581 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1582 | assert(err == 0); 1583 | 1584 | assert(argc == 2); 1585 | 1586 | bare_fs_req_t *req; 1587 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1588 | assert(err == 0); 1589 | 1590 | bare_fs_path_t path; 1591 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1592 | assert(err == 0); 1593 | 1594 | uv_loop_t *loop; 1595 | err = js_get_env_loop(env, &loop); 1596 | assert(err == 0); 1597 | 1598 | err = uv_fs_readlink(loop, &req->handle, (char *) path, async ? bare_fs__on_readlink : NULL); 1599 | (void) err; 1600 | 1601 | err = bare_fs__request_pending(env, req, async, NULL); 1602 | (void) err; 1603 | 1604 | return NULL; 1605 | } 1606 | 1607 | static js_value_t * 1608 | bare_fs_readlink(js_env_t *env, js_callback_info_t *info) { 1609 | return bare_fs__readlink(env, info, bare_fs_async); 1610 | } 1611 | 1612 | static js_value_t * 1613 | bare_fs_readlink_sync(js_env_t *env, js_callback_info_t *info) { 1614 | return bare_fs__readlink(env, info, bare_fs_sync); 1615 | } 1616 | 1617 | static void 1618 | bare_fs__on_symlink(uv_fs_t *handle) { 1619 | bare_fs__on_request_result(handle); 1620 | } 1621 | 1622 | static inline js_value_t * 1623 | bare_fs__symlink(js_env_t *env, js_callback_info_t *info, bool async) { 1624 | int err; 1625 | 1626 | size_t argc = 4; 1627 | js_value_t *argv[4]; 1628 | 1629 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1630 | assert(err == 0); 1631 | 1632 | assert(argc == 4); 1633 | 1634 | bare_fs_req_t *req; 1635 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1636 | assert(err == 0); 1637 | 1638 | bare_fs_path_t target; 1639 | err = js_get_value_string_utf8(env, argv[1], target, sizeof(bare_fs_path_t), NULL); 1640 | assert(err == 0); 1641 | 1642 | bare_fs_path_t path; 1643 | err = js_get_value_string_utf8(env, argv[2], path, sizeof(bare_fs_path_t), NULL); 1644 | assert(err == 0); 1645 | 1646 | int32_t flags; 1647 | err = js_get_value_int32(env, argv[3], &flags); 1648 | assert(err == 0); 1649 | 1650 | uv_loop_t *loop; 1651 | err = js_get_env_loop(env, &loop); 1652 | assert(err == 0); 1653 | 1654 | err = uv_fs_symlink(loop, &req->handle, (char *) target, (char *) path, flags, async ? bare_fs__on_symlink : NULL); 1655 | (void) err; 1656 | 1657 | err = bare_fs__request_pending(env, req, async, NULL); 1658 | (void) err; 1659 | 1660 | return NULL; 1661 | } 1662 | 1663 | static js_value_t * 1664 | bare_fs_symlink(js_env_t *env, js_callback_info_t *info) { 1665 | return bare_fs__symlink(env, info, bare_fs_async); 1666 | } 1667 | 1668 | static js_value_t * 1669 | bare_fs_symlink_sync(js_env_t *env, js_callback_info_t *info) { 1670 | return bare_fs__symlink(env, info, bare_fs_sync); 1671 | } 1672 | 1673 | static void 1674 | bare_fs__on_opendir(uv_fs_t *handle) { 1675 | int err; 1676 | 1677 | bare_fs_req_t *req = (bare_fs_req_t *) handle; 1678 | 1679 | int status = handle->result; 1680 | 1681 | if (req->exiting && status >= 0) { 1682 | uv_dir_t *dir = handle->ptr; 1683 | 1684 | uv_fs_req_cleanup(handle); 1685 | 1686 | err = uv_fs_closedir(handle->loop, handle, dir, NULL); 1687 | assert(err == 0); 1688 | } 1689 | 1690 | bare_fs__on_request_result(handle); 1691 | } 1692 | 1693 | static inline js_value_t * 1694 | bare_fs__opendir(js_env_t *env, js_callback_info_t *info, bool async) { 1695 | int err; 1696 | 1697 | size_t argc = 2; 1698 | js_value_t *argv[2]; 1699 | 1700 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1701 | assert(err == 0); 1702 | 1703 | assert(argc == 2); 1704 | 1705 | bare_fs_req_t *req; 1706 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1707 | assert(err == 0); 1708 | 1709 | bare_fs_path_t path; 1710 | err = js_get_value_string_utf8(env, argv[1], path, sizeof(bare_fs_path_t), NULL); 1711 | assert(err == 0); 1712 | 1713 | uv_loop_t *loop; 1714 | err = js_get_env_loop(env, &loop); 1715 | assert(err == 0); 1716 | 1717 | err = uv_fs_opendir(loop, &req->handle, (char *) path, async ? bare_fs__on_opendir : NULL); 1718 | (void) err; 1719 | 1720 | err = bare_fs__request_pending(env, req, async, NULL); 1721 | (void) err; 1722 | 1723 | return NULL; 1724 | } 1725 | 1726 | static js_value_t * 1727 | bare_fs_opendir(js_env_t *env, js_callback_info_t *info) { 1728 | return bare_fs__opendir(env, info, bare_fs_async); 1729 | } 1730 | 1731 | static js_value_t * 1732 | bare_fs_opendir_sync(js_env_t *env, js_callback_info_t *info) { 1733 | return bare_fs__opendir(env, info, bare_fs_sync); 1734 | } 1735 | 1736 | static void 1737 | bare_fs__on_readdir(uv_fs_t *handle) { 1738 | bare_fs__on_request_result(handle); 1739 | } 1740 | 1741 | static inline js_value_t * 1742 | bare_fs__readdir(js_env_t *env, js_callback_info_t *info, bool async) { 1743 | int err; 1744 | 1745 | size_t argc = 3; 1746 | js_value_t *argv[3]; 1747 | 1748 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1749 | assert(err == 0); 1750 | 1751 | assert(argc == 3); 1752 | 1753 | bare_fs_req_t *req; 1754 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1755 | assert(err == 0); 1756 | 1757 | bare_fs_dir_t *dir; 1758 | err = js_get_arraybuffer_info(env, argv[1], (void **) &dir, NULL); 1759 | assert(err == 0); 1760 | 1761 | uint32_t capacity; 1762 | err = js_get_value_uint32(env, argv[2], &capacity); 1763 | assert(err == 0); 1764 | 1765 | js_value_t *result; 1766 | 1767 | bare_fs_dirent_t *dirents; 1768 | err = js_create_arraybuffer(env, capacity * sizeof(bare_fs_dirent_t), (void **) &dirents, &result); 1769 | assert(err == 0); 1770 | 1771 | uv_loop_t *loop; 1772 | err = js_get_env_loop(env, &loop); 1773 | assert(err == 0); 1774 | 1775 | dir->handle->dirents = dirents; 1776 | dir->handle->nentries = capacity; 1777 | 1778 | err = uv_fs_readdir(loop, &req->handle, dir->handle, async ? bare_fs__on_readdir : NULL); 1779 | (void) err; 1780 | 1781 | err = bare_fs__request_pending(env, req, async, NULL); 1782 | (void) err; 1783 | 1784 | return result; 1785 | } 1786 | 1787 | static js_value_t * 1788 | bare_fs_readdir(js_env_t *env, js_callback_info_t *info) { 1789 | return bare_fs__readdir(env, info, bare_fs_async); 1790 | } 1791 | 1792 | static js_value_t * 1793 | bare_fs_readdir_sync(js_env_t *env, js_callback_info_t *info) { 1794 | return bare_fs__readdir(env, info, bare_fs_sync); 1795 | } 1796 | 1797 | static void 1798 | bare_fs__on_closedir(uv_fs_t *handle) { 1799 | bare_fs__on_request_result(handle); 1800 | } 1801 | 1802 | static inline js_value_t * 1803 | bare_fs__closedir(js_env_t *env, js_callback_info_t *info, bool async) { 1804 | int err; 1805 | 1806 | size_t argc = 2; 1807 | js_value_t *argv[2]; 1808 | 1809 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1810 | assert(err == 0); 1811 | 1812 | assert(argc == 2); 1813 | 1814 | bare_fs_req_t *req; 1815 | err = js_get_arraybuffer_info(env, argv[0], (void **) &req, NULL); 1816 | assert(err == 0); 1817 | 1818 | bare_fs_dir_t *dir; 1819 | err = js_get_arraybuffer_info(env, argv[1], (void **) &dir, NULL); 1820 | assert(err == 0); 1821 | 1822 | uv_loop_t *loop; 1823 | err = js_get_env_loop(env, &loop); 1824 | assert(err == 0); 1825 | 1826 | err = uv_fs_closedir(loop, &req->handle, dir->handle, async ? bare_fs__on_closedir : NULL); 1827 | (void) err; 1828 | 1829 | err = bare_fs__request_pending(env, req, async, NULL); 1830 | (void) err; 1831 | 1832 | return NULL; 1833 | } 1834 | 1835 | static js_value_t * 1836 | bare_fs_closedir(js_env_t *env, js_callback_info_t *info) { 1837 | return bare_fs__closedir(env, info, bare_fs_async); 1838 | } 1839 | 1840 | static js_value_t * 1841 | bare_fs_closedir_sync(js_env_t *env, js_callback_info_t *info) { 1842 | return bare_fs__closedir(env, info, bare_fs_sync); 1843 | } 1844 | 1845 | static void 1846 | bare_fs__on_watcher_event(uv_fs_event_t *handle, const char *filename, int events, int status) { 1847 | int err; 1848 | 1849 | bare_fs_watcher_t *watcher = (bare_fs_watcher_t *) handle; 1850 | 1851 | if (watcher->exiting) return; 1852 | 1853 | js_env_t *env = watcher->env; 1854 | 1855 | js_handle_scope_t *scope; 1856 | err = js_open_handle_scope(env, &scope); 1857 | assert(err == 0); 1858 | 1859 | js_value_t *ctx; 1860 | err = js_get_reference_value(env, watcher->ctx, &ctx); 1861 | assert(err == 0); 1862 | 1863 | js_value_t *on_event; 1864 | err = js_get_reference_value(env, watcher->on_event, &on_event); 1865 | assert(err == 0); 1866 | 1867 | js_value_t *args[3]; 1868 | 1869 | if (status < 0) { 1870 | js_value_t *code; 1871 | err = js_create_string_utf8(env, (utf8_t *) uv_err_name(status), -1, &code); 1872 | assert(err == 0); 1873 | 1874 | js_value_t *message; 1875 | err = js_create_string_utf8(env, (utf8_t *) uv_strerror(status), -1, &message); 1876 | assert(err == 0); 1877 | 1878 | err = js_create_error(env, code, message, &args[0]); 1879 | assert(err == 0); 1880 | 1881 | err = js_create_int32(env, 0, &args[1]); 1882 | assert(err == 0); 1883 | 1884 | err = js_get_null(env, &args[2]); 1885 | assert(err == 0); 1886 | } else { 1887 | err = js_get_null(env, &args[0]); 1888 | assert(err == 0); 1889 | 1890 | err = js_create_int32(env, events, &args[1]); 1891 | assert(err == 0); 1892 | 1893 | size_t len = strlen(filename); 1894 | 1895 | void *data; 1896 | err = js_create_arraybuffer(env, len, &data, &args[2]); 1897 | assert(err == 0); 1898 | 1899 | memcpy(data, (void *) filename, len); 1900 | } 1901 | 1902 | err = js_call_function(env, ctx, on_event, 3, args, NULL); 1903 | (void) err; 1904 | 1905 | err = js_close_handle_scope(env, scope); 1906 | assert(err == 0); 1907 | } 1908 | 1909 | static void 1910 | bare_fs__on_watcher_close(uv_handle_t *handle) { 1911 | int err; 1912 | 1913 | bare_fs_watcher_t *watcher = (bare_fs_watcher_t *) handle; 1914 | 1915 | js_env_t *env = watcher->env; 1916 | 1917 | js_deferred_teardown_t *teardown = watcher->teardown; 1918 | 1919 | if (watcher->exiting) { 1920 | err = js_delete_reference(env, watcher->on_event); 1921 | assert(err == 0); 1922 | 1923 | err = js_delete_reference(env, watcher->on_close); 1924 | assert(err == 0); 1925 | 1926 | err = js_delete_reference(env, watcher->ctx); 1927 | assert(err == 0); 1928 | } else { 1929 | js_handle_scope_t *scope; 1930 | err = js_open_handle_scope(env, &scope); 1931 | assert(err == 0); 1932 | 1933 | js_value_t *ctx; 1934 | err = js_get_reference_value(env, watcher->ctx, &ctx); 1935 | assert(err == 0); 1936 | 1937 | js_value_t *on_close; 1938 | err = js_get_reference_value(env, watcher->on_close, &on_close); 1939 | assert(err == 0); 1940 | 1941 | err = js_delete_reference(env, watcher->on_event); 1942 | assert(err == 0); 1943 | 1944 | err = js_delete_reference(env, watcher->on_close); 1945 | assert(err == 0); 1946 | 1947 | err = js_delete_reference(env, watcher->ctx); 1948 | assert(err == 0); 1949 | 1950 | err = js_call_function(env, ctx, on_close, 0, NULL, NULL); 1951 | (void) err; 1952 | 1953 | err = js_close_handle_scope(env, scope); 1954 | assert(err == 0); 1955 | } 1956 | 1957 | err = js_finish_deferred_teardown_callback(teardown); 1958 | assert(err == 0); 1959 | } 1960 | 1961 | static void 1962 | bare_fs__on_watcher_teardown(js_deferred_teardown_t *handle, void *data) { 1963 | bare_fs_watcher_t *watcher = (bare_fs_watcher_t *) data; 1964 | 1965 | watcher->exiting = true; 1966 | 1967 | if (watcher->closing) return; 1968 | 1969 | uv_close((uv_handle_t *) &watcher->handle, bare_fs__on_watcher_close); 1970 | } 1971 | 1972 | static js_value_t * 1973 | bare_fs_watcher_init(js_env_t *env, js_callback_info_t *info) { 1974 | int err; 1975 | 1976 | size_t argc = 5; 1977 | js_value_t *argv[5]; 1978 | 1979 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 1980 | assert(err == 0); 1981 | 1982 | assert(argc == 5); 1983 | 1984 | bare_fs_path_t path; 1985 | err = js_get_value_string_utf8(env, argv[0], path, sizeof(bare_fs_path_t), NULL); 1986 | assert(err == 0); 1987 | 1988 | bool recursive; 1989 | err = js_get_value_bool(env, argv[1], &recursive); 1990 | assert(err == 0); 1991 | 1992 | js_value_t *result; 1993 | 1994 | bare_fs_watcher_t *watcher; 1995 | err = js_create_arraybuffer(env, sizeof(bare_fs_watcher_t), (void **) &watcher, &result); 1996 | assert(err == 0); 1997 | 1998 | uv_loop_t *loop; 1999 | err = js_get_env_loop(env, &loop); 2000 | assert(err == 0); 2001 | 2002 | err = uv_fs_event_init(loop, &watcher->handle); 2003 | 2004 | if (err < 0) { 2005 | err = js_throw_error(env, uv_err_name(err), uv_strerror(err)); 2006 | assert(err == 0); 2007 | 2008 | return NULL; 2009 | } 2010 | 2011 | err = uv_fs_event_start(&watcher->handle, bare_fs__on_watcher_event, (char *) path, recursive ? UV_FS_EVENT_RECURSIVE : 0); 2012 | assert(err == 0); 2013 | 2014 | watcher->env = env; 2015 | watcher->closing = false; 2016 | watcher->exiting = false; 2017 | 2018 | err = js_create_reference(env, argv[2], 1, &watcher->ctx); 2019 | assert(err == 0); 2020 | 2021 | err = js_create_reference(env, argv[3], 1, &watcher->on_event); 2022 | assert(err == 0); 2023 | 2024 | err = js_create_reference(env, argv[4], 1, &watcher->on_close); 2025 | assert(err == 0); 2026 | 2027 | err = js_add_deferred_teardown_callback(env, bare_fs__on_watcher_teardown, (void *) watcher, &watcher->teardown); 2028 | assert(err == 0); 2029 | 2030 | return result; 2031 | } 2032 | 2033 | static js_value_t * 2034 | bare_fs_watcher_close(js_env_t *env, js_callback_info_t *info) { 2035 | int err; 2036 | 2037 | size_t argc = 1; 2038 | js_value_t *argv[1]; 2039 | 2040 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 2041 | assert(err == 0); 2042 | 2043 | assert(argc == 1); 2044 | 2045 | bare_fs_watcher_t *watcher; 2046 | err = js_get_arraybuffer_info(env, argv[0], (void **) &watcher, NULL); 2047 | assert(err == 0); 2048 | 2049 | err = uv_fs_event_stop(&watcher->handle); 2050 | assert(err == 0); 2051 | 2052 | watcher->closing = true; 2053 | 2054 | uv_close((uv_handle_t *) &watcher->handle, bare_fs__on_watcher_close); 2055 | 2056 | return NULL; 2057 | } 2058 | 2059 | static js_value_t * 2060 | bare_fs_watcher_ref(js_env_t *env, js_callback_info_t *info) { 2061 | int err; 2062 | 2063 | size_t argc = 1; 2064 | js_value_t *argv[1]; 2065 | 2066 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 2067 | assert(err == 0); 2068 | 2069 | assert(argc == 1); 2070 | 2071 | bare_fs_watcher_t *watcher; 2072 | err = js_get_arraybuffer_info(env, argv[0], (void **) &watcher, NULL); 2073 | assert(err == 0); 2074 | 2075 | uv_ref((uv_handle_t *) &watcher->handle); 2076 | 2077 | return NULL; 2078 | } 2079 | 2080 | static js_value_t * 2081 | bare_fs_watcher_unref(js_env_t *env, js_callback_info_t *info) { 2082 | int err; 2083 | 2084 | size_t argc = 1; 2085 | js_value_t *argv[1]; 2086 | 2087 | err = js_get_callback_info(env, info, &argc, argv, NULL, NULL); 2088 | assert(err == 0); 2089 | 2090 | assert(argc == 1); 2091 | 2092 | bare_fs_watcher_t *watcher; 2093 | err = js_get_arraybuffer_info(env, argv[0], (void **) &watcher, NULL); 2094 | assert(err == 0); 2095 | 2096 | uv_unref((uv_handle_t *) &watcher->handle); 2097 | 2098 | return NULL; 2099 | } 2100 | 2101 | static js_value_t * 2102 | bare_fs_exports(js_env_t *env, js_value_t *exports) { 2103 | int err; 2104 | 2105 | #define V(name, fn) \ 2106 | { \ 2107 | js_value_t *val; \ 2108 | err = js_create_function(env, name, -1, fn, NULL, &val); \ 2109 | assert(err == 0); \ 2110 | err = js_set_named_property(env, exports, name, val); \ 2111 | assert(err == 0); \ 2112 | } 2113 | 2114 | V("requestInit", bare_fs_request_init) 2115 | V("requestDestroy", bare_fs_request_destroy) 2116 | V("requestReset", bare_fs_request_reset) 2117 | V("requestResultStat", bare_fs_request_result_stat) 2118 | V("requestResultString", bare_fs_request_result_string) 2119 | V("requestResultDir", bare_fs_request_result_dir) 2120 | V("requestResultDirents", bare_fs_request_result_dirents) 2121 | 2122 | V("open", bare_fs_open) 2123 | V("openSync", bare_fs_open_sync) 2124 | V("close", bare_fs_close) 2125 | V("closeSync", bare_fs_close_sync) 2126 | V("access", bare_fs_access) 2127 | V("accessSync", bare_fs_access_sync) 2128 | V("read", bare_fs_read) 2129 | V("readSync", bare_fs_read_sync) 2130 | V("readv", bare_fs_readv) 2131 | V("write", bare_fs_write) 2132 | V("writeSync", bare_fs_write_sync) 2133 | V("writev", bare_fs_writev) 2134 | V("ftruncate", bare_fs_ftruncate) 2135 | V("ftruncateSync", bare_fs_ftruncate_sync) 2136 | V("chmod", bare_fs_chmod) 2137 | V("chmodSync", bare_fs_chmod_sync) 2138 | V("fchmod", bare_fs_fchmod) 2139 | V("fchmodSync", bare_fs_fchmod_sync) 2140 | V("utimes", bare_fs_utimes) 2141 | V("utimesSync", bare_fs_utimes_sync) 2142 | V("rename", bare_fs_rename) 2143 | V("renameSync", bare_fs_rename_sync) 2144 | V("copyfile", bare_fs_copyfile) 2145 | V("copyfileSync", bare_fs_copyfile_sync) 2146 | V("mkdir", bare_fs_mkdir) 2147 | V("mkdirSync", bare_fs_mkdir_sync) 2148 | V("rmdir", bare_fs_rmdir) 2149 | V("rmdirSync", bare_fs_rmdir_sync) 2150 | V("stat", bare_fs_stat) 2151 | V("statSync", bare_fs_stat_sync) 2152 | V("lstat", bare_fs_lstat) 2153 | V("lstatSync", bare_fs_lstat_sync) 2154 | V("fstat", bare_fs_fstat) 2155 | V("fstatSync", bare_fs_fstat_sync) 2156 | V("unlink", bare_fs_unlink) 2157 | V("unlinkSync", bare_fs_unlink_sync) 2158 | V("realpath", bare_fs_realpath) 2159 | V("realpathSync", bare_fs_realpath_sync) 2160 | V("readlink", bare_fs_readlink) 2161 | V("readlinkSync", bare_fs_readlink_sync) 2162 | V("symlink", bare_fs_symlink) 2163 | V("symlinkSync", bare_fs_symlink_sync) 2164 | V("opendir", bare_fs_opendir) 2165 | V("opendirSync", bare_fs_opendir_sync) 2166 | V("readdir", bare_fs_readdir) 2167 | V("readdirSync", bare_fs_readdir_sync) 2168 | V("closedir", bare_fs_closedir) 2169 | V("closedirSync", bare_fs_closedir_sync) 2170 | 2171 | V("watcherInit", bare_fs_watcher_init) 2172 | V("watcherClose", bare_fs_watcher_close) 2173 | V("watcherRef", bare_fs_watcher_ref) 2174 | V("watcherUnref", bare_fs_watcher_unref) 2175 | #undef V 2176 | 2177 | #define V(name) \ 2178 | { \ 2179 | js_value_t *val; \ 2180 | err = js_create_uint32(env, name, &val); \ 2181 | assert(err == 0); \ 2182 | err = js_set_named_property(env, exports, #name, val); \ 2183 | assert(err == 0); \ 2184 | } 2185 | 2186 | V(O_RDWR) 2187 | V(O_RDONLY) 2188 | V(O_WRONLY) 2189 | V(O_CREAT) 2190 | V(O_TRUNC) 2191 | V(O_APPEND) 2192 | 2193 | #ifdef F_OK 2194 | V(F_OK) 2195 | #endif 2196 | #ifdef R_OK 2197 | V(R_OK) 2198 | #endif 2199 | #ifdef W_OK 2200 | V(W_OK) 2201 | #endif 2202 | #ifdef X_OK 2203 | V(X_OK) 2204 | #endif 2205 | 2206 | V(S_IFMT) 2207 | V(S_IFREG) 2208 | V(S_IFDIR) 2209 | V(S_IFCHR) 2210 | V(S_IFLNK) 2211 | #ifdef S_IFBLK 2212 | V(S_IFBLK) 2213 | #endif 2214 | #ifdef S_IFIFO 2215 | V(S_IFIFO) 2216 | #endif 2217 | #ifdef S_IFSOCK 2218 | V(S_IFSOCK) 2219 | #endif 2220 | 2221 | #ifdef S_IRUSR 2222 | V(S_IRUSR) 2223 | #endif 2224 | #ifdef S_IWUSR 2225 | V(S_IWUSR) 2226 | #endif 2227 | #ifdef S_IXUSR 2228 | V(S_IXUSR) 2229 | #endif 2230 | #ifdef S_IRGRP 2231 | V(S_IRGRP) 2232 | #endif 2233 | #ifdef S_IWGRP 2234 | V(S_IWGRP) 2235 | #endif 2236 | #ifdef S_IXGRP 2237 | V(S_IXGRP) 2238 | #endif 2239 | #ifdef S_IROTH 2240 | V(S_IROTH) 2241 | #endif 2242 | #ifdef S_IWOTH 2243 | V(S_IWOTH) 2244 | #endif 2245 | #ifdef S_IXOTH 2246 | V(S_IXOTH) 2247 | #endif 2248 | 2249 | V(UV_DIRENT_UNKNOWN) 2250 | V(UV_DIRENT_FILE) 2251 | V(UV_DIRENT_DIR) 2252 | V(UV_DIRENT_LINK) 2253 | V(UV_DIRENT_FIFO) 2254 | V(UV_DIRENT_SOCKET) 2255 | V(UV_DIRENT_CHAR) 2256 | V(UV_DIRENT_BLOCK) 2257 | 2258 | V(UV_FS_COPYFILE_EXCL) 2259 | V(UV_FS_COPYFILE_FICLONE) 2260 | V(UV_FS_COPYFILE_FICLONE_FORCE) 2261 | V(UV_FS_SYMLINK_DIR) 2262 | V(UV_FS_SYMLINK_JUNCTION) 2263 | 2264 | V(UV_RENAME) 2265 | V(UV_CHANGE) 2266 | #undef V 2267 | 2268 | return exports; 2269 | } 2270 | 2271 | BARE_MODULE(bare_fs, bare_fs_exports) 2272 | --------------------------------------------------------------------------------