Implement dup2. Add debugging lines.

This commit is contained in:
Jeremy Soller 2016-12-27 11:18:41 -07:00
parent 5be2cbfaf4
commit 364e1b542a
6 changed files with 81 additions and 6 deletions

View file

@ -220,6 +220,25 @@ impl Context {
}
}
/// Insert a file with a specific handle number. This is used by dup2
/// Return the file descriptor number or None if the slot was not empty, or i was invalid
pub fn insert_file(&self, i: FileHandle, file: File) -> Option<FileHandle> {
let mut files = self.files.lock();
if i.into() < super::CONTEXT_MAX_FILES {
while i.into() >= files.len() {
files.push(None);
}
if files[i.into()].is_none() {
files[i.into()] = Some(file);
Some(i)
} else {
None
}
} else {
None
}
}
/// Remove a file
// TODO: adjust files vector to smaller size if possible
pub fn remove_file(&self, i: FileHandle) -> Option<File> {

View file

@ -89,6 +89,8 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
(context.canonicalize(path), context.euid, context.egid, context.ens)
};
//println!("open {}", unsafe { ::core::str::from_utf8_unchecked(&path_canon) });
let mut parts = path_canon.splitn(2, |&b| b == b':');
let scheme_name_opt = parts.next();
let reference_opt = parts.next();
@ -261,6 +263,41 @@ pub fn dup(fd: FileHandle, buf: &[u8]) -> Result<FileHandle> {
}).ok_or(Error::new(EMFILE))
}
/// Duplicate file descriptor, replacing another
pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: &[u8]) -> Result<FileHandle> {
if fd == new_fd {
Ok(new_fd)
} else {
let _ = close(new_fd)?;
let file = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let file = context.get_file(fd).ok_or(Error::new(EBADF))?;
file
};
let new_id = {
let scheme = {
let schemes = scheme::schemes();
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
scheme.clone()
};
scheme.dup(file.number, buf)?
};
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
context.insert_file(new_fd, ::context::file::File {
scheme: file.scheme,
number: new_id,
event: None,
}).ok_or(Error::new(EBADF))
}
}
/// Register events for file
pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
let file = {

View file

@ -53,6 +53,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
_ => match a {
SYS_CLOSE => close(fd),
SYS_DUP => dup(fd, validate_slice(c as *const u8, d)?).map(FileHandle::into),
SYS_DUP2 => dup2(fd, FileHandle::from(c), validate_slice(d as *const u8, e)?).map(FileHandle::into),
SYS_FEVENT => fevent(fd, c),
SYS_FUNMAP => funmap(b),
_ => file_op(a, fd, c, d)
@ -103,10 +104,18 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
}
let result = inner(a, b, c, d, e, f, stack);
/*
if let Err(ref err) = result {
println!("{}, {}, {}, {}: {}", a, b, c, d, err);
let contexts = ::context::contexts();
if let Some(context_lock) = contexts.current() {
let context = context_lock.read();
print!("{}: {}: ", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) }, context.id.into());
}
println!("{:X}, {:X}, {:X}, {:X}: {}", a, b, c, d, err);
}
*/
Error::mux(result)
}

View file

@ -26,6 +26,9 @@ pub fn brk(address: usize) -> Result<usize> {
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
//println!("{}: {}: BRK {:X}", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) },
// context.id.into(), address);
let current = if let Some(ref heap_shared) = context.heap {
heap_shared.with(|heap| {
heap.start_address().get() + heap.size()
@ -47,8 +50,10 @@ pub fn brk(address: usize) -> Result<usize> {
panic!("user heap not initialized");
}
//println!("Brk resize {:X}", address);
Ok(address)
} else {
//println!("Brk no mem");
Err(Error::new(ENOMEM))
}
}

View file

@ -9,8 +9,13 @@ fn validate(address: usize, size: usize, flags: entry::EntryFlags) -> Result<()>
let start_page = Page::containing_address(VirtualAddress::new(address));
let end_page = Page::containing_address(VirtualAddress::new(address + size - 1));
for page in Page::range_inclusive(start_page, end_page) {
let page_flags = active_table.translate_page_flags(page).ok_or(Error::new(EFAULT))?;
if let Some(page_flags) = active_table.translate_page_flags(page) {
if ! page_flags.contains(flags) {
//println!("{:X}: Not {:?}", page.start_address().get(), flags);
return Err(Error::new(EFAULT));
}
} else {
//println!("{:X}: Not found", page.start_address().get());
return Err(Error::new(EFAULT));
}
}

@ -1 +1 @@
Subproject commit 9b0c363b2711c64ad5be298bdf39c65b2a5d5e2f
Subproject commit e79e54d2f5ad6492b4452f74e60c54325997823f