mirror of
https://github.com/tjboldt/ProDOS-Utilities.git
synced 2024-11-28 12:51:35 +00:00
Fix file delete and write
This commit is contained in:
parent
a9b1a9e482
commit
59f4391757
@ -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)
|
||||
}
|
||||
|
107
prodos/file.go
107
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)
|
||||
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user