MCPcopy Create free account
hub / github.com/PLSysSec/wave / wasi_fd_readdir

Function wasi_fd_readdir

src/wrappers.rs:1190–1264  ·  view source on GitHub ↗

TODO: I'm not confident this works for multiple consecutive readdir calls to the same dir Correct behavior: truncate final entry

(
    ctx: &mut VmCtx,
    v_fd: SboxFd,
    buf: SboxFd,
    buf_len: usize,
    cookie: u64,
)

Source from the content-addressed store, hash-verified

1188// TODO: I'm not confident this works for multiple consecutive readdir calls to the same dir
1189// Correct behavior: truncate final entry
1190pub fn wasi_fd_readdir(
1191 ctx: &mut VmCtx,
1192 v_fd: SboxFd,
1193 buf: SboxFd,
1194 buf_len: usize,
1195 cookie: u64,
1196) -> RuntimeResult<u32> {
1197 let fd = ctx.fdmap.fd_to_native(v_fd)?;
1198
1199 let mut host_buf: Vec<u8> = Vec::new();
1200 host_buf.reserve_exact(buf_len as usize);
1201
1202 let res = trace_getdents64(ctx, fd, &mut host_buf, buf_len)?;
1203
1204 // the number of entries we have read so far. If less than cookie, don't output the directory
1205 let mut entry_idx = 0;
1206 let mut in_idx = 0;
1207 let mut out_idx = 0;
1208
1209 let mut out_buf: Vec<u8> = Vec::new();
1210
1211 while in_idx < host_buf.len() && out_idx < buf_len {
1212 body_invariant!(ctx_safe(ctx));
1213 body_invariant!(trace_safe(trace, ctx));
1214 body_invariant!(in_idx < host_buf.len());
1215
1216 let dirent = Dirent::parse(&host_buf, in_idx)?;
1217
1218 // if we haven't hit the cookie entry, skip
1219 if entry_idx < cookie {
1220 in_idx += dirent.reclen as usize;
1221 entry_idx += 1;
1222 continue;
1223 }
1224
1225 let out_next = in_idx + 24 + dirent.out_namlen;
1226
1227 // If we would overflow - don't :)
1228 if out_next > buf_len {
1229 break;
1230 }
1231
1232 // Copy in next offset verbatim
1233 let out_next_bytes: [u8; 8] = out_next.to_le_bytes();
1234 out_buf.extend_from_slice(&out_next_bytes);
1235
1236 // Copy in Inode verbatim
1237 let d_ino_bytes: [u8; 8] = dirent.ino.to_le_bytes();
1238 out_buf.extend_from_slice(&d_ino_bytes);
1239
1240 // Copy namlen
1241 let out_namlen_bytes: [u8; 4] = (dirent.out_namlen as u32).to_le_bytes();
1242 out_buf.extend_from_slice(&out_namlen_bytes);
1243
1244 // Copy type
1245 let d_type = Filetype::from(dirent.typ as libc::mode_t);
1246 let out_type_bytes: [u8; 4] = (d_type.to_wasi() as u32).to_le_bytes();
1247 out_buf.extend_from_slice(&out_type_bytes);

Calls 6

trace_getdents64Function · 0.85
push_dirent_nameFunction · 0.85
fd_to_nativeMethod · 0.80
to_wasiMethod · 0.80
copy_buf_to_sandboxMethod · 0.80
lenMethod · 0.45

Tested by

no test coverage detected