Fix file read and refactor

This commit is contained in:
Terence Boldt 2021-07-02 06:54:25 -04:00
parent 07e0bacab3
commit 48121c279f
3 changed files with 103 additions and 70 deletions

View File

@ -73,7 +73,7 @@ func ReadDirectory(file *os.File, path string) (VolumeHeader, DirectoryHeader, [
return volumeHeader, directoryHeader, fileEntries
}
func GetFreeFileEntryInDirectory(file *os.File, directory string) (FileEntry, error) {
func getFreeFileEntryInDirectory(file *os.File, directory string) (FileEntry, error) {
_, directoryHeader, _ := ReadDirectory(file, directory)
//DumpDirectoryHeader(directoryHeader)
blockNumber := directoryHeader.StartingBlock

View File

@ -8,12 +8,15 @@ import (
)
func LoadFile(file *os.File, path string) ([]byte, error) {
fileEntry, err := GetFileEntry(file, path)
fileEntry, err := getFileEntry(file, path)
if err != nil {
return nil, err
}
blockList := getBlocklist(file, fileEntry)
blockList, err := getDataBlocklist(file, fileEntry)
if err != nil {
return nil, err
}
buffer := make([]byte, fileEntry.EndOfFile)
@ -30,7 +33,7 @@ func LoadFile(file *os.File, path string) ([]byte, error) {
func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []byte) error {
directory, fileName := GetDirectoryAndFileNameFromPath(path)
existingFileEntry, _ := GetFileEntry(file, path)
existingFileEntry, _ := getFileEntry(file, path)
if existingFileEntry.StorageType != StorageDeleted {
DeleteFile(file, path)
}
@ -38,50 +41,14 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b
// get list of blocks to write file to
blockList := createBlockList(file, len(buffer))
fileEntry, err := GetFreeFileEntryInDirectory(file, directory)
if err != nil {
return err
}
// seedling file
if len(buffer) <= 0x200 {
WriteBlock(file, blockList[0], buffer)
fileEntry.StorageType = StorageSeedling
}
// sapling file needs index block
if len(buffer) > 0x200 && len(buffer) <= 0x20000 {
fileEntry.StorageType = StorageSapling
// write index block with pointers to data blocks
indexBuffer := make([]byte, 512)
for i := 0; i < 256; i++ {
if i < len(blockList)-1 {
indexBuffer[i] = byte(blockList[i+1] & 0x00FF)
indexBuffer[i+256] = byte(blockList[i+1] >> 8)
}
}
WriteBlock(file, blockList[0], indexBuffer)
// write all data blocks
blockBuffer := make([]byte, 512)
blockPointer := 0
blockIndexNumber := 1
for i := 0; i < len(buffer); i++ {
blockBuffer[blockPointer] = buffer[i]
if blockPointer == 511 {
WriteBlock(file, blockList[blockIndexNumber], blockBuffer)
blockPointer = 0
blockIndexNumber++
} else if i == len(buffer)-1 {
for j := blockPointer; j < 512; j++ {
blockBuffer[j] = 0
}
WriteBlock(file, blockList[blockIndexNumber], blockBuffer)
} else {
blockPointer++
}
}
writeSaplingFile(file, buffer, blockList)
}
// TODO: add tree file
@ -89,14 +56,13 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b
return errors.New("Files > 128KB not supported yet.")
}
// update volume bitmap
volumeBitmap := ReadVolumeBitmap(file)
for i := 0; i < len(blockList); i++ {
markBlockInVolumeBitmap(volumeBitmap, blockList[i])
}
writeVolumeBitmap(file, volumeBitmap)
updateVolumeBitmap(file, blockList)
// add file entry to directory
fileEntry, err := getFreeFileEntryInDirectory(file, directory)
if err != nil {
return err
}
fileEntry.FileName = fileName
fileEntry.BlocksUsed = len(blockList)
fileEntry.CreationTime = time.Now()
@ -125,8 +91,48 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b
return nil
}
func updateVolumeBitmap(file *os.File, blockList []int) {
volumeBitmap := ReadVolumeBitmap(file)
for i := 0; i < len(blockList); i++ {
markBlockInVolumeBitmap(volumeBitmap, blockList[i])
}
writeVolumeBitmap(file, volumeBitmap)
}
func writeSaplingFile(file *os.File, buffer []byte, blockList []int) {
// write index block with pointers to data blocks
indexBuffer := make([]byte, 512)
for i := 0; i < 256; i++ {
if i < len(blockList)-1 {
indexBuffer[i] = byte(blockList[i+1] & 0x00FF)
indexBuffer[i+256] = byte(blockList[i+1] >> 8)
}
}
WriteBlock(file, blockList[0], indexBuffer)
// write all data blocks
blockBuffer := make([]byte, 512)
blockPointer := 0
blockIndexNumber := 1
for i := 0; i < len(buffer); i++ {
blockBuffer[blockPointer] = buffer[i]
if blockPointer == 511 {
WriteBlock(file, blockList[blockIndexNumber], blockBuffer)
blockPointer = 0
blockIndexNumber++
} else if i == len(buffer)-1 {
for j := blockPointer; j < 512; j++ {
blockBuffer[j] = 0
}
WriteBlock(file, blockList[blockIndexNumber], blockBuffer)
} else {
blockPointer++
}
}
}
func DeleteFile(file *os.File, path string) error {
fileEntry, err := GetFileEntry(file, path)
fileEntry, err := getFileEntry(file, path)
if err != nil {
return errors.New("File not found")
}
@ -135,7 +141,10 @@ func DeleteFile(file *os.File, path string) error {
}
// free the blocks
blocks := getBlocklist(file, fileEntry)
blocks, err := getBlocklist(file, fileEntry)
if err != nil {
return err
}
volumeBitmap := ReadVolumeBitmap(file)
for i := 0; i < len(blocks); i++ {
freeBlockInVolumeBitmap(volumeBitmap, blocks[i])
@ -157,30 +166,71 @@ func DeleteFile(file *os.File, path string) error {
return nil
}
func getBlocklist(file *os.File, fileEntry FileEntry) []int {
func GetDirectoryAndFileNameFromPath(path string) (string, string) {
path = strings.ToUpper(path)
paths := strings.Split(path, "/")
var directoryBuilder strings.Builder
for i := 1; i < len(paths)-1; i++ {
directoryBuilder.WriteString("/")
directoryBuilder.WriteString(paths[i])
}
directory := directoryBuilder.String()
fileName := paths[len(paths)-1]
return directory, fileName
}
// Returns all blocks, including index blocks
func getBlocklist(file *os.File, fileEntry FileEntry) ([]int, error) {
blocks := make([]int, fileEntry.BlocksUsed)
switch fileEntry.StorageType {
case StorageSeedling:
blocks[0] = fileEntry.KeyPointer
return blocks, nil
case StorageSapling:
index := ReadBlock(file, fileEntry.KeyPointer)
blocks[0] = fileEntry.KeyPointer
for i := 0; i < fileEntry.BlocksUsed-1; i++ {
blocks[i+1] = int(index[i]) + int(index[i+256])*256
}
return blocks, nil
case StorageTree:
masterIndex := ReadBlock(file, fileEntry.KeyPointer)
blocks[0] = fileEntry.KeyPointer
for i := 0; i < 128; i++ {
index := ReadBlock(file, int(masterIndex[i])+int(masterIndex[i+256])*256)
for j := 0; j < 256 && i*256+j < fileEntry.BlocksUsed; j++ {
if (int(index[j]) + int(index[j+256])*256) == 0 {
return blocks, nil
}
blocks[i*256+j] = int(index[j]) + int(index[j+256])*256
}
}
}
return blocks
return nil, errors.New("Unsupported file storage type")
}
func getDataBlocklist(file *os.File, fileEntry FileEntry) ([]int, error) {
switch fileEntry.StorageType {
case StorageSeedling:
blocks := make([]int, 1)
blocks[0] = fileEntry.KeyPointer
return blocks, nil
case StorageSapling:
blocks := make([]int, fileEntry.BlocksUsed-1)
index := ReadBlock(file, fileEntry.KeyPointer)
for i := 0; i < fileEntry.BlocksUsed-1; i++ {
blocks[i] = int(index[i]) + int(index[i+256])*256
}
return blocks, nil
}
return nil, errors.New("Unsupported file storage type")
}
func createBlockList(file *os.File, fileSize int) []int {
@ -207,7 +257,7 @@ func createBlockList(file *os.File, fileSize int) []int {
return blockList
}
func GetFileEntry(file *os.File, path string) (FileEntry, error) {
func getFileEntry(file *os.File, path string) (FileEntry, error) {
directory, fileName := GetDirectoryAndFileNameFromPath(path)
_, _, fileEntries := ReadDirectory(file, directory)
@ -229,20 +279,3 @@ func GetFileEntry(file *os.File, path string) (FileEntry, error) {
return fileEntry, nil
}
func GetDirectoryAndFileNameFromPath(path string) (string, string) {
path = strings.ToUpper(path)
paths := strings.Split(path, "/")
var directoryBuilder strings.Builder
for i := 1; i < len(paths)-1; i++ {
directoryBuilder.WriteString("/")
directoryBuilder.WriteString(paths[i])
}
directory := directoryBuilder.String()
fileName := paths[len(paths)-1]
return directory, fileName
}

View File

@ -21,7 +21,7 @@ func TestCreateVolume(t *testing.T) {
testname := fmt.Sprintf("%d", tt.blocks)
t.Run(testname, func(t *testing.T) {
fileName := os.TempDir() + "test-volume.hdv"
os.Remove(fileName)
defer os.Remove(fileName)
CreateVolume(fileName, tt.wantVolumeName, tt.blocks)
file, err := os.Open(fileName)