refactor: Allow refreshing filetable data using dup2 to fix O_CLOEXEC
This commit is contained in:
committed by
Jeremy Soller
parent
e100dd5a71
commit
37ffa2e29e
+51
-17
@@ -771,25 +771,59 @@ impl KernelScheme for ProcScheme {
|
|||||||
} => {
|
} => {
|
||||||
// TODO: Maybe allow userspace to either copy or transfer recently dupped file
|
// TODO: Maybe allow userspace to either copy or transfer recently dupped file
|
||||||
// descriptors between file tables.
|
// descriptors between file tables.
|
||||||
if buf != b"copy" {
|
let new_handle = match buf {
|
||||||
return Err(Error::new(EINVAL));
|
b"copy" => {
|
||||||
}
|
let filetable = filetable.upgrade().ok_or(Error::new(EOWNERDEAD))?;
|
||||||
let filetable = filetable.upgrade().ok_or(Error::new(EOWNERDEAD))?;
|
|
||||||
|
|
||||||
let new_filetable =
|
let new_filetable =
|
||||||
Arc::new(RwLock::new(filetable.read(token.token()).clone()));
|
Arc::new(RwLock::new(filetable.read(token.token()).clone()));
|
||||||
|
|
||||||
handle(
|
Handle {
|
||||||
Handle {
|
kind: ContextHandle::NewFiletable {
|
||||||
kind: ContextHandle::NewFiletable {
|
filetable: new_filetable,
|
||||||
filetable: new_filetable,
|
binary_format,
|
||||||
binary_format,
|
data: data.clone(),
|
||||||
data: data.clone(),
|
},
|
||||||
},
|
context,
|
||||||
context,
|
}
|
||||||
},
|
}
|
||||||
true,
|
b"refresh" => {
|
||||||
)
|
let filetable = filetable.upgrade().ok_or(Error::new(EOWNERDEAD))?;
|
||||||
|
|
||||||
|
let new_data = if binary_format {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
for index in filetable
|
||||||
|
.read(token.token())
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(idx, val)| val.as_ref().map(|_| idx))
|
||||||
|
{
|
||||||
|
data.extend((index as u64).to_le_bytes());
|
||||||
|
}
|
||||||
|
data.into_boxed_slice()
|
||||||
|
} else {
|
||||||
|
use core::fmt::Write;
|
||||||
|
let mut data = String::new();
|
||||||
|
for index in filetable
|
||||||
|
.read(token.token())
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(idx, val)| val.as_ref().map(|_| idx))
|
||||||
|
{
|
||||||
|
writeln!(data, "{}", index).unwrap();
|
||||||
|
}
|
||||||
|
data.into_bytes().into_boxed_slice()
|
||||||
|
};
|
||||||
|
Handle {
|
||||||
|
kind: ContextHandle::Filetable {
|
||||||
|
filetable: Arc::downgrade(&filetable),
|
||||||
|
binary_format,
|
||||||
|
data: new_data,
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(Error::new(EINVAL)),
|
||||||
|
};
|
||||||
|
handle(new_handle, true)
|
||||||
}
|
}
|
||||||
Handle {
|
Handle {
|
||||||
kind: ContextHandle::AddrSpace { ref addrspace },
|
kind: ContextHandle::AddrSpace { ref addrspace },
|
||||||
|
|||||||
+29
-12
@@ -235,19 +235,36 @@ pub fn dup2(
|
|||||||
buf: UserSliceRo,
|
buf: UserSliceRo,
|
||||||
token: &mut CleanLockToken,
|
token: &mut CleanLockToken,
|
||||||
) -> Result<FileHandle> {
|
) -> Result<FileHandle> {
|
||||||
if fd == new_fd {
|
if fd == new_fd && buf.is_empty() {
|
||||||
Ok(new_fd)
|
return Ok(new_fd);
|
||||||
} else {
|
|
||||||
let _ = close(new_fd, token);
|
|
||||||
let new_file = duplicate_file(fd, buf, token)?;
|
|
||||||
|
|
||||||
let current_lock = context::current();
|
|
||||||
let mut current = current_lock.read(token.token());
|
|
||||||
let (context, mut token) = current.token_split();
|
|
||||||
context
|
|
||||||
.insert_file(new_fd, new_file, &mut token)
|
|
||||||
.ok_or(Error::new(EMFILE))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let new_file = duplicate_file(fd, buf, token)?;
|
||||||
|
|
||||||
|
let old_file = {
|
||||||
|
let current_lock = context::current();
|
||||||
|
let mut current = current_lock.write(token.token());
|
||||||
|
let (context, mut split_token) = current.token_split();
|
||||||
|
|
||||||
|
let old_file = context.remove_file(new_fd, &mut split_token.token());
|
||||||
|
|
||||||
|
if context
|
||||||
|
.insert_file(new_fd, new_file, &mut split_token.token())
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
if let Some(old) = old_file {
|
||||||
|
context.insert_file(new_fd, old, &mut split_token.token());
|
||||||
|
}
|
||||||
|
return Err(Error::new(EMFILE));
|
||||||
|
}
|
||||||
|
old_file
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(old) = old_file {
|
||||||
|
let _ = old.close(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(new_fd)
|
||||||
}
|
}
|
||||||
pub fn call(
|
pub fn call(
|
||||||
fds: &[usize],
|
fds: &[usize],
|
||||||
|
|||||||
Reference in New Issue
Block a user