Skip to content

Commit c028edb

Browse files
authored
Fix renaming a file on top of an existing file in memfs and nodefs (#23074)
1 parent c60dcfe commit c028edb

File tree

4 files changed

+76
-8
lines changed

4 files changed

+76
-8
lines changed

src/library_memfs.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,18 @@ addToLibrary({
191191
return MEMFS.createNode(parent, name, mode, dev);
192192
},
193193
rename(old_node, new_dir, new_name) {
194-
// if we're overwriting a directory at new_name, make sure it's empty.
195-
if (FS.isDir(old_node.mode)) {
196-
var new_node;
197-
try {
198-
new_node = FS.lookupNode(new_dir, new_name);
199-
} catch (e) {
200-
}
201-
if (new_node) {
194+
var new_node;
195+
try {
196+
new_node = FS.lookupNode(new_dir, new_name);
197+
} catch (e) {}
198+
if (new_node) {
199+
if (FS.isDir(old_node.mode)) {
200+
// if we're overwriting a directory at new_name, make sure it's empty.
202201
for (var i in new_node.contents) {
203202
throw new FS.ErrnoError({{{ cDefs.ENOTEMPTY }}});
204203
}
205204
}
205+
FS.hashRemoveNode(new_node);
206206
}
207207
// do the internal rewiring
208208
delete old_node.parent.contents[old_node.name];

src/library_nodefs.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ addToLibrary({
197197
rename(oldNode, newDir, newName) {
198198
var oldPath = NODEFS.realPath(oldNode);
199199
var newPath = PATH.join2(NODEFS.realPath(newDir), newName);
200+
try {
201+
FS.unlink(newPath);
202+
} catch(e) {}
200203
NODEFS.tryFSOperation(() => fs.renameSync(oldPath, newPath));
201204
oldNode.name = newName;
202205
},

test/fs/test_fs_rename_on_existing.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <stdio.h>
2+
#include <unistd.h>
3+
#include <assert.h>
4+
#include <fcntl.h>
5+
#include <string.h>
6+
#include <sys/stat.h>
7+
#include <assert.h>
8+
#include <errno.h>
9+
#include <string.h>
10+
11+
12+
#if defined(__EMSCRIPTEN__)
13+
#include <emscripten.h>
14+
#endif
15+
16+
void makedir(const char *dir) {
17+
int rtn = mkdir(dir, 0777);
18+
assert(rtn == 0);
19+
}
20+
21+
void changedir(const char *dir) {
22+
int rtn = chdir(dir);
23+
assert(rtn == 0);
24+
}
25+
26+
static void create_file(const char *path, const char *buffer) {
27+
printf("creating: %s\n", path);
28+
int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666);
29+
printf("error: %s\n", strerror(errno));
30+
assert(fd >= 0);
31+
32+
int err = write(fd, buffer, sizeof(char) * strlen(buffer));
33+
assert(err == (sizeof(char) * strlen(buffer)));
34+
35+
close(fd);
36+
}
37+
38+
39+
void setup() {
40+
#if defined(__EMSCRIPTEN__) && defined(NODEFS)
41+
makedir("working");
42+
EM_ASM(FS.mount(NODEFS, { root: '.' }, 'working'));
43+
changedir("working");
44+
#endif
45+
}
46+
47+
int main() {
48+
setup();
49+
create_file("a", "abc");
50+
create_file("b", "xyz");
51+
assert(rename("a", "b") == 0);
52+
assert(unlink("b") == 0);
53+
create_file("b", "xyz");
54+
printf("success\n");
55+
}

test/test_core.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5935,6 +5935,16 @@ def test_fs_64bit(self):
59355935
self.set_setting('FORCE_FILESYSTEM')
59365936
self.do_runf('fs/test_64bit.c', 'success')
59375937

5938+
@parameterized({
5939+
'': ([],),
5940+
'nodefs': (['-DNODEFS', '-lnodefs.js'],),
5941+
'noderawfs': (['-sNODERAWFS'],)
5942+
})
5943+
def test_fs_rename_on_existing(self, args):
5944+
if self.get_setting('WASMFS'):
5945+
self.set_setting('FORCE_FILESYSTEM')
5946+
self.do_runf('fs/test_fs_rename_on_existing.c', 'success', emcc_args=args)
5947+
59385948
def test_sigalrm(self):
59395949
self.do_runf('test_sigalrm.c', 'Received alarm!')
59405950
self.set_setting('EXIT_RUNTIME')

0 commit comments

Comments
 (0)