部分完成了readdir

This commit is contained in:
fslongjin
2022-05-27 13:41:10 +08:00
parent 156c2c2389
commit a4157bb4a7
10 changed files with 385 additions and 12 deletions

View File

@ -134,4 +134,13 @@ struct vfs_dir_entry_t *vfs_path_walk(char *path, uint64_t flags)
parent = dentry;
}
}
/**
* @brief 填充dentry
*
*/
int vfs_fill_dentry(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset)
{
}

View File

@ -124,6 +124,12 @@ struct vfs_dir_entry_operations_t
long (*iput)(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode);
};
/**
* @brief 填充dirent的函数指针的类型定义
*
*/
typedef int (*vfs_filldir_t)(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset);
struct vfs_file_operations_t
{
long (*open)(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr);
@ -132,6 +138,8 @@ struct vfs_file_operations_t
long (*write)(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position);
long (*lseek)(struct vfs_file_t *file_ptr, long offset, long origin);
long (*ioctl)(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg);
long (*readdir)(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler); // 读取文件夹
};
/**
@ -161,4 +169,10 @@ struct vfs_superblock_t *vfs_mount_fs(char *name, void *DPTE, uint8_t DPT_type,
* @param flags 1返回父目录项 0返回结果目录项
* @return struct vfs_dir_entry_t* 目录项
*/
struct vfs_dir_entry_t *vfs_path_walk(char *path, uint64_t flags);
struct vfs_dir_entry_t *vfs_path_walk(char *path, uint64_t flags);
/**
* @brief 填充dentry
*
*/
int vfs_fill_dentry(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset);

View File

@ -347,7 +347,7 @@ find_lookup_success:; // 找到目标dentry
// todo: 引入devfs后删除这段代码
if ((tmp_dEntry->DIR_FstClusHI >> 12) && (p->attribute & VFS_ATTR_FILE))
p->attribute |= VFS_ATTR_DEVICE;
dest_dentry->dir_inode = p;
kfree(buf);
return dest_dentry;
@ -868,6 +868,7 @@ struct vfs_file_operations_t fat32_file_ops =
.write = fat32_write,
.lseek = fat32_lseek,
.ioctl = fat32_ioctl,
.readdir = fat32_readdir,
};
// todo: create
@ -899,6 +900,180 @@ int64_t fat32_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr)
int64_t fat32_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr)
{
}
/**
* @brief 读取文件夹(在指定目录中找出有效目录项)
*
* @param file_ptr 文件结构体指针
* @param dirent 返回的dirent
* @param filler 填充dirent的函数
* @return int64_t
*/
int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler)
{
struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)file_ptr->dEntry->dir_inode->private_inode_info;
fat32_sb_info_t *fsbi = (fat32_sb_info_t *)file_ptr->dEntry->dir_inode->sb->private_sb_info;
unsigned char *buf = (unsigned char *)kmalloc(fsbi->bytes_per_clus, 0);
uint32_t cluster = finode->first_clus;
// 当前文件指针所在位置的簇号(文件内偏移量)
int clus_num = file_ptr->position / fsbi->bytes_per_clus;
// 循环读取fat entry直到读取到文件当前位置的所在簇号
for (int i = 0; i < clus_num; ++i)
{
cluster = fat32_read_FAT_entry(fsbi, cluster);
if (cluster > 0x0ffffff7) // 文件结尾
{
kerror("file position out of range! (cluster not exists)");
return NULL;
}
}
char *dir_name = NULL;
int name_len = 0;
// ==== 此时已经将文件夹的目录项起始簇的簇号读取到cluster变量中 ===
while (cluster <= 0x0ffffff7) // cluster在循环末尾更新如果当前簇已经没有短目录项的话
{
// 计算文件夹当前位置所在簇的起始扇区号
uint64_t sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus;
// 读取文件夹目录项当前位置起始扇区的数据
if (AHCI_SUCCESS != ahci_operation.transfer(AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)buf, fsbi->ahci_ctrl_num, fsbi->ahci_port_num))
{
// 读取失败
kerror("Failed to read the file's first sector.");
kfree(buf);
return NULL;
}
struct fat32_Directory_t *dentry = NULL;
struct fat32_LongDirectory_t *long_dentry = NULL;
// 找到当前短目录项
dentry = (struct fat32_Directory_t *)(buf + file_ptr->position % fsbi->bytes_per_clus);
name_len = 0;
// 逐个查找短目录项
for (int i = file_ptr->position % fsbi->bytes_per_clus; i < fsbi->bytes_per_clus; i += 32, file_ptr->position += 32, ++dentry)
{
// 若是长目录项则跳过
if (dentry->DIR_Attr == ATTR_LONG_NAME)
continue;
// 跳过无效表项、空闲表项
if (dentry->DIR_Name[0] == 0xe5 || dentry->DIR_Name[0] == 0x00 || dentry->DIR_Name[0] == 0x05)
continue;
// 找到短目录项
// 该短目录项对应的第一个长目录项
long_dentry = (struct fat32_LongDirectory_t *)(dentry - 1);
// 如果长目录项有效,则读取长目录项
if (long_dentry->LDIR_Attr == ATTR_LONG_NAME && long_dentry->LDIR_Ord != 0xe5 && long_dentry->LDIR_Ord != 0x00 && long_dentry->LDIR_Ord != 0x05)
{
int count_long_dentry = 0;
// 统计长目录项的个数
while (long_dentry->LDIR_Attr == ATTR_LONG_NAME && long_dentry->LDIR_Ord != 0xe5 && long_dentry->LDIR_Ord != 0x00 && long_dentry->LDIR_Ord != 0x05)
{
++count_long_dentry;
if (long_dentry->LDIR_Ord & 0x40) // 最后一个长目录项
break;
--long_dentry;
}
// 为目录名分配空间
dir_name = (char *)kmalloc(count_long_dentry * 26 + 1, 0);
memset(dir_name, 0, count_long_dentry * 26 + 1);
// 重新将长目录项指针指向第一个长目录项
long_dentry = (struct fat32_LongDirectory_t *)(dentry - 1);
name_len = 0;
// 逐个存储文件名
for (int j = 0; j < count_long_dentry; ++j, --long_dentry)
{
// 存储name1
for (int k = 0; k < 5; ++k)
{
if (long_dentry->LDIR_Name1[k] != 0xffff && long_dentry->LDIR_Name1[k] != 0x0000)
dir_name[name_len++] = (char)long_dentry->LDIR_Name1[k];
}
// 存储name2
for (int k = 0; k < 6; ++k)
{
if (long_dentry->LDIR_Name2[k] != 0xffff && long_dentry->LDIR_Name2[k] != 0x0000)
dir_name[name_len++] = (char)long_dentry->LDIR_Name2[k];
}
// 存储name3
for (int k = 0; k < 2; ++k)
{
if (long_dentry->LDIR_Name3[k] != 0xffff && long_dentry->LDIR_Name3[k] != 0x0000)
dir_name[name_len++] = (char)long_dentry->LDIR_Name3[k];
}
}
// 读取目录项成功,返回
goto find_dir_success;
}
else // 不存在长目录项
{
dir_name = (char *)kmalloc(15, 0);
memset(dir_name, 0, 15);
name_len = 0;
int total_len = 0;
// 读取基础名
for (int j = 0; j < 8; ++j, ++total_len)
{
if (dentry->DIR_Name[j] == ' ')
break;
if (dentry->DIR_NTRes & LOWERCASE_BASE) // 如果标记了文件名小写,则转换为小写字符
dir_name[name_len++] = dentry->DIR_Name[j] + 32;
else
dir_name[name_len++] = dentry->DIR_Name[j];
}
// 如果当前短目录项为文件夹,则直接返回,不需要读取扩展名
if (dentry->DIR_Attr & ATTR_DIRECTORY)
goto find_dir_success;
// 是文件,增加 .
dir_name[name_len++] = '.';
// 读取扩展名
// 读取基础名
for (int j = 0; j < 3; ++j, ++total_len)
{
if (dentry->DIR_Name[j] == ' ')
break;
if (dentry->DIR_NTRes & LOWERCASE_BASE) // 如果标记了文件名小写,则转换为小写字符
dir_name[name_len++] = dentry->DIR_Name[j] + 32;
else
dir_name[name_len++] = dentry->DIR_Name[j];
}
if (total_len == 8) // 没有扩展名
dir_name[--name_len] = '\0';
goto find_dir_success;
}
}
// 当前簇不存在目录项
cluster = fat32_read_FAT_entry(fsbi, cluster);
}
kfree(buf);
// 在上面的循环中读取到目录项结尾了,仍没有找到
return NULL;
find_dir_success:;
// 将文件夹位置坐标加32即指向下一个目录项
file_ptr->position += 32;
// todo: 计算ino_t
return filler(dirent, 0, dir_name, name_len, 0, 0);
}
struct vfs_inode_operations_t fat32_inode_ops =
{

View File

@ -155,9 +155,9 @@ typedef struct fat32_partition_info_t fat32_sb_info_t;
struct fat32_inode_info_t
{
uint64_t first_clus;
uint64_t dEntry_location_clus; // dEntry struct in cluster (0 is root, 1 is invalid)
uint64_t dEntry_location_clus_offset; // dEntry struct offset in cluster
uint64_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
uint16_t create_date;
uint16_t create_time;
@ -189,4 +189,14 @@ struct vfs_superblock_t *fat32_read_superblock(void *DPTE, uint8_t DPT_type, voi
long fat32_create(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dentry, int mode);
void fat32_init();
void fat32_init();
/**
* @brief 读取文件夹(在指定目录中找出有效目录项)
*
* @param file_ptr 文件结构体指针
* @param dirent 返回的dirent
* @param filler 填充dirent的函数
* @return int64_t
*/
int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler);