Skip to content
Snippets Groups Projects
Verified Commit 571b4d49 authored by jD91mZM2's avatar jD91mZM2
Browse files

Fix getdents on redox

parent 09bd4bc3
No related branches found
No related tags found
No related merge requests found
......@@ -21,9 +21,8 @@ pub struct DIR {
index: usize,
len: usize,
// Offset is like the total index, never erased It is used as an
// alternative to dirent's d_off, but works on redox too.
offset: usize,
// The last value of d_off, used by telldir
offset: usize
}
#[repr(C)]
......@@ -89,20 +88,7 @@ pub unsafe extern "C" fn readdir(dir: *mut DIR) -> *mut dirent {
let ptr = (*dir).buf.as_mut_ptr().offset((*dir).index as isize) as *mut dirent;
#[cfg(target_os = "redox")]
{
if (*dir).index != 0 || (*dir).offset != 0 {
// This should happen every time but the first, making the offset
// point to the current element and not the next
(*dir).offset += mem::size_of::<dirent>();
}
(*ptr).d_off = (*dir).offset as off_t;
}
#[cfg(not(target_os = "redox"))]
{
(*dir).offset = (*ptr).d_off as usize;
}
(*dir).offset = (*ptr).d_off as usize;
(*dir).index += (*ptr).d_reclen as usize;
ptr
}
......
......@@ -418,50 +418,93 @@ impl Pal for Sys {
}
}
fn getdents(fd: c_int, mut dirents: *mut dirent, mut bytes: usize) -> c_int {
let mut amount = 0;
fn getdents(fd: c_int, mut dirents: *mut dirent, max_bytes: usize) -> c_int {
// Get initial reading position
let mut read = match syscall::lseek(fd as usize, 0, SEEK_CUR) {
Ok(pos) => pos as isize,
Err(err) => return -err.errno
};
let mut written = 0;
let mut buf = [0; 1024];
let mut bindex = 0;
let mut blen = 0;
let mut name = [0; 256];
let mut nindex = 0;
loop {
if bindex >= blen {
bindex = 0;
blen = match syscall::read(fd as usize, &mut buf) {
Ok(0) => return amount,
Ok(n) => n,
Err(err) => return -err.errno,
let mut i = 0;
let mut flush = |written: &mut usize, i: &mut usize, name: &mut [c_char; 256]| {
if *i < name.len() {
// Set NUL byte
name[*i] = 0;
}
// Get size: full size - unused bytes
let size = mem::size_of::<dirent>() - name.len().saturating_sub(*i + 1);
if *written + size > max_bytes {
// Seek back to after last read entry and return
match syscall::lseek(fd as usize, read, SEEK_SET as usize) {
Ok(_) => return Some(*written as c_int),
Err(err) => return Some(-err.errno)
}
}
unsafe {
*dirents = dirent {
d_ino: 0,
d_off: read as off_t,
d_reclen: size as c_ushort,
d_type: 0,
d_name: *name
};
dirents = (dirents as *mut u8).offset(size as isize) as *mut dirent;
}
read += *i as isize + /* newline */ 1;
*written += size;
*i = 0;
None
};
if buf[bindex] == b'\n' {
// Put a NUL byte either at the end, or if it's too big, at where it's truncated.
name[nindex.min(name.len() - 1)] = 0;
unsafe {
*dirents = dirent {
d_ino: 0,
d_off: 0,
d_reclen: mem::size_of::<dirent>() as c_ushort,
d_type: 0,
d_name: name,
loop {
// Read a chunk from the directory
let len = match syscall::read(fd as usize, &mut buf) {
Ok(0) => {
if i > 0 {
if let Some(value) = flush(&mut written, &mut i, &mut name) {
return value;
}
}
return written as c_int;
},
Ok(n) => n,
Err(err) => return -err.errno
};
// Handle everything
let mut start = 0;
while start < len {
let buf = &buf[start..len];
// Copy everything up until a newline
let newline = buf.iter().position(|&c| c == b'\n');
let pre_len = newline.unwrap_or(buf.len());
let post_len = newline.map(|i| i + 1).unwrap_or(buf.len());
if i < pre_len {
// Reserve space for NUL byte
let name_len = name.len()-1;
let name = &mut name[i..name_len];
let copy = pre_len.min(name.len());
let buf = unsafe {
slice::from_raw_parts(buf.as_ptr() as *const c_char, copy)
};
dirents = dirents.offset(1);
}
amount += 1;
if bytes <= mem::size_of::<dirent>() {
return amount;
name[..copy].copy_from_slice(buf);
}
bytes -= mem::size_of::<dirent>();
} else {
if nindex < name.len() {
name[nindex] = buf[bindex] as c_char;
i += pre_len;
start += post_len;
// Write the directory entry
if newline.is_some() {
if let Some(value) = flush(&mut written, &mut i, &mut name) {
return value;
}
}
nindex += 1;
bindex += 1;
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment