Skip to content

Commit

Permalink
fs: support pseudofiles in promises.readFile
Browse files Browse the repository at this point in the history
PR-URL: #21497
Fixes: #21331
Refs: http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
Refs: https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
  • Loading branch information
TimothyGu committed Jul 4, 2018
1 parent c01601e commit 5057dd4
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 21 deletions.
17 changes: 9 additions & 8 deletions lib/internal/fs/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ async function writeFileHandle(filehandle, data, options) {
} while (remaining > 0);
}

// Note: This is different from kReadFileBufferLength used for non-promisified
// fs.readFile.
const kReadFileMaxChunkSize = 16384;

async function readFileHandle(filehandle, options) {
const statFields = await binding.fstat(filehandle.fd, false, kUsePromises);

Expand All @@ -135,22 +139,19 @@ async function readFileHandle(filehandle, options) {
size = 0;
}

if (size === 0)
return options.encoding ? '' : Buffer.alloc(0);

if (size > kMaxLength)
throw new ERR_FS_FILE_TOO_LARGE(size);

const chunks = [];
const chunkSize = Math.min(size, 16384);
let totalRead = 0;
const chunkSize = size === 0 ?
kReadFileMaxChunkSize :
Math.min(size, kReadFileMaxChunkSize);
let endOfFile = false;
do {
const buf = Buffer.alloc(chunkSize);
const { bytesRead, buffer } =
await read(filehandle, buf, 0, chunkSize, totalRead);
totalRead += bytesRead;
endOfFile = bytesRead !== chunkSize;
await read(filehandle, buf, 0, chunkSize, -1);
endOfFile = bytesRead === 0;
if (bytesRead > 0)
chunks.push(buffer.slice(0, bytesRead));
} while (!endOfFile);
Expand Down
17 changes: 17 additions & 0 deletions test/parallel/test-fs-promises-file-handle-readFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,22 @@ async function validateReadFile() {
assert.deepStrictEqual(buffer, readFileData);
}

async function validateReadFileProc() {
// Test to make sure reading a file under the /proc directory works. Adapted
// from test-fs-read-file-sync-hostname.js.
// Refs:
// - https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0
// - https://github.com/nodejs/node/issues/21331

// Test is Linux-specific.
if (!common.isLinux)
return;

const fileHandle = await open('/proc/sys/kernel/hostname', 'r');
const hostname = await fileHandle.readFile();
assert.ok(hostname.length > 0);
}

validateReadFile()
.then(() => validateReadFileProc())
.then(common.mustCall());
44 changes: 31 additions & 13 deletions test/parallel/test-fs-promises-readfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,35 @@ const fn = path.join(tmpdir.path, 'large-file');

common.crashOnUnhandledRejection();

// Creating large buffer with random content
const buffer = Buffer.from(
Array.apply(null, { length: 16834 * 2 })
.map(Math.random)
.map((number) => (number * (1 << 8)))
);

// Writing buffer to a file then try to read it
writeFile(fn, buffer)
.then(() => readFile(fn))
.then((readBuffer) => {
assert.strictEqual(readBuffer.equals(buffer), true);
})
async function validateReadFile() {
// Creating large buffer with random content
const buffer = Buffer.from(
Array.apply(null, { length: 16834 * 2 })
.map(Math.random)
.map((number) => (number * (1 << 8)))
);

// Writing buffer to a file then try to read it
await writeFile(fn, buffer);
const readBuffer = await readFile(fn);
assert.strictEqual(readBuffer.equals(buffer), true);
}

async function validateReadFileProc() {
// Test to make sure reading a file under the /proc directory works. Adapted
// from test-fs-read-file-sync-hostname.js.
// Refs:
// - https://groups.google.com/forum/#!topic/nodejs-dev/rxZ_RoH1Gn0
// - https://github.com/nodejs/node/issues/21331

// Test is Linux-specific.
if (!common.isLinux)
return;

const hostname = await readFile('/proc/sys/kernel/hostname');
assert.ok(hostname.length > 0);
}

validateReadFile()
.then(() => validateReadFileProc())
.then(common.mustCall());

0 comments on commit 5057dd4

Please sign in to comment.