| 754 | } |
| 755 | |
| 756 | int Ext2Volume::WriteDir(Ext2Node* node, List<DirectoryEntry>& entries){ |
| 757 | if((node->flags & FS_NODE_TYPE) != FS_NODE_DIRECTORY){ |
| 758 | return -ENOTDIR; |
| 759 | } |
| 760 | |
| 761 | if(node->inode < 1){ |
| 762 | Log::Warning("[Ext2] WriteDir: Invalid inode: %d", node->inode); |
| 763 | return -1; |
| 764 | } |
| 765 | |
| 766 | ext2_inode_t& ino = node->e2inode; |
| 767 | |
| 768 | uint8_t buffer[blocksize]; |
| 769 | uint32_t currentBlockIndex = 0; |
| 770 | uint32_t blockOffset = 0; |
| 771 | uint32_t totalOffset = 0; |
| 772 | |
| 773 | ext2_directory_entry_t* e2dirent = (ext2_directory_entry_t*)kmalloc(sizeof(ext2_directory_entry_t) + NAME_MAX); |
| 774 | |
| 775 | unsigned lastIndex = entries.get_length() - 1; |
| 776 | for(unsigned i = 0; i < entries.get_length(); i++){ |
| 777 | DirectoryEntry ent = entries[i]; |
| 778 | |
| 779 | if(debugLevelExt2 >= DebugLevelVerbose){ |
| 780 | Log::Info("[Ext2] Writing entry: %s", ent.name); |
| 781 | } |
| 782 | |
| 783 | e2dirent->fileType = ent.flags; |
| 784 | e2dirent->inode = ent.inode; |
| 785 | strncpy(e2dirent->name, ent.name, strlen(ent.name)); |
| 786 | e2dirent->nameLength = strlen(ent.name); |
| 787 | |
| 788 | if(i == lastIndex){ |
| 789 | e2dirent->recordLength = blocksize - blockOffset; |
| 790 | } else { |
| 791 | if(strlen(entries[i + 1].name) + sizeof(ext2_directory_entry_t) + blockOffset > blocksize){ |
| 792 | e2dirent->recordLength = blocksize - blockOffset; // Directory entries cannot span multiple blocks |
| 793 | } else { |
| 794 | e2dirent->recordLength = sizeof(ext2_directory_entry_t) + e2dirent->nameLength; |
| 795 | if(e2dirent->recordLength && e2dirent->recordLength % 4){ |
| 796 | memset(((uint8_t*)e2dirent) + e2dirent->recordLength, 0, 4 - (e2dirent->recordLength % 4)); // Pad with zeros |
| 797 | e2dirent->recordLength += 4 - (e2dirent->recordLength % 4); // Round up to nearest multiple of 4 |
| 798 | } |
| 799 | } |
| 800 | } |
| 801 | |
| 802 | memcpy((buffer + blockOffset), e2dirent, sizeof(ext2_directory_entry_t) + e2dirent->nameLength); |
| 803 | blockOffset += e2dirent->recordLength; |
| 804 | totalOffset += e2dirent->recordLength; |
| 805 | |
| 806 | if(blockOffset >= blocksize){ |
| 807 | if(WriteBlockCached(GetInodeBlock(currentBlockIndex, ino), buffer)){ |
| 808 | Log::Error("[Ext2] WriteDir: Failed to write directory block"); |
| 809 | error = DiskWriteError; |
| 810 | return -1; |
| 811 | } |
| 812 | |
| 813 | currentBlockIndex++; |