From b79ba099dfc44461e78260ff2730cfb02ec312bb Mon Sep 17 00:00:00 2001 From: fslongjin Date: Wed, 6 Jul 2022 17:10:54 +0800 Subject: [PATCH] =?UTF-8?q?bugfix:=20=E4=BF=AE=E5=A4=8D=E4=BA=86fat32=5Fmk?= =?UTF-8?q?dir=E7=9A=84bug(=E5=9C=A8=E9=9D=9E=E6=A0=B9=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E4=B8=8B=E5=88=9B=E5=BB=BA=E6=96=87=E4=BB=B6=E5=A4=B9=E4=BC=9A?= =?UTF-8?q?=E5=87=BA=E9=94=99)(=E5=9C=A8/dev=E4=B8=AD=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E5=AD=90=E6=96=87=E4=BB=B6=E5=A4=B9=EF=BC=8Copendir=E6=97=B6?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E8=AE=BE=E7=BD=AE=E9=94=99=E8=AF=AF=E7=9A=84?= =?UTF-8?q?bug)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- kernel/filesystem/VFS/VFS.c | 7 ++- kernel/filesystem/fat32/fat32.c | 81 ++++++++++++++++++++----------- kernel/filesystem/fat32/fat_ent.c | 6 ++- kernel/syscall/syscall.c | 17 ++++--- user/apps/shell/cmd.c | 29 ++++++++--- 6 files changed, 98 insertions(+), 45 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f1e84dfb..ac1b53cc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -101,7 +101,8 @@ "stdio.h": "c", "wait_queue.h": "c", "stddef.h": "c", - "spinlock.h": "c" + "spinlock.h": "c", + "stat.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index b1cd0c7f..b60a48b9 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -90,7 +90,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) return parent; struct vfs_dir_entry_t *dentry; - + kdebug("path before walk:%s", path); while (true) { // 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中 @@ -98,7 +98,6 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) while ((*path && *path != '\0') && (*path != '/')) ++path; int tmp_path_len = path - tmp_path; - dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0); memset(dentry, 0, sizeof(struct vfs_dir_entry_t)); // 为目录项的名称分配内存 @@ -108,6 +107,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) memcpy(dentry->name, (void*)tmp_path, tmp_path_len); dentry->name[tmp_path_len] = '\0'; + kdebug("tmp_path_len=%d, dentry->name= %s", tmp_path_len, dentry->name); dentry->name_length = tmp_path_len; if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL) @@ -215,11 +215,13 @@ uint64_t sys_mkdir(struct pt_regs *regs) else strncpy(buf, path, last_slash); buf[last_slash + 1] = '\0'; + kdebug("to walk: %s", buf); // 查找父目录 struct vfs_dir_entry_t *parent_dir = vfs_path_walk(buf, 0); if (parent_dir == NULL) { + kwarn("parent dir is NULL."); kfree(buf); return -ENOENT; } @@ -230,6 +232,7 @@ uint64_t sys_mkdir(struct pt_regs *regs) { // 目录中已有对应的文件夹 kwarn("Dir '%s' aleardy exists.", path); + kdebug("name = %s", vfs_path_walk((const char *)path, 0)->name) return -EEXIST; } diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index 24390908..f545fcf5 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/kernel/filesystem/fat32/fat32.c @@ -139,6 +139,8 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru if (js >= dest_dentry->name_length) // 找到需要的目录项,返回 { + kdebug("found target long name."); + goto find_lookup_success; } @@ -149,6 +151,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru js = 0; for (int x = 0; x < 8; ++x) { + kdebug("no long name, comparing short name"); // kdebug("value = %#02x", tmp_dEntry->DIR_Name[x]); switch (tmp_dEntry->DIR_Name[x]) { @@ -214,11 +217,16 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru break; default: - ++js; + // ++js; + goto continue_cmp_fail; break; } } - + if (js > dest_dentry->name_length) + { + kdebug("js > namelen"); + goto continue_cmp_fail; + } // 若短目录项为文件,则匹配扩展名 if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY)) { @@ -269,6 +277,11 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru } } } + if (js > dest_dentry->name_length) + { + kdebug("js > namelen"); + goto continue_cmp_fail; + } goto find_lookup_success; continue_cmp_fail:; } @@ -762,13 +775,13 @@ long fat32_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *po break; if (next_clus >= 0x0ffffff8) // 已经到达了最后一个簇,需要分配新簇 { - if(fat32_alloc_clusters(file_ptr->dEntry->dir_inode, &next_clus, 1) != 0) + if (fat32_alloc_clusters(file_ptr->dEntry->dir_inode, &next_clus, 1) != 0) { - // 没有空闲簇 + // 没有空闲簇 kfree(tmp_buffer); return -ENOSPC; } - + cluster = next_clus; // 切换当前簇 flags = 1; // 标记当前簇是新分配的簇 } @@ -892,7 +905,29 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ uint64_t tmp_parent_dentry_clus = 0; // 寻找空闲目录项 struct fat32_Directory_t *empty_fat32_dentry = fat32_find_empty_dentry(parent_inode, cnt_longname + 1, 0, &tmp_dentry_sector, &tmp_parent_dentry_clus, &tmp_dentry_clus_buf_addr); - kdebug("found empty dentry"); + kdebug("found empty dentry, cnt_longname=%ld", cnt_longname); + + // ====== 初始化inode ======= + struct vfs_index_node_t *inode = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); + memset(inode, 0, sizeof(struct vfs_index_node_t)); + inode->attribute = VFS_ATTR_DIR; + inode->blocks = fsbi->sec_per_clus; + inode->file_ops = &fat32_file_ops; + inode->file_size = fsbi->bytes_per_clus; + inode->inode_ops = &fat32_inode_ops; + inode->sb = parent_inode->sb; + + // ===== 初始化inode的文件系统私有信息 ==== + + inode->private_inode_info = (fat32_inode_info_t *)kmalloc(sizeof(fat32_inode_info_t), 0); + memset(inode->private_inode_info, 0, sizeof(fat32_inode_info_t)); + fat32_inode_info_t *p = (fat32_inode_info_t *)inode->private_inode_info; + p->first_clus = 0; + p->dEntry_location_clus = tmp_parent_dentry_clus; + p->dEntry_location_clus_offset = empty_fat32_dentry - (struct fat32_Directory_t *)tmp_dentry_clus_buf_addr; + kdebug(" p->dEntry_location_clus_offset=%d", p->dEntry_location_clus_offset); + // todo: 填写完全fat32_inode_info的信息 + // ====== 为新的文件夹分配一个簇 ======= // uint32_t new_dir_clus = fat32_find_available_cluster(fsbi); // kdebug("new_dir_clus=%d", new_dir_clus); @@ -900,12 +935,14 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ // ====== 为新的文件夹分配一个簇 ======= uint32_t new_dir_clus; - if (fat32_alloc_clusters(parent_inode, &new_dir_clus, 1) != 0) + if (fat32_alloc_clusters(inode, &new_dir_clus, 1) != 0) { retval = -ENOSPC; goto fail; } + kdebug("new dir clus=%ld", new_dir_clus); + // ====== 填写短目录项 memset(empty_fat32_dentry, 0, sizeof(struct fat32_Directory_t)); { @@ -938,9 +975,10 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ // ======== 填写长目录项 uint32_t current_name_index = 0; - struct fat32_LongDirectory_t *Ldentry = (struct fat32_LongDirectory_t *)(empty_fat32_dentry - 1); - for (int i = 1; i <= cnt_longname; ++i, --Ldentry) + struct fat32_LongDirectory_t *Ldentry = (struct fat32_LongDirectory_t *)(empty_fat32_dentry); + for (int i = 1; i <= cnt_longname; ++i) { + --Ldentry; Ldentry->LDIR_Ord = i; for (int j = 0; j < 5; ++j, ++current_name_index) @@ -969,13 +1007,16 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ Ldentry->LDIR_Type = 0; Ldentry->LDIR_Chksum = short_dentry_ChkSum; } + // 最后一个长目录项的ord要|=0x40 - Ldentry->LDIR_Ord = 0xe5 | 0x40; + Ldentry->LDIR_Ord |= 0x40; // ====== 将目录项写回磁盘 + kdebug("tmp_dentry_sector=%ld", tmp_dentry_sector); ahci_operation.transfer(AHCI_CMD_WRITE_DMA_EXT, tmp_dentry_sector, fsbi->sec_per_clus, tmp_dentry_clus_buf_addr, fsbi->ahci_ctrl_num, fsbi->ahci_port_num); // ====== 初始化新的文件夹的目录项 ===== { + kdebug("to create dot and dot dot."); void *buf = kmalloc(fsbi->bytes_per_clus, 0); struct fat32_Directory_t *new_dir_dentries = (struct fat32_Directory_t *)buf; memset((void *)new_dir_dentries, 0, fsbi->bytes_per_clus); @@ -1004,31 +1045,15 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ // 写入磁盘 uint64_t sector = fsbi->first_data_sector + (new_dir_clus - 2) * fsbi->sec_per_clus; + kdebug("add dot and dot dot: sector=%ld", sector); ahci_operation.transfer(AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)buf, fsbi->ahci_ctrl_num, fsbi->ahci_port_num); } - // ===== 初始化inode ==== - - struct vfs_index_node_t *finode = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); - memset(finode, 0, sizeof(struct vfs_index_node_t)); - finode->attribute = VFS_ATTR_DIR; - finode->blocks = fsbi->sec_per_clus; - finode->file_ops = &fat32_file_ops; - finode->file_size = fsbi->bytes_per_clus; - finode->inode_ops = &fat32_inode_ops; - finode->sb = parent_inode->sb; - finode->private_inode_info = (fat32_inode_info_t *)kmalloc(sizeof(fat32_inode_info_t), 0); - memset(finode->private_inode_info, 0, sizeof(fat32_inode_info_t)); - fat32_inode_info_t *p = (fat32_inode_info_t *)finode->private_inode_info; - p->first_clus = new_dir_clus; - p->dEntry_location_clus = tmp_parent_dentry_clus; - p->dEntry_location_clus_offset = empty_fat32_dentry - (struct fat32_Directory_t *)tmp_dentry_clus_buf_addr; - // todo: 填写fat32_inode_info的信息 // 初始化dentry信息 list_init(&dEntry->child_node_list); list_init(&dEntry->subdirs_list); dEntry->dir_ops = &fat32_dEntry_ops; - dEntry->dir_inode = finode; + dEntry->dir_inode = inode; // 注意:parent字段需要在调用函数的地方进行设置 // 注意:需要将当前dentry加入父目录的subdirs_list diff --git a/kernel/filesystem/fat32/fat_ent.c b/kernel/filesystem/fat32/fat_ent.c index a0e85200..b90c4474 100644 --- a/kernel/filesystem/fat32/fat_ent.c +++ b/kernel/filesystem/fat32/fat_ent.c @@ -41,6 +41,7 @@ int fat32_alloc_clusters(struct vfs_index_node_t *inode, uint32_t *clusters, int // 找到空闲簇 if ((buf[j] & 0x0fffffff) == 0) { + kdebug("clus[%d] = %d", clus_idx, i * ent_per_sec + j); clusters[clus_idx] = i * ent_per_sec + j; ++clus_idx; } @@ -68,10 +69,11 @@ done:; // todo: 跳转到文件当前的最后一个簇 idx = 0; int tmp_clus = finode->first_clus; + cluster = tmp_clus; while (true) { tmp_clus = fat32_read_FAT_entry(fsbi, cluster); - if (tmp_clus < 0x0ffffff7) + if (tmp_clus <= 0x0ffffff7) cluster = tmp_clus; else break; @@ -81,6 +83,7 @@ done:; // 写入fat表 for (int i = idx; i < num_clusters; ++i) { + kdebug("write cluster i=%d : cluster=%d, value= %d", i, cluster, clusters[i]); fat32_write_FAT_entry(fsbi, cluster, clusters[i]); cluster = clusters[i]; } @@ -90,6 +93,7 @@ done:; } else // 出现错误 { + kwarn("err in alloc clusters"); if (clus_idx < num_clusters) fat32_free_clusters(inode, clusters[0]); return retval; diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 588a362c..e435e2c2 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -156,10 +156,13 @@ uint64_t sys_open(struct pt_regs *regs) // 暂时遇到设备文件的话,就将其first clus设置为特定值 if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/') { - // 对于fat32文件系统上面的设备文件,设置其起始扇区 - ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000; - dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode); - dentry->dir_inode->attribute |= VFS_ATTR_DEVICE; + if (dentry->dir_inode->attribute & VFS_ATTR_FILE) + { + // 对于fat32文件系统上面的设备文件,设置其起始扇区 + ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000; + dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode); + dentry->dir_inode->attribute |= VFS_ATTR_DEVICE; + } } // 创建文件描述符 @@ -483,7 +486,7 @@ uint64_t sys_reboot(struct pt_regs *regs) uint64_t sys_chdir(struct pt_regs *regs) { char *dest_path = (char *)regs->r8; - // kdebug("dest_path=%s", dest_path); + kdebug("dest_path=%s", dest_path); // 检查目标路径是否为NULL if (dest_path == NULL) return -EFAULT; @@ -517,14 +520,14 @@ uint64_t sys_chdir(struct pt_regs *regs) } else strncpy(path, dest_path, dest_path_len + 1); - + kdebug("chdir: path = %s", path); struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0); kfree(path); if (dentry == NULL) return -ENOENT; - + kdebug("dentry->name=%s, namelen=%d", dentry->name, dentry->name_length); // 目标不是目录 if (dentry->dir_inode->attribute != VFS_ATTR_DIR) return -ENOTDIR; diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index 35800091..6e3c9314 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -10,7 +10,7 @@ #include #include #include - +#include #include "cmd_help.h" // 当前工作目录(在main_loop中初始化) @@ -191,7 +191,7 @@ int shell_cmd_cd(int argc, char **argv) } int new_len = current_dir_len + dest_len - dest_offset; - + if (new_len >= SHELL_CWD_MAX_SIZE - 1) { printf("ERROR: Path too long!\n"); @@ -211,7 +211,7 @@ int shell_cmd_cd(int argc, char **argv) { free(shell_current_path); // printf("new_path=%s, newlen= %d\n", new_path, new_len); - new_path[new_len+1] = '\0'; + new_path[new_len + 1] = '\0'; shell_current_path = new_path; goto done; } @@ -351,7 +351,25 @@ int shell_cmd_rm(int argc, char **argv) {} * @return int */ // todo: -int shell_cmd_mkdir(int argc, char **argv) {} +int shell_cmd_mkdir(int argc, char **argv) +{ + int result_path_len = -1; + const char *full_path = NULL; + if (argv[1][0] == '/') + full_path = argv[1]; + else + { + full_path = get_target_filepath(argv[1], &result_path_len); + } + printf("mkdir: full_path = %s\n", full_path); + int retval = mkdir(full_path, 0); + + if (result_path_len != -1) + { + free((void *)full_path); + } + return retval; +} /** * @brief 删除文件夹的命令 @@ -407,13 +425,12 @@ int shell_cmd_about(int argc, char **argv) char **aav; unsigned char input_buffer[INPUT_BUFFER_SIZE] = {0}; - + strcpy(input_buffer, "exec /about.elf\0"); parse_command(input_buffer, &aac, &aav); shell_cmd_exec(aac, aav); - } /**