Fix file delete and write

This commit is contained in:
Terence Boldt 2021-06-30 08:22:08 -04:00
parent a9b1a9e482
commit 59f4391757
2 changed files with 68 additions and 50 deletions

View File

@ -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) { func getFileEntriesInDirectory(file *os.File, blockNumber int, currentPath int, paths []string) (DirectoryHeader, []FileEntry) {
buffer := ReadBlock(file, blockNumber) buffer := ReadBlock(file, blockNumber)
directoryHeader := parseDirectoryHeader(buffer, blockNumber) directoryHeader := parseDirectoryHeader(buffer, blockNumber)
@ -281,8 +280,10 @@ func parseDirectoryHeader(buffer []byte, blockNumber int) DirectoryHeader {
return directoryEntry return directoryEntry
} }
func writeDirectoryHeader(file *os.File, directoryHeader DirectoryHeader, blockNumber int) { func writeDirectoryHeader(file *os.File, directoryHeader DirectoryHeader) {
buffer := ReadBlock(file, blockNumber) buffer := ReadBlock(file, directoryHeader.StartingBlock)
buffer[0x00] = byte(directoryHeader.PreviousBlock & 0x00FF)
buffer[0x01] = byte(directoryHeader.PreviousBlock >> 8)
buffer[0x02] = byte(directoryHeader.NextBlock & 0x00FF) buffer[0x02] = byte(directoryHeader.NextBlock & 0x00FF)
buffer[0x03] = byte(directoryHeader.NextBlock >> 8) buffer[0x03] = byte(directoryHeader.NextBlock >> 8)
buffer[0x04] = buffer[0x04] | byte(len(directoryHeader.Name)) 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[0x25] = byte(directoryHeader.ActiveFileCount & 0x00FF)
buffer[0x26] = byte(directoryHeader.ActiveFileCount >> 8) buffer[0x26] = byte(directoryHeader.ActiveFileCount >> 8)
file.WriteAt(buffer, int64(blockNumber*512)) WriteBlock(file, directoryHeader.StartingBlock, buffer)
} }

View File

@ -2,7 +2,6 @@ package prodos
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"strings" "strings"
"time" "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 { func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []byte) error {
directory, fileName := GetDirectoryAndFileNameFromPath(path) 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 // get list of blocks to write file to
blockList := createBlockList(file, len(buffer)) 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 // write index block with pointers to data blocks
indexBuffer := make([]byte, 512) indexBuffer := make([]byte, 512)
for i := 1; i < 256; i++ { for i := 0; i < 256; i++ {
if i < len(blockList) { if i < len(blockList)-1 {
indexBuffer[i] = byte(blockList[i] & 0x00FF) indexBuffer[i] = byte(blockList[i+1] & 0x00FF)
indexBuffer[i+256] = byte(blockList[i] >> 8) indexBuffer[i+256] = byte(blockList[i+1] >> 8)
} }
} }
fmt.Println("writing index block")
WriteBlock(file, blockList[0], indexBuffer) WriteBlock(file, blockList[0], indexBuffer)
// write all data blocks // 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++ { for i := 0; i < len(buffer); i++ {
blockBuffer[blockPointer] = buffer[i] blockBuffer[blockPointer] = buffer[i]
if blockPointer == 511 { 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) WriteBlock(file, blockList[blockIndexNumber], blockBuffer)
blockPointer = 0 blockPointer = 0
blockIndexNumber++ blockIndexNumber++
} else if i == len(buffer)-1 { } 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++ { for j := blockPointer; j < 512; j++ {
blockBuffer[j] = 0 blockBuffer[j] = 0
} }
@ -87,6 +85,9 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b
} }
// TODO: add tree file // TODO: add tree file
if len(buffer) > 0x20000 {
return errors.New("Files > 128KB not supported yet.")
}
// update volume bitmap // update volume bitmap
volumeBitmap := ReadVolumeBitmap(file) volumeBitmap := ReadVolumeBitmap(file)
@ -105,9 +106,54 @@ func WriteFile(file *os.File, path string, fileType int, auxType int, buffer []b
fileEntry.FileType = fileType fileEntry.FileType = fileType
fileEntry.KeyPointer = blockList[0] fileEntry.KeyPointer = blockList[0]
fileEntry.Access = 0b11100011 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) 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 return nil
} }
@ -120,8 +166,8 @@ func getBlocklist(file *os.File, fileEntry FileEntry) []int {
case StorageSapling: case StorageSapling:
index := ReadBlock(file, fileEntry.KeyPointer) index := ReadBlock(file, fileEntry.KeyPointer)
blocks[0] = fileEntry.KeyPointer blocks[0] = fileEntry.KeyPointer
for i := 1; i < fileEntry.BlocksUsed-1; i++ { for i := 0; i < fileEntry.BlocksUsed-1; i++ {
blocks[i] = int(index[i]) + int(index[i+256])*256 blocks[i+1] = int(index[i]) + int(index[i+256])*256
} }
case StorageTree: case StorageTree:
masterIndex := ReadBlock(file, fileEntry.KeyPointer) 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) { func GetFileEntry(file *os.File, path string) (FileEntry, error) {
directory, fileName := GetDirectoryAndFileNameFromPath(path) directory, fileName := GetDirectoryAndFileNameFromPath(path)
_, _, fileEntries := ReadDirectory(file, directory) _, _, fileEntries := ReadDirectory(file, directory)
if fileEntries == nil { if fileEntries == nil || len(fileEntries) == 0 {
return FileEntry{}, errors.New("File entry not found") 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 return fileEntry, nil
} }
@ -197,35 +246,3 @@ func GetDirectoryAndFileNameFromPath(path string) (string, string) {
return directory, fileName 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
}