Add directory creation

This commit is contained in:
Terence Boldt 2023-01-19 00:30:17 -05:00
parent ee3d187fb3
commit 876564d261
4 changed files with 136 additions and 11 deletions

12
main.go
View File

@ -169,6 +169,18 @@ func main() {
} }
defer file.Close() defer file.Close()
prodos.DeleteFile(file, pathName) prodos.DeleteFile(file, pathName)
case "mkdir":
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
if err != nil {
fmt.Printf("Failed to open drive image %s:\n %s", fileName, err)
os.Exit(1)
}
defer file.Close()
err = prodos.CreateDirectory(file, pathName)
if err != nil {
fmt.Printf("failed to create directory %s: %s\n", pathName, err)
return
}
case "dumpfile": case "dumpfile":
file, err := os.OpenFile(fileName, os.O_RDWR, 0755) file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
if err != nil { if err != nil {

View File

@ -31,11 +31,20 @@ type VolumeHeader struct {
// DirectoryHeader from ProDOS // DirectoryHeader from ProDOS
type DirectoryHeader struct { type DirectoryHeader struct {
Name string PreviousBlock int
ActiveFileCount int NextBlock int
StartingBlock int Name string
PreviousBlock int CreationTime time.Time
NextBlock int Version int
MinVersion int
Access int
EntryLength int
EntriesPerBlock int
ActiveFileCount int
StartingBlock int
ParentBlock int
ParentEntry int
ParentEntryLength int
} }
const ( const (
@ -97,6 +106,75 @@ func ReadDirectory(reader io.ReaderAt, path string) (VolumeHeader, DirectoryHead
return volumeHeader, directoryHeader, fileEntries, nil return volumeHeader, directoryHeader, fileEntries, nil
} }
func CreateDirectory(readerWriter ReaderWriterAt, path string) error {
parentPath, newDirectory := GetDirectoryAndFileNameFromPath(path)
existingFileEntry, _ := GetFileEntry(readerWriter, path)
if existingFileEntry.StorageType != StorageDeleted {
//DeleteFile(readerWriter, path)
return errors.New("directory already exists")
}
fileEntry, err := getFreeFileEntryInDirectory(readerWriter, parentPath)
if err != nil {
errString := fmt.Sprintf("failed to create directory: %s", err)
return errors.New(errString)
}
// get list of blocks to write file to
blockList, err := createBlockList(readerWriter, 512)
if err != nil {
errString := fmt.Sprintf("failed to create directory: %s", err)
return errors.New(errString)
}
updateVolumeBitmap(readerWriter, blockList)
fileEntry.FileName = newDirectory
fileEntry.BlocksUsed = 1
fileEntry.CreationTime = time.Now()
fileEntry.ModifiedTime = time.Now()
fileEntry.AuxType = 0
fileEntry.EndOfFile = 0x200
fileEntry.FileType = 0x0F
fileEntry.KeyPointer = blockList[0]
fileEntry.Access = 0b11100011
fileEntry.StorageType = StorageDirectory
writeFileEntry(readerWriter, fileEntry)
err = incrementFileCount(readerWriter, fileEntry)
if err != nil {
errString := fmt.Sprintf("failed to create directory: %s", err)
return errors.New(errString)
}
directoryEntry := DirectoryHeader{
PreviousBlock: 0,
NextBlock: 0,
Name: newDirectory,
CreationTime: time.Now(),
Version: 0x24,
MinVersion: 0,
Access: 0xE3,
EntryLength: 0x27,
EntriesPerBlock: 0x0D,
ActiveFileCount: 0,
StartingBlock: blockList[0],
ParentBlock: fileEntry.DirectoryBlock,
ParentEntry: fileEntry.DirectoryOffset,
ParentEntryLength: 0x27,
}
err = writeDirectoryHeader(readerWriter, directoryEntry)
if err != nil {
errString := fmt.Sprintf("failed to create directory: %s", err)
return errors.New(errString)
}
return nil
}
func getFreeFileEntryInDirectory(reader io.ReaderAt, directory string) (FileEntry, error) { func getFreeFileEntryInDirectory(reader io.ReaderAt, directory string) (FileEntry, error) {
_, directoryHeader, _, err := ReadDirectory(reader, directory) _, directoryHeader, _, err := ReadDirectory(reader, directory)
if err != nil { if err != nil {
@ -305,14 +383,32 @@ func parseDirectoryHeader(buffer []byte, blockNumber int) DirectoryHeader {
nextBlock := int(buffer[0x02]) + int(buffer[0x03])*256 nextBlock := int(buffer[0x02]) + int(buffer[0x03])*256
filenameLength := buffer[0x04] & 15 filenameLength := buffer[0x04] & 15
name := string(buffer[0x05 : filenameLength+0x05]) name := string(buffer[0x05 : filenameLength+0x05])
creationTime := DateTimeFromProDOS(buffer[0x1C:0x20])
version := int(buffer[0x20])
minVersion := int(buffer[0x21])
access := int(buffer[0x22])
entryLength := int(buffer[0x23])
entriesPerBlock := int(buffer[0x24])
fileCount := int(buffer[0x25]) + int(buffer[0x26])*256 fileCount := int(buffer[0x25]) + int(buffer[0x26])*256
parentBlock := int(buffer[0x27]) + int(buffer[0x28])*256
parentEntry := int(buffer[0x29])
parentEntryLength := int(buffer[0x2A])
directoryEntry := DirectoryHeader{ directoryEntry := DirectoryHeader{
PreviousBlock: previousBlock, PreviousBlock: previousBlock,
NextBlock: nextBlock, NextBlock: nextBlock,
StartingBlock: blockNumber, StartingBlock: blockNumber,
Name: name, Name: name,
ActiveFileCount: fileCount, CreationTime: creationTime,
Version: version,
MinVersion: minVersion,
Access: access,
EntryLength: entryLength,
EntriesPerBlock: entriesPerBlock,
ActiveFileCount: fileCount,
ParentBlock: parentBlock,
ParentEntry: parentEntry,
ParentEntryLength: parentEntryLength,
} }
return directoryEntry return directoryEntry
@ -331,8 +427,21 @@ func writeDirectoryHeader(readerWriter ReaderWriterAt, directoryHeader Directory
for i := 0; i < len(directoryHeader.Name); i++ { for i := 0; i < len(directoryHeader.Name); i++ {
buffer[0x05+i] = directoryHeader.Name[i] buffer[0x05+i] = directoryHeader.Name[i]
} }
creationTime := DateTimeToProDOS(directoryHeader.CreationTime)
for i := 0; i < 4; i++ {
buffer[0x1C+i] = creationTime[i]
}
buffer[0x20] = byte(directoryHeader.Version)
buffer[0x21] = byte(directoryHeader.MinVersion)
buffer[0x22] = byte(directoryHeader.Access)
buffer[0x23] = byte(directoryHeader.EntryLength)
buffer[0x24] = byte(directoryHeader.EntriesPerBlock)
buffer[0x25] = byte(directoryHeader.ActiveFileCount & 0x00FF) buffer[0x25] = byte(directoryHeader.ActiveFileCount & 0x00FF)
buffer[0x26] = byte(directoryHeader.ActiveFileCount >> 8) buffer[0x26] = byte(directoryHeader.ActiveFileCount >> 8)
buffer[0x27] = byte(directoryHeader.ParentBlock & 0x00FF)
buffer[0x28] = byte(directoryHeader.ParentBlock >> 8)
buffer[0x29] = byte(directoryHeader.ParentEntry)
buffer[0x2A] = byte(directoryHeader.ParentEntryLength)
WriteBlock(readerWriter, directoryHeader.StartingBlock, buffer) WriteBlock(readerWriter, directoryHeader.StartingBlock, buffer)
return nil return nil

View File

@ -102,7 +102,10 @@ func WriteFile(readerWriter ReaderWriterAt, path string, fileType int, auxType i
writeFileEntry(readerWriter, fileEntry) writeFileEntry(readerWriter, fileEntry)
// increment file count return incrementFileCount(readerWriter, fileEntry)
}
func incrementFileCount(readerWriter ReaderWriterAt, fileEntry FileEntry) error {
directoryHeaderBlock, err := ReadBlock(readerWriter, fileEntry.HeaderPointer) directoryHeaderBlock, err := ReadBlock(readerWriter, fileEntry.HeaderPointer)
if err != nil { if err != nil {
return err return err

View File

@ -99,6 +99,7 @@ func DumpFileEntry(fileEntry FileEntry) {
fmt.Printf("File type: %02X\n", fileEntry.FileType) fmt.Printf("File type: %02X\n", fileEntry.FileType)
fmt.Printf("Storage type: %02X\n", fileEntry.StorageType) fmt.Printf("Storage type: %02X\n", fileEntry.StorageType)
fmt.Printf("Header pointer: %04X\n", fileEntry.HeaderPointer) fmt.Printf("Header pointer: %04X\n", fileEntry.HeaderPointer)
fmt.Printf("Access: %04X\n", fileEntry.Access)
fmt.Printf("\n") fmt.Printf("\n")
} }