fix fs.readFile with lying size=0 stat results
This commit is contained in:
parent
d53cdc5378
commit
6ce013dd4b
73
lib/fs.js
73
lib/fs.js
@ -108,7 +108,8 @@ fs.readFile = function(path, encoding_) {
|
||||
|
||||
// first, stat the file, so we know the size.
|
||||
var size;
|
||||
var buffer;
|
||||
var buffer; // single buffer with file data
|
||||
var buffers; // list for when size is unknown
|
||||
var pos = 0;
|
||||
var fd;
|
||||
|
||||
@ -120,8 +121,10 @@ fs.readFile = function(path, encoding_) {
|
||||
if (er) return callback(er);
|
||||
size = st.size;
|
||||
if (size === 0) {
|
||||
buffer = new Buffer(0);
|
||||
return afterRead(null, 0);
|
||||
// the kernel lies about many files.
|
||||
// Go ahead and try to read some bytes.
|
||||
buffers = [];
|
||||
return read();
|
||||
}
|
||||
|
||||
buffer = new Buffer(size);
|
||||
@ -130,7 +133,12 @@ fs.readFile = function(path, encoding_) {
|
||||
});
|
||||
|
||||
function read() {
|
||||
fs.read(fd, buffer, pos, size - pos, pos, afterRead);
|
||||
if (size === 0) {
|
||||
buffer = new Buffer(8192);
|
||||
fs.read(fd, buffer, 0, 8192, pos, afterRead);
|
||||
} else {
|
||||
fs.read(fd, buffer, pos, size - pos, pos, afterRead);
|
||||
}
|
||||
}
|
||||
|
||||
function afterRead(er, bytesRead) {
|
||||
@ -141,12 +149,27 @@ fs.readFile = function(path, encoding_) {
|
||||
}
|
||||
|
||||
pos += bytesRead;
|
||||
if (pos === size) close();
|
||||
else read();
|
||||
if (size !== 0) {
|
||||
if (pos === size) close();
|
||||
else read();
|
||||
} else {
|
||||
// unknown size, just read until we don't get bytes.
|
||||
if (bytesRead > 0) {
|
||||
buffers.push(buffer.slice(0, bytesRead));
|
||||
read();
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
fs.close(fd, function(er) {
|
||||
if (size === 0) {
|
||||
// collected the data into the buffers list.
|
||||
buffer = Buffer.concat(buffer.length, pos);
|
||||
}
|
||||
|
||||
if (encoding) buffer = buffer.toString(encoding);
|
||||
return callback(er, buffer);
|
||||
});
|
||||
@ -165,28 +188,52 @@ fs.readFileSync = function(path, encoding) {
|
||||
if (threw) fs.closeSync(fd);
|
||||
}
|
||||
|
||||
var pos = 0;
|
||||
var buffer; // single buffer with file data
|
||||
var buffers; // list for when size is unknown
|
||||
|
||||
if (size === 0) {
|
||||
fs.closeSync(fd);
|
||||
return encoding ? '' : new Buffer(0);
|
||||
buffers = [];
|
||||
} else {
|
||||
buffer = new Buffer(size);
|
||||
}
|
||||
|
||||
var buffer = new Buffer(size);
|
||||
var pos = 0;
|
||||
|
||||
while (pos < size) {
|
||||
var done = false;
|
||||
while (!done) {
|
||||
var threw = true;
|
||||
try {
|
||||
var bytesRead = fs.readSync(fd, buffer, pos, size - pos, pos);
|
||||
if (size !== 0) {
|
||||
var bytesRead = fs.readSync(fd, buffer, pos, size - pos, pos);
|
||||
} else {
|
||||
// the kernel lies about many files.
|
||||
// Go ahead and try to read some bytes.
|
||||
buffer = new Buffer(8192);
|
||||
var bytesRead = fs.readSync(fd, buffer, 0, 8192, pos);
|
||||
if (bytesRead) {
|
||||
buffers.push(buffer.slice(0, bytesRead));
|
||||
}
|
||||
}
|
||||
threw = false;
|
||||
} finally {
|
||||
if (threw) fs.closeSync(fd);
|
||||
}
|
||||
|
||||
pos += bytesRead;
|
||||
|
||||
if (size !== 0) {
|
||||
done = pos >= size;
|
||||
} else {
|
||||
done = bytesRead > 0;
|
||||
}
|
||||
}
|
||||
|
||||
fs.closeSync(fd);
|
||||
|
||||
if (size === 0) {
|
||||
// data was collected into the buffers list.
|
||||
buffer = Buffer.concat(buffers, pos);
|
||||
}
|
||||
|
||||
if (encoding) buffer = buffer.toString(encoding);
|
||||
return buffer;
|
||||
};
|
||||
|
58
test/simple/test-fs-readfile-zero-byte-liar.js
Normal file
58
test/simple/test-fs-readfile-zero-byte-liar.js
Normal file
@ -0,0 +1,58 @@
|
||||
// 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.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
var dataExpected = fs.readFileSync(__filename, 'utf8');
|
||||
|
||||
// sometimes stat returns size=0, but it's a lie.
|
||||
fs._fstat = fs.fstat;
|
||||
fs._fstatSync = fs.fstatSync;
|
||||
|
||||
fs.fstat = function(fd, cb) {
|
||||
fs._fstat(fd, function(er, st) {
|
||||
if (er) return cb(er);
|
||||
st.size = 0;
|
||||
return cb(er, st);
|
||||
});
|
||||
};
|
||||
|
||||
fs.fstatSync = function(fd) {
|
||||
var st = fs._fstatSync;
|
||||
st.size = 0;
|
||||
return st;
|
||||
};
|
||||
|
||||
var d = fs.readFileSync(__filename, 'utf8');
|
||||
assert.equal(d, dataExpected);
|
||||
|
||||
var called = false;
|
||||
fs.readFile(__filename, 'utf8', function (er, d) {
|
||||
assert.equal(d, dataExpected);
|
||||
called = true;
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert(called);
|
||||
console.log("ok");
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user