diff --git a/lab5/user/lab5/apps/init.c b/lab5/user/lab5/apps/init.c index b6398af..821d3f5 100644 --- a/lab5/user/lab5/apps/init.c +++ b/lab5/user/lab5/apps/init.c @@ -7,6 +7,7 @@ #include #include #include +#include "malloc.h" #define SERVER_READY_FLAG(vaddr) (*(int *)(vaddr)) #define SERVER_EXIT_FLAG(vaddr) (*(int *)((u64)vaddr+ 4)) @@ -14,6 +15,7 @@ extern ipc_struct_t *tmpfs_ipc_struct; static ipc_struct_t ipc_struct; static int tmpfs_scan_pmo_cap; +static int tmpfs_read_pmo_cap; /* fs_server_cap in current process; can be copied to others */ int fs_server_cap; @@ -83,21 +85,51 @@ int do_top() return 0; } +/** + * 转为绝对路径 + */ +void path_to_absolute(char *path) { + char pathbuf[BUFLEN]; + strcpy(pathbuf + 1, path); + pathbuf[0] = '/'; + strcpy(path, pathbuf); +} + +/** + * 路径连接 + */ +void path_append(char *path, char *sub) { + size_t path_len = strlen(path); + // path 末尾应该有 '/' + if (path[path_len - 1] == '/') { + path += path_len; + } else { + path[path_len] = '/'; + path += path_len + 1; + } + // sub 之前没有 '/' + while (*sub == '/') sub++; + // 连接路径 + strcpy(path, sub); +} + +/** + * 扫描目录 + */ int fs_scan(char *path) { - // TODO: your code here int count = 4096/2; - char str[256]; struct fs_request fr; int ret; + // 拼接请求 fr.req = FS_REQ_SCAN; fr.buff = (char *) TMPFS_SCAN_BUF_VADDR; - strcpy(fr.path + 1, path); - fr.path[0] = '/'; + strcpy(fr.path, path); fr.offset = 0; fr.count = count; + // 发送 printf("Send ls: %s\n", path); ipc_msg_t *ipc_msg = ipc_create_msg(tmpfs_ipc_struct, sizeof(fr), 1); ipc_set_msg_data(ipc_msg, (void *)&fr, 0, sizeof(fr)); @@ -108,16 +140,98 @@ int fs_scan(char *path) return ret; } +/** + * 获得文件大小 + */ +int fs_get_size(char *path) +{ + struct fs_request fr; + int ret; + + // 拼接请求 + fr.req = FS_REQ_GET_SIZE; + strcpy(fr.path, path); + + // 发送 + ipc_msg_t *ipc_msg = ipc_create_msg(tmpfs_ipc_struct, sizeof(fr), 1); + ipc_set_msg_data(ipc_msg, (void *)&fr, 0, sizeof(fr)); + ipc_set_msg_cap(ipc_msg, 0, tmpfs_scan_pmo_cap); + ret = ipc_call(tmpfs_ipc_struct, ipc_msg); + ipc_destroy_msg(ipc_msg); + return ret; +} + +int fs_read(char *path, off_t offset, ssize_t count) { + struct fs_request fr; + int ret; + + fail_cond(count > PAGE_SIZE, + "read size should smaller than %d, now %d", PAGE_SIZE, count); + + // 拼接请求 + fr.req = FS_REQ_READ; + fr.buff = (char *) TMPFS_READ_BUF_VADDR; + strcpy(fr.path, path); + fr.offset = offset; + fr.count = count; + + // 发送 + ipc_msg_t *ipc_msg = ipc_create_msg(tmpfs_ipc_struct, sizeof(fr), 1); + ipc_set_msg_data(ipc_msg, (void *)&fr, 0, sizeof(fr)); + ipc_set_msg_cap(ipc_msg, 0, tmpfs_read_pmo_cap); + ret = ipc_call(tmpfs_ipc_struct, ipc_msg); + ipc_destroy_msg(ipc_msg); + return ret; +} + +/** + * 读入文件并返回长度 + */ +int fs_read_all(char *path, void **ret_buf) +{ + // 获得文件长度 + int size = fs_get_size(path); + if (size < 0) { + return size; + } + + // 申请缓冲 + unsigned char *buf = malloc(size); + if (!buf) { + return -1; + } + *ret_buf = buf; + + // 读入文件 + // FIXME: 读取 1 页以上会遇到 warning: vmr overlap + int pos = 0; + while (size - pos > 0) { + int cur = fs_read(path, pos, PAGE_SIZE - 1); + if (cur < 0) { + return cur; + } + memcpy(buf, (const void *) TMPFS_READ_BUF_VADDR, cur); + pos += cur; + buf += cur; + } + + return size; +} + int do_ls(char *cmdline) { char pathbuf[BUFLEN]; + char fpathbuf[BUFLEN]; int ret; pathbuf[0] = '\0'; cmdline += 2; while (*cmdline == ' ') cmdline++; - strcat(pathbuf, cmdline); + // 路径格式化 + strcat(pathbuf, cmdline); + path_to_absolute(pathbuf); + // 请求 fs ret = fs_scan(pathbuf); if (ret >= 0) { char *print_ptr; @@ -126,7 +240,17 @@ int do_ls(char *cmdline) for (int i = 0; i < ret; i++) { dirat = (struct dirent *) print_ptr; - printf(" %s\n", dirat->d_name); + // 文件类型 + char type = 'f'; + if (dirat->d_type == 2) { + type = 'd'; // 目录 + } + // 文件大小 + strcpy(fpathbuf, pathbuf); + path_append(fpathbuf, dirat->d_name); + int size = fs_get_size(fpathbuf); + // 输出 + printf("%c %10d %s\n", type, size, dirat->d_name); print_ptr += dirat->d_reclen; } } else { @@ -143,9 +267,22 @@ int do_cat(char *cmdline) cmdline += 3; while (*cmdline == ' ') cmdline++; - strcat(pathbuf, cmdline); - // fs_scan(pathbuf); - printf("apple banana This is a test file.\n"); + // 路径格式化 + strcat(pathbuf, cmdline); + path_to_absolute(pathbuf); + // 读入文件 + char *buf; + int ret = fs_read_all(pathbuf, (void **) &buf); + if (ret < 0) { + printf("cannot cat file, code %d\n", ret); + return ret; + } + // 打印 + for (int i = 0; i < ret; i++) { + usys_putc(buf[i]); + } + free(buf); + return 0; } @@ -296,5 +433,15 @@ void boot_fs(void) TMPFS_SCAN_BUF_VADDR, VM_READ | VM_WRITE); fail_cond(ret < 0, "usys_map_pmo ret %d\n", ret); + // 创建读文件 pmo + tmpfs_read_pmo_cap = usys_create_pmo(PAGE_SIZE, PMO_DATA); + fail_cond(tmpfs_read_pmo_cap < 0, "usys create_ret ret %d\n", + tmpfs_read_pmo_cap); + + ret = usys_map_pmo(SELF_CAP, + tmpfs_read_pmo_cap, + TMPFS_READ_BUF_VADDR, VM_READ | VM_WRITE); + fail_cond(ret < 0, "usys_map_pmo ret %d\n", ret); + printf("fs is UP.\n"); }