handle directories
This commit is contained in:
parent
e004212c9c
commit
960de83bbc
8 changed files with 225 additions and 27 deletions
|
|
@ -10,5 +10,12 @@ pub struct TaskSetup {
|
||||||
pub epc: usize,
|
pub epc: usize,
|
||||||
pub ddi_first_addr: usize,
|
pub ddi_first_addr: usize,
|
||||||
pub ddi_size: usize,
|
pub ddi_size: usize,
|
||||||
|
pub environment: usize,
|
||||||
pub wait_for_task_exit: bool,
|
pub wait_for_task_exit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Environment {
|
||||||
|
pub current_directory_path: usize,
|
||||||
|
pub current_directory_path_len: usize,
|
||||||
|
}
|
||||||
|
|
@ -65,6 +65,8 @@ pub enum SysCall {
|
||||||
/// waits for a sent notification to be received
|
/// waits for a sent notification to be received
|
||||||
/// (taskid) -> 0
|
/// (taskid) -> 0
|
||||||
WaitForNotifAck = 13,
|
WaitForNotifAck = 13,
|
||||||
|
/// returns the environment pointer for the given task
|
||||||
|
EnvironmentPointer = 14,
|
||||||
|
|
||||||
/// initializes kernel, ONLY CALL ONCE! IN FACT, YOU PROBABLY NEVER NEED TO CALL THIS
|
/// initializes kernel, ONLY CALL ONCE! IN FACT, YOU PROBABLY NEVER NEED TO CALL THIS
|
||||||
InitKernel = 666
|
InitKernel = 666
|
||||||
|
|
@ -90,6 +92,7 @@ pub fn usize2sc(u: usize) -> SysCall {
|
||||||
11 => SysCall::WaitForNotification,
|
11 => SysCall::WaitForNotification,
|
||||||
12 => SysCall::PendingNotifications,
|
12 => SysCall::PendingNotifications,
|
||||||
13 => SysCall::WaitForNotifAck,
|
13 => SysCall::WaitForNotifAck,
|
||||||
|
14 => SysCall::EnvironmentPointer,
|
||||||
666 => SysCall::InitKernel,
|
666 => SysCall::InitKernel,
|
||||||
_ => SysCall::NoAction,
|
_ => SysCall::NoAction,
|
||||||
}
|
}
|
||||||
|
|
@ -159,6 +162,10 @@ pub fn wait_for_notif_ack(taskid: u8) {
|
||||||
syscall(SysCall::WaitForNotifAck, taskid as usize, 0, 0, 0, 0, 0);
|
syscall(SysCall::WaitForNotifAck, taskid as usize, 0, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn environment_pointer() -> usize {
|
||||||
|
syscall(SysCall::EnvironmentPointer, 0, 0, 0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_kernel() {
|
pub fn init_kernel() {
|
||||||
syscall(SysCall::InitKernel, 0, 0, 0, 0, 0, 0);
|
syscall(SysCall::InitKernel, 0, 0, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -85,6 +85,7 @@ extern "C" fn _virt_init() -> ! {
|
||||||
epc: ktask as usize,
|
epc: ktask as usize,
|
||||||
ddi_first_addr: 0,
|
ddi_first_addr: 0,
|
||||||
ddi_size: 0,
|
ddi_size: 0,
|
||||||
|
environment: 0,
|
||||||
wait_for_task_exit: false,
|
wait_for_task_exit: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,10 @@ pub fn reader_from_cluster(bpb: &BPBUseful, cluster: usize) -> Fat32FileReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn root_target(bpb: &BPBUseful) -> u32 {
|
||||||
|
bpb.root_cluster as u32
|
||||||
|
}
|
||||||
|
|
||||||
pub fn root_reader(bpb: &BPBUseful) -> Fat32DirectoryReader {
|
pub fn root_reader(bpb: &BPBUseful) -> Fat32DirectoryReader {
|
||||||
let cluster = bpb.root_cluster as usize;
|
let cluster = bpb.root_cluster as usize;
|
||||||
Fat32DirectoryReader {
|
Fat32DirectoryReader {
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,13 @@ pub fn open_fs(fs: &mut FileSystem) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn root_target(fs: &FileSystem) -> u32 {
|
||||||
|
#[cfg(feature = "fs_fat32")]
|
||||||
|
{
|
||||||
|
fat32::root_target(fs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn root_reader(fs: &FileSystem) -> DirectoryReader {
|
pub fn root_reader(fs: &FileSystem) -> DirectoryReader {
|
||||||
#[cfg(feature = "fs_fat32")]
|
#[cfg(feature = "fs_fat32")]
|
||||||
{
|
{
|
||||||
|
|
@ -94,8 +101,8 @@ pub fn read_one_record(fs: &FileSystem, reader: &mut DirectoryReader, record: &m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_directory(fs: &FileSystem, path: &mut [u8], reader: &mut DirectoryReader) -> usize {
|
pub fn open_directory(fs: &FileSystem, path: &[u8], reader: &mut DirectoryReader) -> usize {
|
||||||
path.make_ascii_uppercase();
|
//path.make_ascii_uppercase();
|
||||||
if path[0] != b'/' {
|
if path[0] != b'/' {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
@ -104,6 +111,10 @@ pub fn open_directory(fs: &FileSystem, path: &mut [u8], reader: &mut DirectoryRe
|
||||||
*reader = root_reader;
|
*reader = root_reader;
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
|
let mut target_stack = [0u32; 128]; // todo: make this actually dynamic
|
||||||
|
target_stack[0] = root_target(fs);
|
||||||
|
let mut target_stack_idx = 1;
|
||||||
|
|
||||||
let mut record = Record {
|
let mut record = Record {
|
||||||
name: [0; 12],
|
name: [0; 12],
|
||||||
record_type: 0,
|
record_type: 0,
|
||||||
|
|
@ -111,28 +122,67 @@ pub fn open_directory(fs: &FileSystem, path: &mut [u8], reader: &mut DirectoryRe
|
||||||
total_size_bytes: 0,
|
total_size_bytes: 0,
|
||||||
};
|
};
|
||||||
let mut current_reader = root_reader;
|
let mut current_reader = root_reader;
|
||||||
let mut next_path_start = path[1..].iter().position(|&x| x == b'/').unwrap_or(path.len());
|
let mut next_path_start = path[1..].iter().position(|&x| x == b'/').unwrap_or(path.len()) + 1;
|
||||||
let mut search_for = &path[1..next_path_start];
|
let mut search_for = &path[1..next_path_start];
|
||||||
loop {
|
'into_next_dir: loop {
|
||||||
if !read_one_record(fs, &mut current_reader, &mut record) {
|
if search_for == b"." {
|
||||||
return 1;
|
// do nothing and skip this part of the path
|
||||||
|
let new_path_start = next_path_start + 1;
|
||||||
|
if new_path_start >= path.len() {
|
||||||
|
// we're at the end of the path
|
||||||
|
*reader = current_reader;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
next_path_start = path[new_path_start..].iter().position(|&x| x == b'/').unwrap_or(path.len()) + new_path_start;
|
||||||
|
search_for = &path[new_path_start..next_path_start];
|
||||||
|
target_stack[target_stack_idx] = record.target;
|
||||||
|
target_stack_idx += 1;
|
||||||
|
continue 'into_next_dir;
|
||||||
|
} else if search_for == b".." {
|
||||||
|
// go back up
|
||||||
|
if target_stack_idx < 2 {
|
||||||
|
directory_reader(fs, &mut current_reader, target_stack[0]);
|
||||||
|
*reader = current_reader;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
target_stack_idx -= 2; // skip the current directory and the one before that
|
||||||
|
let prev_target = target_stack[target_stack_idx];
|
||||||
|
let new_path_start = next_path_start + 1;
|
||||||
|
if new_path_start >= path.len() {
|
||||||
|
// we're at the end of the path
|
||||||
|
directory_reader(fs, &mut current_reader, prev_target);
|
||||||
|
*reader = current_reader;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
next_path_start = path[new_path_start..].iter().position(|&x| x == b'/').unwrap_or(path.len()) + new_path_start;
|
||||||
|
search_for = &path[new_path_start..next_path_start];
|
||||||
|
directory_reader(fs, &mut current_reader, prev_target);
|
||||||
|
continue 'into_next_dir;
|
||||||
}
|
}
|
||||||
let record_name = &record.name[..record.name.iter().position(|&x| x == 0).unwrap_or(11)];
|
loop {
|
||||||
if record_name == search_for {
|
if !read_one_record(fs, &mut current_reader, &mut record) {
|
||||||
// this is the next record we want
|
return 1;
|
||||||
if record.record_type == RecordType::Directory as u8 {
|
}
|
||||||
let new_path_start = next_path_start + 1; // skip the slash
|
let record_name = &record.name[..record.name.iter().position(|&x| x == 0).unwrap_or(11)];
|
||||||
if new_path_start >= path.len() {
|
if record_name == search_for {
|
||||||
// we're at the end of the path
|
// this is the next record we want
|
||||||
|
if record.record_type == RecordType::Directory as u8 {
|
||||||
|
let new_path_start = next_path_start + 1; // skip the slash
|
||||||
|
if new_path_start >= path.len() {
|
||||||
|
// we're at the end of the path
|
||||||
|
directory_reader(fs, &mut current_reader, record.target);
|
||||||
|
*reader = current_reader;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
next_path_start = path[new_path_start..].iter().position(|&x| x == b'/').unwrap_or(path.len()) + new_path_start;
|
||||||
|
search_for = &path[new_path_start..next_path_start];
|
||||||
directory_reader(fs, &mut current_reader, record.target);
|
directory_reader(fs, &mut current_reader, record.target);
|
||||||
*reader = current_reader;
|
target_stack[target_stack_idx] = record.target;
|
||||||
return 0;
|
target_stack_idx += 1;
|
||||||
|
continue 'into_next_dir;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
next_path_start = path[new_path_start..].iter().position(|&x| x == b'/').unwrap_or(path.len()) + new_path_start;
|
|
||||||
search_for = &path[next_path_start..next_path_start];
|
|
||||||
directory_reader(fs, &mut current_reader, record.target);
|
|
||||||
} else {
|
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ pub extern "C" fn ktask() -> ! {
|
||||||
epc: entrypoint,
|
epc: entrypoint,
|
||||||
ddi_first_addr: first_addr,
|
ddi_first_addr: first_addr,
|
||||||
ddi_size: size,
|
ddi_size: size,
|
||||||
|
environment: 0,
|
||||||
wait_for_task_exit: false,
|
wait_for_task_exit: false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ pub fn handle_syscall(
|
||||||
#[cfg(feature = "arch_virt")]
|
#[cfg(feature = "arch_virt")]
|
||||||
let t = Some(Task {
|
let t = Some(Task {
|
||||||
epc: unsafe { (*add).epc },
|
epc: unsafe { (*add).epc },
|
||||||
|
environment: unsafe { (*add).environment },
|
||||||
want_exit: false,
|
want_exit: false,
|
||||||
sp,
|
sp,
|
||||||
wait: 0,
|
wait: 0,
|
||||||
|
|
@ -319,6 +320,14 @@ pub fn handle_syscall(
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
SysCall::EnvironmentPointer => {
|
||||||
|
let ci = tc.current;
|
||||||
|
if let Some(task) = tc.tasks[ci].as_ref() {
|
||||||
|
task.environment
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
suspend,
|
suspend,
|
||||||
)
|
)
|
||||||
|
|
@ -413,6 +422,7 @@ pub struct TrafficControl {
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
#[cfg(feature = "arch_virt")]
|
#[cfg(feature = "arch_virt")]
|
||||||
pub epc: usize,
|
pub epc: usize,
|
||||||
|
pub environment: usize,
|
||||||
pub want_exit: bool,
|
pub want_exit: bool,
|
||||||
/// THE ORIGINAL STACK POINTER THAT THE TASK STARTED WITH
|
/// THE ORIGINAL STACK POINTER THAT THE TASK STARTED WITH
|
||||||
pub sp: usize,
|
pub sp: usize,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
|
||||||
use crate::terminal::{print, println};
|
use crate::terminal::{print, println};
|
||||||
use liblbos::fs::{DirectoryReader, FileSystem};
|
use liblbos::fs::{DirectoryReader, FileSystem};
|
||||||
|
|
||||||
static NO_EXIT: AtomicBool = AtomicBool::new(false);
|
static NO_EXIT: AtomicBool = AtomicBool::new(false);
|
||||||
|
static CURRENT_DIR_PATH: AtomicPtr<u8> = AtomicPtr::new(0 as *mut _);
|
||||||
|
static CURRENT_DIR_PATH_LEN: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
struct Environment<'a> {
|
||||||
|
pub current_directory_path: &'a [u8],
|
||||||
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
|
@ -13,14 +19,83 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lsdir() {
|
fn cd(new_path: &str, environment: &mut Environment<'_>) {
|
||||||
|
let old_path = environment.current_directory_path;
|
||||||
|
let abs_new_path = if new_path.starts_with('/') {
|
||||||
|
// absolute path, replaces old path
|
||||||
|
let new_path_buf = liblbos::syscalls::alloc_blocks(new_path.len().div_ceil(512));
|
||||||
|
let new_path_buf = unsafe { core::slice::from_raw_parts_mut(new_path_buf as *mut _, new_path.len()) };
|
||||||
|
// copy
|
||||||
|
{
|
||||||
|
for (i, &x) in new_path.as_bytes().iter().enumerate() {
|
||||||
|
new_path_buf[i] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_path_buf
|
||||||
|
} else {
|
||||||
|
// todo: ".." is currently handled on the ktask level, however...
|
||||||
|
// todo: we should evaluate this and instead modify the absolute path to remove the ".."
|
||||||
|
// todo: otherwise, we're bound to end up with a path like "/a/b/../../c" which is not nice
|
||||||
|
// relative path, append
|
||||||
|
let new_path_len = old_path.len() + new_path.len() + 1;
|
||||||
|
let new_path_buf = liblbos::syscalls::alloc_blocks(new_path_len.div_ceil(512));
|
||||||
|
let new_path_buf = unsafe { core::slice::from_raw_parts_mut(new_path_buf as *mut _, new_path_len) };
|
||||||
|
// copy old path
|
||||||
|
{
|
||||||
|
for (i, &x) in old_path.iter().enumerate() {
|
||||||
|
new_path_buf[i] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// copy new path
|
||||||
|
{
|
||||||
|
for (i, &x) in new_path.as_bytes().iter().enumerate() {
|
||||||
|
new_path_buf[old_path.len() + i] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add separator
|
||||||
|
new_path_buf[old_path.len() + new_path.len()] = b'/';
|
||||||
|
|
||||||
|
new_path_buf
|
||||||
|
};
|
||||||
|
|
||||||
|
// check to make sure the new path is valid
|
||||||
|
{
|
||||||
|
let mut fs = FileSystem::empty();
|
||||||
|
if liblbos::ktask::ktask_fsopen(&mut fs) != 0 {
|
||||||
|
println("failed to open fs");
|
||||||
|
// free
|
||||||
|
liblbos::syscalls::free_blocks(abs_new_path.as_ptr() as usize, abs_new_path.len().div_ceil(512));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut dir = DirectoryReader::empty();
|
||||||
|
if liblbos::ktask::ktask_fsopendir(&fs, &mut dir, abs_new_path) != 0 {
|
||||||
|
println("invalid dir");
|
||||||
|
// free
|
||||||
|
liblbos::syscalls::free_blocks(abs_new_path.as_ptr() as usize, abs_new_path.len().div_ceil(512));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// it is valid, update everything
|
||||||
|
{
|
||||||
|
// free old path
|
||||||
|
liblbos::syscalls::free_blocks(CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize, CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed).div_ceil(512));
|
||||||
|
}
|
||||||
|
CURRENT_DIR_PATH.store(abs_new_path.as_ptr() as *mut _, Ordering::Relaxed);
|
||||||
|
CURRENT_DIR_PATH_LEN.store(abs_new_path.len(), Ordering::Relaxed);
|
||||||
|
environment.current_directory_path = unsafe {
|
||||||
|
core::slice::from_raw_parts_mut(CURRENT_DIR_PATH.load(Ordering::Relaxed) as *mut _, CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lsdir(env: &Environment<'_>) {
|
||||||
let mut fs = FileSystem::empty();
|
let mut fs = FileSystem::empty();
|
||||||
if liblbos::ktask::ktask_fsopen(&mut fs) != 0 {
|
if liblbos::ktask::ktask_fsopen(&mut fs) != 0 {
|
||||||
println("failed to open fs");
|
println("failed to open fs");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut dir = DirectoryReader::empty();
|
let mut dir = DirectoryReader::empty();
|
||||||
if liblbos::ktask::ktask_fsopendir(&fs, &mut dir, b"/") != 0 {
|
if liblbos::ktask::ktask_fsopendir(&fs, &mut dir, env.current_directory_path) != 0 {
|
||||||
println("failed to open dir");
|
println("failed to open dir");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -107,6 +182,7 @@ fn attempt_run_file(name: &str) {
|
||||||
epc: 0,
|
epc: 0,
|
||||||
ddi_first_addr: 0,
|
ddi_first_addr: 0,
|
||||||
ddi_size: 0,
|
ddi_size: 0,
|
||||||
|
environment: 0,
|
||||||
wait_for_task_exit: true,
|
wait_for_task_exit: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -118,19 +194,26 @@ fn attempt_run_file(name: &str) {
|
||||||
|
|
||||||
liblbos::syscalls::free_blocks(buf, size.div_ceil(512));
|
liblbos::syscalls::free_blocks(buf, size.div_ceil(512));
|
||||||
|
|
||||||
let task_id = liblbos::syscalls::create_task(task_setup);
|
liblbos::syscalls::create_task(task_setup);
|
||||||
|
|
||||||
println("\ntask exited\n");
|
println("\ntask exited\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(cmd: &str) {
|
fn execute(cmd: &str, environment: &mut Environment<'_>) {
|
||||||
print("\n");
|
print("\n");
|
||||||
let mut split = cmd.split_ascii_whitespace();
|
let mut split = cmd.split_ascii_whitespace();
|
||||||
|
|
||||||
if let Some(cmd) = split.next() {
|
if let Some(cmd) = split.next() {
|
||||||
match cmd {
|
match cmd {
|
||||||
"ls" => {
|
"ls" => {
|
||||||
lsdir();
|
lsdir(environment);
|
||||||
|
}
|
||||||
|
"cd" => {
|
||||||
|
if let Some(path) = split.next() {
|
||||||
|
cd(path, environment);
|
||||||
|
} else {
|
||||||
|
println("cd requires a path");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"exit" => {
|
"exit" => {
|
||||||
if NO_EXIT.load(Ordering::Relaxed) {
|
if NO_EXIT.load(Ordering::Relaxed) {
|
||||||
|
|
@ -168,6 +251,40 @@ extern "C" fn main() {
|
||||||
let tid = liblbos::syscalls::current_task();
|
let tid = liblbos::syscalls::current_task();
|
||||||
NO_EXIT.store(tid == 1, Ordering::Relaxed);
|
NO_EXIT.store(tid == 1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let environment = liblbos::syscalls::environment_pointer();
|
||||||
|
let mut environment = if environment == 0 {
|
||||||
|
// no environment, construct it ourself
|
||||||
|
static DEFAULT_CURRENT_DIRECTORY: &[u8] = b"/";
|
||||||
|
let environment = Environment {
|
||||||
|
current_directory_path: DEFAULT_CURRENT_DIRECTORY,
|
||||||
|
};
|
||||||
|
environment
|
||||||
|
} else {
|
||||||
|
let env = unsafe { &mut *(environment as *mut liblbos::Environment) };
|
||||||
|
let current_directory_path = unsafe { core::slice::from_raw_parts(env.current_directory_path as *const u8, env.current_directory_path_len) };
|
||||||
|
let environment = Environment {
|
||||||
|
current_directory_path,
|
||||||
|
};
|
||||||
|
environment
|
||||||
|
};
|
||||||
|
// replace the current path with one that we allocate ourself, so that we can modify it later
|
||||||
|
{
|
||||||
|
let path = environment.current_directory_path;
|
||||||
|
let len = environment.current_directory_path.len();
|
||||||
|
CURRENT_DIR_PATH.store(liblbos::syscalls::alloc_blocks(len.div_ceil(512)) as *mut u8, Ordering::Relaxed);
|
||||||
|
CURRENT_DIR_PATH_LEN.store(len, Ordering::Relaxed);
|
||||||
|
{
|
||||||
|
// copy
|
||||||
|
let dest = unsafe {
|
||||||
|
core::slice::from_raw_parts_mut(CURRENT_DIR_PATH.load(Ordering::Relaxed) as *mut _, len)
|
||||||
|
};
|
||||||
|
for (i, &x) in path.iter().enumerate() {
|
||||||
|
dest[i] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
environment.current_directory_path = unsafe { core::slice::from_raw_parts_mut(CURRENT_DIR_PATH.load(Ordering::Relaxed) as *mut u8, CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed)) };
|
||||||
|
}
|
||||||
|
|
||||||
print("\n\n");
|
print("\n\n");
|
||||||
print("turntable v");
|
print("turntable v");
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
@ -198,7 +315,8 @@ extern "C" fn main() {
|
||||||
if *c == b'\r' {
|
if *c == b'\r' {
|
||||||
execute(unsafe {
|
execute(unsafe {
|
||||||
core::str::from_utf8_unchecked(&cmdbuf[0..cmdbuf_len - 1])
|
core::str::from_utf8_unchecked(&cmdbuf[0..cmdbuf_len - 1])
|
||||||
});
|
},
|
||||||
|
&mut environment);
|
||||||
cmdbuf_len = 0;
|
cmdbuf_len = 0;
|
||||||
print("> ");
|
print("> ");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue