mirror of
https://github.com/denoland/deno.git
synced 2025-02-01 20:25:12 -05:00
feat(std/wasi): implement fd_readdir (#6631)
This commit is contained in:
parent
9ac416913e
commit
79400b8f7d
3 changed files with 102 additions and 14 deletions
|
@ -27,7 +27,7 @@ This module provides an implementation of the WebAssembly System Interface
|
|||
- [x] fd_prestat_dir_name
|
||||
- [x] fd_pwrite
|
||||
- [x] fd_read
|
||||
- [ ] fd_readdir
|
||||
- [x] fd_readdir
|
||||
- [x] fd_renumber
|
||||
- [x] fd_seek
|
||||
- [x] fd_sync
|
||||
|
|
|
@ -317,15 +317,12 @@ export default class Module {
|
|||
|
||||
if (options.preopens) {
|
||||
for (const [vpath, path] of Object.entries(options.preopens)) {
|
||||
const info = Deno.statSync(path);
|
||||
if (!info.isDirectory) {
|
||||
throw new TypeError(`${path} is not a directory`);
|
||||
}
|
||||
|
||||
const type = FILETYPE_DIRECTORY;
|
||||
const entries = Array.from(Deno.readDirSync(path));
|
||||
|
||||
const entry = {
|
||||
type,
|
||||
entries,
|
||||
path,
|
||||
vpath,
|
||||
};
|
||||
|
@ -485,7 +482,10 @@ export default class Module {
|
|||
return ERRNO_BADF;
|
||||
}
|
||||
|
||||
entry.handle.close();
|
||||
if (entry.handle) {
|
||||
entry.handle.close();
|
||||
}
|
||||
|
||||
delete this.fds[fd];
|
||||
|
||||
return ERRNO_SUCCESS;
|
||||
|
@ -797,7 +797,70 @@ export default class Module {
|
|||
cookie: bigint,
|
||||
bufused_out: number
|
||||
): number => {
|
||||
return ERRNO_NOSYS;
|
||||
const entry = this.fds[fd];
|
||||
if (!entry) {
|
||||
return ERRNO_BADF;
|
||||
}
|
||||
|
||||
const heap = new Uint8Array(this.memory.buffer);
|
||||
const view = new DataView(this.memory.buffer);
|
||||
|
||||
let bufused = 0;
|
||||
|
||||
try {
|
||||
const entries = Array.from(Deno.readDirSync(entry.path));
|
||||
for (let i = Number(cookie); i < entries.length; i++) {
|
||||
const name_data = new TextEncoder().encode(entries[i].name);
|
||||
|
||||
const entry_info = Deno.statSync(
|
||||
resolve(entry.path, entries[i].name)
|
||||
);
|
||||
const entry_data = new Uint8Array(24 + name_data.byteLength);
|
||||
const entry_view = new DataView(entry_data.buffer);
|
||||
|
||||
entry_view.setBigUint64(0, BigInt(i + 1), true);
|
||||
entry_view.setBigUint64(
|
||||
8,
|
||||
BigInt(entry_info.ino ? entry_info.ino : 0),
|
||||
true
|
||||
);
|
||||
entry_view.setUint32(16, name_data.byteLength, true);
|
||||
|
||||
switch (true) {
|
||||
case entries[i].isFile:
|
||||
var type = FILETYPE_REGULAR_FILE;
|
||||
break;
|
||||
|
||||
case entries[i].isDirectory:
|
||||
var type = FILETYPE_REGULAR_FILE;
|
||||
break;
|
||||
|
||||
case entries[i].isSymlink:
|
||||
var type = FILETYPE_SYMBOLIC_LINK;
|
||||
break;
|
||||
|
||||
default:
|
||||
var type = FILETYPE_REGULAR_FILE;
|
||||
break;
|
||||
}
|
||||
|
||||
entry_view.setUint8(20, type);
|
||||
entry_data.set(name_data, 24);
|
||||
|
||||
const data = entry_data.slice(
|
||||
0,
|
||||
Math.min(entry_data.length, buf_len - bufused)
|
||||
);
|
||||
heap.set(data, buf_ptr + bufused);
|
||||
bufused += data.byteLength;
|
||||
}
|
||||
} catch (err) {
|
||||
return errno(err);
|
||||
}
|
||||
|
||||
view.setUint32(bufused_out, bufused, true);
|
||||
|
||||
return ERRNO_SUCCESS;
|
||||
},
|
||||
|
||||
fd_renumber: (fd: number, to: number): number => {
|
||||
|
@ -1126,6 +1189,28 @@ export default class Module {
|
|||
const data = new Uint8Array(this.memory.buffer, path_ptr, path_len);
|
||||
const path = resolve(entry.path, text.decode(data));
|
||||
|
||||
if ((oflags & OFLAGS_DIRECTORY) !== 0) {
|
||||
// XXX (caspervonb) this isn't ideal as we can't get a rid for the
|
||||
// directory this way so there's no native fstat but Deno.open
|
||||
// doesn't work with directories on windows so we'll have to work
|
||||
// around it for now.
|
||||
try {
|
||||
const entries = Array.from(Deno.readDirSync(path));
|
||||
const opened_fd =
|
||||
this.fds.push({
|
||||
entries,
|
||||
path,
|
||||
}) - 1;
|
||||
|
||||
const view = new DataView(this.memory.buffer);
|
||||
view.setUint32(opened_fd_out, opened_fd, true);
|
||||
} catch (err) {
|
||||
return errno(err);
|
||||
}
|
||||
|
||||
return ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
const options = {
|
||||
read: false,
|
||||
write: false,
|
||||
|
@ -1140,12 +1225,6 @@ export default class Module {
|
|||
options.write = true;
|
||||
}
|
||||
|
||||
if ((oflags & OFLAGS_DIRECTORY) !== 0) {
|
||||
// TODO (caspervonb) review if we can
|
||||
// emulate this; unix supports opening
|
||||
// directories, windows does not.
|
||||
}
|
||||
|
||||
if ((oflags & OFLAGS_EXCL) !== 0) {
|
||||
options.createNew = true;
|
||||
}
|
||||
|
|
9
std/wasi/testdata/std_fs_read_dir.rs
vendored
Normal file
9
std/wasi/testdata/std_fs_read_dir.rs
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// { "preopens": { "/fixture": "fixture" } }
|
||||
|
||||
fn main() {
|
||||
let entries = std::fs::read_dir("/fixture").unwrap();
|
||||
assert_eq!(entries.count(), 4);
|
||||
|
||||
let entries = std::fs::read_dir("/fixture/directory").unwrap();
|
||||
assert_eq!(entries.count(), 2);
|
||||
}
|
Loading…
Add table
Reference in a new issue