Last active
November 10, 2017 02:18
-
-
Save sajattack/f9fbe988be4ef8e9c3eade8c606fb86e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use ::{c_int, c_char}; | |
extern crate libc; | |
extern crate core; | |
use syscall::{self, O_CLOEXEC, O_RDONLY, O_DIRECTORY, Stat}; | |
use core::ptr::null; | |
use core::ptr; | |
use core::default::Default; | |
use core::mem::swap; | |
use alloc::boxed::Box; | |
use ::file::PATH_MAX; | |
use ::types::{ino_t, off_t}; | |
use libc::*; | |
extern crate quicksort; | |
#[repr(C)] | |
pub struct dirent { | |
pub d_ino: ino_t, | |
pub d_off: off_t, | |
pub d_reclen: c_ushort, | |
pub d_type: c_uchar, | |
pub d_name: [c_char; PATH_MAX] | |
} | |
impl core::default::Default for dirent { | |
fn default() -> dirent { | |
dirent { | |
d_ino: 0, | |
d_off: 0, | |
d_reclen: 0, | |
d_type: 0, | |
d_name: [0; PATH_MAX], | |
} | |
} | |
} | |
pub struct DIR { | |
pub fd: ::RawFile, | |
pub ent: dirent, | |
pub buf: [u8; PATH_MAX], | |
pub count: usize, | |
pub pos: usize | |
} | |
libc_fn!(unsafe opendir(path: *mut c_char) -> Result<*mut DIR> { | |
let path = ::cstr_to_slice(path); | |
let fd = ::RawFile::open(path, O_RDONLY | O_CLOEXEC | O_DIRECTORY)?; | |
let dir = Box::new(DIR { | |
fd, | |
ent: dirent::default(), | |
buf: [0; PATH_MAX], | |
count: 0, | |
pos: 0 | |
}); | |
Ok(Box::into_raw(dir)) | |
}); | |
libc_fn!(unsafe readdir(dir: *mut DIR) -> Result<*const dirent> { | |
if let Some(dir) = dir.as_mut() { | |
let mut i = 0; | |
'outer: while i < PATH_MAX - 1 { | |
while dir.pos < dir.count { | |
dir.ent.d_name[i] = dir.buf[dir.pos] as c_char; | |
dir.pos += 1; | |
if dir.buf[dir.pos-1] == b'\n' { | |
break 'outer; | |
} | |
i += 1; | |
} | |
dir.count = syscall::read(*dir.fd, &mut dir.buf)?; | |
if dir.count == 0 { | |
break; | |
} | |
dir.pos = 0; | |
} | |
if i != 0 { | |
dir.ent.d_name[i] = 0; | |
return Ok(&dir.ent); | |
} | |
} | |
Ok(null()) | |
}); | |
libc_fn!(unsafe rewinddir(dir: *mut DIR) { | |
if let Some(dir) = dir.as_mut() { | |
dir.count = 0; | |
let _ = syscall::lseek(*dir.fd, 0, syscall::SEEK_SET); | |
} | |
}); | |
libc_fn!(unsafe closedir(dir: *mut DIR) -> Result<c_int> { | |
Box::from_raw(dir); | |
Ok(0) | |
}); | |
/*macro_rules! DIRSZ { | |
($dp:expr) => (sizeof(dirent) - sizeof($dp.d_name)) + ((($dp)->d_reclen + 1 + 3) &~ 3); | |
}*/ | |
libc_fn!(unsafe scandir(dirname: *mut c_char, | |
namelist: *mut *mut *mut dirent, | |
filter: fn(*const dirent) -> Result<c_int, c_int>, | |
compar: fn(*const c_void, *const c_void) -> c_int) | |
-> Result<c_int, c_int> { | |
let mut d: dirent = dirent::default(); | |
let mut p: dirent = dirent::default(); | |
let mut nitems: size_t = 0; | |
let mut stb: syscall::Stat = Stat::default(); | |
let mut arraysz: usize = 0; | |
let dirp: *mut DIR; | |
let dirname = "file:/home/user/\0".as_bytes().as_ptr() as *mut c_char; | |
let dirname_slice = ::cstr_to_slice(dirname); | |
let _ = syscall::write(2, dirname_slice); | |
let _ = syscall::write(2, "\n".as_bytes()); | |
dirp = opendir(dirname); | |
if dirp.is_null() { | |
let _ = syscall::write(2, "null ptr at line 116\n".as_bytes()); | |
perror("scandir\0".as_bytes().as_ptr() as *const c_char); | |
return Err(-1); | |
} | |
if let Some(dirp) = dirp.as_mut() { | |
if !syscall::call::fstat(*dirp.fd, &mut stb).is_ok() { | |
let _ = syscall::write(2, "error calling fstat at line 114\n".as_bytes()); | |
return Err(-1); | |
} | |
/* | |
* estimate the array size by taking the size of the directory file | |
* and dividing it by a multiple of the minimum size entry. | |
*/ | |
arraysz = (stb.st_size as usize) / 24; | |
let mut names: *mut *mut dirent = malloc(arraysz * ::mem::size_of::<dirent>()) as *mut _; | |
if names.is_null() { | |
let _ = syscall::write(2, "null ptr at line 131\n".as_bytes()); | |
return Err(-1); | |
} | |
nitems = 0; | |
loop { | |
let d_ptr = readdir(dirp); | |
if d_ptr.is_null() { | |
break; | |
} | |
d = ptr::read(d_ptr); | |
let _ = syscall::write(2, ::cstr_to_slice(d.d_name.as_ptr())); | |
let _ = syscall::write(2, "\n".as_bytes()); | |
/*if !filter(&mut d) | |
{ continue; }*/ | |
p.d_ino = d.d_ino; | |
p.d_reclen = d.d_reclen; | |
p.d_name = d.d_name; | |
/* | |
* Check to make sure the array has space left and | |
* realloc the maximum size. | |
*/ | |
if nitems+1 >= arraysz as usize { | |
if !syscall::call::fstat(*dirp.fd, &mut stb).is_ok() { | |
let _ = syscall::write(2, "error calling fstat line 157\n".as_bytes()); | |
return Err(-1); | |
} | |
arraysz = (stb.st_size as usize) / 12; | |
let _ = syscall::write(2, "got to line 162\n".as_bytes()); | |
names = realloc(names as *mut c_void, arraysz * ::mem::size_of::<dirent>() as usize) as *mut _; | |
if names.is_null() { | |
let _ = syscall::write(2, "null ptr at line 163\n".as_bytes()); | |
return Err(-1); | |
} | |
} | |
*names.offset(nitems as isize -1) = &mut p; | |
let _ = syscall::write(2, "got to line 169\n".as_bytes()); | |
nitems+=1; | |
let _ = syscall::write(2, ::cstr_to_slice(format!("{}\n", nitems).as_str().as_bytes().as_ptr() as *const c_char)); | |
} | |
//closedir(dirp); | |
let _ = syscall::write(2, "got to line 175\n".as_bytes()); | |
qsort(names, nitems, ::mem::size_of::<dirent>(), compar); | |
swap(&mut *namelist, &mut names); | |
} | |
Ok(nitems as i32) | |
}); | |
libc_fn!(unsafe alphasort(a: *mut c_void, b: *mut c_void) -> c_int { | |
let _ = syscall::write(2, "got to alphasort\n".as_bytes()); | |
let a: &mut dirent = unsafe { &mut *(a as *mut dirent) }; | |
let b: &mut dirent = unsafe { &mut *(b as *mut dirent) }; | |
strcmp(a.d_name.as_ptr(), b.d_name.as_ptr()) | |
}); | |
#[link(name="c")] | |
libc_fn!(qsort(base: *mut c_void, nmemb: size_t, size: size_t, | |
compar: extern fn(*const c_void, *const c_void, *const c_void) -> i32) { | |
}); | |
fn native_compar<T>(a: *const T, b: *const T) -> c_int where T: Ord { | |
let mut rv: c_int = -2; | |
if *a < *b { | |
rv = -1; | |
} else if *a > *b { | |
rv = 1; | |
} else if *a == *b { | |
rv = 0; | |
} | |
rv | |
} | |
fn sort<T>(v: &mut [T]) where T: Ord { | |
unsafe { | |
qsort(v.as_mut_ptr() as *mut c_void, | |
v.len() as size_t, | |
::mem::size_of::<T>() as size_t, | |
native_compar); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment