Complete mkdir and touch support

This commit is contained in:
Baptiste Wicht 2013-12-28 16:50:32 +01:00
parent 375413505a
commit 47c44e7e4d

View File

@ -145,8 +145,8 @@ bool cache_disk_partition(fat32::dd disk, const disks::partition_descriptor& par
}
//Write information sector to the disk
bool write_is(fat32::dd disk, const disks::partition_descriptor& partition){
auto fs_information_sector = partition.start + static_cast<uint64_t>(fat_bs->fs_information_sector);
bool write_is(fat32::dd disk){
auto fs_information_sector = partition_start + static_cast<uint64_t>(fat_bs->fs_information_sector);
return write_sectors(disk, fs_information_sector, 1, fat_is);
}
@ -247,11 +247,6 @@ inline bool entry_unused(const cluster_entry& entry){
return entry.name[0] == 0xE5;
}
//Indicates if the entry is used, or namely, not unused
inline bool entry_used(const cluster_entry& entry){
return entry.name[0] != 0xE5;
}
//Indicates if the entry marks the end of the directory
inline bool end_of_directory(const cluster_entry& entry){
return entry.name[0] == 0x0;
@ -275,6 +270,8 @@ std::vector<disks::file> files(fat32::dd disk, uint32_t cluster_number){
std::unique_heap_array<cluster_entry> cluster(16 * fat_bs->sectors_per_cluster);
while(!end_reached){
k_printf("Read cluster %u\n", cluster_number);
if(!read_sectors(disk, cluster_lba(cluster_number), fat_bs->sectors_per_cluster, cluster.get())){
return std::move(files);
}
@ -285,7 +282,10 @@ std::vector<disks::file> files(fat32::dd disk, uint32_t cluster_number){
break;
}
if(entry_used(entry)){
if(entry_unused(entry)){
continue;
}
if(is_long_name(entry)){
auto& l_entry = reinterpret_cast<long_entry&>(entry);
long_name = true;
@ -327,7 +327,6 @@ std::vector<disks::file> files(fat32::dd disk, uint32_t cluster_number){
continue;
}
disks::file file;
if(long_name){
@ -355,6 +354,8 @@ std::vector<disks::file> files(fat32::dd disk, uint32_t cluster_number){
file.directory = entry.attrib & 0x10;
if(file.directory){
//TODO Should read the cluster chain to get the number of
//clusters
file.size = fat_bs->sectors_per_cluster * 512;
} else {
file.size = entry.file_size;
@ -364,7 +365,6 @@ std::vector<disks::file> files(fat32::dd disk, uint32_t cluster_number){
files.push_back(file);
}
}
if(!end_reached){
cluster_number = next_cluster(disk, cluster_number);
@ -447,8 +447,57 @@ size_t number_of_entries(const std::string& name){
return (name.size() - 1) / 13 + 2;
}
cluster_entry* extend_directory(fat32::dd disk, std::unique_heap_array<cluster_entry>& directory_cluster, size_t entries, uint32_t& cluster_number){
auto cluster = find_free_cluster(disk);
if(!cluster){
return nullptr;
}
fat_is->free_clusters -= 1;
if(!write_is(disk)){
return nullptr;
}
//Update the cluster chain
if(!write_fat_value(disk, cluster_number, cluster)){
return nullptr;
}
if(!write_fat_value(disk, cluster, 0x0FFFFFF8)){
return nullptr;
}
//Remove all the end of directory marker in the previous cluster
for(size_t i = 0; i < directory_cluster.size(); ++i){
auto& entry = directory_cluster[i];
if(end_of_directory(entry)){
entry.name[0] = 0xE5;
}
}
//Write back the previous cluster
if(!write_sectors(disk, cluster_lba(cluster_number), fat_bs->sectors_per_cluster, directory_cluster.get())){
return nullptr;
}
cluster_number = cluster;
//In the new directory, mark all entries, but the first entries one as
//end of directory
for(size_t i = entries; i < directory_cluster.size(); ++i){
auto& entry = directory_cluster[i];
entry.name[0] = 0x0;
entry.attrib = 0x0;
}
return &directory_cluster[0];
}
//Finds "entries" consecutive free entries in the given directory cluster
cluster_entry* find_free_entry(std::unique_heap_array<cluster_entry>& directory_cluster, size_t entries){
cluster_entry* find_free_entry(fat32::dd disk, std::unique_heap_array<cluster_entry>& directory_cluster, size_t entries, uint32_t& cluster_number){
while(true){
size_t end;
bool end_found = false;
@ -463,11 +512,8 @@ cluster_entry* find_free_entry(std::unique_heap_array<cluster_entry>& directory_
}
}
if(!end_found){
k_print_line("Unsupported free");
return nullptr;
}
if(end_found){
//2. Find a big-enough sequence of free entries
size_t sequence_size = 0;
size_t sequence_start = 0;
size_t sequence_end = 0;
@ -488,11 +534,8 @@ cluster_entry* find_free_entry(std::unique_heap_array<cluster_entry>& directory_
}
}
if(sequence_size != entries){
//TODO Read the next cluster to find an empty entry
k_print_line("Unsupported free");
return nullptr;
}
if(sequence_size == entries){
bool ok = true;
//If the free sequence position is after end or if end is inside the free
//sequence
@ -511,21 +554,72 @@ cluster_entry* find_free_entry(std::unique_heap_array<cluster_entry>& directory_
}
}
//If there is not enough room to hold the entries and
//the end of directory marker, try with the next cluster
if(new_end < 0){
//TODO Read the next cluster to find an empty entry
k_print_line("Unsupported free");
return nullptr;
}
ok = false;
} else {
//Mark the old end as unused
directory_cluster[end].name[0] = 0xE5;
//Mark the new end as the end of the directory
directory_cluster[new_end].name[0] = 0x0;
}
}
if(ok){
return &directory_cluster[sequence_start];
}
}
}
//If there is an end and we have to go to the next cluster,
//remove the end of directory markers
if(end_found){
//Remove all the end of directory marker in the cluster
for(size_t i = 0; i < directory_cluster.size(); ++i){
auto& entry = directory_cluster[i];
if(end_of_directory(entry)){
entry.name[0] = 0xE5;
}
}
//Write back the cluster
if(!write_sectors(disk, cluster_lba(cluster_number), fat_bs->sectors_per_cluster, directory_cluster.get())){
return nullptr;
}
}
//3. Go to the next cluster
auto next = next_cluster(disk, cluster_number);
//If there are no next blocks, exit the loop and extend the
//directory cluster chain
if(!next){
break;
}
//If the block is corrupted, we do not try to do anything else
if(next == 0x0FFFFFF7){
return nullptr;
}
//Try again with the cluster in the chain
cluster_number = next;
//Read the next sector
if(!read_sectors(disk, cluster_lba(cluster_number), fat_bs->sectors_per_cluster, directory_cluster.get())){
return nullptr;
}
}
k_print_line("extension");
//At this point, we tried all the possible clusters of the directory,
//So it is necessary to add a new cluster to the chain
return extend_directory(disk, directory_cluster, entries, cluster_number);
}
//Init an entry
template<bool Long>
@ -755,7 +849,7 @@ bool fat32::mkdir(dd disk, const disks::partition_descriptor& partition, const s
}
auto entries = number_of_entries(directory);
auto new_directory_entry = find_free_entry(directory_cluster, entries);
auto new_directory_entry = find_free_entry(disk, directory_cluster, entries, parent_cluster_number);
init_directory_entry<true>(new_directory_entry, directory.c_str(), cluster);
@ -771,7 +865,7 @@ bool fat32::mkdir(dd disk, const disks::partition_descriptor& partition, const s
//One cluster is now used for the directory entries
fat_is->free_clusters -= 1;
if(!write_is(disk, partition)){
if(!write_is(disk)){
return false;
}
@ -811,18 +905,20 @@ bool fat32::touch(dd disk, const disks::partition_descriptor& partition, const s
return false;
}
auto parent_cluster_number = cluster_number.second;
std::unique_heap_array<cluster_entry> directory_cluster(16 * fat_bs->sectors_per_cluster);
if(!read_sectors(disk, cluster_lba(cluster_number.second), fat_bs->sectors_per_cluster, directory_cluster.get())){
if(!read_sectors(disk, cluster_lba(parent_cluster_number), fat_bs->sectors_per_cluster, directory_cluster.get())){
return false;
}
auto entries = number_of_entries(file);
auto new_directory_entry = find_free_entry(directory_cluster, entries);
auto new_directory_entry = find_free_entry(disk, directory_cluster, entries, parent_cluster_number);
init_file_entry<true>(new_directory_entry, file.c_str(), 0);
//Write back the parent directory cluster
if(!write_sectors(disk, cluster_lba(cluster_number.second), fat_bs->sectors_per_cluster, directory_cluster.get())){
if(!write_sectors(disk, cluster_lba(parent_cluster_number), fat_bs->sectors_per_cluster, directory_cluster.get())){
return false;
}