0
0
Fork 0
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:
Casper Beyer 2020-07-06 06:08:05 +08:00 committed by GitHub
parent 9ac416913e
commit 79400b8f7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 14 deletions

View file

@ -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

View file

@ -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
View 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);
}