🆕 cd命令

This commit is contained in:
fslongjin 2022-05-25 22:50:32 +08:00
parent 8bd7b64a0b
commit 37669ebf87
15 changed files with 443 additions and 94 deletions

View File

@ -140,7 +140,7 @@ uint64_t sys_open(struct pt_regs *regs)
printk_color(ORANGE, BLACK, "Can`t find file\n");
kfree(path);
if (dentry == NULL)
if (dentry == NULL)
return -ENOENT;
// 暂时认为目标是目录是一种错误
@ -445,7 +445,7 @@ uint64_t sys_sbrk(struct pt_regs *regs)
/**
* @brief
*
* @return
* @return
*/
uint64_t sys_reboot(struct pt_regs *regs)
{
@ -455,6 +455,69 @@ uint64_t sys_reboot(struct pt_regs *regs)
return 0;
}
/**
* @brief
*
* @param dest_path
* @return
+--------------+------------------------+
| | |
+--------------+------------------------+
| 0 | |
| EACCESS | |
| ELOOP | path时遇到路径循环 |
| ENAMETOOLONG | |
| ENOENT | |
| ENODIR | |
| ENOMEM | |
| EFAULT | |
| ENAMETOOLONG | |
+--------------+------------------------+
*/
uint64_t sys_chdir(struct pt_regs *regs)
{
char *dest_path = (char *)regs->r8;
// kdebug("dest_path=%s", dest_path);
// 检查目标路径是否为NULL
if (dest_path == NULL)
return -EFAULT;
// 计算输入的路径长度
int dest_path_len = strnlen_user(dest_path, PAGE_4K_SIZE);
// 长度小于等于0
if (dest_path_len <= 0)
return -EFAULT;
else if (dest_path_len >= PAGE_4K_SIZE)
return -ENAMETOOLONG;
// 为路径字符串申请空间
char *path = kmalloc(dest_path_len + 1, 0);
// 系统内存不足
if (path == NULL)
return -ENOMEM;
memset(path, 0, dest_path_len + 1);
// 将字符串从用户空间拷贝进来, +1是为了拷贝结尾的\0
strncpy_from_user(path, dest_path, dest_path_len + 1);
struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
kfree(path);
if (dentry == NULL)
return -ENOENT;
// 目标不是目录
if (dentry->dir_inode->attribute != VFS_ATTR_DIR)
return -ENOTDIR;
return 0;
}
ul sys_ahci_end_req(struct pt_regs *regs)
{
ahci_end_request();
@ -483,5 +546,6 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] =
[9] = sys_brk,
[10] = sys_sbrk,
[11] = sys_reboot,
[12 ... 254] = system_call_not_exists,
[12] = sys_chdir,
[13 ... 254] = system_call_not_exists,
[255] = sys_ahci_end_req};

View File

@ -21,5 +21,6 @@
#define SYS_BRK 9
#define SYS_SBRK 10
#define SYS_REBOOT 11 // 重启
#define SYS_CHDIR 12 // 切换工作目录
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用

View File

@ -1,7 +1,10 @@
all: shell.o cmd.o
all: shell.o cmd.o cmd_help.o
shell.o: shell.c
gcc $(CFLAGS) -c shell.c -o shell.o
cmd.o: cmd.c
gcc $(CFLAGS) -c cmd.c -o cmd.o
cmd_help.o: cmd_help.c
gcc $(CFLAGS) -c cmd_help.c -o cmd_help.o

View File

@ -3,6 +3,12 @@
#include <libc/stdio.h>
#include <libc/stddef.h>
#include <libsystem/syscall.h>
#include <libc/string.h>
#include <libc/errno.h>
#include <libc/unistd.h>
#include <libc/stdlib.h>
#include "cmd_help.h"
// 当前工作目录在main_loop中初始化
char *shell_current_path = NULL;
@ -22,6 +28,7 @@ struct built_in_cmd_t shell_cmds[] =
{"rmdir", shell_cmd_rmdir},
{"reboot", shell_cmd_reboot},
{"touch", shell_cmd_touch},
{"help", shell_help},
};
// 总共的内建命令数量
@ -69,8 +76,112 @@ void shell_run_built_in_command(int index, int argc, char **argv)
* @param argv
* @return int
*/
// todo:
int shell_cmd_cd(int argc, char **argv) {}
int shell_cmd_cd(int argc, char **argv)
{
int current_dir_len = strlen(shell_current_path);
if (argc < 2)
{
shell_help_cd();
goto done;
}
// 进入当前文件夹
if (!strcmp(".", argv[1]))
goto done;
// 进入父目录
if (!strcmp("..", argv[1]))
{
// 当前已经是根目录
if (!strcmp("/", shell_current_path))
goto done;
// 返回到父目录
int index = current_dir_len - 1;
for (; index > 1; --index)
{
if (shell_current_path[index] == '/')
break;
}
shell_current_path[index] = '\0';
// printf("switch to \" %s \"\n", shell_current_path);
goto done;
}
int dest_len = strlen(argv[1]);
// 路径过长
if (dest_len >= SHELL_CWD_MAX_SIZE - 1)
{
printf("ERROR: Path too long!\n");
goto fail;
}
if (argv[1][0] == '/')
{
// ======进入绝对路径=====
int ec = chdir(argv[1]);
if (ec == -1)
ec = errno;
if (ec == 0)
{
// 获取新的路径字符串
char *new_path = (char *)malloc(dest_len + 2);
memset(new_path, 0, dest_len + 2);
strncpy(new_path, argv[1], dest_len);
// 释放原有的路径字符串的内存空间
free(shell_current_path);
shell_current_path = new_path;
shell_current_path[dest_len] = '\0';
return 0;
}
else
goto fail;; // 出错则直接忽略
}
else
{
int new_len = current_dir_len + dest_len;
// ======进入相对路径=====
if (new_len >= SHELL_CWD_MAX_SIZE - 1)
{
printf("ERROR: Path too long!\n");
goto fail;
}
// 拼接出新的字符串
char *new_path = (char *)malloc(new_len + 2);
memset(new_path, 0, sizeof(new_path));
strncpy(new_path, shell_current_path, current_dir_len);
if (current_dir_len > 1)
new_path[current_dir_len] = '/';
strcat(new_path, argv[1]);
if (chdir(new_path) == 0) // 成功切换目录
{
free(shell_current_path);
new_path[new_len] = '\0';
shell_current_path = new_path;
goto done;
}
else
{
printf("ERROR: Cannot switch to directory: %s\n", new_path);
goto fail;
}
}
fail:;
done:;
// 释放参数所占的内存
free(argv);
return 0;
}
/**
* @brief
@ -80,7 +191,10 @@ int shell_cmd_cd(int argc, char **argv) {}
* @return int
*/
// todo:
int shell_cmd_ls(int argc, char **argv) {}
int shell_cmd_ls(int argc, char **argv)
{
return 0;
}
/**
* @brief
@ -93,6 +207,8 @@ int shell_cmd_pwd(int argc, char **argv)
{
if (shell_current_path)
printf("%s\n", shell_current_path);
free(argv);
}
/**

View File

@ -1,5 +1,8 @@
#pragma once
// cwd字符串的最大大小
#define SHELL_CWD_MAX_SIZE 256
/**
* @brief shell内建命令结构体
*

View File

@ -0,0 +1,23 @@
#include "cmd_help.h"
#include <libc/stdio.h>
struct help_table_item_t
{
void (*func)();
};
struct help_table_item_t help_table[] = {
{shell_help_cd},
};
static const int help_table_num = sizeof(help_table) / sizeof(struct help_table_item_t);
void shell_help()
{
printf("Help:\n");
for (int i = 0; i < help_table_num; ++i)
help_table[i].func();
}
void shell_help_cd()
{
printf("Example of cd: cd [destination]\n");
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "cmd.h"
void shell_help();
/**
* @brief cd命令的帮助信息
*
*/
void shell_help_cd();

View File

@ -42,9 +42,10 @@ static void main_loop(int kb_fd)
unsigned char input_buffer[INPUT_BUFFER_SIZE] = {0};
// 初始化当前工作目录的路径
shell_current_path = (char *)malloc(256);
memset(shell_current_path, 0, 256);
shell_current_path = "/";
shell_current_path = (char *)malloc(3);
memset(shell_current_path, 0, 3);
shell_current_path[0] = '/';
shell_current_path[1] = '\0';
// shell命令行的主循环
while (true)
@ -52,17 +53,22 @@ static void main_loop(int kb_fd)
int argc = 0;
char **argv;
printf("[DragonOS] # ");
printf("[DragonOS] %s # ", shell_current_path);
memset(input_buffer, 0, INPUT_BUFFER_SIZE);
// 循环读取每一行到buffer
shell_readline(kb_fd, input_buffer);
int count = shell_readline(kb_fd, input_buffer);
int cmd_num = parse_command(input_buffer, &argc, &argv);
printf("\n");
if (cmd_num >= 0)
shell_run_built_in_command(cmd_num, argc, argv);
if (count)
{
int cmd_num = parse_command(input_buffer, &argc, &argv);
printf("\n");
if (cmd_num >= 0)
shell_run_built_in_command(cmd_num, argc, argv);
}
else
printf("\n");
}
}
@ -120,13 +126,14 @@ int shell_readline(int fd, char *buf)
*/
int parse_command(char *buf, int *argc, char ***argv)
{
// printf("parse command\n");
int index = 0; // 当前访问的是buf的第几位
// 去除命令前导的空格
while (index < INPUT_BUFFER_SIZE && buf[index] == ' ')
++index;
// 计算参数数量
for (int i = index; i < INPUT_BUFFER_SIZE - 1; ++i)
for (int i = index; i < (INPUT_BUFFER_SIZE - 1); ++i)
{
// 到达了字符串末尾
if (!buf[i])
@ -140,13 +147,12 @@ int parse_command(char *buf, int *argc, char ***argv)
// 为指向每个指令的指针分配空间
*argv = (char **)malloc(sizeof(char **) * (*argc));
memset(*argv, 0, sizeof(char **) * (*argc));
// 将每个命令都单独提取出来
for (int i = 0; i < *argc && index < INPUT_BUFFER_SIZE; ++i)
{
// 提取出命令,以空格作为分割
*((*argv) + i) = &buf[index];
while (index < INPUT_BUFFER_SIZE - 1 && buf[index] && buf[index] != ' ')
while (index < (INPUT_BUFFER_SIZE - 1) && buf[index] && buf[index] != ' ')
++index;
buf[index++] = '\0';

View File

@ -5,7 +5,7 @@ CFLAGS += -I .
libc_sub_dirs=math
libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o
libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o
@list='$(libc_sub_dirs)'; for subdir in $$list; do \
echo "make all in $$subdir";\
cd $$subdir;\
@ -32,4 +32,7 @@ stdlib.o: stdlib.c
gcc $(CFLAGS) -c stdlib.c -o stdlib.o
ctype.o: ctype.c
gcc $(CFLAGS) -c ctype.c -o ctype.o
gcc $(CFLAGS) -c ctype.c -o ctype.o
string.o: string.c
gcc $(CFLAGS) -c string.c -o string.o

View File

@ -268,7 +268,7 @@ static void malloc_insert_free_list(malloc_mem_chunk_t *ck)
*/
void *malloc(ssize_t size)
{
// printf("malloc\n");
// 计算需要分配的块的大小
if (size + sizeof(uint64_t) <= sizeof(malloc_mem_chunk_t))
size = sizeof(malloc_mem_chunk_t);
@ -281,6 +281,7 @@ void *malloc(ssize_t size)
if (ck == NULL) // 没有空闲块
{
// printf("no free blocks\n");
// 尝试合并空闲块
malloc_merge_free_chunk();
ck = malloc_query_free_chunk_bf(size);
@ -288,10 +289,12 @@ void *malloc(ssize_t size)
// 找到了合适的块
if (ck)
goto found;
// printf("before enlarge\n");
// 找不到合适的块,扩容堆区域
if (malloc_enlarge(size) == -ENOMEM)
return (void *)-ENOMEM; // 内存不足
malloc_merge_free_chunk(); // 扩容后运行合并,否则会导致碎片
@ -304,6 +307,7 @@ found:;
// printf("ck = %#018lx\n", (uint64_t)ck);
if (ck == NULL)
return (void *)-ENOMEM;
// printf("ck->prev=%#018lx ck->next=%#018lx\n", ck->prev, ck->next);
// 分配空闲块
// 从空闲链表取出
if (ck->prev == NULL) // 当前是链表的第一个块
@ -321,6 +325,7 @@ found:;
// 当前块剩余的空间还能容纳多一个结点的空间,则分裂当前块
if ((int64_t)(ck->length) - size > sizeof(malloc_mem_chunk_t))
{
// printf("seperate\n");
malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)(((uint64_t)ck) + size);
new_ck->length = ck->length - size;
new_ck->prev = new_ck->next = NULL;
@ -328,7 +333,7 @@ found:;
ck->length = size;
malloc_insert_free_list(new_ck);
}
// printf("malloc done: %#018lx, length=%#018lx\n", ((uint64_t)ck + sizeof(uint64_t)), ck->length);
// 此时链表结点的指针的空间被分配出去
return (void *)((uint64_t)ck + sizeof(uint64_t));
}
@ -367,13 +372,13 @@ static void release_brk()
*
* @param ptr
*/
void free(void *ptr)
void free(void *ptr)
{
// 找到结点此时prev和next都处于未初始化的状态
malloc_mem_chunk_t *ck = (malloc_mem_chunk_t *)((uint64_t)ptr - sizeof(uint64_t));
// printf("free(): addr = %#018lx\t len=%#018lx\n", (uint64_t)ck, ck->length);
count_last_free_size += ck->length;
malloc_insert_free_list(ck);
if (count_last_free_size > PAGE_2M_SIZE)

109
user/libs/libc/string.c Normal file
View File

@ -0,0 +1,109 @@
#include "string.h"
size_t strlen(const char *s)
{
register int __res = 0;
while (s[__res] != '\0')
{
++__res;
}
return __res;
}
int strcmp(const char *FirstPart, const char *SecondPart)
{
register int __res;
__asm__ __volatile__("cld \n\t"
"1: \n\t"
"lodsb \n\t"
"scasb \n\t"
"jne 2f \n\t"
"testb %%al, %%al \n\t"
"jne 1b \n\t"
"xorl %%eax, %%eax \n\t"
"jmp 3f \n\t"
"2: \n\t"
"movl $1, %%eax \n\t"
"jl 3f \n\t"
"negl %%eax \n\t"
"3: \n\t"
: "=a"(__res)
: "D"(FirstPart), "S"(SecondPart)
:);
return __res;
}
void *memset(void *dst, unsigned char C, uint64_t size)
{
int d0, d1;
unsigned long tmp = C * 0x0101010101010101UL;
__asm__ __volatile__("cld \n\t"
"rep \n\t"
"stosq \n\t"
"testb $4, %b3 \n\t"
"je 1f \n\t"
"stosl \n\t"
"1:\ttestb $2, %b3 \n\t"
"je 2f\n\t"
"stosw \n\t"
"2:\ttestb $1, %b3 \n\t"
"je 3f \n\t"
"stosb \n\t"
"3: \n\t"
: "=&c"(d0), "=&D"(d1)
: "a"(tmp), "q"(size), "0"(size / 8), "1"(dst)
: "memory");
return dst;
}
/**
* @brief
*
* @param dst
* @param src
* @param Count
* @return char*
*/
char *strncpy(char *dst, char *src, long Count)
{
__asm__ __volatile__("cld \n\t"
"1: \n\t"
"decq %2 \n\t"
"js 2f \n\t"
"lodsb \n\t"
"stosb \n\t"
"testb %%al, %%al \n\t"
"jne 1b \n\t"
"rep \n\t"
"stosb \n\t"
"2: \n\t"
:
: "S"(src), "D"(dst), "c"(Count)
: "ax", "memory");
return dst;
}
/**
* @brief src接到dest末尾
*
* @param dest
* @param src
* @return char*
*/
char *strcat(char *dest, const char *src)
{
unsigned int dest_size = strlen(dest);
unsigned int src_size = strlen(src);
char *d = dest;
for (size_t i = 0; i < src_size; i++)
{
d[dest_size + i] = src[i];
}
d[dest_size + src_size] = '\0';
return dest;
}

View File

@ -2,40 +2,14 @@
#include <libc/sys/types.h>
void *memset(void *dst, unsigned char C, uint64_t size)
{
int d0, d1;
unsigned long tmp = C * 0x0101010101010101UL;
__asm__ __volatile__("cld \n\t"
"rep \n\t"
"stosq \n\t"
"testb $4, %b3 \n\t"
"je 1f \n\t"
"stosl \n\t"
"1:\ttestb $2, %b3 \n\t"
"je 2f\n\t"
"stosw \n\t"
"2:\ttestb $1, %b3 \n\t"
"je 3f \n\t"
"stosb \n\t"
"3: \n\t"
: "=&c"(d0), "=&D"(d1)
: "a"(tmp), "q"(size), "0"(size / 8), "1"(dst)
: "memory");
return dst;
}
size_t strlen(const char *s)
{
register size_t __res = 0;
while (s[__res] != '\0')
{
++__res;
}
return __res;
}
void *memset(void *dst, unsigned char C, uint64_t size);
/**
* @brief
*
* @param s
* @return size_t
*/
size_t strlen(const char *s);
/*
FirstPart and SecondPart
@ -44,25 +18,23 @@ size_t strlen(const char *s)
FirstPart < SecondPart => -1
*/
int strcmp(const char *FirstPart, const char *SecondPart)
{
register int __res;
__asm__ __volatile__("cld \n\t"
"1: \n\t"
"lodsb \n\t"
"scasb \n\t"
"jne 2f \n\t"
"testb %%al, %%al \n\t"
"jne 1b \n\t"
"xorl %%eax, %%eax \n\t"
"jmp 3f \n\t"
"2: \n\t"
"movl $1, %%eax \n\t"
"jl 3f \n\t"
"negl %%eax \n\t"
"3: \n\t"
: "=a"(__res)
: "D"(FirstPart), "S"(SecondPart)
:);
return __res;
}
int strcmp(const char *FirstPart, const char *SecondPart);
/**
* @brief
*
* @param dst
* @param src
* @param Count
* @return char*
*/
char *strncpy(char *dst, char *src, long Count);
/**
* @brief src接到dest末尾
*
* @param dest
* @param src
* @return char*
*/
char *strcat(char *dest, const char *src);

View File

@ -2,6 +2,7 @@
#include <libsystem/syscall.h>
#include <libc/errno.h>
#include <libc/stdio.h>
#include <libc/stddef.h>
/**
* @brief
@ -105,4 +106,33 @@ void *sbrk(int64_t increment)
errno = 0;
return (void *)retval;
}
}
/**
* @brief
*
* @param dest_path
* @return int64_t 0,
*/
int64_t chdir(char *dest_path)
{
if (dest_path == NULL)
{
errno = -EFAULT;
return -1;
}
else
{
int retval = syscall_invoke(SYS_CHDIR, (uint64_t)dest_path, 0,0,0,0,0,0,0);
if(retval == 0)
{
errno = 0;
return 0;
}
else
{
errno = retval;
return -1;
}
}
}

View File

@ -2,11 +2,6 @@
#include <stdint.h>
#include <libc/sys/types.h>
/**
* @brief
*
@ -47,15 +42,15 @@ off_t lseek(int fd, off_t offset, int whence);
/**
* @brief fork当前进程
*
* @return pid_t
*
* @return pid_t
*/
pid_t fork(void);
/**
* @brief fork当前进程VMflagsfd
*
* @return pid_t
*
* @return pid_t
*/
pid_t vfork(void);
@ -72,8 +67,16 @@ uint64_t brk(uint64_t end_brk);
/**
* @brief offset线
*
*
* @param increment offset偏移量
* @return uint64_t the previous program break
*/
void * sbrk(int64_t increment);
void *sbrk(int64_t increment);
/**
* @brief
*
* @param dest_path
* @return int64_t 0,
*/
int64_t chdir(char *dest_path);

View File

@ -15,6 +15,7 @@
#define SYS_BRK 9
#define SYS_SBRK 10
#define SYS_REBOOT 11
#define SYS_CHDIR 12 // 切换工作目录
/**
* @brief