|
|
# 总代码
|
|
|
```c
|
|
|
//查找目录项
|
|
|
int find_directory_entry(struct block_device *device, const char *filename, struct fat32_dir_entry *entry) {
|
|
|
uint32_t cluster = fs.root_cluster
|
|
|
char buffer[fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster]
|
|
|
int i
|
|
|
|
|
|
while (cluster < 0x0FFFFFF8) {
|
|
|
read_cluster(device, cluster, buffer)
|
|
|
|
|
|
for (i = 0 i < fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster / sizeof(struct fat32_dir_entry) i++) {
|
|
|
struct fat32_dir_entry *dir = (struct fat32_dir_entry *)(buffer + i * sizeof(struct fat32_dir_entry))
|
|
|
|
|
|
if (dir->name[0] == 0x00) {
|
|
|
return -1 // End of directory
|
|
|
}
|
|
|
|
|
|
if (strncmp((const char *)dir->name, filename, 11) == 0) {
|
|
|
memcpy(entry, dir, sizeof(struct fat32_dir_entry))
|
|
|
return 0 // Found
|
|
|
}
|
|
|
}
|
|
|
|
|
|
cluster = read_fat_entry(device, cluster)
|
|
|
}
|
|
|
|
|
|
return -1 // Not found
|
|
|
}
|
|
|
```
|
|
|
### 代码详细解释
|
|
|
|
|
|
1. **函数定义和参数**:
|
|
|
```c
|
|
|
int find_directory_entry(struct block_device *device, const char *filename, struct fat32_dir_entry *entry)
|
|
|
|
|
|
```
|
|
|
- `device`:块设备结构指针,表示要操作的设备。
|
|
|
- `filename`:要查找的文件名。
|
|
|
- `entry`:找到的目录项将被复制到这个结构中。
|
|
|
|
|
|
|
|
|
***1、struct block_device***
|
|
|
|
|
|
struct block_device 用于表示块设备。这个结构体通常包含设备的基本信息和用于读写设备的函数指针。具体定义可能因系统而异。以下是一个假设的示例定义:
|
|
|
|
|
|
```c
|
|
|
struct block_device {
|
|
|
char *device_name // 设备名称
|
|
|
uint32_t block_size // 每个块的大小(以字节为单位)
|
|
|
uint64_t total_blocks // 设备的总块数
|
|
|
int (*read)(struct block_device *dev, uint64_t block, void *buffer, size_t size) // 读取块的函数指针
|
|
|
int (*write)(struct block_device *dev, uint64_t block, const void *buffer, size_t size) // 写入块的函数指针
|
|
|
// 其他可能的字段
|
|
|
}
|
|
|
```
|
|
|
***2、struct fat32_dir_entry***
|
|
|
|
|
|
struct fat32_dir_entry 用于表示FAT32文件系统中的目录项。
|
|
|
|
|
|
|
|
|
### 使用示例
|
|
|
|
|
|
在你的代码中,这两个结构体被用来处理文件系统操作:
|
|
|
|
|
|
#### `struct block_device` 使用示例
|
|
|
|
|
|
```c
|
|
|
struct block_device my_device = {
|
|
|
.device_name = "/dev/sda1",
|
|
|
.block_size = 512,
|
|
|
.total_blocks = 1024 * 1024,
|
|
|
.read = my_device_read, // 假设你有相应的读函数实现
|
|
|
.write = my_device_write, // 假设你有相应的写函数实现
|
|
|
}
|
|
|
|
|
|
// 使用读取函数
|
|
|
char buffer[512]
|
|
|
if (my_device.read(&my_device, 0, buffer, sizeof(buffer)) == 0) {
|
|
|
// 读取成功
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### `struct fat32_dir_entry` 使用示例
|
|
|
|
|
|
在 `find_directory_entry` 函数中,`struct fat32_dir_entry` 被用来表示目录项:
|
|
|
|
|
|
```c
|
|
|
int find_directory_entry(struct block_device *device, const char *filename, struct fat32_dir_entry *entry) {
|
|
|
uint32_t cluster = fs.root_cluster
|
|
|
char buffer[fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster]
|
|
|
int i
|
|
|
|
|
|
while (cluster < 0x0FFFFFF8) {
|
|
|
read_cluster(device, cluster, buffer)
|
|
|
|
|
|
for (i = 0 i < fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster / sizeof(struct fat32_dir_entry) i++) {
|
|
|
struct fat32_dir_entry *dir = (struct fat32_dir_entry *)(buffer + i * sizeof(struct fat32_dir_entry))
|
|
|
|
|
|
if (dir->name[0] == 0x00) {
|
|
|
return -1 // End of directory
|
|
|
}
|
|
|
|
|
|
if (strncmp((const char *)dir->name, filename, 11) == 0) {
|
|
|
memcpy(entry, dir, sizeof(struct fat32_dir_entry))
|
|
|
return 0 // Found
|
|
|
}
|
|
|
}
|
|
|
|
|
|
cluster = read_fat_entry(device, cluster)
|
|
|
}
|
|
|
|
|
|
return -1 // Not found
|
|
|
}
|
|
|
```
|
|
|
|
|
|
在这个函数中,通过读取每个簇并解析其中的目录项,将找到的目录项信息复制到 `entry` 结构体中。
|
|
|
|
|
|
### 总结
|
|
|
|
|
|
`struct block_device` 和 `struct fat32_dir_entry` 都是结构体,分别用于表示块设备和FAT32文件系统中的目录项。通过定义这些结构体,可以方便地管理和操作相关的数据和功能。
|
|
|
|
|
|
|
|
|
2. **初始化起始簇和缓冲区**:
|
|
|
```c
|
|
|
uint32_t cluster = fs.root_cluster
|
|
|
char buffer[fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster]
|
|
|
int i
|
|
|
```
|
|
|
- `cluster`:初始化为根簇,表示从根目录开始查找。
|
|
|
- `buffer`:定义一个缓冲区,用于存储从设备读取的簇数据。
|
|
|
- `i`:循环变量。
|
|
|
|
|
|
这个初始化过程是查找目录项的前提,确保我们有正确的起始簇和足够的空间来存储读取的数据,并准备好遍历操作所需的循环变量。
|
|
|
这段代码初始化了三个变量,用于文件系统操作。以下是每个变量的详细解释:
|
|
|
|
|
|
```c
|
|
|
uint32_t cluster = fs.root_cluster
|
|
|
char buffer[fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster]
|
|
|
int i
|
|
|
```
|
|
|
|
|
|
### 详细解释
|
|
|
|
|
|
1. **`uint32_t cluster = fs.root_cluster `**
|
|
|
- **类型**: `uint32_t` 是一个无符号32位整数类型
|
|
|
- **变量名**: `cluster` 表示当前正在处理的簇号
|
|
|
- **初始化**: `fs.root_cluster` 根目录的起始簇号
|
|
|
- **作用**: 这行代码将文件系统的根簇号赋值给 `cluster` 变量,从根目录开始操作。
|
|
|
|
|
|
2. **`char buffer[fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster] `**
|
|
|
- **类型**: `char` 是字符类型,这里用作字节数组。
|
|
|
- **变量名**: `buffer` 表示一个缓冲区,用于存储从设备读取的数据。
|
|
|
- **大小**: 数组的大小由 `fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster` 决定。
|
|
|
- `fs.bpb.bytes_per_sector` 表示每个扇区的字节数。
|
|
|
- `fs.bpb.sectors_per_cluster` 表示每个簇包含的扇区数。
|
|
|
- **作用**: 这行代码定义了一个大小为一个簇的缓冲区,用于从块设备中读取一个簇的数据。
|
|
|
|
|
|
3. **`int i `**
|
|
|
- **类型**: `int` 是一个整数类型。
|
|
|
- **变量名**: `i` 通常用作循环变量。
|
|
|
- **作用**: 这行代码声明了一个整数变量 `i`,通常在遍历或循环操作中使用。
|
|
|
|
|
|
### 总结
|
|
|
|
|
|
```c
|
|
|
int find_directory_entry(struct block_device *device, const char *filename, struct fat32_dir_entry *entry) {
|
|
|
uint32_t cluster = fs.root_cluster
|
|
|
char buffer[fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster]
|
|
|
int i
|
|
|
|
|
|
while (cluster < 0x0FFFFFF8) {
|
|
|
read_cluster(device, cluster, buffer)
|
|
|
|
|
|
for (i = 0 i < fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster / sizeof(struct fat32_dir_entry) i++) {
|
|
|
struct fat32_dir_entry *dir = (struct fat32_dir_entry *)(buffer + i * sizeof(struct fat32_dir_entry))
|
|
|
|
|
|
if (dir->name[0] == 0x00) {
|
|
|
return -1 // End of directory
|
|
|
}
|
|
|
|
|
|
if (strncmp((const char *)dir->name, filename, 11) == 0) {
|
|
|
memcpy(entry, dir, sizeof(struct fat32_dir_entry))
|
|
|
return 0 // Found
|
|
|
}
|
|
|
}
|
|
|
|
|
|
cluster = read_fat_entry(device, cluster)
|
|
|
}
|
|
|
|
|
|
return -1 // Not found
|
|
|
}
|
|
|
```
|
|
|
在这个函数中:
|
|
|
- `cluster` 用于追踪当前正在处理的簇,从根目录开始。
|
|
|
- `buffer` 用于存储从设备读取的一个簇的数据。
|
|
|
- `i` 用于遍历缓冲区中的目录项,逐个检查是否匹配指定的文件名。
|
|
|
|
|
|
|
|
|
3. **循环遍历簇链**:
|
|
|
```c
|
|
|
while (cluster < 0x0FFFFFF8) {
|
|
|
read_cluster(device, cluster, buffer)
|
|
|
}
|
|
|
```
|
|
|
- 循环遍历每个簇,直到遇到FAT表中表示簇链结束的簇号(`cluster` >= `0x0FFFFFF8`)。
|
|
|
- `read_cluster` 函数读取当前簇的数据到缓冲区 `buffer` 中。
|
|
|
|
|
|
4. **遍历簇中的目录项**:
|
|
|
```c
|
|
|
for (i = 0 i < fs.bpb.bytes_per_sector * fs.bpb.sectors_per_cluster / sizeof(struct fat32_dir_entry) i++) {
|
|
|
struct fat32_dir_entry *dir = (struct fat32_dir_entry *)(buffer + i * sizeof(struct fat32_dir_entry))
|
|
|
|
|
|
if (dir->name[0] == 0x00) {
|
|
|
return -1 // End of directory
|
|
|
}
|
|
|
|
|
|
if (strncmp((const char *)dir->name, filename, 11) == 0) {
|
|
|
memcpy(entry, dir, sizeof(struct fat32_dir_entry))
|
|
|
return 0 // Found
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
- 内部循环遍历当前簇中的每个目录项。
|
|
|
- `dir`:指向当前目录项。
|
|
|
- 检查目录项的第一个字节是否为 `0x00`,表示目录的结束。如果是,返回 `-1`,表示未找到。
|
|
|
- 使用 `strncmp` 比较目录项名称和目标文件名。如果匹配,将目录项信息复制到 `entry`,并返回 `0`,表示找到。
|
|
|
|
|
|
|
|
|
5. **读取下一个簇号**:
|
|
|
```c
|
|
|
cluster = read_fat_entry(device, cluster)
|
|
|
```
|
|
|
- `read_fat_entry` 函数读取FAT表中的条目,获取当前簇号的下一个簇号,并将其赋值给 `cluster`,以便在下一次循环中处理。
|
|
|
|
|
|
6. **返回未找到**:
|
|
|
```c
|
|
|
return -1 // Not found
|
|
|
```
|
|
|
- 如果遍历完整个簇链都未找到匹配的文件名,返回 `-1`,表示未找到。
|
|
|
|
|
|
### 总结
|
|
|
这段代码的作用是从根目录开始,遍历FAT32文件系统中的簇链,逐个检查每个簇中的目录项,直到找到匹配的文件名或遍历完整个簇链。如果找到匹配的文件名,将目录项信息复制到 `entry` 并返回 `0`;如果未找到,返回 `-1`。
|
|
|
|
|
|
|
|
|
|