Implement sys_openat and sys_renameat

toolchain_update
Jiajie Chen 6 years ago
parent 7b20c72864
commit 556d263d8e

@ -217,6 +217,6 @@ impl ThreadPool {
fn new_vec_default<T: Default>(size: usize) -> Vec<T> {
let mut vec = Vec::new();
vec.resize_default(size);
vec.resize_with(size, Default::default);
vec
}

@ -136,9 +136,9 @@ impl PciTag {
let mut max_base_lo = self.read(bar, 4);
self.write(bar, base_lo);
let mut base = 0usize;
let mut max_base = 0usize;
let mut address_mark = 0usize;
let mut base;
let mut max_base;
let mut address_mark;
// memory instead of io
assert!(base_lo & PCI_BASE_ADDRESS_SPACE == PCI_BASE_ADDRESS_SPACE_MEMORY);

@ -96,6 +96,10 @@ impl FileHandle {
self.inode.metadata()
}
pub fn lookup_follow(&self, path: &str, max_follow: usize) -> Result<Arc<INode>> {
self.inode.lookup_follow(path, max_follow)
}
pub fn read_entry(&mut self) -> Result<String> {
if !self.options.read {
return Err(FsError::InvalidParam); // FIXME: => EBADF

@ -28,7 +28,7 @@ pub extern fn shell(_arg: usize) -> ! {
let name = cmd.trim().split(' ').next().unwrap();
if let Ok(file) = ROOT_INODE.lookup(name) {
let data = file.read_as_vec().unwrap();
let pid = processor().manager().add(Thread::new_user(data.as_slice(), cmd.split(' ')));
let _pid = processor().manager().add(Thread::new_user(data.as_slice(), cmd.split(' ')));
// TODO: wait until process exits, or use user land shell completely
//unsafe { thread::JoinHandle::<()>::_of(pid) }.join().unwrap();
} else {

@ -297,31 +297,63 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu
}
}
const AT_FDCWD: usize = -100isize as usize;
pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult {
sys_openat(AT_FDCWD, path, flags, mode)
}
pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) -> SysResult {
let mut proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let flags = OpenFlags::from_bits_truncate(flags);
info!("open: path: {:?}, flags: {:?}, mode: {:#o}", path, flags, mode);
info!("openat: dir_fd: {}, path: {:?}, flags: {:?}, mode: {:#o}", dir_fd as isize, path, flags, mode);
let inode =
if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
let dir_inode = proc.lookup_inode(dir_path)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
return Err(SysError::EEXIST);
}
file_inode
},
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
if dir_fd == AT_FDCWD {
// from process cwd
if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
// relative to cwd
let dir_inode = proc.lookup_inode(dir_path)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
return Err(SysError::EEXIST);
}
file_inode
},
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
Err(e) => return Err(SysError::from(e)),
}
} else {
proc.lookup_inode(&path)?
}
Err(e) => return Err(SysError::from(e)),
}
} else {
proc.lookup_inode(&path)?
};
} else {
// relative to dir_fd
let dir_file = proc.get_file(dir_fd)?;
if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
// relative to cwd
let dir_inode = dir_file.lookup_follow(dir_path, FOLLOW_MAX_DEPTH)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
return Err(SysError::EEXIST);
}
file_inode
},
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
Err(e) => return Err(SysError::from(e)),
}
} else {
dir_file.lookup_follow(&path, FOLLOW_MAX_DEPTH)?
}
};
let fd = proc.get_free_fd();
@ -506,15 +538,27 @@ pub fn sys_chdir(path: *const u8) -> SysResult {
}
pub fn sys_rename(oldpath: *const u8, newpath: *const u8) -> SysResult {
let proc = process();
sys_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath)
}
pub fn sys_renameat(olddirfd: usize, oldpath: *const u8, newdirfd: usize, newpath: *const u8) -> SysResult {
let mut proc = process();
let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? };
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
info!("rename: oldpath: {:?}, newpath: {:?}", oldpath, newpath);
info!("renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}", olddirfd, oldpath, newdirfd, newpath);
let (old_dir_path, old_file_name) = split_path(&oldpath);
let (new_dir_path, new_file_name) = split_path(&newpath);
let old_dir_inode = proc.lookup_inode(old_dir_path)?;
let new_dir_inode = proc.lookup_inode(new_dir_path)?;
let old_dir_inode = if olddirfd == AT_FDCWD {
proc.lookup_inode(old_dir_path)?
} else {
proc.get_file(olddirfd)?.lookup_follow(old_dir_path, FOLLOW_MAX_DEPTH)?
};
let new_dir_inode = if newdirfd == AT_FDCWD {
proc.lookup_inode(new_dir_path)?
} else {
proc.get_file(newdirfd)?.lookup_follow(new_dir_path, FOLLOW_MAX_DEPTH)?
};
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
Ok(0)
}
@ -622,7 +666,7 @@ pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usiz
let mut bytes_read = 0;
while bytes_read < count {
let len = min(buffer.len(), count - bytes_read);
let read_len = in_file.read(&mut buffer)?;
let read_len = in_file.read(&mut buffer[..len])?;
if read_len == 0 {
break;
}
@ -638,16 +682,16 @@ pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usiz
}
return Ok(bytes_read);
} else {
let mut proc_mem = unsafe {&mut *proc_cell.get()};
let proc_mem = unsafe {&mut *proc_cell.get()};
proc_mem.vm.check_read_ptr(offset)?;
let mut read_offset = unsafe {
*offset
};
// read from specified offset and write back
// read from specified offset and write new offset back
let mut bytes_read = 0;
while bytes_read < count {
let len = min(buffer.len(), count - bytes_read);
let read_len = in_file.read_at(read_offset, &mut buffer)?;
let read_len = in_file.read_at(read_offset, &mut buffer[..len])?;
if read_len == 0 {
break;
}

@ -79,7 +79,7 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S
.vm
.check_write_ptr(uaddr as *mut AtomicI32)?;
let atomic = unsafe { &mut *(uaddr as *mut AtomicI32) };
let timeout = if timeout.is_null() {
let _timeout = if timeout.is_null() {
None
} else {
process().vm.check_read_ptr(timeout)?;
@ -114,7 +114,7 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S
const LINUX_REBOOT_CMD_HALT: u32 = 0xcdef0123;
pub fn sys_reboot(magic: u32, magic2: u32, cmd: u32, arg: *const u8) -> SysResult {
pub fn sys_reboot(_magic: u32, magic2: u32, cmd: u32, _arg: *const u8) -> SysResult {
// we will skip verifying magic
if cmd == LINUX_REBOOT_CMD_HALT {
unsafe {

@ -199,12 +199,12 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
}
SYS_CLOCK_GETTIME => sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
SYS_EXIT_GROUP => sys_exit_group(args[0]),
SYS_OPENAT => sys_open(args[1] as *const u8, args[2], args[3]), // TODO: handle `dfd`
SYS_OPENAT => sys_openat(args[0], args[1] as *const u8, args[2], args[3]), // TODO: handle `dfd`
SYS_MKDIRAT => sys_mkdir(args[1] as *const u8, args[2]), // TODO: handle `dfd`
// SYS_MKNODAT => sys_mknod(),
SYS_NEWFSTATAT => sys_stat(args[1] as *const u8, args[2] as *mut Stat), // TODO: handle `dfd`, `flag`
SYS_UNLINKAT => sys_unlink(args[1] as *const u8), // TODO: handle `dfd`, `flag`
SYS_RENAMEAT => sys_rename(args[1] as *const u8, args[3] as *const u8), // TODO: handle `olddfd`, `newdfd`
SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8), // TODO: handle `olddfd`, `newdfd`
SYS_LINKAT => sys_link(args[1] as *const u8, args[3] as *const u8), // TODO: handle `olddfd`, `newdfd`, `flags`
SYS_FACCESSAT => sys_access(args[1] as *const u8, args[2]), // TODO: handle `dfd`
// 280
@ -418,7 +418,7 @@ impl From<VMError> for SysError {
const SPIN_WAIT_TIMES: usize = 100;
pub fn spin_and_wait<T>(condvars: &[&Condvar], mut action: impl FnMut() -> Option<T>) -> T {
for i in 0..SPIN_WAIT_TIMES {
for _i in 0..SPIN_WAIT_TIMES {
if let Some(result) = action() {
return result;
}

@ -118,8 +118,8 @@ pub fn sys_setsockopt(
fd: usize,
level: usize,
optname: usize,
optval: *const u8,
optlen: usize,
_optval: *const u8,
_optlen: usize,
) -> SysResult {
info!(
"setsockopt: fd: {}, level: {}, optname: {}",
@ -266,7 +266,7 @@ pub fn sys_sendto(
fd: usize,
base: *const u8,
len: usize,
flags: usize,
_flags: usize,
addr: *const SockAddr,
addr_len: usize,
) -> SysResult {
@ -382,7 +382,7 @@ pub fn sys_listen(fd: usize, backlog: usize) -> SysResult {
tcp_state.is_listening = true;
Ok(0)
}
Err(err) => Err(SysError::EINVAL),
Err(_err) => Err(SysError::EINVAL),
}
} else {
Ok(0)

@ -98,7 +98,7 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
pub fn sys_exec(name: *const u8, argv: *const *const u8, envp: *const *const u8, tf: &mut TrapFrame) -> SysResult {
info!("exec: name: {:?}, argv: {:?} envp: {:?}", name, argv, envp);
let proc = process();
let name = if name.is_null() { String::from("") } else {
let _name = if name.is_null() { String::from("") } else {
unsafe { proc.vm.check_and_clone_cstr(name)? }
};
@ -235,7 +235,7 @@ pub fn sys_exit(exit_code: usize) -> ! {
/// Exit the current thread group (i.e. process)
pub fn sys_exit_group(exit_code: usize) -> ! {
let mut proc = process();
let proc = process();
info!("exit_group: {}, code: {}", proc.pid, exit_code);
// quit all threads

Loading…
Cancel
Save