Skip to main content
Module

std/wasi/snapshot_preview1.ts

Deno standard library
Go to Latest
File
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
/* eslint-disable */// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { resolve } from "../path/mod.ts";
const CLOCKID_REALTIME = 0;const CLOCKID_MONOTONIC = 1;const CLOCKID_PROCESS_CPUTIME_ID = 2;const CLOCKID_THREAD_CPUTIME_ID = 3;
const ERRNO_SUCCESS = 0;const ERRNO_2BIG = 1;const ERRNO_ACCES = 2;const ERRNO_ADDRINUSE = 3;const ERRNO_ADDRNOTAVAIL = 4;const ERRNO_AFNOSUPPORT = 5;const ERRNO_AGAIN = 6;const ERRNO_ALREADY = 7;const ERRNO_BADF = 8;const ERRNO_BADMSG = 9;const ERRNO_BUSY = 10;const ERRNO_CANCELED = 11;const ERRNO_CHILD = 12;const ERRNO_CONNABORTED = 13;const ERRNO_CONNREFUSED = 14;const ERRNO_CONNRESET = 15;const ERRNO_DEADLK = 16;const ERRNO_DESTADDRREQ = 17;const ERRNO_DOM = 18;const ERRNO_DQUOT = 19;const ERRNO_EXIST = 20;const ERRNO_FAULT = 21;const ERRNO_FBIG = 22;const ERRNO_HOSTUNREACH = 23;const ERRNO_IDRM = 24;const ERRNO_ILSEQ = 25;const ERRNO_INPROGRESS = 26;const ERRNO_INTR = 27;const ERRNO_INVAL = 28;const ERRNO_IO = 29;const ERRNO_ISCONN = 30;const ERRNO_ISDIR = 31;const ERRNO_LOOP = 32;const ERRNO_MFILE = 33;const ERRNO_MLINK = 34;const ERRNO_MSGSIZE = 35;const ERRNO_MULTIHOP = 36;const ERRNO_NAMETOOLONG = 37;const ERRNO_NETDOWN = 38;const ERRNO_NETRESET = 39;const ERRNO_NETUNREACH = 40;const ERRNO_NFILE = 41;const ERRNO_NOBUFS = 42;const ERRNO_NODEV = 43;const ERRNO_NOENT = 44;const ERRNO_NOEXEC = 45;const ERRNO_NOLCK = 46;const ERRNO_NOLINK = 47;const ERRNO_NOMEM = 48;const ERRNO_NOMSG = 49;const ERRNO_NOPROTOOPT = 50;const ERRNO_NOSPC = 51;const ERRNO_NOSYS = 52;const ERRNO_NOTCONN = 53;const ERRNO_NOTDIR = 54;const ERRNO_NOTEMPTY = 55;const ERRNO_NOTRECOVERABLE = 56;const ERRNO_NOTSOCK = 57;const ERRNO_NOTSUP = 58;const ERRNO_NOTTY = 59;const ERRNO_NXIO = 60;const ERRNO_OVERFLOW = 61;const ERRNO_OWNERDEAD = 62;const ERRNO_PERM = 63;const ERRNO_PIPE = 64;const ERRNO_PROTO = 65;const ERRNO_PROTONOSUPPORT = 66;const ERRNO_PROTOTYPE = 67;const ERRNO_RANGE = 68;const ERRNO_ROFS = 69;const ERRNO_SPIPE = 70;const ERRNO_SRCH = 71;const ERRNO_STALE = 72;const ERRNO_TIMEDOUT = 73;const ERRNO_TXTBSY = 74;const ERRNO_XDEV = 75;const ERRNO_NOTCAPABLE = 76;
const RIGHTS_FD_DATASYNC = 0x0000000000000001n;const RIGHTS_FD_READ = 0x0000000000000002n;const RIGHTS_FD_SEEK = 0x0000000000000004n;const RIGHTS_FD_FDSTAT_SET_FLAGS = 0x0000000000000008n;const RIGHTS_FD_SYNC = 0x0000000000000010n;const RIGHTS_FD_TELL = 0x0000000000000020n;const RIGHTS_FD_WRITE = 0x0000000000000040n;const RIGHTS_FD_ADVISE = 0x0000000000000080n;const RIGHTS_FD_ALLOCATE = 0x0000000000000100n;const RIGHTS_PATH_CREATE_DIRECTORY = 0x0000000000000200n;const RIGHTS_PATH_CREATE_FILE = 0x0000000000000400n;const RIGHTS_PATH_LINK_SOURCE = 0x0000000000000800n;const RIGHTS_PATH_LINK_TARGET = 0x0000000000001000n;const RIGHTS_PATH_OPEN = 0x0000000000002000n;const RIGHTS_FD_READDIR = 0x0000000000004000n;const RIGHTS_PATH_READLINK = 0x0000000000008000n;const RIGHTS_PATH_RENAME_SOURCE = 0x0000000000010000n;const RIGHTS_PATH_RENAME_TARGET = 0x0000000000020000n;const RIGHTS_PATH_FILESTAT_GET = 0x0000000000040000n;const RIGHTS_PATH_FILESTAT_SET_SIZE = 0x0000000000080000n;const RIGHTS_PATH_FILESTAT_SET_TIMES = 0x0000000000100000n;const RIGHTS_FD_FILESTAT_GET = 0x0000000000200000n;const RIGHTS_FD_FILESTAT_SET_SIZE = 0x0000000000400000n;const RIGHTS_FD_FILESTAT_SET_TIMES = 0x0000000000800000n;const RIGHTS_PATH_SYMLINK = 0x0000000001000000n;const RIGHTS_PATH_REMOVE_DIRECTORY = 0x0000000002000000n;const RIGHTS_PATH_UNLINK_FILE = 0x0000000004000000n;const RIGHTS_POLL_FD_READWRITE = 0x0000000008000000n;const RIGHTS_SOCK_SHUTDOWN = 0x0000000010000000n;
const WHENCE_SET = 0;const WHENCE_CUR = 1;const WHENCE_END = 2;
const FILETYPE_UNKNOWN = 0;const FILETYPE_BLOCK_DEVICE = 1;const FILETYPE_CHARACTER_DEVICE = 2;const FILETYPE_DIRECTORY = 3;const FILETYPE_REGULAR_FILE = 4;const FILETYPE_SOCKET_DGRAM = 5;const FILETYPE_SOCKET_STREAM = 6;const FILETYPE_SYMBOLIC_LINK = 7;
const ADVICE_NORMAL = 0;const ADVICE_SEQUENTIAL = 1;const ADVICE_RANDOM = 2;const ADVICE_WILLNEED = 3;const ADVICE_DONTNEED = 4;const ADVICE_NOREUSE = 5;
const FDFLAGS_APPEND = 0x0001;const FDFLAGS_DSYNC = 0x0002;const FDFLAGS_NONBLOCK = 0x0004;const FDFLAGS_RSYNC = 0x0008;const FDFLAGS_SYNC = 0x0010;
const FSTFLAGS_ATIM = 0x0001;const FSTFLAGS_ATIM_NOW = 0x0002;const FSTFLAGS_MTIM = 0x0004;const FSTFLAGS_MTIM_NOW = 0x0008;
const LOOKUPFLAGS_SYMLINK_FOLLOW = 0x0001;
const OFLAGS_CREAT = 0x0001;const OFLAGS_DIRECTORY = 0x0002;const OFLAGS_EXCL = 0x0004;const OFLAGS_TRUNC = 0x0008;
const EVENTTYPE_CLOCK = 0;const EVENTTYPE_FD_READ = 1;const EVENTTYPE_FD_WRITE = 2;
const EVENTRWFLAGS_FD_READWRITE_HANGUP = 1;const SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME = 1;
const SIGNAL_NONE = 0;const SIGNAL_HUP = 1;const SIGNAL_INT = 2;const SIGNAL_QUIT = 3;const SIGNAL_ILL = 4;const SIGNAL_TRAP = 5;const SIGNAL_ABRT = 6;const SIGNAL_BUS = 7;const SIGNAL_FPE = 8;const SIGNAL_KILL = 9;const SIGNAL_USR1 = 10;const SIGNAL_SEGV = 11;const SIGNAL_USR2 = 12;const SIGNAL_PIPE = 13;const SIGNAL_ALRM = 14;const SIGNAL_TERM = 15;const SIGNAL_CHLD = 16;const SIGNAL_CONT = 17;const SIGNAL_STOP = 18;const SIGNAL_TSTP = 19;const SIGNAL_TTIN = 20;const SIGNAL_TTOU = 21;const SIGNAL_URG = 22;const SIGNAL_XCPU = 23;const SIGNAL_XFSZ = 24;const SIGNAL_VTALRM = 25;const SIGNAL_PROF = 26;const SIGNAL_WINCH = 27;const SIGNAL_POLL = 28;const SIGNAL_PWR = 29;const SIGNAL_SYS = 30;
const RIFLAGS_RECV_PEEK = 0x0001;const RIFLAGS_RECV_WAITALL = 0x0002;
const ROFLAGS_RECV_DATA_TRUNCATED = 0x0001;
const SDFLAGS_RD = 0x0001;const SDFLAGS_WR = 0x0002;
const PREOPENTYPE_DIR = 0;
const clock_res_realtime = function (): bigint { return BigInt(1e6);};
const clock_res_monotonic = function (): bigint { return BigInt(1e3);};
const clock_res_process = clock_res_monotonic;const clock_res_thread = clock_res_monotonic;
const clock_time_realtime = function (): bigint { return BigInt(Date.now()) * BigInt(1e6);};
const clock_time_monotonic = function (): bigint { const t = performance.now(); const s = Math.trunc(t); const ms = Math.floor((t - s) * 1e3);
return BigInt(s) * BigInt(1e9) + BigInt(ms) * BigInt(1e6);};
const clock_time_process = clock_time_monotonic;const clock_time_thread = clock_time_monotonic;
// deno-lint-ignore ban-typesfunction syscall(target: Function): Function { return function (...args: unknown[]): number { try { return target(...args); } catch (err) { switch (err.name) { case "NotFound": return ERRNO_NOENT;
case "PermissionDenied": return ERRNO_ACCES;
case "ConnectionRefused": return ERRNO_CONNREFUSED;
case "ConnectionReset": return ERRNO_CONNRESET;
case "ConnectionAborted": return ERRNO_CONNABORTED;
case "NotConnected": return ERRNO_NOTCONN;
case "AddrInUse": return ERRNO_ADDRINUSE;
case "AddrNotAvailable": return ERRNO_ADDRNOTAVAIL;
case "BrokenPipe": return ERRNO_PIPE;
case "InvalidData": return ERRNO_INVAL;
case "TimedOut": return ERRNO_TIMEDOUT;
case "Interrupted": return ERRNO_INTR;
case "BadResource": return ERRNO_BADF;
case "Busy": return ERRNO_BUSY;
default: return ERRNO_INVAL; } } };}
export interface ContextOptions { args?: string[]; env?: { [key: string]: string | undefined }; preopens?: { [key: string]: string }; memory?: WebAssembly.Memory;}
export default class Context { args: string[]; env: { [key: string]: string | undefined }; memory: WebAssembly.Memory;
// deno-lint-ignore no-explicit-any fds: any[];
// deno-lint-ignore ban-types exports: Record<string, Function>;
constructor(options: ContextOptions) { this.args = options.args ? options.args : []; this.env = options.env ? options.env : {}; this.memory = options.memory!;
this.fds = [ { fdflags: FDFLAGS_APPEND, type: FILETYPE_CHARACTER_DEVICE, handle: Deno.stdin, }, { fdflags: FDFLAGS_APPEND, type: FILETYPE_CHARACTER_DEVICE, handle: Deno.stdout, }, { fdflags: FDFLAGS_APPEND, type: FILETYPE_CHARACTER_DEVICE, handle: Deno.stderr, }, ];
if (options.preopens) { for (const [vpath, path] of Object.entries(options.preopens)) { const type = FILETYPE_DIRECTORY; const entries = Array.from(Deno.readDirSync(path));
const entry = { type, entries, path, vpath, };
this.fds.push(entry); } }
this.exports = { args_get: syscall((argv_ptr: number, argv_buf_ptr: number): number => { const args = this.args; const text = new TextEncoder(); const heap = new Uint8Array(this.memory.buffer); const view = new DataView(this.memory.buffer);
for (let arg of args) { view.setUint32(argv_ptr, argv_buf_ptr, true); argv_ptr += 4;
const data = text.encode(`${arg}\0`); heap.set(data, argv_buf_ptr); argv_buf_ptr += data.length; }
return ERRNO_SUCCESS; }),
args_sizes_get: syscall( (argc_out: number, argv_buf_size_out: number): number => { const args = this.args; const text = new TextEncoder(); const view = new DataView(this.memory.buffer);
view.setUint32(argc_out, args.length, true); view.setUint32( argv_buf_size_out, args.reduce(function (acc, arg) { return acc + text.encode(`${arg}\0`).length; }, 0), true, );
return ERRNO_SUCCESS; }, ),
environ_get: syscall( (environ_ptr: number, environ_buf_ptr: number): number => { const entries = Object.entries(this.env); const text = new TextEncoder(); const heap = new Uint8Array(this.memory.buffer); const view = new DataView(this.memory.buffer);
for (let [key, value] of entries) { view.setUint32(environ_ptr, environ_buf_ptr, true); environ_ptr += 4;
const data = text.encode(`${key}=${value}\0`); heap.set(data, environ_buf_ptr); environ_buf_ptr += data.length; }
return ERRNO_SUCCESS; }, ),
environ_sizes_get: syscall(( environc_out: number, environ_buf_size_out: number, ): number => { const entries = Object.entries(this.env); const text = new TextEncoder(); const view = new DataView(this.memory.buffer);
view.setUint32(environc_out, entries.length, true); view.setUint32( environ_buf_size_out, entries.reduce(function (acc, [key, value]) { return acc + text.encode(`${key}=${value}\0`).length; }, 0), true, );
return ERRNO_SUCCESS; }),
clock_res_get: syscall((id: number, resolution_out: number): number => { const view = new DataView(this.memory.buffer);
switch (id) { case CLOCKID_REALTIME: view.setBigUint64(resolution_out, clock_res_realtime(), true); break;
case CLOCKID_MONOTONIC: view.setBigUint64(resolution_out, clock_res_monotonic(), true); break;
case CLOCKID_PROCESS_CPUTIME_ID: view.setBigUint64(resolution_out, clock_res_process(), true); break;
case CLOCKID_THREAD_CPUTIME_ID: view.setBigUint64(resolution_out, clock_res_thread(), true); break;
default: return ERRNO_INVAL; }
return ERRNO_SUCCESS; }),
clock_time_get: syscall(( id: number, precision: bigint, time_out: number, ): number => { const view = new DataView(this.memory.buffer);
switch (id) { case CLOCKID_REALTIME: view.setBigUint64(time_out, clock_time_realtime(), true); break;
case CLOCKID_MONOTONIC: view.setBigUint64(time_out, clock_time_monotonic(), true); break;
case CLOCKID_PROCESS_CPUTIME_ID: view.setBigUint64(time_out, clock_time_process(), true); break;
case CLOCKID_THREAD_CPUTIME_ID: view.setBigUint64(time_out, clock_time_thread(), true); break;
default: return ERRNO_INVAL; }
return ERRNO_SUCCESS; }),
fd_advise: syscall(( fd: number, offset: bigint, len: bigint, advice: number, ): number => { return ERRNO_NOSYS; }),
fd_allocate: syscall( (fd: number, offset: bigint, len: bigint): number => { return ERRNO_NOSYS; }, ),
fd_close: syscall((fd: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (entry.handle) { entry.handle.close(); }
delete this.fds[fd];
return ERRNO_SUCCESS; }),
fd_datasync: syscall((fd: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
Deno.fdatasyncSync(entry.handle.rid);
return ERRNO_SUCCESS; }),
fd_fdstat_get: syscall((fd: number, stat_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer); view.setUint8(stat_out, entry.type); view.setUint16(stat_out + 2, entry.fdflags, true); view.setBigUint64(stat_out + 8, 0n, true); // TODO view.setBigUint64(stat_out + 16, 0n, true); // TODO
return ERRNO_SUCCESS; }),
fd_fdstat_set_flags: syscall((fd: number, flags: number): number => { return ERRNO_NOSYS; }),
fd_fdstat_set_rights: syscall(( fd: number, fs_rights_base: bigint, fs_rights_inheriting: bigint, ): number => { return ERRNO_NOSYS; }),
fd_filestat_get: syscall((fd: number, buf_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
const info = Deno.fstatSync(entry.handle.rid);
if (entry.type === undefined) { switch (true) { case info.isFile: entry.type = FILETYPE_REGULAR_FILE; break;
case info.isDirectory: entry.type = FILETYPE_DIRECTORY; break;
case info.isSymlink: entry.type = FILETYPE_SYMBOLIC_LINK; break;
default: entry.type = FILETYPE_UNKNOWN; break; } }
view.setBigUint64(buf_out, BigInt(info.dev ? info.dev : 0), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.ino ? info.ino : 0), true); buf_out += 8;
view.setUint8(buf_out, entry.type); buf_out += 8;
view.setUint32(buf_out, Number(info.nlink), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.size), true); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.atime ? info.atime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.mtime ? info.mtime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.birthtime ? info.birthtime.getTime() * 1e6 : 0), true, ); buf_out += 8;
return ERRNO_SUCCESS; }),
fd_filestat_set_size: syscall((fd: number, size: bigint): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
Deno.ftruncateSync(entry.handle.rid, Number(size));
return ERRNO_SUCCESS; }),
fd_filestat_set_times: syscall(( fd: number, atim: bigint, mtim: bigint, fst_flags: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
if ((fst_flags & FSTFLAGS_ATIM_NOW) == FSTFLAGS_ATIM_NOW) { atim = BigInt(Date.now() * 1e6); }
if ((fst_flags & FSTFLAGS_MTIM_NOW) == FSTFLAGS_MTIM_NOW) { mtim = BigInt(Date.now() * 1e6); }
Deno.utimeSync(entry.path, Number(atim), Number(mtim));
return ERRNO_SUCCESS; }),
fd_pread: syscall(( fd: number, iovs_ptr: number, iovs_len: number, offset: bigint, nread_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const seek = entry.handle.seekSync(0, Deno.SeekMode.Current); const view = new DataView(this.memory.buffer);
let nread = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data = new Uint8Array(this.memory.buffer, data_ptr, data_len); nread += entry.handle.readSync(data); }
entry.handle.seekSync(seek, Deno.SeekMode.Start); view.setUint32(nread_out, nread, true);
return ERRNO_SUCCESS; }),
fd_prestat_get: syscall((fd: number, buf_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.vpath) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer); view.setUint8(buf_out, PREOPENTYPE_DIR); view.setUint32( buf_out + 4, new TextEncoder().encode(entry.vpath).byteLength, true, );
return ERRNO_SUCCESS; }),
fd_prestat_dir_name: syscall(( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.vpath) { return ERRNO_BADF; }
const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); data.set(new TextEncoder().encode(entry.vpath));
return ERRNO_SUCCESS; }),
fd_pwrite: syscall(( fd: number, iovs_ptr: number, iovs_len: number, offset: bigint, nwritten_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const seek = entry.handle.seekSync(0, Deno.SeekMode.Current); const view = new DataView(this.memory.buffer);
let nwritten = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data = new Uint8Array(this.memory.buffer, data_ptr, data_len); nwritten += entry.handle.writeSync(data); }
entry.handle.seekSync(seek, Deno.SeekMode.Start); view.setUint32(nwritten_out, nwritten, true);
return ERRNO_SUCCESS; }),
fd_read: syscall(( fd: number, iovs_ptr: number, iovs_len: number, nread_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
let nread = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data = new Uint8Array(this.memory.buffer, data_ptr, data_len); nread += entry.handle.readSync(data); }
view.setUint32(nread_out, nread, true);
return ERRNO_SUCCESS; }),
fd_readdir: syscall(( fd: number, buf_ptr: number, buf_len: number, cookie: bigint, bufused_out: number, ): number => { 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;
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);
let type: number; switch (true) { case entries[i].isFile: type = FILETYPE_REGULAR_FILE; break;
case entries[i].isDirectory: type = FILETYPE_REGULAR_FILE; break;
case entries[i].isSymlink: type = FILETYPE_SYMBOLIC_LINK; break;
default: 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; }
view.setUint32(bufused_out, bufused, true);
return ERRNO_SUCCESS; }),
fd_renumber: syscall((fd: number, to: number): number => { if (!this.fds[fd]) { return ERRNO_BADF; }
if (!this.fds[to]) { return ERRNO_BADF; }
this.fds[to].handle.close(); this.fds[to] = this.fds[fd]; delete this.fds[fd];
return ERRNO_SUCCESS; }),
fd_seek: syscall(( fd: number, offset: bigint, whence: number, newoffset_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
// FIXME Deno does not support seeking with big integers const newoffset = entry.handle.seekSync(Number(offset), whence); view.setBigUint64(newoffset_out, BigInt(newoffset), true);
return ERRNO_SUCCESS; }),
fd_sync: syscall((fd: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
Deno.fsyncSync(entry.handle.rid);
return ERRNO_SUCCESS; }),
fd_tell: syscall((fd: number, offset_out: number): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
const offset = entry.handle.seekSync(0, Deno.SeekMode.Current); view.setBigUint64(offset_out, BigInt(offset), true);
return ERRNO_SUCCESS; }),
fd_write: syscall(( fd: number, iovs_ptr: number, iovs_len: number, nwritten_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
const view = new DataView(this.memory.buffer);
let nwritten = 0; for (let i = 0; i < iovs_len; i++) { const data_ptr = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
const data_len = view.getUint32(iovs_ptr, true); iovs_ptr += 4;
nwritten += entry.handle.writeSync( new Uint8Array(this.memory.buffer, data_ptr, data_len), ); }
view.setUint32(nwritten_out, nwritten, true);
return ERRNO_SUCCESS; }),
path_create_directory: syscall(( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
Deno.mkdirSync(path);
return ERRNO_SUCCESS; }),
path_filestat_get: syscall(( fd: number, flags: number, path_ptr: number, path_len: number, buf_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
const view = new DataView(this.memory.buffer);
const info = (flags & LOOKUPFLAGS_SYMLINK_FOLLOW) != 0 ? Deno.statSync(path) : Deno.lstatSync(path);
view.setBigUint64(buf_out, BigInt(info.dev ? info.dev : 0), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.ino ? info.ino : 0), true); buf_out += 8;
switch (true) { case info.isFile: view.setUint8(buf_out, FILETYPE_REGULAR_FILE); buf_out += 8; break;
case info.isDirectory: view.setUint8(buf_out, FILETYPE_DIRECTORY); buf_out += 8; break;
case info.isSymlink: view.setUint8(buf_out, FILETYPE_SYMBOLIC_LINK); buf_out += 8; break;
default: view.setUint8(buf_out, FILETYPE_UNKNOWN); buf_out += 8; break; }
view.setUint32(buf_out, Number(info.nlink), true); buf_out += 8;
view.setBigUint64(buf_out, BigInt(info.size), true); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.atime ? info.atime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.mtime ? info.mtime.getTime() * 1e6 : 0), true, ); buf_out += 8;
view.setBigUint64( buf_out, BigInt(info.birthtime ? info.birthtime.getTime() * 1e6 : 0), true, ); buf_out += 8;
return ERRNO_SUCCESS; }),
path_filestat_set_times: syscall(( fd: number, flags: number, path_ptr: number, path_len: number, atim: bigint, mtim: bigint, fst_flags: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
if ((fst_flags & FSTFLAGS_ATIM_NOW) == FSTFLAGS_ATIM_NOW) { atim = BigInt(Date.now()) * BigInt(1e6); }
if ((fst_flags & FSTFLAGS_MTIM_NOW) == FSTFLAGS_MTIM_NOW) { mtim = BigInt(Date.now()) * BigInt(1e6); }
Deno.utimeSync(path, Number(atim), Number(mtim));
return ERRNO_SUCCESS; }),
path_link: syscall(( old_fd: number, old_flags: number, old_path_ptr: number, old_path_len: number, new_fd: number, new_path_ptr: number, new_path_len: number, ): number => { const old_entry = this.fds[old_fd]; const new_entry = this.fds[new_fd]; if (!old_entry || !new_entry) { return ERRNO_BADF; }
if (!old_entry.path || !new_entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const old_data = new Uint8Array( this.memory.buffer, old_path_ptr, old_path_len, ); const old_path = resolve(old_entry.path, text.decode(old_data)); const new_data = new Uint8Array( this.memory.buffer, new_path_ptr, new_path_len, ); const new_path = resolve(new_entry.path, text.decode(new_data));
Deno.linkSync(old_path, new_path);
return ERRNO_SUCCESS; }),
path_open: syscall(( fd: number, dirflags: number, path_ptr: number, path_len: number, oflags: number, fs_rights_base: bigint, fs_rights_inherting: bigint, fdflags: number, opened_fd_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); 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. const entries = Array.from(Deno.readDirSync(path)); const opened_fd = this.fds.push({ fdflags, entries, path, }) - 1;
const view = new DataView(this.memory.buffer); view.setUint32(opened_fd_out, opened_fd, true);
return ERRNO_SUCCESS; }
const options = { read: false, write: false, append: false, truncate: false, create: false, createNew: false, };
if ((oflags & OFLAGS_CREAT) !== 0) { options.create = true; options.write = true; }
if ((oflags & OFLAGS_EXCL) !== 0) { options.createNew = true; }
if ((oflags & OFLAGS_TRUNC) !== 0) { options.truncate = true; options.write = true; }
const read = ( RIGHTS_FD_READ | RIGHTS_FD_READDIR );
if ((fs_rights_base & read) != 0n) { options.read = true; }
const write = ( RIGHTS_FD_DATASYNC | RIGHTS_FD_WRITE | RIGHTS_FD_ALLOCATE | RIGHTS_FD_FILESTAT_SET_SIZE );
if ((fs_rights_base & write) != 0n) { options.write = true; }
if ((fdflags & FDFLAGS_APPEND) != 0) { options.append = true; }
if ((fdflags & FDFLAGS_DSYNC) != 0) { // TODO (caspervonb) review if we can emulate this. }
if ((fdflags & FDFLAGS_NONBLOCK) != 0) { // TODO (caspervonb) review if we can emulate this. }
if ((fdflags & FDFLAGS_RSYNC) != 0) { // TODO (caspervonb) review if we can emulate this. }
if ((fdflags & FDFLAGS_SYNC) != 0) { // TODO (caspervonb) review if we can emulate this. }
if (!options.read && !options.write && !options.truncate) { options.read = true; }
const handle = Deno.openSync(path, options); const opened_fd = this.fds.push({ fdflags, handle, path, }) - 1;
const view = new DataView(this.memory.buffer); view.setUint32(opened_fd_out, opened_fd, true);
return ERRNO_SUCCESS; }),
path_readlink: syscall(( fd: number, path_ptr: number, path_len: number, buf_ptr: number, buf_len: number, bufused_out: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const view = new DataView(this.memory.buffer); const heap = new Uint8Array(this.memory.buffer);
const path_data = new Uint8Array( this.memory.buffer, path_ptr, path_len, ); const path = resolve(entry.path, new TextDecoder().decode(path_data));
const link = Deno.readLinkSync(path); const link_data = new TextEncoder().encode(link); heap.set(new Uint8Array(link_data, 0, buf_len), buf_ptr);
const bufused = Math.min(link_data.byteLength, buf_len); view.setUint32(bufused_out, bufused, true);
return ERRNO_SUCCESS; }),
path_remove_directory: syscall(( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
if (!Deno.statSync(path).isDirectory) { return ERRNO_NOTDIR; }
Deno.removeSync(path);
return ERRNO_SUCCESS; }),
path_rename: syscall(( fd: number, old_path_ptr: number, old_path_len: number, new_fd: number, new_path_ptr: number, new_path_len: number, ): number => { const old_entry = this.fds[fd]; const new_entry = this.fds[new_fd]; if (!old_entry || !new_entry) { return ERRNO_BADF; }
if (!old_entry.path || !new_entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const old_data = new Uint8Array( this.memory.buffer, old_path_ptr, old_path_len, ); const old_path = resolve(old_entry.path, text.decode(old_data)); const new_data = new Uint8Array( this.memory.buffer, new_path_ptr, new_path_len, ); const new_path = resolve(new_entry.path, text.decode(new_data));
Deno.renameSync(old_path, new_path);
return ERRNO_SUCCESS; }),
path_symlink: syscall(( old_path_ptr: number, old_path_len: number, fd: number, new_path_ptr: number, new_path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const old_data = new Uint8Array( this.memory.buffer, old_path_ptr, old_path_len, ); const old_path = text.decode(old_data); const new_data = new Uint8Array( this.memory.buffer, new_path_ptr, new_path_len, ); const new_path = resolve(entry.path, text.decode(new_data));
Deno.symlinkSync(old_path, new_path);
return ERRNO_SUCCESS; }),
path_unlink_file: syscall(( fd: number, path_ptr: number, path_len: number, ): number => { const entry = this.fds[fd]; if (!entry) { return ERRNO_BADF; }
if (!entry.path) { return ERRNO_INVAL; }
const text = new TextDecoder(); const data = new Uint8Array(this.memory.buffer, path_ptr, path_len); const path = resolve(entry.path, text.decode(data));
Deno.removeSync(path);
return ERRNO_SUCCESS; }),
poll_oneoff: syscall(( in_ptr: number, out_ptr: number, nsubscriptions: number, nevents_out: number, ): number => { return ERRNO_NOSYS; }),
proc_exit: syscall((rval: number): never => { Deno.exit(rval); }),
proc_raise: syscall((sig: number): number => { return ERRNO_NOSYS; }),
sched_yield: syscall((): number => { return ERRNO_SUCCESS; }),
random_get: syscall((buf_ptr: number, buf_len: number): number => { const buffer = new Uint8Array(this.memory.buffer, buf_ptr, buf_len); crypto.getRandomValues(buffer);
return ERRNO_SUCCESS; }),
sock_recv: syscall(( fd: number, ri_data_ptr: number, ri_data_len: number, ri_flags: number, ro_datalen_out: number, ro_flags_out: number, ): number => { return ERRNO_NOSYS; }),
sock_send: syscall(( fd: number, si_data_ptr: number, si_data_len: number, si_flags: number, so_datalen_out: number, ): number => { return ERRNO_NOSYS; }),
sock_shutdown: syscall((fd: number, how: number): number => { return ERRNO_NOSYS; }), }; }}