瀏覽代碼

:new: fat32_create

fslongjin 2 年之前
父節點
當前提交
8c8352e748

+ 2 - 3
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);

+ 4 - 3
kernel/filesystem/VFS/VFS.h

@@ -12,6 +12,7 @@
 #pragma once
 
 #include <common/glib.h>
+#include <common/fcntl.h>
 
 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 父目录项(在这个目录下查找)

+ 95 - 14
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
 

+ 8 - 3
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();
 

+ 21 - 4
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;

+ 63 - 4
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设置为特定值

+ 14 - 6
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;
 }
 

+ 1 - 1
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);
 }