mirror of
https://github.com/tjboldt/ProDOS-Utilities.git
synced 2024-12-01 01:49:59 +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) {
|
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)
|
||||||
}
|
}
|
||||||
|
107
prodos/file.go
107
prodos/file.go
@ -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)
|
||||||
|
|
||||||
|
existingFileEntry, _ := GetFileEntry(file, path)
|
||||||
|
if existingFileEntry.StorageType != StorageDeleted {
|
||||||
DeleteFile(file, path)
|
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
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user