diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index b60a48b9..8da1218b 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -105,7 +105,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) // 貌似这里不需要memset,因为空间会被覆盖 // memset(dentry->name, 0, tmp_path_len+1); - memcpy(dentry->name, (void*)tmp_path, tmp_path_len); + 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; @@ -232,8 +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; + kdebug("name = %s", vfs_path_walk((const char *)path, 0)->name) return -EEXIST; } struct vfs_dir_entry_t *subdir_dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0); diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 815d7e0f..be43a0d4 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -12,6 +12,7 @@ #pragma once #include +#include struct vfs_superblock_t *vfs_root_sb = NULL; @@ -109,11 +110,11 @@ struct vfs_inode_operations_t { /** * @brief 创建新的文件 - * @param inode 要被创建的文件的inode结构体 - * @param parent_dEntry 父目录的dentry + * @param parent_inode 父目录的inode结构体 + * @param dest_dEntry 新文件的dentry * @param mode 创建模式 */ - long (*create)(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *parent_dEntry, int mode); + long (*create)(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode); /** * @brief 在文件系统中查找指定的目录项 * @param parent_inode 父目录项(在这个目录下查找) diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index 743fbc89..18948fae 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/kernel/filesystem/fat32/fat32.c @@ -862,16 +862,101 @@ struct vfs_file_operations_t fat32_file_ops = /** * @brief 创建新的文件 - * @param inode 要被创建的文件的inode结构体 - * @param parent_dEntry 父目录的dentry + * @param parent_inode 父目录的inode结构体 + * @param dest_dEntry 新文件的dentry * @param mode 创建模式 */ -long fat32_create(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *parent_dEntry, int mode) +long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode) { // 文件系统超级块信息 - fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_dEntry->dir_inode->sb->private_sb_info; + fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info; // 父目录项的inode的私有信息 - struct fat32_inode_info_t *parent_inode_info = (struct fat32_inode_info_t *)parent_dEntry->dir_inode->private_inode_info; + struct fat32_inode_info_t *parent_inode_info = (struct fat32_inode_info_t *)parent_inode->private_inode_info; + + int64_t retval = 0; + + kdebug("dest_dEntry->name=%s",dest_dEntry->name); + // ======== 检验名称的合法性 + retval = fat32_check_name_available(dest_dEntry->name, dest_dEntry->name_length, 0); + kdebug("dest_dEntry->name=%s",dest_dEntry->name); + if (retval != 0) + return retval; + + if (dest_dEntry->dir_inode != NULL) + return -EEXIST; + + struct vfs_index_node_t *inode = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); + memset((void *)inode, 0, sizeof(struct vfs_index_node_t)); + dest_dEntry->dir_inode = inode; + dest_dEntry->dir_ops = &fat32_dEntry_ops; + + struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)kmalloc(sizeof(struct fat32_inode_info_t), 0); + memset((void *)finode, 0, sizeof(struct fat32_inode_info_t)); + inode->attribute = VFS_ATTR_FILE; + inode->file_ops = &fat32_file_ops; + inode->file_size = 0; + inode->sb = parent_inode->sb; + inode->inode_ops = &fat32_inode_ops; + inode->private_inode_info = (void *)finode; + inode->blocks = fsbi->sec_per_clus; + + // 计算总共需要多少个目录项 + uint32_t cnt_longname = (dest_dEntry->name_length + 25) / 26; + // 默认都是创建长目录项来存储 + if (cnt_longname == 0) + cnt_longname = 1; + + // 空闲dentry所在的扇区号 + uint32_t tmp_dentry_sector = 0; + // 空闲dentry所在的缓冲区的基地址 + uint64_t tmp_dentry_clus_buf_addr = 0; + 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, cnt_longname=%ld", cnt_longname); + + finode->first_clus = 0; + finode->dEntry_location_clus = tmp_parent_dentry_clus; + finode->dEntry_location_clus_offset = empty_fat32_dentry - (struct fat32_Directory_t *)tmp_dentry_clus_buf_addr; + + // ====== 为新的文件分配一个簇 ======= + uint32_t new_dir_clus; + if (fat32_alloc_clusters(inode, &new_dir_clus, 1) != 0) + { + retval = -ENOSPC; + goto fail; + } + + kdebug("new dir clus=%ld", new_dir_clus); + kdebug("dest_dEntry->name=%s",dest_dEntry->name); + // ====== 填写短目录项 + fat32_fill_shortname(dest_dEntry, empty_fat32_dentry, new_dir_clus); + kdebug("dest_dEntry->name=%s",dest_dEntry->name); + + // 计算校验和 + uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name); + + kdebug("dest_dEntry->name=%s",dest_dEntry->name); + // ======== 填写长目录项 + fat32_fill_longname(dest_dEntry, (struct fat32_LongDirectory_t *)(empty_fat32_dentry - 1), short_dentry_ChkSum, cnt_longname); + + // ====== 将目录项写回磁盘 + 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); + + // 注意:parent字段需要在调用函数的地方进行设置 + + // 释放在find empty dentry中动态申请的缓冲区 + kfree((void *)tmp_dentry_clus_buf_addr); + return 0; +fail:; + // 释放在find empty dentry中动态申请的缓冲区 + kfree((void *)tmp_dentry_clus_buf_addr); + dest_dEntry->dir_inode = NULL; + dest_dEntry->dir_ops = NULL; + kfree(finode); + kfree(inode); + return retval; } /** @@ -886,9 +971,9 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ // 文件系统超级块信息 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info; - // 父目录项的inode + // 父目录项的inode私有信息 struct fat32_inode_info_t *parent_inode_info = (struct fat32_inode_info_t *)parent_inode->private_inode_info; - // ======== todo:检验名称的合法性 + // ======== 检验名称的合法性 retval = fat32_check_name_available(dEntry->name, dEntry->name_length, 0); if (retval != 0) return retval; @@ -915,7 +1000,7 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ 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->file_size = 0; inode->inode_ops = &fat32_inode_ops; inode->sb = parent_inode->sb; @@ -930,14 +1015,12 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ kdebug(" p->dEntry_location_clus_offset=%d", p->dEntry_location_clus_offset); // 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 = inode; - // ====== 为新的文件夹分配一个簇 ======= uint32_t new_dir_clus; if (fat32_alloc_clusters(inode, &new_dir_clus, 1) != 0) @@ -952,10 +1035,10 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ fat32_fill_shortname(dEntry, empty_fat32_dentry, new_dir_clus); // 计算校验和 - uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name); + uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name); // ======== 填写长目录项 - fat32_fill_longname(dEntry, (struct fat32_LongDirectory_t * )(empty_fat32_dentry-1), short_dentry_ChkSum, cnt_longname); + fat32_fill_longname(dEntry, (struct fat32_LongDirectory_t *)(empty_fat32_dentry - 1), short_dentry_ChkSum, cnt_longname); // ====== 将目录项写回磁盘 kdebug("tmp_dentry_sector=%ld", tmp_dentry_sector); @@ -995,8 +1078,6 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ ahci_operation.transfer(AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)buf, fsbi->ahci_ctrl_num, fsbi->ahci_port_num); } - - // 注意:parent字段需要在调用函数的地方进行设置 // 注意:需要将当前dentry加入父目录的subdirs_list diff --git a/kernel/filesystem/fat32/fat32.h b/kernel/filesystem/fat32/fat32.h index 326c183c..ec592d7c 100644 --- a/kernel/filesystem/fat32/fat32.h +++ b/kernel/filesystem/fat32/fat32.h @@ -155,7 +155,7 @@ typedef struct fat32_partition_info_t fat32_sb_info_t; struct fat32_inode_info_t { - uint32_t first_clus; // 文件的起始簇号 + uint32_t first_clus; // 文件的起始簇号 uint64_t dEntry_location_clus; // fat entry的起始簇号 dEntry struct in cluster (0 is root, 1 is invalid) uint64_t dEntry_location_clus_offset; // fat entry在起始簇中的偏移量(是第几个entry) dEntry struct offset in cluster @@ -176,7 +176,6 @@ typedef struct fat32_inode_info_t fat32_inode_info_t; */ struct vfs_superblock_t *fat32_register_partition(uint8_t ahci_ctrl_num, uint8_t ahci_port_num, uint8_t part_num); - /** * @brief 创建fat32文件系统的超级块 * @@ -187,7 +186,13 @@ struct vfs_superblock_t *fat32_register_partition(uint8_t ahci_ctrl_num, uint8_t */ struct vfs_superblock_t *fat32_read_superblock(void *DPTE, uint8_t DPT_type, void *buf, int8_t ahci_ctrl_num, int8_t ahci_port_num, int8_t part_num); -long fat32_create(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dentry, int mode); +/** + * @brief 创建新的文件 + * @param parent_inode 父目录的inode结构体 + * @param dest_dEntry 新文件的dentry + * @param mode 创建模式 + */ +long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode); void fat32_init(); diff --git a/kernel/filesystem/fat32/fat_ent.c b/kernel/filesystem/fat32/fat_ent.c index 8696c8dd..53dd776c 100644 --- a/kernel/filesystem/fat32/fat_ent.c +++ b/kernel/filesystem/fat32/fat_ent.c @@ -328,12 +328,28 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory } // 不满的部分使用0x20填充 - while (tmp_index < 11) + while (tmp_index < 8) { // kdebug("tmp index = %d", tmp_index); - dEntry->name[tmp_index] = 0x20; + target->DIR_Name[tmp_index] = 0x20; ++tmp_index; } + if (dEntry->dir_inode->attribute & VFS_ATTR_DIR) + { + while (tmp_index < 11) + { + // kdebug("tmp index = %d", tmp_index); + target->DIR_Name[tmp_index] = 0x20; + ++tmp_index; + } + } + else + { + for(int j = 8;j<11;++j) + { + target->DIR_Name[j] = 'a'; + } + } } struct vfs_index_node_t *inode = dEntry->dir_inode; @@ -350,7 +366,7 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory /** * @brief 填充长目录项的函数 - * + * * @param dEntry 目标dentry * @param target 起始长目录项 * @param checksum 短目录项的校验和 @@ -359,7 +375,8 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirectory_t *target, uint8_t checksum, uint32_t cnt_longname) { uint32_t current_name_index = 0; - struct fat32_LongDirectory_t *Ldentry = (struct fat32_LongDirectory_t *)(target+1); + struct fat32_LongDirectory_t *Ldentry = (struct fat32_LongDirectory_t *)(target + 1); + // kdebug("filling long name, name=%s, namelen=%d", dEntry->name, dEntry->name_length); for (int i = 1; i <= cnt_longname; ++i) { --Ldentry; diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index e435e2c2..bfcc6565 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -108,7 +108,6 @@ ul sys_put_string(struct pt_regs *regs) uint64_t sys_open(struct pt_regs *regs) { - char *filename = (char *)(regs->r8); int flags = (int)(regs->r9); // kdebug("filename=%s", filename); @@ -131,6 +130,12 @@ uint64_t sys_open(struct pt_regs *regs) memset(path, 0, path_len); strncpy_from_user(path, filename, path_len); + // 去除末尾的 '/' + if (path_len >= 2 && path[path_len - 2] == '/') + { + path[path_len - 2] = '\0'; + --path_len; + } // 寻找文件 struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0); @@ -139,7 +144,61 @@ uint64_t sys_open(struct pt_regs *regs) // printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size); // else // printk_color(ORANGE, BLACK, "Can`t find file\n"); + kdebug("flags=%#018lx", flags); + if (dentry == NULL && flags & O_CREAT) + { + // 先找到倒数第二级目录 + int tmp_index = -1; + for (int i = path_len - 1; i >= 0; --i) + { + if (path[i] == '/') + { + tmp_index = i; + break; + } + } + struct vfs_dir_entry_t *parent_dentry = NULL; + kdebug("tmp_index=%d", tmp_index); + if (tmp_index > 0) + { + + path[tmp_index] = '\0'; + dentry = vfs_path_walk(path, 0); + if (dentry == NULL) + { + kfree(path); + return -ENOENT; + } + parent_dentry = dentry; + } + else + parent_dentry = vfs_root_sb->root; + + // 创建新的文件 + dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0); + memset(dentry, 0, sizeof(struct vfs_dir_entry_t)); + + dentry->name_length = path_len - tmp_index - 1; + dentry->name = (char *)kmalloc(dentry->name_length, 0); + memset(dentry->name, 0, dentry->name_length); + strncpy(dentry->name, path + tmp_index + 1, dentry->name_length); + kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length) + dentry->parent = parent_dentry; + uint64_t retval = parent_dentry->dir_inode->inode_ops->create(parent_dentry->dir_inode, dentry, 0); + if (retval != 0) + { + kfree(dentry->name); + kfree(dentry); + kfree(path); + return retval; + } + + list_init(&dentry->child_node_list); + list_init(&dentry->subdirs_list); + list_add(&parent_dentry->subdirs_list, &dentry->child_node_list); + kdebug("created."); + } kfree(path); if (dentry == NULL) return -ENOENT; @@ -148,9 +207,9 @@ uint64_t sys_open(struct pt_regs *regs) if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_ATTR_DIR)) return -ENOTDIR; - // 要找的目标是文件夹 - if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_ATTR_DIR) - return -EISDIR; + // // 要找的目标是文件夹 + // if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_ATTR_DIR) + // return -EISDIR; // todo: 引入devfs后删除这段代码 // 暂时遇到设备文件的话,就将其first clus设置为特定值 diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index 6e3c9314..ecf896ec 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -331,7 +331,17 @@ int shell_cmd_cat(int argc, char **argv) * @return int */ // todo: -int shell_cmd_touch(int argc, char **argv) {} +int shell_cmd_touch(int argc, char **argv) +{ + int path_len = 0; + char *file_path = get_target_filepath(argv[1], &path_len); + + // 打开文件 + int fd = open(file_path, O_CREAT); + close(fd); + if (argv != NULL) + free(argv); +} /** * @brief 删除命令 @@ -350,7 +360,6 @@ int shell_cmd_rm(int argc, char **argv) {} * @param argv * @return int */ -// todo: int shell_cmd_mkdir(int argc, char **argv) { int result_path_len = -1; @@ -364,10 +373,9 @@ int shell_cmd_mkdir(int argc, char **argv) printf("mkdir: full_path = %s\n", full_path); int retval = mkdir(full_path, 0); - if (result_path_len != -1) - { - free((void *)full_path); - } + if (argv != NULL) + free(argv); + return retval; } diff --git a/user/libs/libc/fcntl.c b/user/libs/libc/fcntl.c index 1e7630e7..98554838 100644 --- a/user/libs/libc/fcntl.c +++ b/user/libs/libc/fcntl.c @@ -11,5 +11,5 @@ */ int open(const char *path, int options, ...) { - return syscall_invoke(SYS_OPEN, (uint64_t)path, 0, 0, 0, 0, 0, 0, 0); + return syscall_invoke(SYS_OPEN, (uint64_t)path, options, 0, 0, 0, 0, 0, 0); } \ No newline at end of file