1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
use crate::{ resource::Resource, scheme::{Gemini, Http, Https, Log, Null, Random, Zero}, *, }; use log::debug; use std::cell::RefCell; use std::io::{Read, Write}; use url::Url; use wasmer_runtime::{Array, Ctx, WasmPtr}; pub fn open(ctx: &mut Ctx, ptr: WasmPtr<u8, Array>, len: u32) -> Result<i32, error::Error> { let (memory, env) = Process::get_memory_and_environment(ctx, 0); env.log_call("resource_open".to_string()); let violations = RefCell::new(Vec::new()); let raw_uri = ptr .get_utf8_string(memory, len) .ok_or(error::Error::InvalidArgument)?; let uri = Url::options() .syntax_violation_callback(Some(&|v| violations.borrow_mut().push(v))) .parse(&raw_uri); env.log_url(raw_uri.to_string()); match uri { Ok(uri) => { let fd = env.get_fd(); return match uri.scheme() { "gemini" => match Gemini::new(uri) { Ok(res) => { env.resources.insert(fd, Box::new(res)); return Ok(fd as i32); } Err(why) => Ok(why as i32), }, "http" => match Http::new(uri) { Ok(res) => { env.resources.insert(fd, Box::new(res)); return Ok(fd as i32); } Err(why) => Ok(why as i32), }, "https" => match Https::new(uri) { Ok(res) => { env.resources.insert(fd, Box::new(res)); return Ok(fd as i32); } Err(why) => Ok(why as i32), }, "log" => { env.resources.insert(fd, Box::new(Log::new(uri).unwrap())); Ok(fd as i32) } "null" => { env.resources.insert(fd, Box::new(Null::new(uri).unwrap())); Ok(fd as i32) } "random" => { env.resources .insert(fd, Box::new(Random::new(uri).unwrap())); Ok(fd as i32) } "zero" => { env.resources.insert(fd, Box::new(Zero::new(uri).unwrap())); Ok(fd as i32) } _ => Ok(error::Error::InvalidArgument as i32), }; } Err(why) => { log::error!("URL parsing error {}: {:?}", &raw_uri, why); Ok(error::Error::InvalidArgument as i32) } } } pub fn close(ctx: &mut Ctx, fd: u32) -> Result<(), ()> { let (_, env) = Process::get_memory_and_environment(ctx, 0); env.log_call("resource_close".to_string()); if !env.resources.contains_key(&fd) { return Err(()); } let resources = &mut env.resources.as_mut(); let res = &mut resources.get_mut(&fd); let res = &mut res.as_mut().expect("wanted mutable ref"); res.close(); resources.remove(&fd); Ok(()) } pub fn read( ctx: &mut Ctx, fd: u32, ptr: WasmPtr<u8, Array>, len: u32, ) -> Result<i32, std::option::NoneError> { let (memory, env) = Process::get_memory_and_environment(ctx, 0); env.log_call("resource_read".to_string()); if !env.resources.contains_key(&fd) { return Ok(error::Error::InvalidArgument as i32); } let res = &mut env.resources.as_mut().get_mut(&fd); let res = res.as_mut()?; let mut data = vec![0; len as usize]; match res.read(&mut data) { Err(why) => { log::error!("File read error: {:?}", why); Ok(error::Error::Unknown as i32) } Ok(read_len) => { if read_len == 0 { return Ok(error::Error::EOF as i32); } unsafe { let memory_writer = ptr.deref_mut(memory, 0, len)?; for (i, b) in data.bytes().enumerate() { memory_writer[i].set(b.unwrap()); } } Ok(len as i32) } } } pub fn write( ctx: &mut Ctx, fd: u32, ptr: WasmPtr<u8, Array>, len: u32, ) -> Result<i32, std::option::NoneError> { let (memory, env) = Process::get_memory_and_environment(ctx, 0); env.log_call("resource_write".to_string()); debug!("write: {:?} {} {}", ptr, len, fd); if !env.resources.contains_key(&fd) { return Ok(error::Error::InvalidArgument as i32); } let res = &mut env.resources.as_mut().get_mut(&fd); let res = &mut res.as_mut()?; let reader = ptr.deref(memory, 0, len)?; let mut data = vec![0; len as usize]; for (i, b) in reader.iter().enumerate() { data[i] = b.get(); } if let Err(why) = res.write(&data) { log::error!("File write error: {:?}", why); return Ok(error::Error::Unknown as i32); } Ok(len as i32) } pub fn flush(ctx: &mut Ctx, fd: u32) -> Result<i32, std::option::NoneError> { let (_, env) = Process::get_memory_and_environment(ctx, 0); env.log_call("resource_flush".to_string()); if !env.resources.contains_key(&fd) { return Ok(error::Error::InvalidArgument as i32); } let res = &mut env.resources.as_mut().get_mut(&fd); let res = &mut res.as_mut()?; if let Err(why) = res.flush() { log::error!("File flush error: {:?}", why); } Ok(0) }