From 59f4391757ebddecd327bcc8af0da18b59964ae1 Mon Sep 17 00:00:00 2001 From: Terence Boldt Date: Wed, 30 Jun 2021 08:22:08 -0400 Subject: [PATCH] Fix file delete and write --- prodos/directory.go | 9 ++-- prodos/file.go | 109 +++++++++++++++++++++++++------------------- 2 files changed, 68 insertions(+), 50 deletions(-) diff --git a/prodos/directory.go b/prodos/directory.go index 786a1e2..309ab6e 100644 --- a/prodos/directory.go +++ b/prodos/directory.go @@ -110,7 +110,6 @@ func GetFreeFileEntryInDirectory(file *os.File, directory string) (FileEntry, er } func getFileEntriesInDirectory(file *os.File, blockNumber int, currentPath int, paths []string) (DirectoryHeader, []FileEntry) { - buffer := ReadBlock(file, blockNumber) directoryHeader := parseDirectoryHeader(buffer, blockNumber) @@ -281,8 +280,10 @@ func parseDirectoryHeader(buffer []byte, blockNumber int) DirectoryHeader { return directoryEntry } -func writeDirectoryHeader(file *os.File, directoryHeader DirectoryHeader, blockNumber int) { - buffer := ReadBlock(file, blockNumber) +func writeDirectoryHeader(file *os.File, directoryHeader DirectoryHeader) { + buffer := ReadBlock(file, directoryHeader.StartingBlock) + buffer[0x00] = byte(directoryHeader.PreviousBlock & 0x00FF) + buffer[0x01] = byte(directoryHeader.PreviousBlock >> 8) buffer[0x02] = byte(directoryHeader.NextBlock & 0x00FF) buffer[0x03] = byte(directoryHeader.NextBlock >> 8) buffer[0x04] = buffer[0x04] | byte(len(directoryHeader.Name)) @@ -291,5 +292,5 @@ func writeDirectoryHeader(file *os.File, directoryHeader DirectoryHeader, blockN } buffer[0x25] = byte(directoryHeader.ActiveFileCount & 0x00FF) buffer[0x26] = byte(directoryHeader.ActiveFileCount >> 8) - file.WriteAt(buffer, int64(blockNumber*512)) + WriteBlock(file, directoryHeader.StartingBlock, buffer) } diff --git a/prodos/file.go b/prodos/file.go index 16dce5b..b7171d3 100644 --- a/prodos/file.go +++ b/prodos/file.go @@ -2,7 +2,6 @@ package prodos import ( "errors" - "fmt" "os" "strings" "time" @@ -31,7 +30,10 @@ 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) - DeleteFile(file, path) + existingFileEntry, _ := GetFileEntry(file, path) + if existingFileEntry.StorageType != StorageDeleted { + DeleteFile(file, path) + } // get list of blocks to write file to blockList := createBlockList(file, len(buffer)) @@ -53,13 +55,12 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b // write index block with pointers to data blocks indexBuffer := make([]byte, 512) - for i := 1; i < 256; i++ { - if i < len(blockList) { - indexBuffer[i] = byte(blockList[i] & 0x00FF) - indexBuffer[i+256] = byte(blockList[i] >> 8) + 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) } } - fmt.Println("writing index block") WriteBlock(file, blockList[0], indexBuffer) // write all data blocks @@ -69,13 +70,10 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b for i := 0; i < len(buffer); i++ { blockBuffer[blockPointer] = buffer[i] if blockPointer == 511 { - fmt.Printf("A i: %d, blockIndexNumber: %d, blockPointer: %d blockList[blockIndexNumber]: %d\n", i, blockIndexNumber, blockPointer, blockList[blockIndexNumber]) - fmt.Println(blockIndexNumber) WriteBlock(file, blockList[blockIndexNumber], blockBuffer) blockPointer = 0 blockIndexNumber++ } else if i == len(buffer)-1 { - fmt.Printf("B i: %d, blockIndexNumber: %d, blockPointer: %d\n", i, blockIndexNumber, blockPointer) for j := blockPointer; j < 512; j++ { blockBuffer[j] = 0 } @@ -87,6 +85,9 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b } // TODO: add tree file + if len(buffer) > 0x20000 { + return errors.New("Files > 128KB not supported yet.") + } // update volume bitmap volumeBitmap := ReadVolumeBitmap(file) @@ -105,9 +106,54 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b fileEntry.FileType = fileType fileEntry.KeyPointer = blockList[0] fileEntry.Access = 0b11100011 + if len(blockList) == 1 { + fileEntry.StorageType = StorageSeedling + } else if len(blockList) <= 257 { + fileEntry.StorageType = StorageSapling + } else { + fileEntry.StorageType = StorageTree + } writeFileEntry(file, fileEntry) + // increment file count + directoryHeaderBlock := ReadBlock(file, fileEntry.HeaderPointer) + directoryHeader := parseDirectoryHeader(directoryHeaderBlock, fileEntry.HeaderPointer) + directoryHeader.ActiveFileCount++ + writeDirectoryHeader(file, directoryHeader) + + return nil +} + +func DeleteFile(file *os.File, path string) error { + fileEntry, err := GetFileEntry(file, path) + if err != nil { + return errors.New("File not found") + } + if fileEntry.StorageType == StorageDeleted { + return errors.New("File already deleted") + } + + // free the blocks + blocks := getBlocklist(file, fileEntry) + volumeBitmap := ReadVolumeBitmap(file) + for i := 0; i < len(blocks); i++ { + freeBlockInVolumeBitmap(volumeBitmap, blocks[i]) + } + writeVolumeBitmap(file, volumeBitmap) + + // decrement the directory entry count + directoryBlock := ReadBlock(file, fileEntry.HeaderPointer) + directoryHeader := parseDirectoryHeader(directoryBlock, fileEntry.HeaderPointer) + + directoryHeader.ActiveFileCount-- + writeDirectoryHeader(file, directoryHeader) + + // zero out directory entry + fileEntry.StorageType = 0 + fileEntry.FileName = "" + writeFileEntry(file, fileEntry) + return nil } @@ -120,8 +166,8 @@ func getBlocklist(file *os.File, fileEntry FileEntry) []int { case StorageSapling: index := ReadBlock(file, fileEntry.KeyPointer) blocks[0] = fileEntry.KeyPointer - for i := 1; i < fileEntry.BlocksUsed-1; i++ { - blocks[i] = int(index[i]) + int(index[i+256])*256 + for i := 0; i < fileEntry.BlocksUsed-1; i++ { + blocks[i+1] = int(index[i]) + int(index[i+256])*256 } case StorageTree: masterIndex := ReadBlock(file, fileEntry.KeyPointer) @@ -163,10 +209,9 @@ func createBlockList(file *os.File, fileSize int) []int { func GetFileEntry(file *os.File, path string) (FileEntry, error) { directory, fileName := GetDirectoryAndFileNameFromPath(path) - _, _, fileEntries := ReadDirectory(file, directory) - if fileEntries == nil { + if fileEntries == nil || len(fileEntries) == 0 { return FileEntry{}, errors.New("File entry not found") } @@ -178,6 +223,10 @@ func GetFileEntry(file *os.File, path string) (FileEntry, error) { } } + if fileEntry.StorageType == StorageDeleted { + return FileEntry{}, errors.New("File not found") + } + return fileEntry, nil } @@ -197,35 +246,3 @@ func GetDirectoryAndFileNameFromPath(path string) (string, string) { return directory, fileName } - -func DeleteFile(file *os.File, path string) error { - fileEntry, err := GetFileEntry(file, path) - if err != nil { - return errors.New("File not found") - } - if fileEntry.StorageType == StorageDeleted { - return errors.New("File already deleted") - } - - // free the blocks - blocks := getBlocklist(file, fileEntry) - volumeBitmap := ReadVolumeBitmap(file) - for i := 0; i < len(blocks); i++ { - freeBlockInVolumeBitmap(volumeBitmap, blocks[i]) - } - writeVolumeBitmap(file, volumeBitmap) - - // zero out directory entry - fileEntry.StorageType = 0 - fileEntry.FileName = "" - writeFileEntry(file, fileEntry) - - // decrement the directory entry count - directoryBlock := ReadBlock(file, fileEntry.HeaderPointer) - directoryHeader := parseDirectoryHeader(directoryBlock, fileEntry.HeaderPointer) - - directoryHeader.ActiveFileCount-- - writeDirectoryHeader(file, directoryHeader, fileEntry.HeaderPointer) - - return nil -}