Skip to content

Commit

Permalink
Implement path_rename
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Dec 23, 2023
1 parent a52cae8 commit 9c43c9e
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 15 deletions.
7 changes: 5 additions & 2 deletions src/fd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,12 @@ export abstract class Fd {
): number {
return wasi.ERRNO_NOTSUP;
}
path_link(path: string, inode: Inode): number {
path_link(path: string, inode: Inode, allow_dir: boolean): number {
return wasi.ERRNO_NOTSUP;
}
path_unlink(path: string): { ret: number; inode_obj: Inode | null } {
return { ret: wasi.ERRNO_NOTSUP, inode_obj: null };
}
path_lookup(
path: string,
dirflags: number,
Expand All @@ -117,7 +120,7 @@ export abstract class Fd {
fs_rights_inheriting: bigint,
fd_flags: number,
): { ret: number; fd_obj: Fd | null } {
return { ret: wasi.ERRNO_NOTSUP, fd_obj: null };
return { ret: wasi.ERRNO_NOTDIR, fd_obj: null };
}
path_readlink(path: string): { ret: number; data: string | null } {
return { ret: wasi.ERRNO_NOTSUP, data: null };
Expand Down
54 changes: 51 additions & 3 deletions src/fs_core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ export class OpenDirectory extends Fd {
).ret;
}

path_link(path_str: string, inode: Inode): number {
path_link(path_str: string, inode: Inode, allow_dir: boolean): number {
const { ret: path_ret, path } = Path.from(path_str);
if (path_str == null) {
return path_ret;
Expand All @@ -450,10 +450,33 @@ export class OpenDirectory extends Fd {
}

if (entry != null) {
return wasi.ERRNO_EXIST;
const source_is_dir = inode.stat().filetype == wasi.FILETYPE_DIRECTORY;
const target_is_dir = entry.stat().filetype == wasi.FILETYPE_DIRECTORY;
if (source_is_dir && target_is_dir) {
if (allow_dir && entry instanceof Directory) {
if (entry.contents.size == 0) {
// Allow overwriting empty directories
} else {
return wasi.ERRNO_NOTEMPTY;
}
} else {
return wasi.ERRNO_EXIST;
}
} else if (source_is_dir && !target_is_dir) {
return wasi.ERRNO_NOTDIR;
} else if (!source_is_dir && target_is_dir) {
return wasi.ERRNO_ISDIR;
} else if (
inode.stat().filetype == wasi.FILETYPE_REGULAR_FILE &&
entry.stat().filetype == wasi.FILETYPE_REGULAR_FILE
) {
// Overwriting regular files is fine
} else {
return wasi.ERRNO_EXIST;
}
}

if (inode.stat().filetype == wasi.FILETYPE_DIRECTORY) {
if (!allow_dir && inode.stat().filetype == wasi.FILETYPE_DIRECTORY) {
return wasi.ERRNO_PERM;
}

Expand All @@ -462,6 +485,31 @@ export class OpenDirectory extends Fd {
return wasi.ERRNO_SUCCESS;
}

path_unlink(path_str: string): { ret: number; inode_obj: Inode | null } {
const { ret: path_ret, path } = Path.from(path_str);
if (path_str == null) {
return { ret: path_ret, inode_obj: null };
}

const {
ret: parent_ret,
parent_entry,
filename,
entry,
} = this.dir.get_parent_dir_and_entry_for_path(path, true);
if (parent_entry == null || filename == null) {
return { ret: parent_ret, inode_obj: null };
}

if (entry == null) {
return { ret: wasi.ERRNO_NOENT, inode_obj: null };
}

parent_entry.contents.delete(filename);

return { ret: wasi.ERRNO_SUCCESS, inode_obj: entry };
}

path_unlink_file(path_str: string): number {
const { ret: path_ret, path } = Path.from(path_str);
if (path == null) {
Expand Down
35 changes: 27 additions & 8 deletions src/wasi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ export default class WASI {
if (inode_obj == null) {
return ret;
}
return self.fds[new_fd].path_link(new_path, inode_obj);
return self.fds[new_fd].path_link(new_path, inode_obj, false);
} else {
return wasi.ERRNO_BADF;
}
Expand Down Expand Up @@ -688,20 +688,39 @@ export default class WASI {
}
},
path_rename(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
fd: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
old_path_ptr: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
old_path_len: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
new_fd: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
new_path_ptr: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
new_path_len: number,
): number {
throw "FIXME what is the best abstraction for this?";
const buffer8 = new Uint8Array(self.inst.exports.memory.buffer);
if (self.fds[fd] != undefined && self.fds[new_fd] != undefined) {
const old_path = new TextDecoder("utf-8").decode(
buffer8.slice(old_path_ptr, old_path_ptr + old_path_len),
);
const new_path = new TextDecoder("utf-8").decode(
buffer8.slice(new_path_ptr, new_path_ptr + new_path_len),
);
// eslint-disable-next-line prefer-const
let { ret, inode_obj } = self.fds[fd].path_unlink(old_path);
if (inode_obj == null) {
return ret;
}
ret = self.fds[new_fd].path_link(new_path, inode_obj, true);
if (ret != wasi.ERRNO_SUCCESS) {
if (
self.fds[fd].path_link(old_path, inode_obj, true) !=
wasi.ERRNO_SUCCESS
) {
throw "path_link should always return success when relinking an inode back to the original place";
}
}
return ret;
} else {
return wasi.ERRNO_BADF;
}
},
path_symlink(
old_path_ptr: number,
Expand Down
2 changes: 0 additions & 2 deletions test/skip.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
"fdopendir-with-access": "fail"
},
"WASI Rust tests": {
"path_rename": "fail",
"path_exists": "fail",
"path_open_dirfd_not_dir": "fail",
"fd_filestat_set": "fail",
"symlink_create": "fail",
"path_open_read_write": "fail",
Expand Down

0 comments on commit 9c43c9e

Please sign in to comment.