Skip to content

Commit 375f0a7

Browse files
committed
fs: adjust truncate mode from r+ to a
1 parent 8bf7754 commit 375f0a7

File tree

5 files changed

+74
-15
lines changed

5 files changed

+74
-15
lines changed

doc/api/fs.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ try {
593593
```
594594
595595
If the file previously was shorter than `len` bytes, it is extended, and the
596-
extended part is filled with null bytes (`'\0'`):
596+
extended part is filled with null bytes (`'\0'`).
597597
598598
If `len` is negative then `0` will be used.
599599
@@ -1481,6 +1481,10 @@ automatically be normalized to absolute path.
14811481
14821482
<!-- YAML
14831483
added: v10.0.0
1484+
changes:
1485+
- version: REPLACEME
1486+
pr-url: https://github.com/nodejs/node/pull/43315
1487+
description: Creates a file if it didn't exist.
14841488
-->
14851489
14861490
* `path` {string|Buffer|URL}
@@ -4073,6 +4077,9 @@ $ tree .
40734077
<!-- YAML
40744078
added: v0.8.6
40754079
changes:
4080+
- version: REPLACEME
4081+
pr-url: https://github.com/nodejs/node/pull/43315
4082+
description: Creates a file if it didn't exist.
40764083
- version: v18.0.0
40774084
pr-url: https://github.com/nodejs/node/pull/41678
40784085
description: Passing an invalid callback to the `callback` argument
@@ -5781,6 +5788,10 @@ this API: [`fs.symlink()`][].
57815788
57825789
<!-- YAML
57835790
added: v0.8.6
5791+
changes:
5792+
- version: REPLACEME
5793+
pr-url: https://github.com/nodejs/node/pull/43315
5794+
description: Creates a file if it didn't exist.
57845795
-->
57855796
57865797
* `path` {string|Buffer|URL}

lib/fs.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,7 @@ function truncate(path, len, callback) {
10601060
validateInteger(len, 'len');
10611061
len = MathMax(0, len);
10621062
callback = maybeCallback(callback);
1063-
fs.open(path, 'r+', (er, fd) => {
1063+
fs.open(path, 'a', (er, fd) => {
10641064
if (er) return callback(er);
10651065
const req = new FSReqCallback();
10661066
req.oncomplete = function oncomplete(er) {
@@ -1088,7 +1088,7 @@ function truncateSync(path, len) {
10881088
len = 0;
10891089
}
10901090
// Allow error to be thrown, but still close fd.
1091-
const fd = fs.openSync(path, 'r+');
1091+
const fd = fs.openSync(path, 'a');
10921092
let ret;
10931093

10941094
try {

lib/internal/fs/promises.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ async function rename(oldPath, newPath) {
635635
}
636636

637637
async function truncate(path, len = 0) {
638-
const fd = await open(path, 'r+');
638+
const fd = await open(path, 'a');
639639
return handleFdClose(ftruncate(fd, len), fd.close);
640640
}
641641

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
// This test ensures that truncate works on non-readable files
6+
7+
const assert = require('assert');
8+
const fs = require('fs');
9+
const fsPromises = fs.promises;
10+
const path = require('path');
11+
const tmpdir = require('../common/tmpdir');
12+
tmpdir.refresh();
13+
14+
const expected = Buffer.from('good');
15+
16+
function checkContents(filepath) {
17+
fs.chmodSync(filepath, 0o400);
18+
assert.deepStrictEqual(
19+
fs.readFileSync(filepath),
20+
expected
21+
);
22+
}
23+
24+
(async () => {
25+
const MODE = 0o200;
26+
{
27+
const filepath = path.resolve(tmpdir.path, 'promises.txt');
28+
fs.writeFileSync(filepath, 'good bad');
29+
fs.chmodSync(filepath, MODE);
30+
await fsPromises.truncate(filepath, 4);
31+
checkContents(filepath);
32+
}
33+
{
34+
const filepath = path.resolve(tmpdir.path, 'callback.txt');
35+
fs.writeFileSync(filepath, 'good bad');
36+
fs.chmodSync(filepath, MODE);
37+
fs.truncate(filepath, 4, common.mustSucceed(() => {
38+
checkContents(filepath);
39+
}));
40+
}
41+
{
42+
const filepath = path.resolve(tmpdir.path, 'synchronous.txt');
43+
fs.writeFileSync(filepath, 'good bad');
44+
fs.chmodSync(filepath, MODE);
45+
fs.truncateSync(filepath, 4);
46+
checkContents(filepath);
47+
}
48+
})().then(common.mustCall());

test/parallel/test-fs-truncate.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -242,17 +242,17 @@ function testFtruncate(cb) {
242242
}
243243

244244
{
245-
const file8 = path.resolve(tmp, 'non-existent-truncate-file.txt');
246-
const validateError = (err) => {
247-
assert.strictEqual(file8, err.path);
248-
assert.strictEqual(
249-
err.message,
250-
`ENOENT: no such file or directory, open '${file8}'`);
251-
assert.strictEqual(err.code, 'ENOENT');
252-
assert.strictEqual(err.syscall, 'open');
253-
return true;
254-
};
255-
fs.truncate(file8, 0, common.mustCall(validateError));
245+
const file8 = path.resolve(tmp, 'non-existent-truncate-file-1.txt');
246+
fs.truncate(file8, 0, common.mustSucceed(() => {
247+
assert(fs.readFileSync(file8).equals(Buffer.from('')));
248+
}));
249+
}
250+
251+
{
252+
const file9 = path.resolve(tmp, 'non-existent-truncate-file-2.txt');
253+
fs.truncate(file9, 2, common.mustSucceed(() => {
254+
assert(fs.readFileSync(file9).equals(Buffer.from('\u0000\u0000')));
255+
}));
256256
}
257257

258258
['', false, null, {}, []].forEach((input) => {

0 commit comments

Comments
 (0)