mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
new: FAT32删除文件的功能 (#73)
* new: 将sys_rmdir更改为sys_unlink,.且完成删除文件操作的vfs部分 * new: fat32删除文件 *bugfix: 解决创建文件时的bug
This commit is contained in:
parent
8e3f5674f8
commit
31b7b49d8c
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -147,7 +147,8 @@
|
||||
"compiler_attributes.h": "c",
|
||||
"timer.h": "c",
|
||||
"hid.h": "c",
|
||||
"cfs.h": "c"
|
||||
"cfs.h": "c",
|
||||
"fat32.h": "c"
|
||||
},
|
||||
"C_Cpp.errorSquiggles": "Enabled",
|
||||
"esbonio.sphinx.confDir": ""
|
||||
|
@ -160,7 +160,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
|
||||
char *tmpname = kzalloc(tmp_path_len + 1, 0);
|
||||
strncpy(tmpname, tmp_path, tmp_path_len);
|
||||
tmpname[tmp_path_len] = '\0';
|
||||
|
||||
// kdebug("tmpname=%s", tmpname);
|
||||
dentry = vfs_search_dentry_list(parent, tmpname);
|
||||
|
||||
kfree(tmpname);
|
||||
@ -179,7 +179,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
|
||||
if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL)
|
||||
{
|
||||
// 搜索失败
|
||||
// kerror("cannot find the file/dir : %s", dentry->name);
|
||||
// kwarn("cannot find the file/dir : %s", dentry->name);
|
||||
kfree(dentry->name);
|
||||
kfree(dentry);
|
||||
return NULL;
|
||||
@ -429,9 +429,10 @@ uint64_t do_open(const char *filename, int flags)
|
||||
// 创建新的文件
|
||||
dentry = vfs_alloc_dentry(path_len - tmp_index);
|
||||
|
||||
dentry->name_length = path_len - tmp_index - 1;
|
||||
dentry->name_length = path_len - tmp_index - 2;
|
||||
|
||||
// kdebug("to create new file:%s namelen=%d", dentry->name, 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;
|
||||
|
||||
// 对父目录项加锁
|
||||
@ -639,7 +640,6 @@ int64_t vfs_rmdir(const char *path, bool from_userland)
|
||||
if (dentry == NULL)
|
||||
{
|
||||
retval = -ENOENT;
|
||||
kdebug("noent");
|
||||
goto out0;
|
||||
}
|
||||
|
||||
@ -776,14 +776,14 @@ int do_unlink_at(int dfd, const char *pathname, bool from_userland)
|
||||
else if (pathname[0] != '/')
|
||||
return -EINVAL;
|
||||
|
||||
char *buf = (char *)kzalloc(last_slash + 2, 0);
|
||||
char *buf = (char *)kzalloc(last_slash + 1, 0);
|
||||
|
||||
// 拷贝字符串(不包含要被创建的部分)
|
||||
// 拷贝字符串
|
||||
if (from_userland)
|
||||
strncpy_from_user(buf, pathname, last_slash);
|
||||
else
|
||||
strncpy(buf, pathname, last_slash);
|
||||
buf[last_slash + 1] = '\0';
|
||||
buf[last_slash] = '\0';
|
||||
|
||||
struct vfs_dir_entry_t *dentry = vfs_path_walk(buf, 0);
|
||||
kfree(buf);
|
||||
@ -797,13 +797,20 @@ int do_unlink_at(int dfd, const char *pathname, bool from_userland)
|
||||
struct vfs_index_node_t *p_inode = dentry->parent->dir_inode;
|
||||
// 对父inode加锁
|
||||
spin_lock(&p_inode->lockref.lock);
|
||||
retval = vfs_unlink(NULL, dentry->parent->dir_inode, dentry, NULL);
|
||||
|
||||
spin_lock(&dentry->lockref.lock);
|
||||
retval = vfs_dentry_put(dentry);
|
||||
retval = vfs_unlink(NULL, dentry->parent->dir_inode, dentry, NULL);
|
||||
if (unlikely(retval != 0))
|
||||
{
|
||||
// kdebug("retval=%d", retval);
|
||||
spin_unlock(&dentry->lockref.lock);
|
||||
spin_unlock(&p_inode->lockref.lock);
|
||||
goto out;
|
||||
}
|
||||
// kdebug("vfs_dentry_put=%d", retval);
|
||||
spin_unlock(&dentry->lockref.lock);
|
||||
spin_unlock(&p_inode->lockref.lock);
|
||||
|
||||
if (IS_ERR(retval))
|
||||
if (IS_ERR_VALUE(retval))
|
||||
kwarn("In do_unlink_at: dentry put failed; retval=%d", retval);
|
||||
else
|
||||
retval = 0;
|
||||
@ -822,14 +829,14 @@ out:;
|
||||
uint64_t sys_unlink_at(struct pt_regs *regs)
|
||||
{
|
||||
int dfd = regs->r8;
|
||||
const char *pathname = regs->r9;
|
||||
const char *pathname = (const char *)regs->r9;
|
||||
int flag = regs->r10;
|
||||
bool from_user = SYSCALL_FROM_USER(regs) ? true : false;
|
||||
if ((flag & (~AT_REMOVEDIR)) != 0)
|
||||
return -EINVAL;
|
||||
if (flag & AT_REMOVEDIR)
|
||||
return vfs_rmdir(pathname, from_user);
|
||||
|
||||
// kdebug("to do_unlink_at, path=%s", pathname);
|
||||
return do_unlink_at(dfd, pathname, from_user);
|
||||
}
|
||||
|
||||
|
@ -89,9 +89,12 @@ int vfs_dentry_put(struct vfs_dir_entry_t *dentry)
|
||||
}
|
||||
else // 是文件或设备
|
||||
{
|
||||
kdebug("to put dentry: file: %s", dentry->name);
|
||||
list_del(&dentry->child_node_list); // 从父dentry中删除
|
||||
// 释放inode
|
||||
spin_lock(&dentry->dir_inode->lockref.lock);
|
||||
retval = vfs_free_inode(dentry->dir_inode);
|
||||
kdebug("retval=%d", retval);
|
||||
if (retval > 0) // 还有其他的dentry引用着这个inode
|
||||
spin_unlock(&dentry->dir_inode->lockref.lock);
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
#include "fat32.h"
|
||||
#include "fat_ent.h"
|
||||
#include "internal.h"
|
||||
#include <common/errno.h>
|
||||
#include <common/kprint.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <common/stdio.h>
|
||||
#include <common/string.h>
|
||||
#include <driver/disk/ahci/ahci.h>
|
||||
#include <filesystem/MBR.h>
|
||||
#include <mm/slab.h>
|
||||
@ -12,9 +14,14 @@ struct vfs_super_block_operations_t fat32_sb_ops;
|
||||
struct vfs_dir_entry_operations_t fat32_dEntry_ops;
|
||||
struct vfs_file_operations_t fat32_file_ops;
|
||||
struct vfs_inode_operations_t fat32_inode_ops;
|
||||
|
||||
extern struct blk_gendisk ahci_gendisk0;
|
||||
|
||||
static unsigned int vfat_striptail_len(unsigned int len, const char *name);
|
||||
static int vfat_find(struct vfs_index_node_t *dir, const char *name, struct fat32_slot_info *slot_info);
|
||||
static int __fat32_search_long_short(struct vfs_index_node_t *parent_inode, const char *name, int name_len,
|
||||
struct fat32_slot_info *sinfo);
|
||||
static int fat32_detach_inode(struct vfs_index_node_t *inode);
|
||||
|
||||
/**
|
||||
* @brief 注册指定磁盘上的指定分区的fat32文件系统
|
||||
*
|
||||
@ -46,17 +53,9 @@ static uint8_t fat32_ChkSum(uint8_t *name)
|
||||
return chksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在父目录中寻找指定的目录项
|
||||
*
|
||||
* @param parent_inode 父目录项的inode
|
||||
* @param dest_dentry 搜索目标目录项
|
||||
* @return struct vfs_dir_entry_t* 目标目录项
|
||||
*/
|
||||
struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dentry)
|
||||
static int __fat32_search_long_short(struct vfs_index_node_t *parent_inode, const char *name, int name_len,
|
||||
struct fat32_slot_info *sinfo)
|
||||
{
|
||||
int errcode = 0;
|
||||
|
||||
struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
|
||||
fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
|
||||
struct block_device *blk = parent_inode->sb->blk_device;
|
||||
@ -67,12 +66,13 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
uint32_t cluster = finode->first_clus;
|
||||
|
||||
struct fat32_Directory_t *tmp_dEntry = NULL;
|
||||
int cnt_long_dir = 0; // 最终结果中,长目录项的数量
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
// 计算父目录项的起始LBA扇区号
|
||||
uint64_t sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus;
|
||||
uint64_t sector = __fat32_calculate_LBA(fsbi->first_data_sector, fsbi->sec_per_clus, cluster);
|
||||
// kdebug("fat32_part_info[part_id].bootsector.BPB_SecPerClus=%d",fat32_part_info[part_id].bootsector.BPB_SecPerClus);
|
||||
// kdebug("sector=%d",sector);
|
||||
|
||||
@ -81,7 +81,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
|
||||
tmp_dEntry = (struct fat32_Directory_t *)buf;
|
||||
|
||||
// 查找短目录项
|
||||
// 查找每个文件的短目录项
|
||||
for (int i = 0; i < fsbi->bytes_per_clus; i += 32, ++tmp_dEntry)
|
||||
{
|
||||
// 跳过长目录项
|
||||
@ -94,7 +94,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
// kdebug("short name [%d] %s\n 33333==[%#02x]", i / 32, tmp_dEntry->DIR_Name, tmp_dEntry->DIR_Name[3]);
|
||||
// 找到长目录项,位于短目录项之前
|
||||
struct fat32_LongDirectory_t *tmp_ldEntry = (struct fat32_LongDirectory_t *)tmp_dEntry - 1;
|
||||
|
||||
cnt_long_dir = 0;
|
||||
int js = 0;
|
||||
// 遍历每个长目录项
|
||||
while (tmp_ldEntry->LDIR_Attr == ATTR_LONG_NAME && tmp_ldEntry->LDIR_Ord != 0xe5)
|
||||
@ -102,41 +102,38 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
// 比较name1
|
||||
for (int x = 0; x < 5; ++x)
|
||||
{
|
||||
if (js > dest_dentry->name_length && tmp_ldEntry->LDIR_Name1[x] == 0xffff)
|
||||
if (js >= name_len && (tmp_ldEntry->LDIR_Name1[x] == 0xffff))
|
||||
continue;
|
||||
else if (js > dest_dentry->name_length ||
|
||||
tmp_ldEntry->LDIR_Name1[x] !=
|
||||
(uint16_t)(dest_dentry->name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
else if (js > name_len ||
|
||||
tmp_ldEntry->LDIR_Name1[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
|
||||
// 比较name2
|
||||
for (int x = 0; x < 6; ++x)
|
||||
{
|
||||
if (js > dest_dentry->name_length && tmp_ldEntry->LDIR_Name2[x] == 0xffff)
|
||||
if (js >= name_len && (tmp_ldEntry->LDIR_Name2[x] == 0xffff))
|
||||
continue;
|
||||
else if (js > dest_dentry->name_length ||
|
||||
tmp_ldEntry->LDIR_Name2[x] !=
|
||||
(uint16_t)(dest_dentry->name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
else if (js > name_len ||
|
||||
tmp_ldEntry->LDIR_Name2[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
|
||||
// 比较name3
|
||||
for (int x = 0; x < 2; ++x)
|
||||
{
|
||||
if (js > dest_dentry->name_length && tmp_ldEntry->LDIR_Name3[x] == 0xffff)
|
||||
if (js >= name_len && (tmp_ldEntry->LDIR_Name3[x] == 0xffff))
|
||||
continue;
|
||||
else if (js > dest_dentry->name_length ||
|
||||
tmp_ldEntry->LDIR_Name3[x] !=
|
||||
(uint16_t)(dest_dentry->name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
else if (js > name_len ||
|
||||
tmp_ldEntry->LDIR_Name3[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
|
||||
if (js >= dest_dentry->name_length) // 找到需要的目录项,返回
|
||||
if (js >= name_len) // 找到需要的目录项,返回
|
||||
{
|
||||
// kdebug("found target long name.");
|
||||
|
||||
goto find_lookup_success;
|
||||
cnt_long_dir = tmp_dEntry - (struct fat32_Directory_t *)tmp_ldEntry;
|
||||
goto success;
|
||||
}
|
||||
|
||||
--tmp_ldEntry; // 检索下一个长目录项
|
||||
@ -153,9 +150,9 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
case ' ':
|
||||
if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY)) // 不是文件夹(是文件)
|
||||
{
|
||||
if (dest_dentry->name[js] == '.')
|
||||
if (name[js] == '.')
|
||||
continue;
|
||||
else if (tmp_dEntry->DIR_Name[x] == dest_dentry->name[js])
|
||||
else if (tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
@ -165,13 +162,12 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
}
|
||||
else // 是文件夹
|
||||
{
|
||||
if (js < dest_dentry->name_length &&
|
||||
tmp_dEntry->DIR_Name[x] == dest_dentry->name[js]) // 当前位正确匹配
|
||||
if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js]) // 当前位正确匹配
|
||||
{
|
||||
++js;
|
||||
break; // 进行下一位的匹配
|
||||
}
|
||||
else if (js == dest_dentry->name_length)
|
||||
else if (js == name_len)
|
||||
continue;
|
||||
else
|
||||
goto continue_cmp_fail;
|
||||
@ -183,7 +179,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
case 'a' ... 'z':
|
||||
if (tmp_dEntry->DIR_NTRes & LOWERCASE_BASE) // 为兼容windows系统,检测DIR_NTRes字段
|
||||
{
|
||||
if (js < dest_dentry->name_length && (tmp_dEntry->DIR_Name[x] + 32 == dest_dentry->name[js]))
|
||||
if (js < name_len && (tmp_dEntry->DIR_Name[x] + 32 == name[js]))
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
@ -193,7 +189,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
}
|
||||
else
|
||||
{
|
||||
if (js < dest_dentry->name_length && tmp_dEntry->DIR_Name[x] == dest_dentry->name[js])
|
||||
if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
@ -203,7 +199,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
}
|
||||
break;
|
||||
case '0' ... '9':
|
||||
if (js < dest_dentry->name_length && tmp_dEntry->DIR_Name[x] == dest_dentry->name[js])
|
||||
if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
@ -218,9 +214,9 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (js > dest_dentry->name_length)
|
||||
if (js > name_len)
|
||||
{
|
||||
kdebug("js > namelen");
|
||||
// kdebug("js > namelen");
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
// 若短目录项为文件,则匹配扩展名
|
||||
@ -236,7 +232,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
case 'a' ... 'z':
|
||||
if (tmp_dEntry->DIR_NTRes & LOWERCASE_EXT) // 为兼容windows系统,检测DIR_NTRes字段
|
||||
{
|
||||
if ((tmp_dEntry->DIR_Name[x] + 32 == dest_dentry->name[js]))
|
||||
if ((tmp_dEntry->DIR_Name[x] + 32 == name[js]))
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
@ -246,7 +242,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmp_dEntry->DIR_Name[x] == dest_dentry->name[js])
|
||||
if (tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
@ -257,7 +253,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
break;
|
||||
case '0' ... '9':
|
||||
case ' ':
|
||||
if (tmp_dEntry->DIR_Name[x] == dest_dentry->name[js])
|
||||
if (tmp_dEntry->DIR_Name[x] == name[js])
|
||||
{
|
||||
++js;
|
||||
break;
|
||||
@ -273,12 +269,13 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
}
|
||||
}
|
||||
}
|
||||
if (js > dest_dentry->name_length)
|
||||
if (js > name_len)
|
||||
{
|
||||
kdebug("js > namelen");
|
||||
// kdebug("js > namelen");
|
||||
goto continue_cmp_fail;
|
||||
}
|
||||
goto find_lookup_success;
|
||||
cnt_long_dir = 0;
|
||||
goto success;
|
||||
continue_cmp_fail:;
|
||||
}
|
||||
|
||||
@ -288,21 +285,53 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru
|
||||
if (cluster >= 0x0ffffff7) // 寻找完父目录的所有簇,都没有找到目标文件名
|
||||
{
|
||||
kfree(buf);
|
||||
return NULL;
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
if(unlikely(tmp_dEntry==NULL))
|
||||
if (unlikely(tmp_dEntry == NULL))
|
||||
{
|
||||
BUG_ON(1);
|
||||
return NULL;
|
||||
kfree(buf);
|
||||
return -ENOENT;
|
||||
}
|
||||
success:;
|
||||
|
||||
// 填充sinfo
|
||||
sinfo->buffer = buf;
|
||||
sinfo->de = tmp_dEntry;
|
||||
sinfo->i_pos = __fat32_calculate_LBA(fsbi->first_data_sector, fsbi->sec_per_clus, cluster);
|
||||
sinfo->num_slots = cnt_long_dir + 1;
|
||||
sinfo->slot_off = tmp_dEntry - (struct fat32_Directory_t *)buf;
|
||||
// kdebug("successfully found:%s", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在父目录中寻找指定的目录项
|
||||
*
|
||||
* @param parent_inode 父目录项的inode
|
||||
* @param dest_dentry 搜索目标目录项
|
||||
* @return struct vfs_dir_entry_t* 目标目录项
|
||||
*/
|
||||
struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dentry)
|
||||
{
|
||||
int errcode = 0;
|
||||
fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
|
||||
struct fat32_inode_info_t *finode = NULL;
|
||||
|
||||
struct fat32_slot_info sinfo = {0};
|
||||
errcode = vfat_find(parent_inode, dest_dentry->name, &sinfo);
|
||||
|
||||
if (unlikely(errcode != 0))
|
||||
return NULL;
|
||||
|
||||
find_lookup_success:; // 找到目标dentry
|
||||
struct vfs_index_node_t *p = vfs_alloc_inode();
|
||||
|
||||
p->file_size = tmp_dEntry->DIR_FileSize;
|
||||
p->file_size = sinfo.de->DIR_FileSize;
|
||||
// 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区
|
||||
p->blocks = (p->file_size + fsbi->bytes_per_clus - 1) / fsbi->bytes_per_sec;
|
||||
p->attribute = (tmp_dEntry->DIR_Attr & ATTR_DIRECTORY) ? VFS_IF_DIR : VFS_IF_FILE;
|
||||
p->attribute = (sinfo.de->DIR_Attr & ATTR_DIRECTORY) ? VFS_IF_DIR : VFS_IF_FILE;
|
||||
p->sb = parent_inode->sb;
|
||||
p->file_ops = &fat32_file_ops;
|
||||
p->inode_ops = &fat32_inode_ops;
|
||||
@ -311,19 +340,19 @@ find_lookup_success:; // 找到目标dentry
|
||||
p->private_inode_info = (void *)kzalloc(sizeof(fat32_inode_info_t), 0);
|
||||
finode = (fat32_inode_info_t *)p->private_inode_info;
|
||||
|
||||
finode->first_clus = ((tmp_dEntry->DIR_FstClusHI << 16) | tmp_dEntry->DIR_FstClusLO) & 0x0fffffff;
|
||||
finode->dEntry_location_clus = cluster;
|
||||
finode->dEntry_location_clus_offset = tmp_dEntry - (struct fat32_Directory_t *)buf; // 计算dentry的偏移量
|
||||
finode->first_clus = ((sinfo.de->DIR_FstClusHI << 16) | sinfo.de->DIR_FstClusLO) & 0x0fffffff;
|
||||
finode->dEntry_location_clus = __fat32_LBA_to_cluster(fsbi->first_data_sector, fsbi->sec_per_clus, sinfo.i_pos);
|
||||
finode->dEntry_location_clus_offset = sinfo.slot_off; // 计算dentry的偏移量
|
||||
// kdebug("finode->dEntry_location_clus=%#018lx", finode->dEntry_location_clus);
|
||||
// kdebug("finode->dEntry_location_clus_offset=%#018lx", finode->dEntry_location_clus_offset);
|
||||
finode->create_date = tmp_dEntry->DIR_CrtDate;
|
||||
finode->create_time = tmp_dEntry->DIR_CrtTime;
|
||||
finode->write_date = tmp_dEntry->DIR_WrtDate;
|
||||
finode->write_time = tmp_dEntry->DIR_WrtTime;
|
||||
finode->create_date = sinfo.de->DIR_CrtDate;
|
||||
finode->create_time = sinfo.de->DIR_CrtTime;
|
||||
finode->write_date = sinfo.de->DIR_WrtDate;
|
||||
finode->write_time = sinfo.de->DIR_WrtTime;
|
||||
|
||||
// 暂时使用fat32的高4bit来标志设备文件
|
||||
// todo: 引入devfs后删除这段代码
|
||||
if ((tmp_dEntry->DIR_FstClusHI >> 12) && (p->attribute & VFS_IF_FILE))
|
||||
if ((sinfo.de->DIR_FstClusHI >> 12) && (p->attribute & VFS_IF_FILE))
|
||||
p->attribute |= VFS_IF_DEVICE;
|
||||
|
||||
dest_dentry->dir_inode = p;
|
||||
@ -331,7 +360,7 @@ find_lookup_success:; // 找到目标dentry
|
||||
list_init(&dest_dentry->child_node_list);
|
||||
list_init(&dest_dentry->subdirs_list);
|
||||
|
||||
kfree(buf);
|
||||
kfree(sinfo.buffer);
|
||||
return dest_dentry;
|
||||
}
|
||||
|
||||
@ -681,7 +710,7 @@ long fat32_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *po
|
||||
// 读取一个簇的数据
|
||||
int errno = blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus,
|
||||
(uint64_t)tmp_buffer);
|
||||
if (errno != AHCI_SUCCESS)
|
||||
if (errno != 0)
|
||||
{
|
||||
// kerror("FAT32 FS(write) read disk error!");
|
||||
retval = -EIO;
|
||||
@ -792,7 +821,8 @@ long fat32_lseek(struct vfs_file_t *file_ptr, long offset, long whence)
|
||||
}
|
||||
// todo: ioctl
|
||||
long fat32_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg)
|
||||
{return 0;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -875,9 +905,9 @@ long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t
|
||||
retval = -ENOSPC;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// kdebug("new dir clus=%ld", new_dir_clus);
|
||||
// kdebug("dest_dEntry->name=%s",dest_dEntry->name);
|
||||
// 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);
|
||||
@ -885,7 +915,7 @@ long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t
|
||||
// 计算校验和
|
||||
uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name);
|
||||
|
||||
// kdebug("dest_dEntry->name=%s",dest_dEntry->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);
|
||||
@ -1068,6 +1098,54 @@ int64_t fat32_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从fat32中卸载inode
|
||||
*
|
||||
* @param inode 要被卸载的inode
|
||||
* @return int 错误码
|
||||
*/
|
||||
static int fat32_detach_inode(struct vfs_index_node_t *inode)
|
||||
{
|
||||
// todo: 当引入哈希表管理inode之后,这个函数负责将inode从哈希表中删除
|
||||
// 参考Linux的fat_detach
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取消inode和dentry之间的链接关系(删除文件)
|
||||
*
|
||||
* @param inode 要被取消关联关系的目录项的【父目录项】
|
||||
* @param dentry 要被取消关联关系的子目录项
|
||||
*/
|
||||
int64_t fat32_unlink(struct vfs_index_node_t *dir, struct vfs_dir_entry_t *dentry)
|
||||
{
|
||||
int retval = 0;
|
||||
struct vfs_superblock_t *sb = dir->sb;
|
||||
struct vfs_index_node_t *inode_to_remove = dentry->dir_inode;
|
||||
fat32_sb_info_t *fsbi = (fat32_sb_info_t *)sb->private_sb_info;
|
||||
struct fat32_slot_info sinfo = {0};
|
||||
// todo: 对fat32的超级块加锁
|
||||
|
||||
retval = vfat_find(dir, dentry->name, &sinfo);
|
||||
|
||||
if (unlikely(retval != 0))
|
||||
goto out;
|
||||
|
||||
// 从fat表删除目录项
|
||||
retval = fat32_remove_entries(dir, &sinfo);
|
||||
if (unlikely(retval != 0))
|
||||
goto out;
|
||||
retval = fat32_detach_inode(dentry->dir_inode);
|
||||
if (unlikely(retval != 0))
|
||||
goto out;
|
||||
out:;
|
||||
if (sinfo.buffer != NULL)
|
||||
kfree(sinfo.buffer);
|
||||
// todo: 对fat32的超级块放锁
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 读取文件夹(在指定目录中找出有效目录项)
|
||||
*
|
||||
@ -1269,9 +1347,57 @@ struct vfs_inode_operations_t fat32_inode_ops = {
|
||||
.rename = fat32_rename,
|
||||
.getAttr = fat32_getAttr,
|
||||
.setAttr = fat32_setAttr,
|
||||
.unlink = fat32_unlink,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 给定字符串长度,计算去除字符串尾部的'.'后,剩余部分的长度
|
||||
*
|
||||
* @param len 字符串长度(不包括\0)
|
||||
* @param name 名称字符串
|
||||
* @return unsigned int 去除'.'后的
|
||||
*/
|
||||
static unsigned int vfat_striptail_len(unsigned int len, const char *name)
|
||||
{
|
||||
while (len && name[len - 1] == '.')
|
||||
--len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在指定inode的长目录项中搜索目标子目录项
|
||||
*
|
||||
* @param dir 父目录项inode
|
||||
* @param name 要查找的子目录项的名称
|
||||
* @param len 子目录项名称长度
|
||||
* @param slot_info 返回的对应的子目录项的短目录项。
|
||||
* @return int 错误码
|
||||
*/
|
||||
static int fat_search_long(struct vfs_index_node_t *dir, const char *name, int len, struct fat32_slot_info *slot_info)
|
||||
{
|
||||
int retval = 0;
|
||||
retval = __fat32_search_long_short(dir, name, len, slot_info);
|
||||
return retval;
|
||||
}
|
||||
/**
|
||||
* @brief 在fat32中,根据父inode,寻找给定名称的子inode
|
||||
*
|
||||
* @param dir 父目录项的inode
|
||||
* @param name 子目录项名称
|
||||
* @param slot_info 找到的slot的信息
|
||||
* @return int 错误码
|
||||
*/
|
||||
static int vfat_find(struct vfs_index_node_t *dir, const char *name, struct fat32_slot_info *slot_info)
|
||||
{
|
||||
uint32_t len = vfat_striptail_len(strnlen(name, PAGE_4K_SIZE - 1), name);
|
||||
|
||||
if (len == 0)
|
||||
return -ENOENT;
|
||||
|
||||
return fat_search_long(dir, name, len, slot_info);
|
||||
}
|
||||
|
||||
struct vfs_filesystem_type_t fat32_fs_type = {
|
||||
.name = "FAT32",
|
||||
.fs_flags = 0,
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#define FAT32_MAX_PARTITION_NUM 128 // 系统支持的最大的fat32分区数量
|
||||
|
||||
#define FAT32_DELETED_FLAG 0xe5 // 如果短目录项的name[0]为这个值,那么意味着这个短目录项是空闲的
|
||||
|
||||
/**
|
||||
* @brief fat32文件系统引导扇区结构体
|
||||
*
|
||||
@ -128,6 +130,7 @@ struct fat32_LongDirectory_t
|
||||
struct fat32_partition_info_t
|
||||
{
|
||||
uint16_t partition_id; // 全局fat32分区id
|
||||
// todo: 增加mutex,使得对fat32文件系统的访问是互斥的
|
||||
|
||||
struct fat32_BootSector_t bootsector;
|
||||
struct fat32_FSInfo_t fsinfo;
|
||||
@ -164,6 +167,21 @@ struct fat32_inode_info_t
|
||||
|
||||
typedef struct fat32_inode_info_t fat32_inode_info_t;
|
||||
|
||||
/**
|
||||
* @brief FAT32目录项插槽信息
|
||||
* 一个插槽指的是 一个长目录项/短目录项
|
||||
*/
|
||||
struct fat32_slot_info
|
||||
{
|
||||
off_t i_pos; // on-disk position of directory entry(扇区号)
|
||||
off_t slot_off; // offset for slot or (de) start
|
||||
int num_slots; // number of slots +1(de) in filename
|
||||
struct fat32_Directory_t * de;
|
||||
|
||||
// todo: 加入block io层后,在这里引入buffer_head
|
||||
void *buffer; // 记得释放这个buffer!!!
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 注册指定磁盘上的指定分区的fat32文件系统
|
||||
*
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "fat_ent.h"
|
||||
#include "internal.h"
|
||||
#include <common/errno.h>
|
||||
#include <driver/disk/ahci/ahci.h>
|
||||
#include <mm/slab.h>
|
||||
@ -22,10 +23,8 @@ int fat32_alloc_clusters(struct vfs_index_node_t *inode, uint32_t *clusters, int
|
||||
struct block_device *blk = inode->sb->blk_device;
|
||||
uint64_t sec_per_fat = fsbi->sec_per_FAT;
|
||||
|
||||
// todo: 对alloc的过程加锁
|
||||
|
||||
// 申请1扇区的缓冲区
|
||||
uint32_t *buf = (uint32_t *)kmalloc(fsbi->bytes_per_sec, 0);
|
||||
uint32_t *buf = (uint32_t *)kzalloc(fsbi->bytes_per_sec, 0);
|
||||
int ent_per_sec = (fsbi->bytes_per_sec >> 2);
|
||||
int clus_idx = 0;
|
||||
for (int i = 0; i < sec_per_fat; ++i)
|
||||
@ -67,7 +66,7 @@ done:;
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: 跳转到文件当前的最后一个簇
|
||||
// 跳转到文件当前的最后一个簇
|
||||
idx = 0;
|
||||
int tmp_clus = finode->first_clus;
|
||||
cluster = tmp_clus;
|
||||
@ -150,7 +149,7 @@ uint32_t fat32_read_FAT_entry(struct block_device *blk, fat32_sb_info_t *fsbi, u
|
||||
* @param value 要写入该fat表项的值
|
||||
* @return uint32_t errcode
|
||||
*/
|
||||
uint32_t fat32_write_FAT_entry(struct block_device *blk, fat32_sb_info_t *fsbi, uint32_t cluster, uint32_t value)
|
||||
int fat32_write_FAT_entry(struct block_device *blk, fat32_sb_info_t *fsbi, uint32_t cluster, uint32_t value)
|
||||
{
|
||||
// 计算每个扇区内含有的FAT表项数
|
||||
// FAT每项4bytes
|
||||
@ -216,7 +215,8 @@ struct fat32_Directory_t *fat32_find_empty_dentry(struct vfs_index_node_t *paren
|
||||
// 查找连续num个空闲目录项
|
||||
for (int i = 0; (i < fsbi->bytes_per_clus) && count_continuity < num; i += 32, ++tmp_dEntry)
|
||||
{
|
||||
if (!(tmp_dEntry->DIR_Name[0] == 0xe5 || tmp_dEntry->DIR_Name[0] == 0x00))
|
||||
if (!(tmp_dEntry->DIR_Name[0] == 0xe5 || tmp_dEntry->DIR_Name[0] == 0x00 ||
|
||||
tmp_dEntry->DIR_Name[0] == 0x05))
|
||||
{
|
||||
count_continuity = 0;
|
||||
continue;
|
||||
@ -234,6 +234,7 @@ struct fat32_Directory_t *fat32_find_empty_dentry(struct vfs_index_node_t *paren
|
||||
*res_sector = sector;
|
||||
*res_data_buf_base = (uint64_t)buf;
|
||||
*res_cluster = cluster;
|
||||
|
||||
return result_dEntry;
|
||||
}
|
||||
|
||||
@ -332,12 +333,6 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory
|
||||
else
|
||||
target->DIR_Name[tmp_index] = 0x20;
|
||||
}
|
||||
// 在字符串末尾加入\0
|
||||
if (tmp_index < 8 && tmp_index == dEntry->name_length)
|
||||
{
|
||||
target->DIR_Name[tmp_index] = '\0';
|
||||
++tmp_index;
|
||||
}
|
||||
|
||||
// 不满的部分使用0x20填充
|
||||
while (tmp_index < 8)
|
||||
@ -390,35 +385,31 @@ void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirect
|
||||
uint32_t current_name_index = 0;
|
||||
struct fat32_LongDirectory_t *Ldentry = (struct fat32_LongDirectory_t *)(target + 1);
|
||||
// kdebug("filling long name, name=%s, namelen=%d", dEntry->name, dEntry->name_length);
|
||||
int name_length = dEntry->name_length + 1;
|
||||
for (int i = 1; i <= cnt_longname; ++i)
|
||||
{
|
||||
--Ldentry;
|
||||
|
||||
Ldentry->LDIR_Ord = i;
|
||||
|
||||
for (int j = 0; j < 5; ++j, ++current_name_index)
|
||||
{
|
||||
if (current_name_index < dEntry->name_length)
|
||||
if (current_name_index < name_length)
|
||||
Ldentry->LDIR_Name1[j] = dEntry->name[current_name_index];
|
||||
else if (current_name_index == dEntry->name_length)
|
||||
Ldentry->LDIR_Name1[j] = '\0';
|
||||
else
|
||||
Ldentry->LDIR_Name1[j] = 0xffff;
|
||||
}
|
||||
for (int j = 0; j < 6; ++j, ++current_name_index)
|
||||
{
|
||||
if (current_name_index < dEntry->name_length)
|
||||
if (current_name_index < name_length)
|
||||
Ldentry->LDIR_Name2[j] = dEntry->name[current_name_index];
|
||||
else if (current_name_index == dEntry->name_length)
|
||||
Ldentry->LDIR_Name1[j] = '\0';
|
||||
else
|
||||
Ldentry->LDIR_Name2[j] = 0xffff;
|
||||
}
|
||||
for (int j = 0; j < 2; ++j, ++current_name_index)
|
||||
{
|
||||
if (current_name_index < dEntry->name_length)
|
||||
if (current_name_index < name_length)
|
||||
Ldentry->LDIR_Name3[j] = dEntry->name[current_name_index];
|
||||
else if (current_name_index == dEntry->name_length)
|
||||
Ldentry->LDIR_Name1[j] = '\0';
|
||||
else
|
||||
Ldentry->LDIR_Name3[j] = 0xffff;
|
||||
}
|
||||
@ -430,4 +421,61 @@ void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirect
|
||||
|
||||
// 最后一个长目录项的ord要|=0x40
|
||||
Ldentry->LDIR_Ord |= 0x40;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 删除目录项
|
||||
*
|
||||
* @param dir 父目录的inode
|
||||
* @param sinfo 待删除的dentry的插槽信息
|
||||
* @return int 错误码
|
||||
*/
|
||||
int fat32_remove_entries(struct vfs_index_node_t *dir, struct fat32_slot_info *sinfo)
|
||||
{
|
||||
int retval = 0;
|
||||
struct vfs_superblock_t *sb = dir->sb;
|
||||
struct fat32_Directory_t *de = sinfo->de;
|
||||
fat32_sb_info_t *fsbi = (fat32_sb_info_t *)sb->private_sb_info;
|
||||
int cnt_dentries = sinfo->num_slots;
|
||||
|
||||
// 获取文件数据区的起始簇号
|
||||
int data_cluster = ((((uint32_t)de->DIR_FstClusHI) << 16) | ((uint32_t)de->DIR_FstClusLO)) & 0x0fffffff;
|
||||
// kdebug("data_cluster=%d, cnt_dentries=%d, offset=%d", data_cluster, cnt_dentries, sinfo->slot_off);
|
||||
// kdebug("fsbi->first_data_sector=%d, sec per clus=%d, i_pos=%d", fsbi->first_data_sector, fsbi->sec_per_clus,
|
||||
// sinfo->i_pos);
|
||||
// === 第一阶段,先删除短目录项
|
||||
while (cnt_dentries > 0)
|
||||
{
|
||||
de->DIR_Name[0] = FAT32_DELETED_FLAG;
|
||||
--cnt_dentries;
|
||||
--de;
|
||||
}
|
||||
|
||||
// === 第二阶段:将对目录项的更改写入磁盘
|
||||
|
||||
sb->blk_device->bd_disk->fops->transfer(sb->blk_device->bd_disk, AHCI_CMD_WRITE_DMA_EXT, sinfo->i_pos,
|
||||
fsbi->sec_per_clus, (uint64_t)sinfo->buffer);
|
||||
|
||||
// === 第三阶段:清除文件的数据区
|
||||
uint32_t next_clus;
|
||||
int js = 0;
|
||||
// kdebug("data_cluster=%#018lx", data_cluster);
|
||||
while (data_cluster < 0x0ffffff8 && data_cluster >= 2)
|
||||
{
|
||||
// 读取下一个表项
|
||||
next_clus = fat32_read_FAT_entry(sb->blk_device, fsbi, data_cluster);
|
||||
// kdebug("data_cluster=%#018lx, next_clus=%#018lx", data_cluster, next_clus);
|
||||
// 清除当前表项
|
||||
retval = fat32_write_FAT_entry(sb->blk_device, fsbi, data_cluster, 0);
|
||||
if (unlikely(retval != 0))
|
||||
{
|
||||
kerror("fat32_remove_entries: Failed to mark fat entry as unused for cluster:%d", data_cluster);
|
||||
goto out;
|
||||
}
|
||||
++js;
|
||||
data_cluster = next_clus;
|
||||
}
|
||||
out:;
|
||||
// kdebug("Successfully remove %d clusters.", js);
|
||||
return retval;
|
||||
}
|
@ -42,7 +42,7 @@ uint32_t fat32_read_FAT_entry(struct block_device * blk, fat32_sb_info_t *fsbi,
|
||||
* @param value 要写入该fat表项的值
|
||||
* @return uint32_t errcode
|
||||
*/
|
||||
uint32_t fat32_write_FAT_entry(struct block_device * blk, fat32_sb_info_t *fsbi, uint32_t cluster, uint32_t value);
|
||||
int fat32_write_FAT_entry(struct block_device * blk, fat32_sb_info_t *fsbi, uint32_t cluster, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief 在父亲inode的目录项簇中,寻找连续num个空的目录项
|
||||
@ -94,4 +94,6 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory
|
||||
* @param checksum 短目录项的校验和
|
||||
* @param cnt_longname 总的长目录项的个数
|
||||
*/
|
||||
void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirectory_t *target, uint8_t checksum, uint32_t cnt_longname);
|
||||
void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirectory_t *target, uint8_t checksum, uint32_t cnt_longname);
|
||||
|
||||
int fat32_remove_entries(struct vfs_index_node_t *dir, struct fat32_slot_info *sinfo);
|
28
kernel/filesystem/fat32/internal.h
Normal file
28
kernel/filesystem/fat32/internal.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <common/sys/types.h>
|
||||
|
||||
/**
|
||||
* @brief 根据簇号计算该簇的起始扇区号(LBA地址)
|
||||
*
|
||||
* @param first_data_sector 数据区的其实扇区号
|
||||
* @param sec_per_clus 每个簇的扇区数量
|
||||
* @param cluster 簇号
|
||||
* @return uint32_t LBA地址
|
||||
*/
|
||||
static inline uint32_t __fat32_calculate_LBA(uint32_t first_data_sector, uint32_t sec_per_clus, uint32_t cluster)
|
||||
{
|
||||
return first_data_sector + (cluster - 2) * sec_per_clus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算LBA地址所在的簇
|
||||
*
|
||||
* @param first_data_sector 数据区的其实扇区号
|
||||
* @param sec_per_clus 每个簇的扇区数量
|
||||
* @param LBA LBA地址
|
||||
* @return uint32_t 所在的簇
|
||||
*/
|
||||
static inline uint32_t __fat32_LBA_to_cluster(uint32_t first_data_sector, uint32_t sec_per_clus, uint32_t LBA)
|
||||
{
|
||||
return ((LBA - first_data_sector) / sec_per_clus) + 2;
|
||||
}
|
@ -1,18 +1,17 @@
|
||||
#include "cmd.h"
|
||||
#include <libc/string.h>
|
||||
#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 <libc/fcntl.h>
|
||||
#include <libc/dirent.h>
|
||||
#include <libc/sys/wait.h>
|
||||
#include <libc/sys/stat.h>
|
||||
#include "cmd_help.h"
|
||||
#include "cmd_test.h"
|
||||
#include <libc/dirent.h>
|
||||
#include <libc/errno.h>
|
||||
#include <libc/fcntl.h>
|
||||
#include <libc/stddef.h>
|
||||
#include <libc/stdio.h>
|
||||
#include <libc/stdlib.h>
|
||||
#include <libc/string.h>
|
||||
#include <libc/sys/stat.h>
|
||||
#include <libc/sys/wait.h>
|
||||
#include <libc/unistd.h>
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
// 当前工作目录(在main_loop中初始化)
|
||||
char *shell_current_path = NULL;
|
||||
@ -20,22 +19,11 @@ char *shell_current_path = NULL;
|
||||
* @brief shell 内建函数的主命令与处理函数的映射表
|
||||
*
|
||||
*/
|
||||
struct built_in_cmd_t shell_cmds[] =
|
||||
{
|
||||
{"cd", shell_cmd_cd},
|
||||
{"cat", shell_cmd_cat},
|
||||
{"exec", shell_cmd_exec},
|
||||
{"ls", shell_cmd_ls},
|
||||
{"mkdir", shell_cmd_mkdir},
|
||||
{"pwd", shell_cmd_pwd},
|
||||
{"rm", shell_cmd_rm},
|
||||
{"rmdir", shell_cmd_rmdir},
|
||||
{"reboot", shell_cmd_reboot},
|
||||
{"touch", shell_cmd_touch},
|
||||
{"about", shell_cmd_about},
|
||||
{"free", shell_cmd_free},
|
||||
{"help", shell_help},
|
||||
{"pipe", shell_pipe_test},
|
||||
struct built_in_cmd_t shell_cmds[] = {
|
||||
{"cd", shell_cmd_cd}, {"cat", shell_cmd_cat}, {"exec", shell_cmd_exec}, {"ls", shell_cmd_ls},
|
||||
{"mkdir", shell_cmd_mkdir}, {"pwd", shell_cmd_pwd}, {"rm", shell_cmd_rm}, {"rmdir", shell_cmd_rmdir},
|
||||
{"reboot", shell_cmd_reboot}, {"touch", shell_cmd_touch}, {"about", shell_cmd_about}, {"free", shell_cmd_free},
|
||||
{"help", shell_help}, {"pipe", shell_pipe_test},
|
||||
|
||||
};
|
||||
// 总共的内建命令数量
|
||||
@ -210,7 +198,6 @@ int shell_cmd_cd(int argc, char **argv)
|
||||
new_path[current_dir_len] = '/';
|
||||
strcat(new_path, argv[1] + dest_offset);
|
||||
int x = chdir(new_path);
|
||||
|
||||
if (x == 0) // 成功切换目录
|
||||
{
|
||||
free(shell_current_path);
|
||||
@ -221,6 +208,7 @@ int shell_cmd_cd(int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
free(new_path);
|
||||
printf("ERROR: Cannot switch to directory: %s\n", new_path);
|
||||
goto fail;
|
||||
}
|
||||
@ -326,6 +314,7 @@ int shell_cmd_cat(int argc, char **argv)
|
||||
|
||||
close(fd);
|
||||
free(buf);
|
||||
free(file_path);
|
||||
if (argv != NULL)
|
||||
free(argv);
|
||||
return 0;
|
||||
@ -342,10 +331,11 @@ int shell_cmd_touch(int argc, char **argv)
|
||||
{
|
||||
int path_len = 0;
|
||||
char *file_path;
|
||||
bool alloc_full_path=false;
|
||||
if (argv[1][0] == '/')
|
||||
file_path = argv[1];
|
||||
else
|
||||
file_path = get_target_filepath(argv[1], &path_len);
|
||||
{file_path = get_target_filepath(argv[1], &path_len);alloc_full_path=true;}
|
||||
|
||||
// 打开文件
|
||||
int fd = open(file_path, O_CREAT);
|
||||
@ -361,19 +351,11 @@ int shell_cmd_touch(int argc, char **argv)
|
||||
close(fd);
|
||||
if (argv != NULL)
|
||||
free(argv);
|
||||
if(alloc_full_path)
|
||||
free(file_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 删除命令
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
*/
|
||||
// todo:
|
||||
int shell_cmd_rm(int argc, char **argv) {return 0;}
|
||||
|
||||
/**
|
||||
* @brief 创建文件夹的命令
|
||||
*
|
||||
@ -384,19 +366,22 @@ int shell_cmd_rm(int argc, char **argv) {return 0;}
|
||||
int shell_cmd_mkdir(int argc, char **argv)
|
||||
{
|
||||
int result_path_len = -1;
|
||||
const char *full_path = NULL;
|
||||
char *full_path = NULL;
|
||||
bool alloc_full_path = false;
|
||||
if (argv[1][0] == '/')
|
||||
full_path = argv[1];
|
||||
else
|
||||
{
|
||||
full_path = get_target_filepath(argv[1], &result_path_len);
|
||||
alloc_full_path = true;
|
||||
}
|
||||
// printf("mkdir: full_path = %s\n", full_path);
|
||||
int retval = mkdir(full_path, 0);
|
||||
|
||||
if (argv != NULL)
|
||||
free(argv);
|
||||
|
||||
if (alloc_full_path)
|
||||
free(full_path);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -407,20 +392,60 @@ int shell_cmd_mkdir(int argc, char **argv)
|
||||
* @param argv
|
||||
* @return int
|
||||
*/
|
||||
// todo:
|
||||
int shell_cmd_rmdir(int argc, char **argv)
|
||||
{
|
||||
const char *full_path = NULL;
|
||||
char *full_path = NULL;
|
||||
int result_path_len = -1;
|
||||
bool alloc_full_path = false;
|
||||
|
||||
if (argv[1][0] == '/')
|
||||
full_path = argv[1];
|
||||
else
|
||||
{
|
||||
full_path = get_target_filepath(argv[1], &result_path_len);
|
||||
alloc_full_path = true;
|
||||
}
|
||||
int retval = rmdir(full_path);
|
||||
if (retval != 0)
|
||||
printf("Failed to remove %s, retval=%d\n", full_path, retval);
|
||||
// printf("rmdir: path=%s, retval=%d\n", full_path, retval);
|
||||
if (argv != NULL)
|
||||
free(argv);
|
||||
if (alloc_full_path)
|
||||
free(full_path);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 删除文件的命令
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
*/
|
||||
int shell_cmd_rm(int argc, char **argv)
|
||||
{
|
||||
char *full_path = NULL;
|
||||
int result_path_len = -1;
|
||||
int retval = 0;
|
||||
bool alloc_full_path = false;
|
||||
|
||||
if (argv[1][0] == '/')
|
||||
full_path = argv[1];
|
||||
else
|
||||
{
|
||||
full_path = get_target_filepath(argv[1], &result_path_len);
|
||||
alloc_full_path = true;
|
||||
}
|
||||
|
||||
retval = rm(full_path);
|
||||
// printf("rmdir: path=%s, retval=%d\n", full_path, retval);
|
||||
if (retval != 0)
|
||||
printf("Failed to remove %s, retval=%d\n", full_path, retval);
|
||||
if (alloc_full_path)
|
||||
free(full_path);
|
||||
if (argv != NULL)
|
||||
free(argv);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -446,9 +471,9 @@ int shell_cmd_exec(int argc, char **argv)
|
||||
// printf("before execv, path=%s, argc=%d\n", file_path, argc);
|
||||
execv(file_path, argv);
|
||||
free(argv);
|
||||
while (1)
|
||||
;
|
||||
exit(0);
|
||||
free(file_path);
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -510,11 +535,13 @@ int shell_cmd_free(int argc, char **argv)
|
||||
printf("Mem:\t");
|
||||
if (argc == 1) // 按照kb显示
|
||||
{
|
||||
printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 10, mst.used >> 10, mst.free >> 10, mst.shared >> 10, mst.cache_used >> 10, mst.available >> 10);
|
||||
printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 10, mst.used >> 10, mst.free >> 10, mst.shared >> 10,
|
||||
mst.cache_used >> 10, mst.available >> 10);
|
||||
}
|
||||
else // 按照MB显示
|
||||
{
|
||||
printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 20, mst.used >> 20, mst.free >> 20, mst.shared >> 20, mst.cache_used >> 20, mst.available >> 20);
|
||||
printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 20, mst.used >> 20, mst.free >> 20, mst.shared >> 20,
|
||||
mst.cache_used >> 20, mst.available >> 20);
|
||||
}
|
||||
|
||||
done:;
|
||||
|
@ -161,6 +161,17 @@ int rmdir(const char *path)
|
||||
return syscall_invoke(SYS_UNLINK_AT, 0, (uint64_t)path, AT_REMOVEDIR, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 删除文件
|
||||
*
|
||||
* @param path 绝对路径
|
||||
* @return int
|
||||
*/
|
||||
int rm(const char * path)
|
||||
{
|
||||
return syscall_invoke(SYS_UNLINK_AT, 0, (uint64_t)path, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 交换n字节
|
||||
* @param src 源地址
|
||||
|
@ -106,6 +106,8 @@ extern int usleep(useconds_t usec);
|
||||
*/
|
||||
int rmdir(const char *path);
|
||||
|
||||
int rm(const char * path);
|
||||
|
||||
/**
|
||||
* @brief 交换n字节
|
||||
* @param src 源地址
|
||||
|
Loading…
x
Reference in New Issue
Block a user