2017-01-03 22:16:48 +01:00
|
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the
|
|
|
|
// "Software"), to deal in the Software without restriction, including
|
|
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
|
|
// following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included
|
|
|
|
// in all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2015-01-10 21:12:37 +01:00
|
|
|
// Maintainers, keep in mind that ES1-style octal literals (`0666`) are not
|
|
|
|
// allowed in strict mode. Use ES6-style octal literals instead (`0o666`).
|
2011-11-04 13:10:07 +01:00
|
|
|
|
2014-11-22 16:59:48 +01:00
|
|
|
'use strict';
|
|
|
|
|
2020-01-18 10:55:31 +01:00
|
|
|
// Most platforms don't allow reads or writes >= 2 GB.
|
|
|
|
// See https://github.com/libuv/libuv/pull/1501.
|
|
|
|
const kIoMaxLength = 2 ** 31 - 1;
|
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
const {
|
2020-01-02 14:43:02 +01:00
|
|
|
Map,
|
2019-11-22 18:04:46 +01:00
|
|
|
MathMax,
|
2019-11-27 19:59:29 +01:00
|
|
|
NumberIsSafeInteger,
|
2019-11-22 18:04:46 +01:00
|
|
|
ObjectCreate,
|
|
|
|
ObjectDefineProperties,
|
|
|
|
ObjectDefineProperty,
|
2019-12-13 16:46:35 +01:00
|
|
|
Promise,
|
2019-11-22 18:04:46 +01:00
|
|
|
} = primordials;
|
2019-03-31 13:30:12 +02:00
|
|
|
|
2018-10-15 01:41:32 +02:00
|
|
|
const { fs: constants } = internalBinding('constants');
|
2018-05-15 01:36:37 +02:00
|
|
|
const {
|
|
|
|
S_IFIFO,
|
|
|
|
S_IFLNK,
|
|
|
|
S_IFMT,
|
|
|
|
S_IFREG,
|
|
|
|
S_IFSOCK,
|
|
|
|
F_OK,
|
|
|
|
R_OK,
|
|
|
|
W_OK,
|
|
|
|
X_OK,
|
|
|
|
O_WRONLY,
|
2018-05-15 21:34:49 +02:00
|
|
|
O_SYMLINK
|
2018-05-15 01:36:37 +02:00
|
|
|
} = constants;
|
2018-05-15 21:34:49 +02:00
|
|
|
|
2015-01-21 17:36:59 +01:00
|
|
|
const pathModule = require('path');
|
2018-08-06 11:55:59 +02:00
|
|
|
const { isArrayBufferView } = require('internal/util/types');
|
2018-08-23 16:29:40 +02:00
|
|
|
const binding = internalBinding('fs');
|
2020-01-18 10:55:31 +01:00
|
|
|
const { Buffer } = require('buffer');
|
2018-02-27 14:55:32 +01:00
|
|
|
const {
|
2019-03-18 02:29:39 +01:00
|
|
|
codes: {
|
|
|
|
ERR_FS_FILE_TOO_LARGE,
|
|
|
|
ERR_INVALID_ARG_VALUE,
|
|
|
|
ERR_INVALID_ARG_TYPE,
|
2019-10-12 11:23:07 +02:00
|
|
|
ERR_INVALID_CALLBACK,
|
|
|
|
ERR_FEATURE_UNAVAILABLE_ON_PLATFORM
|
2019-03-18 02:29:39 +01:00
|
|
|
},
|
|
|
|
uvException
|
|
|
|
} = require('internal/errors');
|
2018-05-15 21:34:49 +02:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const { FSReqCallback, statValues } = binding;
|
2018-08-24 18:13:32 +02:00
|
|
|
const { toPathIfFileURL } = require('internal/url');
|
2016-12-27 03:38:05 +01:00
|
|
|
const internalUtil = require('internal/util');
|
2017-10-07 16:50:42 +02:00
|
|
|
const {
|
2018-02-14 09:57:42 +01:00
|
|
|
copyObject,
|
2018-07-28 04:29:32 +02:00
|
|
|
Dirent,
|
|
|
|
getDirents,
|
2018-02-14 09:57:42 +01:00
|
|
|
getOptions,
|
2019-05-12 14:30:29 +02:00
|
|
|
getValidatedPath,
|
2019-04-02 01:21:36 +02:00
|
|
|
getValidMode,
|
2019-08-28 02:14:27 +02:00
|
|
|
handleErrorFromBinding,
|
2018-02-14 09:57:42 +01:00
|
|
|
nullCheck,
|
|
|
|
preprocessSymlinkDestination,
|
|
|
|
Stats,
|
2018-03-30 22:02:57 +02:00
|
|
|
getStatsFromBinding,
|
2018-05-15 01:36:37 +02:00
|
|
|
realpathCacheKey,
|
2018-02-14 09:57:42 +01:00
|
|
|
stringToFlags,
|
|
|
|
stringToSymlinkType,
|
|
|
|
toUnixTimestamp,
|
2019-08-17 21:03:46 +02:00
|
|
|
validateBufferArray,
|
2018-02-14 09:57:42 +01:00
|
|
|
validateOffsetLengthRead,
|
|
|
|
validateOffsetLengthWrite,
|
2019-03-29 14:17:55 +01:00
|
|
|
validatePath,
|
2019-08-16 19:17:21 +02:00
|
|
|
validateRmdirOptions,
|
2019-12-19 19:00:45 +01:00
|
|
|
validateStringAfterArrayBufferView,
|
2019-05-22 18:54:34 +02:00
|
|
|
warnOnNonPortableTemplate
|
2018-12-21 09:07:22 +01:00
|
|
|
} = require('internal/fs/utils');
|
2019-08-28 02:14:27 +02:00
|
|
|
const {
|
|
|
|
Dir,
|
|
|
|
opendir,
|
|
|
|
opendirSync
|
|
|
|
} = require('internal/fs/dir');
|
2018-02-13 12:49:53 +01:00
|
|
|
const {
|
|
|
|
CHAR_FORWARD_SLASH,
|
|
|
|
CHAR_BACKWARD_SLASH,
|
|
|
|
} = require('internal/constants');
|
2018-04-15 11:16:50 +02:00
|
|
|
const {
|
|
|
|
isUint32,
|
2019-04-02 01:21:36 +02:00
|
|
|
parseFileMode,
|
2019-03-20 13:15:48 +01:00
|
|
|
validateBuffer,
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger,
|
2020-02-09 16:13:41 +01:00
|
|
|
validateInt32
|
2018-04-15 11:16:50 +02:00
|
|
|
} = require('internal/validators');
|
2020-02-09 16:13:41 +01:00
|
|
|
// 2 ** 32 - 1
|
|
|
|
const kMaxUserId = 4294967295;
|
2010-03-11 23:32:10 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
let truncateWarn = true;
|
|
|
|
let fs;
|
2018-05-03 20:40:48 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
// Lazy loaded
|
2018-12-02 18:08:26 +01:00
|
|
|
let promises = null;
|
2018-05-15 21:34:49 +02:00
|
|
|
let watchers;
|
|
|
|
let ReadFileContext;
|
|
|
|
let ReadStream;
|
|
|
|
let WriteStream;
|
2019-08-16 19:17:21 +02:00
|
|
|
let rimraf;
|
|
|
|
let rimrafSync;
|
2018-03-02 17:28:05 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
// These have to be separate because of how graceful-fs happens to do it's
|
|
|
|
// monkeypatching.
|
|
|
|
let FileReadStream;
|
|
|
|
let FileWriteStream;
|
2010-05-25 00:47:40 +02:00
|
|
|
|
2015-01-21 17:36:59 +01:00
|
|
|
const isWindows = process.platform === 'win32';
|
2019-10-12 11:23:07 +02:00
|
|
|
const isOSX = process.platform === 'darwin';
|
2012-05-23 01:02:10 +02:00
|
|
|
|
2017-10-06 20:06:35 +02:00
|
|
|
|
|
|
|
function showTruncateDeprecation() {
|
|
|
|
if (truncateWarn) {
|
|
|
|
process.emitWarning(
|
|
|
|
'Using fs.truncate with a file descriptor is deprecated. Please use ' +
|
|
|
|
'fs.ftruncate with a file descriptor instead.',
|
|
|
|
'DeprecationWarning', 'DEP0081');
|
|
|
|
truncateWarn = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-23 01:38:36 +02:00
|
|
|
function maybeCallback(cb) {
|
2018-02-09 00:54:31 +01:00
|
|
|
if (typeof cb === 'function')
|
|
|
|
return cb;
|
|
|
|
|
2019-04-02 03:46:17 +02:00
|
|
|
throw new ERR_INVALID_CALLBACK(cb);
|
2016-07-23 01:38:36 +02:00
|
|
|
}
|
|
|
|
|
2012-12-04 03:17:52 +01:00
|
|
|
// Ensure that callbacks run in the global context. Only use this function
|
|
|
|
// for callbacks that are passed to the binding layer, callbacks that are
|
|
|
|
// invoked from JS already run in the proper scope.
|
|
|
|
function makeCallback(cb) {
|
2017-05-11 17:52:20 +02:00
|
|
|
if (typeof cb !== 'function') {
|
2019-04-02 03:46:17 +02:00
|
|
|
throw new ERR_INVALID_CALLBACK(cb);
|
2017-05-11 17:52:20 +02:00
|
|
|
}
|
2015-02-18 18:55:13 +01:00
|
|
|
|
2019-04-22 21:09:56 +02:00
|
|
|
return (...args) => cb(...args);
|
2012-12-04 03:17:52 +01:00
|
|
|
}
|
|
|
|
|
2017-03-12 01:41:20 +01:00
|
|
|
// Special case of `makeCallback()` that is specific to async `*stat()` calls as
|
|
|
|
// an optimization, since the data passed back to the callback needs to be
|
|
|
|
// transformed anyway.
|
|
|
|
function makeStatsCallback(cb) {
|
2017-05-11 17:52:20 +02:00
|
|
|
if (typeof cb !== 'function') {
|
2019-04-02 03:46:17 +02:00
|
|
|
throw new ERR_INVALID_CALLBACK(cb);
|
2017-05-11 17:52:20 +02:00
|
|
|
}
|
2017-03-12 01:41:20 +01:00
|
|
|
|
2018-11-24 08:34:14 +01:00
|
|
|
return (err, stats) => {
|
2017-03-12 01:41:20 +01:00
|
|
|
if (err) return cb(err);
|
2018-03-30 22:02:57 +02:00
|
|
|
cb(err, getStatsFromBinding(stats));
|
2017-03-12 01:41:20 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-04-26 13:22:14 +02:00
|
|
|
const isFd = isUint32;
|
2016-07-23 01:37:54 +02:00
|
|
|
|
2018-04-07 10:57:22 +02:00
|
|
|
function isFileType(stats, fileType) {
|
2018-02-11 19:29:19 +01:00
|
|
|
// Use stats array directly to avoid creating an fs.Stats instance just for
|
|
|
|
// our internal use.
|
2018-04-07 10:57:22 +02:00
|
|
|
return (stats[1/* mode */] & S_IFMT) === fileType;
|
2018-02-11 19:29:19 +01:00
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function access(path, mode, callback) {
|
2014-12-15 16:44:46 +01:00
|
|
|
if (typeof mode === 'function') {
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = mode;
|
2018-05-15 01:36:37 +02:00
|
|
|
mode = F_OK;
|
2014-12-15 16:44:46 +01:00
|
|
|
}
|
|
|
|
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = getValidMode(mode, 'access');
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2017-05-11 17:52:20 +02:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.access(pathModule.toNamespacedPath(path), mode, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2014-12-15 16:44:46 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function accessSync(path, mode) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = getValidMode(mode, 'access');
|
2014-12-15 16:44:46 +01:00
|
|
|
|
2017-11-27 05:08:05 +01:00
|
|
|
const ctx = { path };
|
2017-11-20 21:47:57 +01:00
|
|
|
binding.access(pathModule.toNamespacedPath(path), mode, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2014-12-15 16:44:46 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function exists(path, callback) {
|
2018-02-09 00:54:31 +01:00
|
|
|
maybeCallback(callback);
|
2018-01-23 03:23:46 +01:00
|
|
|
|
|
|
|
function suppressedCallback(err) {
|
|
|
|
callback(err ? false : true);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2018-05-15 01:36:37 +02:00
|
|
|
fs.access(path, F_OK, suppressedCallback);
|
2018-11-04 15:52:28 +01:00
|
|
|
} catch {
|
2018-01-23 03:23:46 +01:00
|
|
|
return callback(false);
|
|
|
|
}
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2012-01-21 02:37:57 +01:00
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
ObjectDefineProperty(exists, internalUtil.promisify.custom, {
|
2017-05-30 23:34:27 +02:00
|
|
|
value: (path) => {
|
2018-05-19 00:25:07 +02:00
|
|
|
return new Promise((resolve) => fs.exists(path, resolve));
|
2017-05-30 23:34:27 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-01-23 03:23:46 +01:00
|
|
|
// fs.existsSync never throws, it only returns true or false.
|
|
|
|
// Since fs.existsSync never throws, users have established
|
|
|
|
// the expectation that passing invalid arguments to it, even like
|
|
|
|
// fs.existsSync(), would only get a false in return, so we cannot signal
|
|
|
|
// validation errors to users properly out of compatibility concerns.
|
|
|
|
// TODO(joyeecheung): deprecate the never-throw-on-invalid-arguments behavior
|
2018-05-15 21:34:49 +02:00
|
|
|
function existsSync(path) {
|
2012-01-21 02:37:57 +01:00
|
|
|
try {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-11-04 15:52:28 +01:00
|
|
|
} catch {
|
2012-01-21 02:37:57 +01:00
|
|
|
return false;
|
|
|
|
}
|
2018-11-01 11:04:57 +01:00
|
|
|
const ctx = { path };
|
2019-11-22 07:01:21 +01:00
|
|
|
const nPath = pathModule.toNamespacedPath(path);
|
|
|
|
binding.access(nPath, F_OK, undefined, ctx);
|
|
|
|
|
|
|
|
// In case of an invalid symlink, `binding.access()` on win32
|
|
|
|
// will **not** return an error and is therefore not enough.
|
|
|
|
// Double check with `binding.stat()`.
|
|
|
|
if (isWindows && ctx.errno === undefined) {
|
|
|
|
binding.stat(nPath, false, undefined, ctx);
|
|
|
|
}
|
|
|
|
|
2018-11-01 11:04:57 +01:00
|
|
|
return ctx.errno === undefined;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2015-02-03 20:07:02 +01:00
|
|
|
|
|
|
|
function readFileAfterOpen(err, fd) {
|
2018-05-15 21:34:49 +02:00
|
|
|
const context = this.context;
|
2015-02-03 20:07:02 +01:00
|
|
|
|
|
|
|
if (err) {
|
2015-06-03 00:11:04 +02:00
|
|
|
context.callback(err);
|
2015-02-03 20:07:02 +01:00
|
|
|
return;
|
2012-05-16 02:35:42 +02:00
|
|
|
}
|
|
|
|
|
2015-02-03 20:07:02 +01:00
|
|
|
context.fd = fd;
|
2012-06-11 23:49:31 +02:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2015-02-03 20:07:02 +01:00
|
|
|
req.oncomplete = readFileAfterStat;
|
|
|
|
req.context = context;
|
2018-04-07 11:01:06 +02:00
|
|
|
binding.fstat(fd, false, req);
|
2015-02-03 20:07:02 +01:00
|
|
|
}
|
|
|
|
|
2018-04-07 10:57:22 +02:00
|
|
|
function readFileAfterStat(err, stats) {
|
2018-05-15 21:34:49 +02:00
|
|
|
const context = this.context;
|
2015-02-03 20:07:02 +01:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
return context.close(err);
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
const size = context.size = isFileType(stats, S_IFREG) ? stats[8] : 0;
|
2015-02-03 20:07:02 +01:00
|
|
|
|
2020-01-18 10:55:31 +01:00
|
|
|
if (size > kIoMaxLength) {
|
2018-03-15 14:22:36 +01:00
|
|
|
err = new ERR_FS_FILE_TOO_LARGE(size);
|
2015-02-03 20:07:02 +01:00
|
|
|
return context.close(err);
|
|
|
|
}
|
|
|
|
|
2017-10-15 13:18:09 +02:00
|
|
|
try {
|
2019-04-03 02:58:31 +02:00
|
|
|
if (size === 0) {
|
|
|
|
context.buffers = [];
|
|
|
|
} else {
|
|
|
|
context.buffer = Buffer.allocUnsafeSlow(size);
|
|
|
|
}
|
2017-10-15 13:18:09 +02:00
|
|
|
} catch (err) {
|
|
|
|
return context.close(err);
|
|
|
|
}
|
2015-02-03 20:07:02 +01:00
|
|
|
context.read();
|
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function readFile(path, options, callback) {
|
|
|
|
callback = maybeCallback(callback || options);
|
|
|
|
options = getOptions(options, { flag: 'r' });
|
|
|
|
if (!ReadFileContext)
|
|
|
|
ReadFileContext = require('internal/fs/read_file_context');
|
|
|
|
const context = new ReadFileContext(callback, options.encoding);
|
2019-03-22 03:44:26 +01:00
|
|
|
context.isUserFd = isFd(path); // File descriptor ownership
|
2015-02-03 20:07:02 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2018-05-15 21:34:49 +02:00
|
|
|
req.context = context;
|
|
|
|
req.oncomplete = readFileAfterOpen;
|
2015-02-03 20:07:02 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
if (context.isUserFd) {
|
|
|
|
process.nextTick(function tick() {
|
|
|
|
req.oncomplete(null, path);
|
|
|
|
});
|
|
|
|
return;
|
2015-10-22 13:58:26 +02:00
|
|
|
}
|
2017-10-15 13:18:09 +02:00
|
|
|
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2019-04-02 01:21:36 +02:00
|
|
|
const flagsNumber = stringToFlags(options.flags);
|
2018-05-15 21:34:49 +02:00
|
|
|
binding.open(pathModule.toNamespacedPath(path),
|
2019-04-02 01:21:36 +02:00
|
|
|
flagsNumber,
|
2018-05-15 21:34:49 +02:00
|
|
|
0o666,
|
|
|
|
req);
|
2015-10-22 13:58:26 +02:00
|
|
|
}
|
2010-03-15 18:41:58 +01:00
|
|
|
|
2016-04-07 16:04:47 +02:00
|
|
|
function tryStatSync(fd, isUserFd) {
|
2017-12-28 16:16:33 +01:00
|
|
|
const ctx = {};
|
2018-04-07 11:01:06 +02:00
|
|
|
const stats = binding.fstat(fd, false, undefined, ctx);
|
2017-12-28 16:16:33 +01:00
|
|
|
if (ctx.errno !== undefined && !isUserFd) {
|
|
|
|
fs.closeSync(fd);
|
2019-03-18 02:29:39 +01:00
|
|
|
throw uvException(ctx);
|
2016-04-07 16:04:47 +02:00
|
|
|
}
|
2018-04-07 10:57:22 +02:00
|
|
|
return stats;
|
2016-04-07 16:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function tryCreateBuffer(size, fd, isUserFd) {
|
2018-05-15 21:34:49 +02:00
|
|
|
let threw = true;
|
|
|
|
let buffer;
|
2016-04-07 16:04:47 +02:00
|
|
|
try {
|
2020-01-18 10:55:31 +01:00
|
|
|
if (size > kIoMaxLength) {
|
2018-03-15 14:22:36 +01:00
|
|
|
throw new ERR_FS_FILE_TOO_LARGE(size);
|
|
|
|
}
|
2016-04-07 16:04:47 +02:00
|
|
|
buffer = Buffer.allocUnsafe(size);
|
|
|
|
threw = false;
|
|
|
|
} finally {
|
|
|
|
if (threw && !isUserFd) fs.closeSync(fd);
|
|
|
|
}
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2017-01-14 20:14:19 +01:00
|
|
|
function tryReadSync(fd, isUserFd, buffer, pos, len) {
|
2018-05-15 21:34:49 +02:00
|
|
|
let threw = true;
|
|
|
|
let bytesRead;
|
2016-04-07 16:04:47 +02:00
|
|
|
try {
|
2017-01-14 20:14:19 +01:00
|
|
|
bytesRead = fs.readSync(fd, buffer, pos, len);
|
2016-04-07 16:04:47 +02:00
|
|
|
threw = false;
|
|
|
|
} finally {
|
|
|
|
if (threw && !isUserFd) fs.closeSync(fd);
|
|
|
|
}
|
|
|
|
return bytesRead;
|
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function readFileSync(path, options) {
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, { flag: 'r' });
|
2019-03-22 03:44:26 +01:00
|
|
|
const isUserFd = isFd(path); // File descriptor ownership
|
2018-10-23 22:26:57 +02:00
|
|
|
const fd = isUserFd ? path : fs.openSync(path, options.flag, 0o666);
|
2010-09-23 02:58:08 +02:00
|
|
|
|
2018-04-07 10:57:22 +02:00
|
|
|
const stats = tryStatSync(fd, isUserFd);
|
2018-05-15 21:34:49 +02:00
|
|
|
const size = isFileType(stats, S_IFREG) ? stats[8] : 0;
|
|
|
|
let pos = 0;
|
2019-03-22 03:44:26 +01:00
|
|
|
let buffer; // Single buffer with file data
|
|
|
|
let buffers; // List for when size is unknown
|
2012-06-11 23:49:31 +02:00
|
|
|
|
2012-05-16 02:35:42 +02:00
|
|
|
if (size === 0) {
|
2012-06-11 23:49:31 +02:00
|
|
|
buffers = [];
|
|
|
|
} else {
|
2016-04-07 16:04:47 +02:00
|
|
|
buffer = tryCreateBuffer(size, fd, isUserFd);
|
2012-05-03 01:03:08 +02:00
|
|
|
}
|
2010-03-15 18:41:58 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
let bytesRead;
|
2015-06-03 00:11:04 +02:00
|
|
|
|
2016-04-07 16:04:47 +02:00
|
|
|
if (size !== 0) {
|
|
|
|
do {
|
2017-01-14 20:14:19 +01:00
|
|
|
bytesRead = tryReadSync(fd, isUserFd, buffer, pos, size - pos);
|
2016-04-07 16:04:47 +02:00
|
|
|
pos += bytesRead;
|
|
|
|
} while (bytesRead !== 0 && pos < size);
|
|
|
|
} else {
|
|
|
|
do {
|
2019-03-07 01:03:53 +01:00
|
|
|
// The kernel lies about many files.
|
2016-04-07 16:04:47 +02:00
|
|
|
// Go ahead and try to read some bytes.
|
|
|
|
buffer = Buffer.allocUnsafe(8192);
|
2017-01-14 20:14:19 +01:00
|
|
|
bytesRead = tryReadSync(fd, isUserFd, buffer, 0, 8192);
|
2016-04-07 16:04:47 +02:00
|
|
|
if (bytesRead !== 0) {
|
|
|
|
buffers.push(buffer.slice(0, bytesRead));
|
2012-06-11 23:49:31 +02:00
|
|
|
}
|
2016-04-07 16:04:47 +02:00
|
|
|
pos += bytesRead;
|
|
|
|
} while (bytesRead !== 0);
|
2010-05-29 22:38:00 +02:00
|
|
|
}
|
2010-09-23 02:58:08 +02:00
|
|
|
|
2015-10-03 02:06:42 +02:00
|
|
|
if (!isUserFd)
|
|
|
|
fs.closeSync(fd);
|
2012-05-16 02:35:42 +02:00
|
|
|
|
2012-06-11 23:49:31 +02:00
|
|
|
if (size === 0) {
|
2019-01-21 01:22:27 +01:00
|
|
|
// Data was collected into the buffers list.
|
2012-06-11 23:49:31 +02:00
|
|
|
buffer = Buffer.concat(buffers, pos);
|
2012-06-12 16:04:56 +02:00
|
|
|
} else if (pos < size) {
|
|
|
|
buffer = buffer.slice(0, pos);
|
2012-06-11 23:49:31 +02:00
|
|
|
}
|
|
|
|
|
2016-06-25 20:33:05 +02:00
|
|
|
if (options.encoding) buffer = buffer.toString(options.encoding);
|
2010-09-23 02:58:08 +02:00
|
|
|
return buffer;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function close(fd, callback) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2016-07-23 01:38:36 +02:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2016-07-23 01:37:54 +02:00
|
|
|
binding.close(fd, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function closeSync(fd) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2017-11-26 21:44:20 +01:00
|
|
|
|
2017-11-29 05:52:16 +01:00
|
|
|
const ctx = {};
|
|
|
|
binding.close(fd, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function open(path, flags, mode, callback) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-10-23 22:26:57 +02:00
|
|
|
if (arguments.length < 3) {
|
|
|
|
callback = flags;
|
|
|
|
flags = 'r';
|
2018-05-09 16:44:44 +02:00
|
|
|
mode = 0o666;
|
2018-11-06 20:17:26 +01:00
|
|
|
} else if (typeof mode === 'function') {
|
2018-10-23 22:26:57 +02:00
|
|
|
callback = mode;
|
|
|
|
mode = 0o666;
|
2019-04-02 01:21:36 +02:00
|
|
|
} else {
|
|
|
|
mode = parseFileMode(mode, 'mode', 0o666);
|
2018-10-23 22:26:57 +02:00
|
|
|
}
|
|
|
|
const flagsNumber = stringToFlags(flags);
|
|
|
|
callback = makeCallback(callback);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
|
|
|
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.open(pathModule.toNamespacedPath(path),
|
2018-05-09 16:44:44 +02:00
|
|
|
flagsNumber,
|
2012-02-19 00:01:35 +01:00
|
|
|
mode,
|
2014-12-09 05:29:47 +01:00
|
|
|
req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
|
|
|
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function openSync(path, flags, mode) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2019-04-02 01:21:36 +02:00
|
|
|
const flagsNumber = stringToFlags(flags);
|
|
|
|
mode = parseFileMode(mode, 'mode', 0o666);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-02-14 20:08:52 +01:00
|
|
|
const ctx = { path };
|
|
|
|
const result = binding.open(pathModule.toNamespacedPath(path),
|
2018-05-09 16:44:44 +02:00
|
|
|
flagsNumber, mode,
|
2018-02-14 20:08:52 +01:00
|
|
|
undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
|
|
|
return result;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2020-01-16 15:46:28 +01:00
|
|
|
// usage:
|
|
|
|
// fs.read(fd, buffer, offset, length, position, callback);
|
|
|
|
// OR
|
|
|
|
// fs.read(fd, {}, callback)
|
2018-05-15 21:34:49 +02:00
|
|
|
function read(fd, buffer, offset, length, position, callback) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2020-01-16 15:46:28 +01:00
|
|
|
|
|
|
|
if (arguments.length <= 3) {
|
|
|
|
// Assume fs.read(fd, options, callback)
|
|
|
|
let options = {};
|
|
|
|
if (arguments.length < 3) {
|
|
|
|
// This is fs.read(fd, callback)
|
|
|
|
// buffer will be the callback
|
|
|
|
callback = buffer;
|
|
|
|
} else {
|
|
|
|
// This is fs.read(fd, {}, callback)
|
|
|
|
// buffer will be the options object
|
|
|
|
// offset is the callback
|
|
|
|
options = buffer;
|
|
|
|
callback = offset;
|
|
|
|
}
|
|
|
|
|
2020-03-25 09:36:35 +01:00
|
|
|
({
|
|
|
|
buffer = Buffer.alloc(16384),
|
|
|
|
offset = 0,
|
|
|
|
length = buffer.length,
|
|
|
|
position
|
|
|
|
} = options);
|
2020-01-16 15:46:28 +01:00
|
|
|
}
|
|
|
|
|
2017-12-14 01:54:09 +01:00
|
|
|
validateBuffer(buffer);
|
2018-08-06 01:17:25 +02:00
|
|
|
callback = maybeCallback(callback);
|
2017-11-27 05:51:01 +01:00
|
|
|
|
2019-03-18 19:27:13 +01:00
|
|
|
if (offset == null) {
|
|
|
|
offset = 0;
|
|
|
|
} else {
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger(offset, 'offset');
|
2019-03-18 19:27:13 +01:00
|
|
|
}
|
|
|
|
|
2017-11-27 05:51:01 +01:00
|
|
|
length |= 0;
|
|
|
|
|
2016-01-06 17:39:03 +01:00
|
|
|
if (length === 0) {
|
2018-04-30 09:08:20 +02:00
|
|
|
return process.nextTick(function tick() {
|
2018-08-06 01:17:25 +02:00
|
|
|
callback(null, 0, buffer);
|
2016-01-06 17:39:03 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-06 11:55:59 +02:00
|
|
|
if (buffer.byteLength === 0) {
|
2018-06-11 15:44:52 +02:00
|
|
|
throw new ERR_INVALID_ARG_VALUE('buffer', buffer,
|
|
|
|
'is empty and cannot be written');
|
|
|
|
}
|
|
|
|
|
2018-08-06 11:55:59 +02:00
|
|
|
validateOffsetLengthRead(offset, length, buffer.byteLength);
|
2017-11-27 05:51:01 +01:00
|
|
|
|
2019-11-27 19:59:29 +01:00
|
|
|
if (!NumberIsSafeInteger(position))
|
2017-11-27 05:51:01 +01:00
|
|
|
position = -1;
|
|
|
|
|
2011-03-23 12:29:49 +01:00
|
|
|
function wrapper(err, bytesRead) {
|
|
|
|
// Retain a reference to buffer so that it can't be GC'ed too soon.
|
2018-08-06 01:17:25 +02:00
|
|
|
callback(err, bytesRead || 0, buffer);
|
2011-03-23 12:29:49 +01:00
|
|
|
}
|
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = wrapper;
|
|
|
|
|
|
|
|
binding.read(fd, buffer, offset, length, position, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
ObjectDefineProperty(read, internalUtil.customPromisifyArgs,
|
|
|
|
{ value: ['bytesRead', 'buffer'], enumerable: false });
|
2017-04-16 21:19:36 +02:00
|
|
|
|
2020-03-24 16:23:33 +01:00
|
|
|
// usage:
|
|
|
|
// fs.readSync(fd, buffer, offset, length, position);
|
|
|
|
// OR
|
|
|
|
// fs.readSync(fd, buffer, {}) or fs.readSync(fd, buffer)
|
2018-05-15 21:34:49 +02:00
|
|
|
function readSync(fd, buffer, offset, length, position) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2020-03-24 16:23:33 +01:00
|
|
|
|
|
|
|
if (arguments.length <= 3) {
|
|
|
|
// Assume fs.read(fd, buffer, options)
|
|
|
|
const options = offset || {};
|
|
|
|
|
|
|
|
({ offset = 0, length = buffer.length, position } = options);
|
|
|
|
}
|
|
|
|
|
2017-12-14 01:54:09 +01:00
|
|
|
validateBuffer(buffer);
|
2017-11-27 05:51:01 +01:00
|
|
|
|
2019-03-18 19:27:13 +01:00
|
|
|
if (offset == null) {
|
|
|
|
offset = 0;
|
|
|
|
} else {
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger(offset, 'offset');
|
2019-03-18 19:27:13 +01:00
|
|
|
}
|
|
|
|
|
2017-11-27 05:51:01 +01:00
|
|
|
length |= 0;
|
|
|
|
|
2016-01-06 17:39:03 +01:00
|
|
|
if (length === 0) {
|
2017-01-10 13:26:23 +01:00
|
|
|
return 0;
|
2010-05-21 00:13:22 +02:00
|
|
|
}
|
|
|
|
|
2018-08-06 11:55:59 +02:00
|
|
|
if (buffer.byteLength === 0) {
|
2018-06-11 15:44:52 +02:00
|
|
|
throw new ERR_INVALID_ARG_VALUE('buffer', buffer,
|
|
|
|
'is empty and cannot be written');
|
|
|
|
}
|
|
|
|
|
2018-08-06 11:55:59 +02:00
|
|
|
validateOffsetLengthRead(offset, length, buffer.byteLength);
|
2017-11-27 05:51:01 +01:00
|
|
|
|
2019-11-27 19:59:29 +01:00
|
|
|
if (!NumberIsSafeInteger(position))
|
2017-11-27 05:51:01 +01:00
|
|
|
position = -1;
|
|
|
|
|
2018-02-27 18:21:19 +01:00
|
|
|
const ctx = {};
|
|
|
|
const result = binding.read(fd, buffer, offset, length, position,
|
|
|
|
undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
|
|
|
return result;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2020-03-16 14:50:27 +01:00
|
|
|
function readv(fd, buffers, position, callback) {
|
|
|
|
function wrapper(err, read) {
|
|
|
|
callback(err, read || 0, buffers);
|
|
|
|
}
|
|
|
|
|
|
|
|
validateInt32(fd, 'fd', /* min */ 0);
|
|
|
|
validateBufferArray(buffers);
|
|
|
|
|
|
|
|
const req = new FSReqCallback();
|
|
|
|
req.oncomplete = wrapper;
|
|
|
|
|
|
|
|
callback = maybeCallback(callback || position);
|
|
|
|
|
|
|
|
if (typeof position !== 'number')
|
|
|
|
position = null;
|
|
|
|
|
|
|
|
return binding.readBuffers(fd, buffers, position, req);
|
|
|
|
}
|
|
|
|
|
|
|
|
function readvSync(fd, buffers, position) {
|
|
|
|
validateInt32(fd, 'fd', 0);
|
|
|
|
validateBufferArray(buffers);
|
|
|
|
|
|
|
|
const ctx = {};
|
|
|
|
|
|
|
|
if (typeof position !== 'number')
|
|
|
|
position = null;
|
|
|
|
|
|
|
|
const result = binding.readBuffers(fd, buffers, position, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-07-02 09:27:26 +02:00
|
|
|
// usage:
|
2016-07-23 22:43:41 +02:00
|
|
|
// fs.write(fd, buffer[, offset[, length[, position]]], callback);
|
2013-07-02 09:27:26 +02:00
|
|
|
// OR
|
|
|
|
// fs.write(fd, string[, position[, encoding]], callback);
|
2018-05-15 21:34:49 +02:00
|
|
|
function write(fd, buffer, offset, length, position, callback) {
|
2015-09-18 10:36:57 +02:00
|
|
|
function wrapper(err, written) {
|
2014-12-09 05:29:47 +01:00
|
|
|
// Retain a reference to buffer so that it can't be GC'ed too soon.
|
|
|
|
callback(err, written || 0, buffer);
|
|
|
|
}
|
|
|
|
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-08-06 11:55:59 +02:00
|
|
|
if (isArrayBufferView(buffer)) {
|
2016-07-23 22:43:41 +02:00
|
|
|
callback = maybeCallback(callback || position || length || offset);
|
2019-03-27 23:23:59 +01:00
|
|
|
if (offset == null || typeof offset === 'function') {
|
2016-07-23 22:43:41 +02:00
|
|
|
offset = 0;
|
2019-03-27 23:23:59 +01:00
|
|
|
} else {
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger(offset, 'offset');
|
2019-03-27 23:23:59 +01:00
|
|
|
}
|
2017-12-13 23:24:34 +01:00
|
|
|
if (typeof length !== 'number')
|
2016-07-23 22:43:41 +02:00
|
|
|
length = buffer.length - offset;
|
2017-12-13 23:24:34 +01:00
|
|
|
if (typeof position !== 'number')
|
2013-07-02 09:27:26 +02:00
|
|
|
position = null;
|
2017-12-23 00:33:31 +01:00
|
|
|
validateOffsetLengthWrite(offset, length, buffer.byteLength);
|
2019-12-19 19:00:45 +01:00
|
|
|
|
|
|
|
const req = new FSReqCallback();
|
|
|
|
req.oncomplete = wrapper;
|
2014-12-09 05:29:47 +01:00
|
|
|
return binding.writeBuffer(fd, buffer, offset, length, position, req);
|
2010-05-19 20:17:50 +02:00
|
|
|
}
|
2010-08-25 05:46:37 +02:00
|
|
|
|
2019-12-19 19:00:45 +01:00
|
|
|
validateStringAfterArrayBufferView(buffer, 'buffer');
|
|
|
|
|
2015-01-29 02:05:53 +01:00
|
|
|
if (typeof position !== 'function') {
|
|
|
|
if (typeof offset === 'function') {
|
2013-07-02 09:27:26 +02:00
|
|
|
position = offset;
|
|
|
|
offset = null;
|
|
|
|
} else {
|
|
|
|
position = length;
|
2010-08-25 05:46:37 +02:00
|
|
|
}
|
2013-07-02 09:27:26 +02:00
|
|
|
length = 'utf8';
|
2010-08-25 05:46:37 +02:00
|
|
|
}
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = maybeCallback(position);
|
2019-12-19 19:00:45 +01:00
|
|
|
|
|
|
|
const req = new FSReqCallback();
|
|
|
|
req.oncomplete = wrapper;
|
2014-12-09 05:29:47 +01:00
|
|
|
return binding.writeString(fd, buffer, offset, length, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
ObjectDefineProperty(write, internalUtil.customPromisifyArgs,
|
|
|
|
{ value: ['bytesWritten', 'buffer'], enumerable: false });
|
2017-04-16 21:19:36 +02:00
|
|
|
|
2019-02-04 17:18:39 +01:00
|
|
|
// Usage:
|
2016-07-23 22:43:41 +02:00
|
|
|
// fs.writeSync(fd, buffer[, offset[, length[, position]]]);
|
2013-07-02 09:27:26 +02:00
|
|
|
// OR
|
|
|
|
// fs.writeSync(fd, string[, position[, encoding]]);
|
2018-05-15 21:34:49 +02:00
|
|
|
function writeSync(fd, buffer, offset, length, position) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2018-02-27 19:17:12 +01:00
|
|
|
const ctx = {};
|
|
|
|
let result;
|
2018-08-06 11:55:59 +02:00
|
|
|
if (isArrayBufferView(buffer)) {
|
2015-01-29 02:05:53 +01:00
|
|
|
if (position === undefined)
|
2013-07-02 09:27:26 +02:00
|
|
|
position = null;
|
2019-03-27 23:23:59 +01:00
|
|
|
if (offset == null) {
|
2016-07-23 22:43:41 +02:00
|
|
|
offset = 0;
|
2019-03-27 23:23:59 +01:00
|
|
|
} else {
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger(offset, 'offset');
|
2019-03-27 23:23:59 +01:00
|
|
|
}
|
2016-07-23 22:43:41 +02:00
|
|
|
if (typeof length !== 'number')
|
2018-08-06 11:55:59 +02:00
|
|
|
length = buffer.byteLength - offset;
|
2017-12-23 00:33:31 +01:00
|
|
|
validateOffsetLengthWrite(offset, length, buffer.byteLength);
|
2018-02-27 19:17:12 +01:00
|
|
|
result = binding.writeBuffer(fd, buffer, offset, length, position,
|
|
|
|
undefined, ctx);
|
|
|
|
} else {
|
2019-12-19 19:00:45 +01:00
|
|
|
validateStringAfterArrayBufferView(buffer, 'buffer');
|
|
|
|
|
2018-02-27 19:17:12 +01:00
|
|
|
if (offset === undefined)
|
|
|
|
offset = null;
|
|
|
|
result = binding.writeString(fd, buffer, offset, length,
|
|
|
|
undefined, ctx);
|
2010-05-19 20:17:50 +02:00
|
|
|
}
|
2018-02-27 19:17:12 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
|
|
|
return result;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-02-04 17:18:39 +01:00
|
|
|
// usage:
|
|
|
|
// fs.writev(fd, buffers[, position], callback);
|
|
|
|
function writev(fd, buffers, position, callback) {
|
|
|
|
function wrapper(err, written) {
|
|
|
|
callback(err, written || 0, buffers);
|
|
|
|
}
|
|
|
|
|
2019-08-17 19:02:53 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2019-08-17 21:03:46 +02:00
|
|
|
validateBufferArray(buffers);
|
2019-02-04 17:18:39 +01:00
|
|
|
|
|
|
|
const req = new FSReqCallback();
|
|
|
|
req.oncomplete = wrapper;
|
|
|
|
|
|
|
|
callback = maybeCallback(callback || position);
|
|
|
|
|
|
|
|
if (typeof position !== 'number')
|
|
|
|
position = null;
|
|
|
|
|
|
|
|
return binding.writeBuffers(fd, buffers, position, req);
|
|
|
|
}
|
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
ObjectDefineProperty(writev, internalUtil.customPromisifyArgs, {
|
2019-02-04 17:18:39 +01:00
|
|
|
value: ['bytesWritten', 'buffer'],
|
|
|
|
enumerable: false
|
|
|
|
});
|
|
|
|
|
|
|
|
function writevSync(fd, buffers, position) {
|
2019-08-17 19:02:53 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2019-08-17 21:03:46 +02:00
|
|
|
validateBufferArray(buffers);
|
2019-02-04 17:18:39 +01:00
|
|
|
|
2019-08-17 21:03:46 +02:00
|
|
|
const ctx = {};
|
2019-02-04 17:18:39 +01:00
|
|
|
|
|
|
|
if (typeof position !== 'number')
|
|
|
|
position = null;
|
|
|
|
|
|
|
|
const result = binding.writeBuffers(fd, buffers, position, undefined, ctx);
|
|
|
|
|
|
|
|
handleErrorFromBinding(ctx);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function rename(oldPath, newPath, callback) {
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = makeCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
oldPath = getValidatedPath(oldPath, 'oldPath');
|
|
|
|
newPath = getValidatedPath(newPath, 'newPath');
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.rename(pathModule.toNamespacedPath(oldPath),
|
|
|
|
pathModule.toNamespacedPath(newPath),
|
2014-12-09 05:29:47 +01:00
|
|
|
req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function renameSync(oldPath, newPath) {
|
2019-05-12 14:30:29 +02:00
|
|
|
oldPath = getValidatedPath(oldPath, 'oldPath');
|
|
|
|
newPath = getValidatedPath(newPath, 'newPath');
|
2018-01-24 02:03:45 +01:00
|
|
|
const ctx = { path: oldPath, dest: newPath };
|
|
|
|
binding.rename(pathModule.toNamespacedPath(oldPath),
|
|
|
|
pathModule.toNamespacedPath(newPath), undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function truncate(path, len, callback) {
|
2016-07-23 01:37:54 +02:00
|
|
|
if (typeof path === 'number') {
|
2017-10-06 20:06:35 +02:00
|
|
|
showTruncateDeprecation();
|
2015-02-07 19:27:20 +01:00
|
|
|
return fs.ftruncate(path, len, callback);
|
2016-07-23 01:37:54 +02:00
|
|
|
}
|
2016-07-23 01:38:36 +02:00
|
|
|
if (typeof len === 'function') {
|
|
|
|
callback = len;
|
|
|
|
len = 0;
|
|
|
|
} else if (len === undefined) {
|
2012-08-04 21:39:11 +02:00
|
|
|
len = 0;
|
|
|
|
}
|
2014-12-09 05:29:47 +01:00
|
|
|
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger(len, 'len');
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = maybeCallback(callback);
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.open(path, 'r+', (er, fd) => {
|
2012-08-04 21:39:11 +02:00
|
|
|
if (er) return callback(er);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2016-10-16 00:02:43 +02:00
|
|
|
req.oncomplete = function oncomplete(er) {
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.close(fd, (er2) => {
|
2012-08-04 21:39:11 +02:00
|
|
|
callback(er || er2);
|
|
|
|
});
|
2014-12-09 05:29:47 +01:00
|
|
|
};
|
|
|
|
binding.ftruncate(fd, len, req);
|
2012-08-04 21:39:11 +02:00
|
|
|
});
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function truncateSync(path, len) {
|
2016-07-23 01:37:54 +02:00
|
|
|
if (typeof path === 'number') {
|
|
|
|
// legacy
|
2017-10-06 20:06:35 +02:00
|
|
|
showTruncateDeprecation();
|
2012-08-08 23:07:18 +02:00
|
|
|
return fs.ftruncateSync(path, len);
|
2016-07-23 01:37:54 +02:00
|
|
|
}
|
|
|
|
if (len === undefined) {
|
2012-08-04 21:39:11 +02:00
|
|
|
len = 0;
|
|
|
|
}
|
2019-01-21 01:22:27 +01:00
|
|
|
// Allow error to be thrown, but still close fd.
|
2018-05-15 21:34:49 +02:00
|
|
|
const fd = fs.openSync(path, 'r+');
|
|
|
|
let ret;
|
2015-06-03 00:11:04 +02:00
|
|
|
|
2012-08-04 21:39:11 +02:00
|
|
|
try {
|
2015-06-03 00:11:04 +02:00
|
|
|
ret = fs.ftruncateSync(fd, len);
|
2012-08-04 21:39:11 +02:00
|
|
|
} finally {
|
|
|
|
fs.closeSync(fd);
|
|
|
|
}
|
|
|
|
return ret;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2012-08-04 21:39:11 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function ftruncate(fd, len = 0, callback) {
|
2016-07-23 01:38:36 +02:00
|
|
|
if (typeof len === 'function') {
|
|
|
|
callback = len;
|
|
|
|
len = 0;
|
2012-08-04 21:39:11 +02:00
|
|
|
}
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger(len, 'len');
|
2019-11-22 18:04:46 +01:00
|
|
|
len = MathMax(0, len);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2016-07-23 01:38:36 +02:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2014-12-09 05:29:47 +01:00
|
|
|
binding.ftruncate(fd, len, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2012-08-04 21:39:11 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function ftruncateSync(fd, len = 0) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2019-08-17 17:50:43 +02:00
|
|
|
validateInteger(len, 'len');
|
2019-11-22 18:04:46 +01:00
|
|
|
len = MathMax(0, len);
|
2018-01-24 02:20:30 +01:00
|
|
|
const ctx = {};
|
|
|
|
binding.ftruncate(fd, len, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-08-16 19:17:21 +02:00
|
|
|
|
|
|
|
function lazyLoadRimraf() {
|
|
|
|
if (rimraf === undefined)
|
|
|
|
({ rimraf, rimrafSync } = require('internal/fs/rimraf'));
|
|
|
|
}
|
|
|
|
|
|
|
|
function rmdir(path, options, callback) {
|
|
|
|
if (typeof options === 'function') {
|
|
|
|
callback = options;
|
|
|
|
options = undefined;
|
|
|
|
}
|
|
|
|
|
2018-02-09 16:31:26 +01:00
|
|
|
callback = makeCallback(callback);
|
2019-08-16 19:17:21 +02:00
|
|
|
path = pathModule.toNamespacedPath(getValidatedPath(path));
|
|
|
|
options = validateRmdirOptions(options);
|
|
|
|
|
|
|
|
if (options.recursive) {
|
|
|
|
lazyLoadRimraf();
|
|
|
|
return rimraf(path, options, callback);
|
|
|
|
}
|
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2019-08-16 19:17:21 +02:00
|
|
|
binding.rmdir(path, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-08-16 19:17:21 +02:00
|
|
|
function rmdirSync(path, options) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2019-08-16 19:17:21 +02:00
|
|
|
options = validateRmdirOptions(options);
|
|
|
|
|
|
|
|
if (options.recursive) {
|
|
|
|
lazyLoadRimraf();
|
|
|
|
return rimrafSync(pathModule.toNamespacedPath(path), options);
|
|
|
|
}
|
|
|
|
|
2018-02-03 14:39:43 +01:00
|
|
|
const ctx = { path };
|
|
|
|
binding.rmdir(pathModule.toNamespacedPath(path), undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fdatasync(fd, callback) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2016-07-23 01:37:54 +02:00
|
|
|
binding.fdatasync(fd, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-22 08:25:24 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fdatasyncSync(fd) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2018-01-24 02:37:52 +01:00
|
|
|
const ctx = {};
|
|
|
|
binding.fdatasync(fd, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-22 08:25:24 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fsync(fd, callback) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2016-07-23 01:38:36 +02:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2016-07-23 01:37:54 +02:00
|
|
|
binding.fsync(fd, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-22 08:25:24 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fsyncSync(fd) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2018-01-24 11:39:35 +01:00
|
|
|
const ctx = {};
|
|
|
|
binding.fsync(fd, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-22 08:25:24 +01:00
|
|
|
|
2018-08-10 01:52:41 +02:00
|
|
|
function mkdir(path, options, callback) {
|
2019-04-02 01:21:36 +02:00
|
|
|
let mode = 0o777;
|
|
|
|
let recursive = false;
|
2018-08-10 01:52:41 +02:00
|
|
|
if (typeof options === 'function') {
|
|
|
|
callback = options;
|
|
|
|
} else if (typeof options === 'number' || typeof options === 'string') {
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = options;
|
|
|
|
} else if (options) {
|
|
|
|
if (options.recursive !== undefined)
|
|
|
|
recursive = options.recursive;
|
|
|
|
if (options.mode !== undefined)
|
|
|
|
mode = options.mode;
|
2018-08-10 01:52:41 +02:00
|
|
|
}
|
|
|
|
callback = makeCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-05-09 16:44:44 +02:00
|
|
|
|
2018-08-10 01:52:41 +02:00
|
|
|
if (typeof recursive !== 'boolean')
|
2020-03-24 22:56:58 +01:00
|
|
|
throw new ERR_INVALID_ARG_TYPE('options.recursive', 'boolean', recursive);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2018-08-10 01:52:41 +02:00
|
|
|
binding.mkdir(pathModule.toNamespacedPath(path),
|
2019-04-02 01:21:36 +02:00
|
|
|
parseFileMode(mode, 'mode'), recursive, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-08-10 01:52:41 +02:00
|
|
|
function mkdirSync(path, options) {
|
2019-04-02 01:21:36 +02:00
|
|
|
let mode = 0o777;
|
|
|
|
let recursive = false;
|
2018-08-10 01:52:41 +02:00
|
|
|
if (typeof options === 'number' || typeof options === 'string') {
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = options;
|
|
|
|
} else if (options) {
|
|
|
|
if (options.recursive !== undefined)
|
|
|
|
recursive = options.recursive;
|
|
|
|
if (options.mode !== undefined)
|
|
|
|
mode = options.mode;
|
2018-08-10 01:52:41 +02:00
|
|
|
}
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-08-10 01:52:41 +02:00
|
|
|
if (typeof recursive !== 'boolean')
|
2020-03-24 22:56:58 +01:00
|
|
|
throw new ERR_INVALID_ARG_TYPE('options.recursive', 'boolean', recursive);
|
2018-08-10 01:52:41 +02:00
|
|
|
|
2018-02-03 14:49:32 +01:00
|
|
|
const ctx = { path };
|
2020-01-29 08:06:44 +01:00
|
|
|
const result = binding.mkdir(pathModule.toNamespacedPath(path),
|
|
|
|
parseFileMode(mode, 'mode'), recursive,
|
|
|
|
undefined, ctx);
|
2018-02-03 14:49:32 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2020-01-29 08:06:44 +01:00
|
|
|
if (recursive) {
|
|
|
|
return result;
|
|
|
|
}
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function readdir(path, options, callback) {
|
2016-06-25 20:33:05 +02:00
|
|
|
callback = makeCallback(typeof options === 'function' ? options : callback);
|
|
|
|
options = getOptions(options, {});
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2018-07-28 04:29:32 +02:00
|
|
|
if (!options.withFileTypes) {
|
|
|
|
req.oncomplete = callback;
|
|
|
|
} else {
|
|
|
|
req.oncomplete = (err, result) => {
|
|
|
|
if (err) {
|
|
|
|
callback(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
getDirents(path, result, callback);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
binding.readdir(pathModule.toNamespacedPath(path), options.encoding,
|
|
|
|
!!options.withFileTypes, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function readdirSync(path, options) {
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, {});
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-02-03 15:45:30 +01:00
|
|
|
const ctx = { path };
|
|
|
|
const result = binding.readdir(pathModule.toNamespacedPath(path),
|
2018-07-28 04:29:32 +02:00
|
|
|
options.encoding, !!options.withFileTypes,
|
|
|
|
undefined, ctx);
|
2018-02-03 15:45:30 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-07-28 04:29:32 +02:00
|
|
|
return options.withFileTypes ? getDirents(path, result) : result;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-08-14 07:15:10 +02:00
|
|
|
function fstat(fd, options = { bigint: false }, callback) {
|
2018-11-06 20:17:26 +01:00
|
|
|
if (typeof options === 'function') {
|
2018-04-07 11:01:06 +02:00
|
|
|
callback = options;
|
|
|
|
options = {};
|
|
|
|
}
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback(options.bigint);
|
2017-03-12 01:41:20 +01:00
|
|
|
req.oncomplete = makeStatsCallback(callback);
|
2018-04-07 11:01:06 +02:00
|
|
|
binding.fstat(fd, options.bigint, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-05-12 22:35:33 +02:00
|
|
|
|
2019-08-14 07:15:10 +02:00
|
|
|
function lstat(path, options = { bigint: false }, callback) {
|
2018-11-06 20:17:26 +01:00
|
|
|
if (typeof options === 'function') {
|
2018-04-07 11:01:06 +02:00
|
|
|
callback = options;
|
|
|
|
options = {};
|
|
|
|
}
|
2017-03-12 01:41:20 +01:00
|
|
|
callback = makeStatsCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback(options.bigint);
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2018-04-07 11:01:06 +02:00
|
|
|
binding.lstat(pathModule.toNamespacedPath(path), options.bigint, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-08-14 07:15:10 +02:00
|
|
|
function stat(path, options = { bigint: false }, callback) {
|
2018-11-06 20:17:26 +01:00
|
|
|
if (typeof options === 'function') {
|
2018-04-07 11:01:06 +02:00
|
|
|
callback = options;
|
|
|
|
options = {};
|
|
|
|
}
|
2017-03-12 01:41:20 +01:00
|
|
|
callback = makeStatsCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback(options.bigint);
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2018-04-07 11:01:06 +02:00
|
|
|
binding.stat(pathModule.toNamespacedPath(path), options.bigint, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-12-26 03:36:33 +01:00
|
|
|
function fstatSync(fd, options = { bigint: false }) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2017-12-28 16:16:33 +01:00
|
|
|
const ctx = { fd };
|
2018-04-07 11:01:06 +02:00
|
|
|
const stats = binding.fstat(fd, options.bigint, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-04-07 10:57:22 +02:00
|
|
|
return getStatsFromBinding(stats);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-05-12 22:35:33 +02:00
|
|
|
|
2019-12-26 03:36:33 +01:00
|
|
|
function lstatSync(path, options = { bigint: false }) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2017-12-28 07:51:05 +01:00
|
|
|
const ctx = { path };
|
2018-04-07 10:57:22 +02:00
|
|
|
const stats = binding.lstat(pathModule.toNamespacedPath(path),
|
2018-04-07 11:01:06 +02:00
|
|
|
options.bigint, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-04-07 10:57:22 +02:00
|
|
|
return getStatsFromBinding(stats);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2019-12-26 03:36:33 +01:00
|
|
|
function statSync(path, options = { bigint: false }) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2017-12-27 21:01:45 +01:00
|
|
|
const ctx = { path };
|
2018-04-07 10:57:22 +02:00
|
|
|
const stats = binding.stat(pathModule.toNamespacedPath(path),
|
2018-04-07 11:01:06 +02:00
|
|
|
options.bigint, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-04-07 10:57:22 +02:00
|
|
|
return getStatsFromBinding(stats);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function readlink(path, options, callback) {
|
2016-06-25 20:33:05 +02:00
|
|
|
callback = makeCallback(typeof options === 'function' ? options : callback);
|
|
|
|
options = getOptions(options, {});
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path, 'oldPath');
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.readlink(pathModule.toNamespacedPath(path), options.encoding, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function readlinkSync(path, options) {
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, {});
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path, 'oldPath');
|
2018-01-24 00:51:08 +01:00
|
|
|
const ctx = { path };
|
|
|
|
const result = binding.readlink(pathModule.toNamespacedPath(path),
|
|
|
|
options.encoding, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-01-24 00:51:08 +01:00
|
|
|
return result;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function symlink(target, path, type_, callback_) {
|
|
|
|
const type = (typeof type_ === 'string' ? type_ : null);
|
|
|
|
const callback = makeCallback(arguments[arguments.length - 1]);
|
2012-05-23 01:02:10 +02:00
|
|
|
|
2019-05-12 14:30:29 +02:00
|
|
|
target = getValidatedPath(target, 'target');
|
|
|
|
path = getValidatedPath(path);
|
2014-12-09 05:29:47 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2017-12-13 23:24:34 +01:00
|
|
|
req.oncomplete = callback;
|
2018-01-23 23:53:47 +01:00
|
|
|
|
2018-10-18 02:42:14 +02:00
|
|
|
if (isWindows && type === null) {
|
|
|
|
let absoluteTarget;
|
|
|
|
try {
|
|
|
|
// Symlinks targets can be relative to the newly created path.
|
|
|
|
// Calculate absolute file name of the symlink target, and check
|
|
|
|
// if it is a directory. Ignore resolve error to keep symlink
|
|
|
|
// errors consistent between platforms if invalid path is
|
|
|
|
// provided.
|
|
|
|
absoluteTarget = pathModule.resolve(path, '..', target);
|
|
|
|
} catch { }
|
|
|
|
if (absoluteTarget !== undefined) {
|
|
|
|
stat(absoluteTarget, (err, stat) => {
|
|
|
|
const resolvedType = !err && stat.isDirectory() ? 'dir' : 'file';
|
|
|
|
const resolvedFlags = stringToSymlinkType(resolvedType);
|
|
|
|
binding.symlink(preprocessSymlinkDestination(target,
|
|
|
|
resolvedType,
|
|
|
|
path),
|
|
|
|
pathModule.toNamespacedPath(path), resolvedFlags, req);
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const flags = stringToSymlinkType(type);
|
2015-11-25 05:40:42 +01:00
|
|
|
binding.symlink(preprocessSymlinkDestination(target, type, path),
|
2017-12-13 23:24:34 +01:00
|
|
|
pathModule.toNamespacedPath(path), flags, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function symlinkSync(target, path, type) {
|
2015-01-29 02:05:53 +01:00
|
|
|
type = (typeof type === 'string' ? type : null);
|
2018-10-18 02:42:14 +02:00
|
|
|
if (isWindows && type === null) {
|
|
|
|
try {
|
|
|
|
const absoluteTarget = pathModule.resolve(path, '..', target);
|
|
|
|
if (statSync(absoluteTarget).isDirectory()) {
|
|
|
|
type = 'dir';
|
|
|
|
}
|
|
|
|
} catch { }
|
|
|
|
}
|
2019-05-12 14:30:29 +02:00
|
|
|
target = getValidatedPath(target, 'target');
|
|
|
|
path = getValidatedPath(path);
|
2017-12-13 23:24:34 +01:00
|
|
|
const flags = stringToSymlinkType(type);
|
2018-01-23 23:53:47 +01:00
|
|
|
|
|
|
|
const ctx = { path: target, dest: path };
|
|
|
|
binding.symlink(preprocessSymlinkDestination(target, type, path),
|
|
|
|
pathModule.toNamespacedPath(path), flags, undefined, ctx);
|
|
|
|
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function link(existingPath, newPath, callback) {
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = makeCallback(callback);
|
2017-01-11 16:02:40 +01:00
|
|
|
|
2019-05-12 14:30:29 +02:00
|
|
|
existingPath = getValidatedPath(existingPath, 'existingPath');
|
|
|
|
newPath = getValidatedPath(newPath, 'newPath');
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
|
|
|
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.link(pathModule.toNamespacedPath(existingPath),
|
|
|
|
pathModule.toNamespacedPath(newPath),
|
2014-12-09 05:29:47 +01:00
|
|
|
req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function linkSync(existingPath, newPath) {
|
2019-05-12 14:30:29 +02:00
|
|
|
existingPath = getValidatedPath(existingPath, 'existingPath');
|
|
|
|
newPath = getValidatedPath(newPath, 'newPath');
|
2018-01-24 00:03:11 +01:00
|
|
|
|
|
|
|
const ctx = { path: existingPath, dest: newPath };
|
|
|
|
const result = binding.link(pathModule.toNamespacedPath(existingPath),
|
|
|
|
pathModule.toNamespacedPath(newPath),
|
|
|
|
undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-01-24 00:03:11 +01:00
|
|
|
return result;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function unlink(path, callback) {
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = makeCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.unlink(pathModule.toNamespacedPath(path), req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function unlinkSync(path) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-01-24 15:18:37 +01:00
|
|
|
const ctx = { path };
|
|
|
|
binding.unlink(pathModule.toNamespacedPath(path), undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fchmod(fd, mode, callback) {
|
2018-05-20 03:09:45 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = parseFileMode(mode, 'mode');
|
2018-05-09 16:44:44 +02:00
|
|
|
callback = makeCallback(callback);
|
2017-11-26 21:44:20 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2018-05-09 16:44:44 +02:00
|
|
|
req.oncomplete = callback;
|
2017-11-26 21:44:20 +01:00
|
|
|
binding.fchmod(fd, mode, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2011-03-30 00:31:41 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fchmodSync(fd, mode) {
|
2018-05-20 03:09:45 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = parseFileMode(mode, 'mode');
|
2018-02-27 18:33:31 +01:00
|
|
|
const ctx = {};
|
|
|
|
binding.fchmod(fd, mode, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2011-03-30 00:31:41 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function lchmod(path, mode, callback) {
|
|
|
|
callback = maybeCallback(callback);
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.open(path, O_WRONLY | O_SYMLINK, (err, fd) => {
|
2018-05-15 21:34:49 +02:00
|
|
|
if (err) {
|
|
|
|
callback(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Prefer to return the chmod error, if one occurs,
|
|
|
|
// but still try to close, and report closing errors if they occur.
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.fchmod(fd, mode, (err) => {
|
|
|
|
fs.close(fd, (err2) => {
|
2018-05-15 21:34:49 +02:00
|
|
|
callback(err || err2);
|
2011-11-22 22:10:57 +01:00
|
|
|
});
|
2011-03-30 01:34:05 +02:00
|
|
|
});
|
2018-05-15 21:34:49 +02:00
|
|
|
});
|
|
|
|
}
|
2011-03-30 01:34:05 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function lchmodSync(path, mode) {
|
|
|
|
const fd = fs.openSync(path, O_WRONLY | O_SYMLINK);
|
2011-11-22 22:10:57 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
// Prefer to return the chmod error, if one occurs,
|
|
|
|
// but still try to close, and report closing errors if they occur.
|
|
|
|
let ret;
|
|
|
|
try {
|
|
|
|
ret = fs.fchmodSync(fd, mode);
|
|
|
|
} finally {
|
|
|
|
fs.closeSync(fd);
|
|
|
|
}
|
|
|
|
return ret;
|
2011-03-30 01:34:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function chmod(path, mode, callback) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = parseFileMode(mode, 'mode');
|
2018-05-09 16:44:44 +02:00
|
|
|
callback = makeCallback(callback);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2017-12-13 23:24:34 +01:00
|
|
|
binding.chmod(pathModule.toNamespacedPath(path), mode, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function chmodSync(path, mode) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = parseFileMode(mode, 'mode');
|
2018-05-09 16:44:44 +02:00
|
|
|
|
2018-02-19 10:09:41 +01:00
|
|
|
const ctx = { path };
|
|
|
|
binding.chmod(pathModule.toNamespacedPath(path), mode, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function lchown(path, uid, gid, callback) {
|
2018-06-23 22:26:29 +02:00
|
|
|
callback = makeCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2020-02-09 16:13:41 +01:00
|
|
|
validateInteger(uid, 'uid', -1, kMaxUserId);
|
|
|
|
validateInteger(gid, 'gid', -1, kMaxUserId);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2018-06-23 22:26:29 +02:00
|
|
|
req.oncomplete = callback;
|
|
|
|
binding.lchown(pathModule.toNamespacedPath(path), uid, gid, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2011-03-30 01:34:05 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function lchownSync(path, uid, gid) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2020-02-09 16:13:41 +01:00
|
|
|
validateInteger(uid, 'uid', -1, kMaxUserId);
|
|
|
|
validateInteger(gid, 'gid', -1, kMaxUserId);
|
2018-06-23 22:26:29 +02:00
|
|
|
const ctx = { path };
|
|
|
|
binding.lchown(pathModule.toNamespacedPath(path), uid, gid, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2011-03-30 01:34:05 +02:00
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fchown(fd, uid, gid, callback) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2020-02-09 16:13:41 +01:00
|
|
|
validateInteger(uid, 'uid', -1, kMaxUserId);
|
|
|
|
validateInteger(gid, 'gid', -1, kMaxUserId);
|
2017-11-27 01:53:33 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2016-07-23 01:38:36 +02:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2016-07-23 01:37:54 +02:00
|
|
|
binding.fchown(fd, uid, gid, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2011-03-30 00:31:41 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function fchownSync(fd, uid, gid) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2020-02-09 16:13:41 +01:00
|
|
|
validateInteger(uid, 'uid', -1, kMaxUserId);
|
|
|
|
validateInteger(gid, 'gid', -1, kMaxUserId);
|
2017-11-27 01:53:33 +01:00
|
|
|
|
2018-02-27 18:45:17 +01:00
|
|
|
const ctx = {};
|
|
|
|
binding.fchown(fd, uid, gid, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2011-03-30 00:31:41 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function chown(path, uid, gid, callback) {
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = makeCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2020-02-09 16:13:41 +01:00
|
|
|
validateInteger(uid, 'uid', -1, kMaxUserId);
|
|
|
|
validateInteger(gid, 'gid', -1, kMaxUserId);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.chown(pathModule.toNamespacedPath(path), uid, gid, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-05-26 19:49:01 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function chownSync(path, uid, gid) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2020-02-09 16:13:41 +01:00
|
|
|
validateInteger(uid, 'uid', -1, kMaxUserId);
|
|
|
|
validateInteger(gid, 'gid', -1, kMaxUserId);
|
2018-02-19 20:35:39 +01:00
|
|
|
const ctx = { path };
|
|
|
|
binding.chown(pathModule.toNamespacedPath(path), uid, gid, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-10-29 12:38:13 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function utimes(path, atime, mtime, callback) {
|
2016-07-23 01:38:36 +02:00
|
|
|
callback = makeCallback(callback);
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2014-12-09 05:29:47 +01:00
|
|
|
req.oncomplete = callback;
|
2017-08-21 07:44:47 +02:00
|
|
|
binding.utimes(pathModule.toNamespacedPath(path),
|
2012-06-06 21:33:29 +02:00
|
|
|
toUnixTimestamp(atime),
|
|
|
|
toUnixTimestamp(mtime),
|
2014-12-09 05:29:47 +01:00
|
|
|
req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-10-29 12:38:13 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function utimesSync(path, atime, mtime) {
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-02-19 21:23:47 +01:00
|
|
|
const ctx = { path };
|
2017-12-13 23:24:34 +01:00
|
|
|
binding.utimes(pathModule.toNamespacedPath(path),
|
2018-02-19 21:23:47 +01:00
|
|
|
toUnixTimestamp(atime), toUnixTimestamp(mtime),
|
|
|
|
undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-10-29 12:38:13 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function futimes(fd, atime, mtime, callback) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2017-11-27 02:05:26 +01:00
|
|
|
atime = toUnixTimestamp(atime, 'atime');
|
|
|
|
mtime = toUnixTimestamp(mtime, 'mtime');
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2016-07-23 01:38:36 +02:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2014-12-09 05:29:47 +01:00
|
|
|
binding.futimes(fd, atime, mtime, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-10-29 12:38:13 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function futimesSync(fd, atime, mtime) {
|
2019-08-05 18:59:28 +02:00
|
|
|
validateInt32(fd, 'fd', 0);
|
2017-11-27 02:05:26 +01:00
|
|
|
atime = toUnixTimestamp(atime, 'atime');
|
|
|
|
mtime = toUnixTimestamp(mtime, 'mtime');
|
2018-02-27 19:25:02 +01:00
|
|
|
const ctx = {};
|
|
|
|
binding.futimes(fd, atime, mtime, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-10-29 12:38:13 +02:00
|
|
|
|
2020-02-28 13:40:30 +01:00
|
|
|
function writeAll(fd, isUserFd, buffer, offset, length, callback) {
|
2010-11-14 05:12:47 +01:00
|
|
|
// write(fd, buffer, offset, length, position, callback)
|
2020-02-28 13:40:30 +01:00
|
|
|
fs.write(fd, buffer, offset, length, null, (writeErr, written) => {
|
2010-03-01 19:14:49 +01:00
|
|
|
if (writeErr) {
|
2015-10-03 02:06:42 +02:00
|
|
|
if (isUserFd) {
|
2016-01-21 16:35:10 +01:00
|
|
|
callback(writeErr);
|
2015-10-03 02:06:42 +02:00
|
|
|
} else {
|
2018-04-30 09:08:20 +02:00
|
|
|
fs.close(fd, function close() {
|
2016-01-21 16:35:10 +01:00
|
|
|
callback(writeErr);
|
2015-10-03 02:06:42 +02:00
|
|
|
});
|
|
|
|
}
|
2017-10-17 00:37:14 +02:00
|
|
|
} else if (written === length) {
|
|
|
|
if (isUserFd) {
|
|
|
|
callback(null);
|
2010-03-01 19:14:49 +01:00
|
|
|
} else {
|
2017-10-17 00:37:14 +02:00
|
|
|
fs.close(fd, callback);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
offset += written;
|
|
|
|
length -= written;
|
2020-02-28 13:40:30 +01:00
|
|
|
writeAll(fd, isUserFd, buffer, offset, length, callback);
|
2010-03-01 19:14:49 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function writeFile(path, data, options, callback) {
|
2017-04-24 08:20:45 +02:00
|
|
|
callback = maybeCallback(callback || options);
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' });
|
|
|
|
const flag = options.flag || 'w';
|
2015-10-03 02:06:42 +02:00
|
|
|
|
2019-12-19 19:00:45 +01:00
|
|
|
if (!isArrayBufferView(data)) {
|
|
|
|
validateStringAfterArrayBufferView(data, 'data');
|
|
|
|
data = Buffer.from(data, options.encoding || 'utf8');
|
|
|
|
}
|
|
|
|
|
2016-07-23 01:37:54 +02:00
|
|
|
if (isFd(path)) {
|
2019-12-19 19:00:45 +01:00
|
|
|
const isUserFd = true;
|
2020-02-28 13:40:30 +01:00
|
|
|
writeAll(path, isUserFd, data, 0, data.byteLength, callback);
|
2015-10-03 02:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.open(path, flag, options.mode, (openErr, fd) => {
|
2010-03-01 19:14:49 +01:00
|
|
|
if (openErr) {
|
2016-01-21 16:35:10 +01:00
|
|
|
callback(openErr);
|
2010-03-01 19:14:49 +01:00
|
|
|
} else {
|
2019-12-19 19:00:45 +01:00
|
|
|
const isUserFd = false;
|
2020-02-28 13:40:30 +01:00
|
|
|
writeAll(fd, isUserFd, data, 0, data.byteLength, callback);
|
2010-03-01 19:14:49 +01:00
|
|
|
}
|
|
|
|
});
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function writeFileSync(path, data, options) {
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' });
|
2019-12-19 19:00:45 +01:00
|
|
|
|
|
|
|
if (!isArrayBufferView(data)) {
|
|
|
|
validateStringAfterArrayBufferView(data, 'data');
|
|
|
|
data = Buffer.from(data, options.encoding || 'utf8');
|
|
|
|
}
|
|
|
|
|
2016-06-25 20:33:05 +02:00
|
|
|
const flag = options.flag || 'w';
|
2013-03-01 18:10:26 +01:00
|
|
|
|
2019-03-22 03:44:26 +01:00
|
|
|
const isUserFd = isFd(path); // File descriptor ownership
|
2018-05-15 21:34:49 +02:00
|
|
|
const fd = isUserFd ? path : fs.openSync(path, flag, options.mode);
|
2015-10-03 02:06:42 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
let offset = 0;
|
2018-08-06 11:55:59 +02:00
|
|
|
let length = data.byteLength;
|
2012-05-03 01:03:08 +02:00
|
|
|
try {
|
2015-03-05 01:03:34 +01:00
|
|
|
while (length > 0) {
|
2020-02-28 13:40:30 +01:00
|
|
|
const written = fs.writeSync(fd, data, offset, length);
|
2015-03-05 01:03:34 +01:00
|
|
|
offset += written;
|
|
|
|
length -= written;
|
2012-05-03 01:03:08 +02:00
|
|
|
}
|
|
|
|
} finally {
|
2015-10-03 02:06:42 +02:00
|
|
|
if (!isUserFd) fs.closeSync(fd);
|
2010-03-01 19:14:49 +01:00
|
|
|
}
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:14:49 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function appendFile(path, data, options, callback) {
|
2017-02-28 15:13:49 +01:00
|
|
|
callback = maybeCallback(callback || options);
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'a' });
|
2011-11-02 19:06:16 +01:00
|
|
|
|
2016-10-09 16:07:59 +02:00
|
|
|
// Don't make changes directly on options object
|
|
|
|
options = copyObject(options);
|
2015-10-03 02:06:42 +02:00
|
|
|
|
2018-12-10 13:27:32 +01:00
|
|
|
// Force append behavior when using a supplied file descriptor
|
2016-10-09 16:07:59 +02:00
|
|
|
if (!options.flag || isFd(path))
|
2015-10-03 02:06:42 +02:00
|
|
|
options.flag = 'a';
|
|
|
|
|
2013-03-01 18:10:26 +01:00
|
|
|
fs.writeFile(path, data, options, callback);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2011-11-02 19:06:16 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function appendFileSync(path, data, options) {
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'a' });
|
2015-10-03 02:06:42 +02:00
|
|
|
|
2016-10-09 16:07:59 +02:00
|
|
|
// Don't make changes directly on options object
|
|
|
|
options = copyObject(options);
|
2011-11-02 19:06:16 +01:00
|
|
|
|
2018-12-10 13:27:32 +01:00
|
|
|
// Force append behavior when using a supplied file descriptor
|
2016-10-09 16:07:59 +02:00
|
|
|
if (!options.flag || isFd(path))
|
2015-10-03 02:06:42 +02:00
|
|
|
options.flag = 'a';
|
|
|
|
|
2013-03-01 18:10:26 +01:00
|
|
|
fs.writeFileSync(path, data, options);
|
2018-04-09 21:00:18 +02:00
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function watch(filename, options, listener) {
|
fs: Buffer and encoding enhancements to fs API
This makes several changes:
1. Allow path/filename to be passed in as a Buffer on fs methods
2. Add `options.encoding` to fs.readdir, fs.readdirSync, fs.readlink,
fs.readlinkSync and fs.watch.
3. Documentation updates
For 1... it's now possible to do:
```js
fs.open(Buffer('/fs/foo/bar'), 'w+', (err, fd) => { });
```
For 2...
```js
fs.readdir('/fs/foo/bar', {encoding:'hex'}, (err,list) => { });
fs.readdir('/fs/foo/bar', {encoding:'buffer'}, (err, list) => { });
```
encoding can also be passed as a string
```js
fs.readdir('/fs/foo/bar', 'hex', (err,list) => { });
```
The default encoding is set to UTF8 so this addresses the
discrepency that existed previously between fs.readdir and
fs.watch handling filenames differently.
Fixes: https://github.com/nodejs/node/issues/2088
Refs: https://github.com/nodejs/node/issues/3519
PR-URL: https://github.com/nodejs/node/pull/5616
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
2016-03-09 05:58:45 +01:00
|
|
|
if (typeof options === 'function') {
|
|
|
|
listener = options;
|
2011-09-23 01:18:08 +02:00
|
|
|
}
|
2016-06-25 20:33:05 +02:00
|
|
|
options = getOptions(options, {});
|
2011-09-23 01:18:08 +02:00
|
|
|
|
2016-10-09 16:07:59 +02:00
|
|
|
// Don't make changes directly on options object
|
|
|
|
options = copyObject(options);
|
|
|
|
|
2015-01-29 02:05:53 +01:00
|
|
|
if (options.persistent === undefined) options.persistent = true;
|
|
|
|
if (options.recursive === undefined) options.recursive = false;
|
2019-10-12 11:23:07 +02:00
|
|
|
if (options.recursive && !(isOSX || isWindows))
|
|
|
|
throw new ERR_FEATURE_UNAVAILABLE_ON_PLATFORM('watch recursively');
|
2018-05-15 21:34:49 +02:00
|
|
|
if (!watchers)
|
|
|
|
watchers = require('internal/fs/watchers');
|
|
|
|
const watcher = new watchers.FSWatcher();
|
2019-10-09 14:40:30 +02:00
|
|
|
watcher[watchers.kFSWatchStart](filename,
|
|
|
|
options.persistent,
|
|
|
|
options.recursive,
|
|
|
|
options.encoding);
|
2011-09-23 01:18:08 +02:00
|
|
|
|
2012-05-19 23:05:43 +02:00
|
|
|
if (listener) {
|
|
|
|
watcher.addListener('change', listener);
|
|
|
|
}
|
|
|
|
|
2011-09-23 01:18:08 +02:00
|
|
|
return watcher;
|
2011-07-19 10:23:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-02 19:02:15 +02:00
|
|
|
const statWatchers = new Map();
|
2011-07-19 10:23:50 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function watchFile(filename, options, listener) {
|
2019-05-12 14:30:29 +02:00
|
|
|
filename = getValidatedPath(filename);
|
2014-02-06 07:29:58 +01:00
|
|
|
filename = pathModule.resolve(filename);
|
2018-05-15 21:34:49 +02:00
|
|
|
let stat;
|
2010-03-01 19:42:37 +01:00
|
|
|
|
2018-12-18 03:15:57 +01:00
|
|
|
if (options === null || typeof options !== 'object') {
|
|
|
|
listener = options;
|
|
|
|
options = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
options = {
|
2012-06-21 15:03:21 +02:00
|
|
|
// Poll interval in milliseconds. 5007 is what libev used to use. It's
|
|
|
|
// a little on the slow side but let's stick with it for now to keep
|
|
|
|
// behavioral changes to a minimum.
|
|
|
|
interval: 5007,
|
2018-12-18 03:15:57 +01:00
|
|
|
persistent: true,
|
|
|
|
...options
|
2012-06-21 15:03:21 +02:00
|
|
|
};
|
|
|
|
|
2016-07-23 01:38:36 +02:00
|
|
|
if (typeof listener !== 'function') {
|
2018-02-27 14:55:32 +01:00
|
|
|
throw new ERR_INVALID_ARG_TYPE('listener', 'Function', listener);
|
2016-07-23 01:38:36 +02:00
|
|
|
}
|
|
|
|
|
2015-06-02 19:02:15 +02:00
|
|
|
stat = statWatchers.get(filename);
|
|
|
|
|
|
|
|
if (stat === undefined) {
|
2018-05-15 21:34:49 +02:00
|
|
|
if (!watchers)
|
|
|
|
watchers = require('internal/fs/watchers');
|
2018-04-07 11:01:06 +02:00
|
|
|
stat = new watchers.StatWatcher(options.bigint);
|
2019-10-14 17:57:24 +02:00
|
|
|
stat[watchers.kFSStatWatcherStart](filename,
|
|
|
|
options.persistent, options.interval);
|
2015-06-02 19:02:15 +02:00
|
|
|
statWatchers.set(filename, stat);
|
2010-03-01 19:42:37 +01:00
|
|
|
}
|
2015-06-02 19:02:15 +02:00
|
|
|
|
2010-12-02 02:43:30 +01:00
|
|
|
stat.addListener('change', listener);
|
2010-03-01 19:42:37 +01:00
|
|
|
return stat;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:42:37 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function unwatchFile(filename, listener) {
|
2019-05-12 14:30:29 +02:00
|
|
|
filename = getValidatedPath(filename);
|
2014-02-06 07:29:58 +01:00
|
|
|
filename = pathModule.resolve(filename);
|
2018-05-15 21:34:49 +02:00
|
|
|
const stat = statWatchers.get(filename);
|
2012-07-08 16:31:07 +02:00
|
|
|
|
2015-06-02 19:02:15 +02:00
|
|
|
if (stat === undefined) return;
|
2012-07-08 16:31:07 +02:00
|
|
|
|
2015-01-29 02:05:53 +01:00
|
|
|
if (typeof listener === 'function') {
|
2012-07-08 16:31:07 +02:00
|
|
|
stat.removeListener('change', listener);
|
|
|
|
} else {
|
|
|
|
stat.removeAllListeners('change');
|
|
|
|
}
|
|
|
|
|
2015-08-11 20:31:50 +02:00
|
|
|
if (stat.listenerCount('change') === 0) {
|
2010-03-01 19:42:37 +01:00
|
|
|
stat.stop();
|
2015-06-02 19:02:15 +02:00
|
|
|
statWatchers.delete(filename);
|
2010-03-01 19:42:37 +01:00
|
|
|
}
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-03-01 19:42:37 +01:00
|
|
|
|
2010-09-10 03:49:28 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
let splitRoot;
|
2017-03-12 05:59:37 +01:00
|
|
|
if (isWindows) {
|
|
|
|
// Regex to find the device root on Windows (e.g. 'c:\\'), including trailing
|
|
|
|
// slash.
|
|
|
|
const splitRootRe = /^(?:[a-zA-Z]:|[\\/]{2}[^\\/]+[\\/][^\\/]+)?[\\/]*/;
|
|
|
|
splitRoot = function splitRoot(str) {
|
|
|
|
return splitRootRe.exec(str)[0];
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
splitRoot = function splitRoot(str) {
|
2019-11-06 16:30:30 +01:00
|
|
|
for (let i = 0; i < str.length; ++i) {
|
2018-02-13 12:49:53 +01:00
|
|
|
if (str.charCodeAt(i) !== CHAR_FORWARD_SLASH)
|
2017-03-12 05:59:37 +01:00
|
|
|
return str.slice(0, i);
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
};
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2017-01-18 04:50:33 +01:00
|
|
|
function encodeRealpathResult(result, options) {
|
|
|
|
if (!options || !options.encoding || options.encoding === 'utf8')
|
2016-07-27 00:18:35 +02:00
|
|
|
return result;
|
|
|
|
const asBuffer = Buffer.from(result);
|
|
|
|
if (options.encoding === 'buffer') {
|
|
|
|
return asBuffer;
|
|
|
|
} else {
|
|
|
|
return asBuffer.toString(options.encoding);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-13 11:09:52 +01:00
|
|
|
// Finds the next portion of a (partial) path, up to the next path delimiter
|
2018-05-15 21:34:49 +02:00
|
|
|
let nextPart;
|
2017-01-13 11:09:52 +01:00
|
|
|
if (isWindows) {
|
|
|
|
nextPart = function nextPart(p, i) {
|
|
|
|
for (; i < p.length; ++i) {
|
|
|
|
const ch = p.charCodeAt(i);
|
2018-02-13 12:49:53 +01:00
|
|
|
|
|
|
|
// Check for a separator character
|
|
|
|
if (ch === CHAR_BACKWARD_SLASH || ch === CHAR_FORWARD_SLASH)
|
2017-01-13 11:09:52 +01:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
nextPart = function nextPart(p, i) { return p.indexOf('/', i); };
|
|
|
|
}
|
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
const emptyObj = ObjectCreate(null);
|
2018-05-15 21:34:49 +02:00
|
|
|
function realpathSync(p, options) {
|
2017-03-12 05:59:37 +01:00
|
|
|
if (!options)
|
|
|
|
options = emptyObj;
|
|
|
|
else
|
|
|
|
options = getOptions(options, emptyObj);
|
2018-08-24 18:13:32 +02:00
|
|
|
p = toPathIfFileURL(p);
|
2017-03-12 05:59:37 +01:00
|
|
|
if (typeof p !== 'string') {
|
2018-01-23 03:23:46 +01:00
|
|
|
p += '';
|
2017-03-12 05:59:37 +01:00
|
|
|
}
|
2018-01-23 03:23:46 +01:00
|
|
|
validatePath(p);
|
2016-07-27 00:18:35 +02:00
|
|
|
p = pathModule.resolve(p);
|
|
|
|
|
2018-05-15 01:36:37 +02:00
|
|
|
const cache = options[realpathCacheKey];
|
2016-08-14 18:41:28 +02:00
|
|
|
const maybeCachedResult = cache && cache.get(p);
|
|
|
|
if (maybeCachedResult) {
|
|
|
|
return maybeCachedResult;
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
const seenLinks = ObjectCreate(null);
|
|
|
|
const knownHard = ObjectCreate(null);
|
2017-01-13 11:07:18 +01:00
|
|
|
const original = p;
|
|
|
|
|
2019-03-07 01:03:53 +01:00
|
|
|
// Current character position in p
|
2018-05-15 21:34:49 +02:00
|
|
|
let pos;
|
2018-12-10 13:27:32 +01:00
|
|
|
// The partial path so far, including a trailing slash if any
|
2018-05-15 21:34:49 +02:00
|
|
|
let current;
|
2018-12-03 17:15:45 +01:00
|
|
|
// The partial path without a trailing slash (except when pointing at a root)
|
2018-05-15 21:34:49 +02:00
|
|
|
let base;
|
2018-12-10 13:27:32 +01:00
|
|
|
// The partial path scanned in the previous round, with slash
|
2018-05-15 21:34:49 +02:00
|
|
|
let previous;
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2017-01-13 11:04:18 +01:00
|
|
|
// Skip over roots
|
2017-03-12 05:59:37 +01:00
|
|
|
current = base = splitRoot(p);
|
|
|
|
pos = current.length;
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2017-01-13 11:04:18 +01:00
|
|
|
// On windows, check that the root exists. On unix there is no need.
|
|
|
|
if (isWindows && !knownHard[base]) {
|
2017-12-28 07:51:05 +01:00
|
|
|
const ctx = { path: base };
|
2018-04-07 11:01:06 +02:00
|
|
|
binding.lstat(pathModule.toNamespacedPath(base), false, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2017-01-13 11:04:18 +01:00
|
|
|
knownHard[base] = true;
|
2016-07-27 00:18:35 +02:00
|
|
|
}
|
|
|
|
|
2018-12-03 17:15:45 +01:00
|
|
|
// Walk down the path, swapping out linked path parts for their real
|
2016-07-27 00:18:35 +02:00
|
|
|
// values
|
|
|
|
// NB: p.length changes.
|
|
|
|
while (pos < p.length) {
|
|
|
|
// find the next part
|
2018-05-15 21:34:49 +02:00
|
|
|
const result = nextPart(p, pos);
|
2016-07-27 00:18:35 +02:00
|
|
|
previous = current;
|
2017-01-13 11:09:52 +01:00
|
|
|
if (result === -1) {
|
2018-05-15 21:34:49 +02:00
|
|
|
const last = p.slice(pos);
|
2017-01-13 11:09:52 +01:00
|
|
|
current += last;
|
|
|
|
base = previous + last;
|
|
|
|
pos = p.length;
|
|
|
|
} else {
|
|
|
|
current += p.slice(pos, result + 1);
|
|
|
|
base = previous + p.slice(pos, result);
|
|
|
|
pos = result + 1;
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2019-01-21 01:22:27 +01:00
|
|
|
// Continue if not a symlink, break if a pipe/socket
|
2016-08-14 18:41:28 +02:00
|
|
|
if (knownHard[base] || (cache && cache.get(base) === base)) {
|
2018-04-07 10:57:22 +02:00
|
|
|
if (isFileType(statValues, S_IFIFO) ||
|
|
|
|
isFileType(statValues, S_IFSOCK)) {
|
2017-05-15 00:57:54 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
let resolvedLink;
|
|
|
|
const maybeCachedResolved = cache && cache.get(base);
|
2016-08-14 18:41:28 +02:00
|
|
|
if (maybeCachedResolved) {
|
|
|
|
resolvedLink = maybeCachedResolved;
|
|
|
|
} else {
|
2017-03-12 01:41:20 +01:00
|
|
|
// Use stats array directly to avoid creating an fs.Stats instance just
|
|
|
|
// for our internal use.
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
const baseLong = pathModule.toNamespacedPath(base);
|
2017-12-28 07:51:05 +01:00
|
|
|
const ctx = { path: base };
|
2018-04-07 11:01:06 +02:00
|
|
|
const stats = binding.lstat(baseLong, false, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2017-03-12 01:41:20 +01:00
|
|
|
|
2018-04-07 10:57:22 +02:00
|
|
|
if (!isFileType(stats, S_IFLNK)) {
|
2016-08-14 18:41:28 +02:00
|
|
|
knownHard[base] = true;
|
2016-12-12 16:56:36 +01:00
|
|
|
if (cache) cache.set(base, base);
|
2016-08-14 18:41:28 +02:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2019-03-07 01:03:53 +01:00
|
|
|
// Read the link if it wasn't read before
|
2016-08-14 18:41:28 +02:00
|
|
|
// dev/ino always return 0 on windows, so skip the check.
|
2018-05-15 21:34:49 +02:00
|
|
|
let linkTarget = null;
|
|
|
|
let id;
|
2016-08-14 18:41:28 +02:00
|
|
|
if (!isWindows) {
|
2018-05-15 21:34:49 +02:00
|
|
|
const dev = stats[0].toString(32);
|
|
|
|
const ino = stats[7].toString(32);
|
2017-03-12 01:41:20 +01:00
|
|
|
id = `${dev}:${ino}`;
|
2017-03-12 05:59:37 +01:00
|
|
|
if (seenLinks[id]) {
|
2016-08-14 18:41:28 +02:00
|
|
|
linkTarget = seenLinks[id];
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
}
|
2016-08-14 18:41:28 +02:00
|
|
|
if (linkTarget === null) {
|
2017-12-27 21:01:45 +01:00
|
|
|
const ctx = { path: base };
|
2018-04-07 11:01:06 +02:00
|
|
|
binding.stat(baseLong, false, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2018-01-24 00:51:08 +01:00
|
|
|
linkTarget = binding.readlink(baseLong, undefined, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2016-08-14 18:41:28 +02:00
|
|
|
}
|
|
|
|
resolvedLink = pathModule.resolve(previous, linkTarget);
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2016-08-14 18:41:28 +02:00
|
|
|
if (cache) cache.set(base, resolvedLink);
|
|
|
|
if (!isWindows) seenLinks[id] = linkTarget;
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2019-03-07 01:03:53 +01:00
|
|
|
// Resolve the link, then start over
|
2016-07-27 00:18:35 +02:00
|
|
|
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
2017-01-13 11:04:18 +01:00
|
|
|
|
|
|
|
// Skip over roots
|
2017-03-12 05:59:37 +01:00
|
|
|
current = base = splitRoot(p);
|
|
|
|
pos = current.length;
|
2017-01-13 11:04:18 +01:00
|
|
|
|
|
|
|
// On windows, check that the root exists. On unix there is no need.
|
|
|
|
if (isWindows && !knownHard[base]) {
|
2017-12-28 07:51:05 +01:00
|
|
|
const ctx = { path: base };
|
2018-04-07 11:01:06 +02:00
|
|
|
binding.lstat(pathModule.toNamespacedPath(base), false, undefined, ctx);
|
2018-02-08 15:24:08 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2017-01-13 11:04:18 +01:00
|
|
|
knownHard[base] = true;
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
}
|
|
|
|
|
2016-08-14 18:41:28 +02:00
|
|
|
if (cache) cache.set(original, p);
|
2016-07-27 00:18:35 +02:00
|
|
|
return encodeRealpathResult(p, options);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-09-10 03:49:28 +02:00
|
|
|
|
2011-02-09 01:54:25 +01:00
|
|
|
|
2018-11-24 08:34:14 +01:00
|
|
|
realpathSync.native = (path, options) => {
|
2017-10-05 13:10:03 +02:00
|
|
|
options = getOptions(options, {});
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-02-03 15:22:05 +01:00
|
|
|
const ctx = { path };
|
|
|
|
const result = binding.realpath(path, options.encoding, undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
|
|
|
return result;
|
2017-10-05 13:10:03 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function realpath(p, options, callback) {
|
2018-12-21 09:03:50 +01:00
|
|
|
callback = typeof options === 'function' ? options : maybeCallback(callback);
|
2019-05-26 16:38:13 +02:00
|
|
|
options = getOptions(options, {});
|
2018-08-24 18:13:32 +02:00
|
|
|
p = toPathIfFileURL(p);
|
2019-05-26 16:38:13 +02:00
|
|
|
|
2017-03-12 05:59:37 +01:00
|
|
|
if (typeof p !== 'string') {
|
2018-01-23 03:23:46 +01:00
|
|
|
p += '';
|
2017-03-12 05:59:37 +01:00
|
|
|
}
|
2018-01-23 03:23:46 +01:00
|
|
|
validatePath(p);
|
2016-07-27 00:18:35 +02:00
|
|
|
p = pathModule.resolve(p);
|
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
const seenLinks = ObjectCreate(null);
|
|
|
|
const knownHard = ObjectCreate(null);
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2019-03-07 01:03:53 +01:00
|
|
|
// Current character position in p
|
2018-05-15 21:34:49 +02:00
|
|
|
let pos;
|
2018-12-10 13:27:32 +01:00
|
|
|
// The partial path so far, including a trailing slash if any
|
2018-05-15 21:34:49 +02:00
|
|
|
let current;
|
2018-12-03 17:15:45 +01:00
|
|
|
// The partial path without a trailing slash (except when pointing at a root)
|
2018-05-15 21:34:49 +02:00
|
|
|
let base;
|
2018-12-10 13:27:32 +01:00
|
|
|
// The partial path scanned in the previous round, with slash
|
2018-05-15 21:34:49 +02:00
|
|
|
let previous;
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2017-03-12 05:59:37 +01:00
|
|
|
current = base = splitRoot(p);
|
|
|
|
pos = current.length;
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2017-01-13 11:04:18 +01:00
|
|
|
// On windows, check that the root exists. On unix there is no need.
|
|
|
|
if (isWindows && !knownHard[base]) {
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.lstat(base, (err, stats) => {
|
2017-01-13 11:04:18 +01:00
|
|
|
if (err) return callback(err);
|
|
|
|
knownHard[base] = true;
|
|
|
|
LOOP();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
process.nextTick(LOOP);
|
2016-07-27 00:18:35 +02:00
|
|
|
}
|
|
|
|
|
2018-12-03 17:15:45 +01:00
|
|
|
// Walk down the path, swapping out linked path parts for their real
|
2016-07-27 00:18:35 +02:00
|
|
|
// values
|
|
|
|
function LOOP() {
|
2019-03-07 01:03:53 +01:00
|
|
|
// Stop if scanned past end of path
|
2016-07-27 00:18:35 +02:00
|
|
|
if (pos >= p.length) {
|
|
|
|
return callback(null, encodeRealpathResult(p, options));
|
|
|
|
}
|
|
|
|
|
|
|
|
// find the next part
|
2018-05-15 21:34:49 +02:00
|
|
|
const result = nextPart(p, pos);
|
2016-07-27 00:18:35 +02:00
|
|
|
previous = current;
|
2017-01-13 11:09:52 +01:00
|
|
|
if (result === -1) {
|
2018-05-15 21:34:49 +02:00
|
|
|
const last = p.slice(pos);
|
2017-01-13 11:09:52 +01:00
|
|
|
current += last;
|
|
|
|
base = previous + last;
|
|
|
|
pos = p.length;
|
|
|
|
} else {
|
|
|
|
current += p.slice(pos, result + 1);
|
|
|
|
base = previous + p.slice(pos, result);
|
|
|
|
pos = result + 1;
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
|
2019-01-21 01:22:27 +01:00
|
|
|
// Continue if not a symlink, break if a pipe/socket
|
2016-07-27 00:18:35 +02:00
|
|
|
if (knownHard[base]) {
|
2018-04-07 10:57:22 +02:00
|
|
|
if (isFileType(statValues, S_IFIFO) ||
|
|
|
|
isFileType(statValues, S_IFSOCK)) {
|
2017-05-15 00:57:54 +02:00
|
|
|
return callback(null, encodeRealpathResult(p, options));
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
return process.nextTick(LOOP);
|
|
|
|
}
|
|
|
|
|
|
|
|
return fs.lstat(base, gotStat);
|
|
|
|
}
|
|
|
|
|
2018-04-07 10:57:22 +02:00
|
|
|
function gotStat(err, stats) {
|
2016-07-27 00:18:35 +02:00
|
|
|
if (err) return callback(err);
|
|
|
|
|
2019-01-21 01:22:27 +01:00
|
|
|
// If not a symlink, skip to the next path part
|
2018-04-07 10:57:22 +02:00
|
|
|
if (!stats.isSymbolicLink()) {
|
2016-07-27 00:18:35 +02:00
|
|
|
knownHard[base] = true;
|
|
|
|
return process.nextTick(LOOP);
|
|
|
|
}
|
|
|
|
|
2019-03-07 01:03:53 +01:00
|
|
|
// Stat & read the link if not read before.
|
|
|
|
// Call `gotTarget()` as soon as the link target is known.
|
|
|
|
// `dev`/`ino` always return 0 on windows, so skip the check.
|
2016-08-14 18:41:28 +02:00
|
|
|
let id;
|
2016-07-27 00:18:35 +02:00
|
|
|
if (!isWindows) {
|
2018-05-15 21:34:49 +02:00
|
|
|
const dev = stats.dev.toString(32);
|
|
|
|
const ino = stats.ino.toString(32);
|
2017-03-12 01:41:20 +01:00
|
|
|
id = `${dev}:${ino}`;
|
2017-03-12 05:59:37 +01:00
|
|
|
if (seenLinks[id]) {
|
2016-07-27 00:18:35 +02:00
|
|
|
return gotTarget(null, seenLinks[id], base);
|
|
|
|
}
|
|
|
|
}
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.stat(base, (err) => {
|
2016-07-27 00:18:35 +02:00
|
|
|
if (err) return callback(err);
|
|
|
|
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.readlink(base, (err, target) => {
|
2016-07-27 00:18:35 +02:00
|
|
|
if (!isWindows) seenLinks[id] = target;
|
|
|
|
gotTarget(err, target);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function gotTarget(err, target, base) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
gotResolvedLink(pathModule.resolve(previous, target));
|
2016-07-27 00:18:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function gotResolvedLink(resolvedLink) {
|
2019-03-07 01:03:53 +01:00
|
|
|
// Resolve the link, then start over
|
2016-07-27 00:18:35 +02:00
|
|
|
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
2017-03-12 05:59:37 +01:00
|
|
|
current = base = splitRoot(p);
|
|
|
|
pos = current.length;
|
2017-01-13 11:04:18 +01:00
|
|
|
|
|
|
|
// On windows, check that the root exists. On unix there is no need.
|
|
|
|
if (isWindows && !knownHard[base]) {
|
2018-11-24 08:34:14 +01:00
|
|
|
fs.lstat(base, (err) => {
|
2017-01-13 11:04:18 +01:00
|
|
|
if (err) return callback(err);
|
|
|
|
knownHard[base] = true;
|
|
|
|
LOOP();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
process.nextTick(LOOP);
|
|
|
|
}
|
2016-07-27 00:18:35 +02:00
|
|
|
}
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2010-05-25 00:47:40 +02:00
|
|
|
|
2017-10-05 13:10:03 +02:00
|
|
|
|
2018-11-24 08:34:14 +01:00
|
|
|
realpath.native = (path, options, callback) => {
|
2018-02-09 16:31:26 +01:00
|
|
|
callback = makeCallback(callback || options);
|
2017-10-05 13:10:03 +02:00
|
|
|
options = getOptions(options, {});
|
2019-05-12 14:30:29 +02:00
|
|
|
path = getValidatedPath(path);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2017-10-05 13:10:03 +02:00
|
|
|
req.oncomplete = callback;
|
|
|
|
return binding.realpath(path, options.encoding, req);
|
|
|
|
};
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function mkdtemp(prefix, options, callback) {
|
2016-06-25 20:33:05 +02:00
|
|
|
callback = makeCallback(typeof options === 'function' ? options : callback);
|
|
|
|
options = getOptions(options, {});
|
2017-08-26 13:46:47 +02:00
|
|
|
if (!prefix || typeof prefix !== 'string') {
|
2018-02-27 14:55:32 +01:00
|
|
|
throw new ERR_INVALID_ARG_TYPE('prefix', 'string', prefix);
|
2017-08-26 13:46:47 +02:00
|
|
|
}
|
2018-01-23 03:23:46 +01:00
|
|
|
nullCheck(prefix, 'prefix');
|
2019-03-29 14:17:55 +01:00
|
|
|
warnOnNonPortableTemplate(prefix);
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2016-05-18 14:17:07 +02:00
|
|
|
req.oncomplete = callback;
|
2017-11-10 13:47:17 +01:00
|
|
|
binding.mkdtemp(`${prefix}XXXXXX`, options.encoding, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2016-05-18 14:17:07 +02:00
|
|
|
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function mkdtempSync(prefix, options) {
|
2018-01-23 03:23:46 +01:00
|
|
|
options = getOptions(options, {});
|
2017-08-26 13:46:47 +02:00
|
|
|
if (!prefix || typeof prefix !== 'string') {
|
2018-02-27 14:55:32 +01:00
|
|
|
throw new ERR_INVALID_ARG_TYPE('prefix', 'string', prefix);
|
2017-08-26 13:46:47 +02:00
|
|
|
}
|
2018-01-23 03:23:46 +01:00
|
|
|
nullCheck(prefix, 'prefix');
|
2019-03-29 14:17:55 +01:00
|
|
|
warnOnNonPortableTemplate(prefix);
|
2018-02-19 21:54:19 +01:00
|
|
|
const path = `${prefix}XXXXXX`;
|
|
|
|
const ctx = { path };
|
|
|
|
const result = binding.mkdtemp(path, options.encoding,
|
|
|
|
undefined, ctx);
|
|
|
|
handleErrorFromBinding(ctx);
|
|
|
|
return result;
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2017-09-06 18:54:29 +02:00
|
|
|
|
|
|
|
|
2019-04-02 01:21:36 +02:00
|
|
|
function copyFile(src, dest, mode, callback) {
|
|
|
|
if (typeof mode === 'function') {
|
|
|
|
callback = mode;
|
|
|
|
mode = 0;
|
2017-09-06 18:54:29 +02:00
|
|
|
} else if (typeof callback !== 'function') {
|
2019-04-02 03:46:17 +02:00
|
|
|
throw new ERR_INVALID_CALLBACK(callback);
|
2017-09-06 18:54:29 +02:00
|
|
|
}
|
|
|
|
|
2019-05-12 14:30:29 +02:00
|
|
|
src = getValidatedPath(src, 'src');
|
|
|
|
dest = getValidatedPath(dest, 'dest');
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2017-09-06 18:54:29 +02:00
|
|
|
src = pathModule._makeLong(src);
|
|
|
|
dest = pathModule._makeLong(dest);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = getValidMode(mode, 'copyFile');
|
2018-07-25 17:35:10 +02:00
|
|
|
const req = new FSReqCallback();
|
2017-09-06 18:54:29 +02:00
|
|
|
req.oncomplete = makeCallback(callback);
|
2019-04-02 01:21:36 +02:00
|
|
|
binding.copyFile(src, dest, mode, req);
|
2018-05-15 21:34:49 +02:00
|
|
|
}
|
2017-09-06 18:54:29 +02:00
|
|
|
|
|
|
|
|
2019-04-02 01:21:36 +02:00
|
|
|
function copyFileSync(src, dest, mode) {
|
2019-05-12 14:30:29 +02:00
|
|
|
src = getValidatedPath(src, 'src');
|
|
|
|
dest = getValidatedPath(dest, 'dest');
|
2017-12-13 23:24:34 +01:00
|
|
|
|
2018-02-16 06:25:21 +01:00
|
|
|
const ctx = { path: src, dest }; // non-prefixed
|
|
|
|
|
2017-09-06 18:54:29 +02:00
|
|
|
src = pathModule._makeLong(src);
|
|
|
|
dest = pathModule._makeLong(dest);
|
2019-04-02 01:21:36 +02:00
|
|
|
mode = getValidMode(mode, 'copyFile');
|
|
|
|
binding.copyFile(src, dest, mode, undefined, ctx);
|
2018-02-16 06:25:21 +01:00
|
|
|
handleErrorFromBinding(ctx);
|
2010-03-02 03:01:44 +01:00
|
|
|
}
|
2010-03-02 23:12:52 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function lazyLoadStreams() {
|
|
|
|
if (!ReadStream) {
|
|
|
|
({ ReadStream, WriteStream } = require('internal/fs/streams'));
|
|
|
|
[ FileReadStream, FileWriteStream ] = [ ReadStream, WriteStream ];
|
2018-04-09 19:32:08 +02:00
|
|
|
}
|
2012-10-05 02:44:48 +02:00
|
|
|
}
|
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function createReadStream(path, options) {
|
|
|
|
lazyLoadStreams();
|
|
|
|
return new ReadStream(path, options);
|
2017-06-05 16:46:55 +02:00
|
|
|
}
|
2010-03-03 12:39:41 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
function createWriteStream(path, options) {
|
|
|
|
lazyLoadStreams();
|
2010-04-28 03:51:41 +02:00
|
|
|
return new WriteStream(path, options);
|
2012-10-05 02:44:48 +02:00
|
|
|
}
|
2010-03-02 23:12:52 +01:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
module.exports = fs = {
|
|
|
|
appendFile,
|
|
|
|
appendFileSync,
|
|
|
|
access,
|
|
|
|
accessSync,
|
|
|
|
chown,
|
|
|
|
chownSync,
|
|
|
|
chmod,
|
|
|
|
chmodSync,
|
|
|
|
close,
|
|
|
|
closeSync,
|
|
|
|
copyFile,
|
|
|
|
copyFileSync,
|
|
|
|
createReadStream,
|
|
|
|
createWriteStream,
|
|
|
|
exists,
|
|
|
|
existsSync,
|
|
|
|
fchown,
|
|
|
|
fchownSync,
|
|
|
|
fchmod,
|
|
|
|
fchmodSync,
|
|
|
|
fdatasync,
|
|
|
|
fdatasyncSync,
|
|
|
|
fstat,
|
|
|
|
fstatSync,
|
|
|
|
fsync,
|
|
|
|
fsyncSync,
|
|
|
|
ftruncate,
|
|
|
|
ftruncateSync,
|
|
|
|
futimes,
|
|
|
|
futimesSync,
|
2018-06-23 22:26:29 +02:00
|
|
|
lchown,
|
|
|
|
lchownSync,
|
2018-05-15 21:34:49 +02:00
|
|
|
lchmod: constants.O_SYMLINK !== undefined ? lchmod : undefined,
|
|
|
|
lchmodSync: constants.O_SYMLINK !== undefined ? lchmodSync : undefined,
|
|
|
|
link,
|
|
|
|
linkSync,
|
|
|
|
lstat,
|
|
|
|
lstatSync,
|
|
|
|
mkdir,
|
|
|
|
mkdirSync,
|
|
|
|
mkdtemp,
|
|
|
|
mkdtempSync,
|
|
|
|
open,
|
|
|
|
openSync,
|
2019-08-28 02:14:27 +02:00
|
|
|
opendir,
|
|
|
|
opendirSync,
|
2018-05-15 21:34:49 +02:00
|
|
|
readdir,
|
|
|
|
readdirSync,
|
|
|
|
read,
|
|
|
|
readSync,
|
2020-03-16 14:50:27 +01:00
|
|
|
readv,
|
|
|
|
readvSync,
|
2018-05-15 21:34:49 +02:00
|
|
|
readFile,
|
|
|
|
readFileSync,
|
|
|
|
readlink,
|
|
|
|
readlinkSync,
|
|
|
|
realpath,
|
|
|
|
realpathSync,
|
|
|
|
rename,
|
|
|
|
renameSync,
|
|
|
|
rmdir,
|
|
|
|
rmdirSync,
|
|
|
|
stat,
|
|
|
|
statSync,
|
|
|
|
symlink,
|
|
|
|
symlinkSync,
|
|
|
|
truncate,
|
|
|
|
truncateSync,
|
|
|
|
unwatchFile,
|
|
|
|
unlink,
|
|
|
|
unlinkSync,
|
|
|
|
utimes,
|
|
|
|
utimesSync,
|
|
|
|
watch,
|
|
|
|
watchFile,
|
|
|
|
writeFile,
|
|
|
|
writeFileSync,
|
|
|
|
write,
|
|
|
|
writeSync,
|
2019-02-04 17:18:39 +01:00
|
|
|
writev,
|
|
|
|
writevSync,
|
2019-08-28 02:14:27 +02:00
|
|
|
Dir,
|
2018-07-28 04:29:32 +02:00
|
|
|
Dirent,
|
2018-05-15 21:34:49 +02:00
|
|
|
Stats,
|
2010-04-08 19:37:10 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
get ReadStream() {
|
|
|
|
lazyLoadStreams();
|
|
|
|
return ReadStream;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
set ReadStream(val) {
|
|
|
|
ReadStream = val;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
get WriteStream() {
|
|
|
|
lazyLoadStreams();
|
|
|
|
return WriteStream;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
set WriteStream(val) {
|
|
|
|
WriteStream = val;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
// Legacy names... these have to be separate because of how graceful-fs
|
|
|
|
// (and possibly other) modules monkey patch the values.
|
|
|
|
get FileReadStream() {
|
|
|
|
lazyLoadStreams();
|
|
|
|
return FileReadStream;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
set FileReadStream(val) {
|
|
|
|
FileReadStream = val;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
get FileWriteStream() {
|
|
|
|
lazyLoadStreams();
|
|
|
|
return FileWriteStream;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
set FileWriteStream(val) {
|
|
|
|
FileWriteStream = val;
|
|
|
|
},
|
2015-07-28 07:59:35 +02:00
|
|
|
|
2018-05-15 21:34:49 +02:00
|
|
|
// For tests
|
|
|
|
_toUnixTimestamp: toUnixTimestamp
|
2015-07-28 07:59:35 +02:00
|
|
|
};
|
|
|
|
|
2019-11-22 18:04:46 +01:00
|
|
|
ObjectDefineProperties(fs, {
|
2018-05-15 21:34:49 +02:00
|
|
|
F_OK: { enumerable: true, value: F_OK || 0 },
|
|
|
|
R_OK: { enumerable: true, value: R_OK || 0 },
|
|
|
|
W_OK: { enumerable: true, value: W_OK || 0 },
|
|
|
|
X_OK: { enumerable: true, value: X_OK || 0 },
|
|
|
|
constants: {
|
|
|
|
configurable: false,
|
|
|
|
enumerable: true,
|
|
|
|
value: constants
|
|
|
|
},
|
|
|
|
promises: {
|
|
|
|
configurable: true,
|
2019-03-11 11:19:47 +01:00
|
|
|
enumerable: true,
|
2018-05-15 21:34:49 +02:00
|
|
|
get() {
|
2019-03-11 11:19:47 +01:00
|
|
|
if (promises === null)
|
2019-10-04 20:37:51 +02:00
|
|
|
promises = require('internal/fs/promises').exports;
|
2018-05-15 21:34:49 +02:00
|
|
|
return promises;
|
2018-01-05 10:41:14 +01:00
|
|
|
}
|
2017-09-14 13:46:02 +02:00
|
|
|
}
|
2018-05-15 21:34:49 +02:00
|
|
|
});
|