mirror of
https://github.com/zellyn/diskii.git
synced 2025-02-19 13:30:48 +00:00
Add error helper, supermon write/delete
This commit is contained in:
parent
a74a047d55
commit
821c2c5bb0
114
lib/errors/errors.go
Normal file
114
lib/errors/errors.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||||
|
|
||||||
|
// Package errors contains helpers for creating and testing for
|
||||||
|
// certain types of errors.
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Copy of errors.New, so you this package can be imported instead.
|
||||||
|
func New(text string) error {
|
||||||
|
return errors.New(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------- Out of space
|
||||||
|
|
||||||
|
// outOfSpace is an error that signals being out of space on a disk
|
||||||
|
// image.
|
||||||
|
type outOfSpace string
|
||||||
|
|
||||||
|
// OutOfSpaceI is the tag interface used to mark out of space errors.
|
||||||
|
type OutOfSpaceI interface {
|
||||||
|
IsOutOfSpace()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ OutOfSpaceI = outOfSpace("test")
|
||||||
|
|
||||||
|
// Error returns the string message of an OutOfSpace error.
|
||||||
|
func (o outOfSpace) Error() string {
|
||||||
|
return string(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag method on our outOfSpace implementation.
|
||||||
|
func (o outOfSpace) IsOutOfSpace() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutOfSpacef is fmt.Errorf for OutOfSpace errors.
|
||||||
|
func OutOfSpacef(format string, a ...interface{}) error {
|
||||||
|
return outOfSpace(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOutOfSpace returns true if a given error is an OutOfSpace error.
|
||||||
|
func IsOutOfSpace(err error) bool {
|
||||||
|
_, ok := err.(OutOfSpaceI)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------- File exists
|
||||||
|
|
||||||
|
// fileExists is an error returned when a problem is caused by a file
|
||||||
|
// with the given name already existing.
|
||||||
|
type fileExists string
|
||||||
|
|
||||||
|
// FileExistsI is the tag interface used to mark FileExists errors.
|
||||||
|
type FileExistsI interface {
|
||||||
|
IsFileExists()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ FileExistsI = fileExists("test")
|
||||||
|
|
||||||
|
// Error returns the string message of a FileExists error.
|
||||||
|
func (o fileExists) Error() string {
|
||||||
|
return string(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag method on our fileExists implementation.
|
||||||
|
func (o fileExists) IsFileExists() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileExistsf is fmt.Errorf for FileExists errors.
|
||||||
|
func FileExistsf(format string, a ...interface{}) error {
|
||||||
|
return fileExists(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFileExists returns true if a given error is a FileExists error.
|
||||||
|
func IsFileExists(err error) bool {
|
||||||
|
_, ok := err.(FileExistsI)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------- File not found
|
||||||
|
|
||||||
|
// fileNotFound is an error returned when a file with the given name
|
||||||
|
// cannot be found.
|
||||||
|
type fileNotFound string
|
||||||
|
|
||||||
|
// FileNotFoundI is the tag interface used to mark FileNotFound errors.
|
||||||
|
type FileNotFoundI interface {
|
||||||
|
IsFileNotFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ FileNotFoundI = fileNotFound("test")
|
||||||
|
|
||||||
|
// Error returns the string message of a FileNotFound error.
|
||||||
|
func (o fileNotFound) Error() string {
|
||||||
|
return string(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag method on our fileNotFound implementation.
|
||||||
|
func (o fileNotFound) IsFileNotFound() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileNotFoundf is fmt.Errorf for FileNotFound errors.
|
||||||
|
func FileNotFoundf(format string, a ...interface{}) error {
|
||||||
|
return fileNotFound(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFileNotFound returns true if a given error is a FileNotFound error.
|
||||||
|
func IsFileNotFound(err error) bool {
|
||||||
|
_, ok := err.(FileNotFoundI)
|
||||||
|
return ok
|
||||||
|
}
|
@ -11,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/zellyn/diskii/lib/disk"
|
"github.com/zellyn/diskii/lib/disk"
|
||||||
|
"github.com/zellyn/diskii/lib/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -47,6 +48,37 @@ func LoadSectorMap(sd disk.SectorDisk) (SectorMap, error) {
|
|||||||
return sm, nil
|
return sm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Persist writes the current contenst of a sector map back back to
|
||||||
|
// disk.
|
||||||
|
func (sm SectorMap) Persist(sd disk.SectorDisk) error {
|
||||||
|
sector09, err := sd.ReadPhysicalSector(0, 9)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
copy(sector09[0xd0:], sm[0:0x30])
|
||||||
|
if err := sd.WritePhysicalSector(0, 9, sector09); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := sd.WritePhysicalSector(0, 0xA, sm[0x30:0x130]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := sd.WritePhysicalSector(0, 0xB, sm[0x130:0x230]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FreeSectors returns the number of blocks free in a sector map.
|
||||||
|
func (sm SectorMap) FreeSectors() int {
|
||||||
|
count := 0
|
||||||
|
for _, file := range sm {
|
||||||
|
if file == FileFree {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
// Verify checks that we actually have a NakedOS disk.
|
// Verify checks that we actually have a NakedOS disk.
|
||||||
func (sm SectorMap) Verify() error {
|
func (sm SectorMap) Verify() error {
|
||||||
for sector := byte(0); sector <= 0xB; sector++ {
|
for sector := byte(0); sector <= 0xB; sector++ {
|
||||||
@ -118,6 +150,49 @@ func (sm SectorMap) ReadFile(sd disk.SectorDisk, file byte) ([]byte, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete deletes a file from the sector map. It does not persist the changes.
|
||||||
|
func (sm SectorMap) Delete(file byte) {
|
||||||
|
for i, f := range sm {
|
||||||
|
if f == file {
|
||||||
|
sm[i] = FileFree
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteFile writes the contents of a file.
|
||||||
|
func (sm SectorMap) WriteFile(sd disk.SectorDisk, file byte, contents []byte, overwrite bool) error {
|
||||||
|
sectorsNeeded := (len(contents) + 255) / 256
|
||||||
|
cts := make([]byte, 256*sectorsNeeded)
|
||||||
|
copy(cts, contents)
|
||||||
|
free := sm.FreeSectors() + len(sm.SectorsForFile(file))
|
||||||
|
if free < sectorsNeeded {
|
||||||
|
return errors.OutOfSpacef("file requires %d sectors, but only %d are available")
|
||||||
|
}
|
||||||
|
sm.Delete(file)
|
||||||
|
|
||||||
|
// TODO(zellyn): continue implementation.
|
||||||
|
return fmt.Errorf("WriteFile not implemented yet")
|
||||||
|
i := 0
|
||||||
|
OUTER:
|
||||||
|
for track := byte(0); track < sd.Tracks(); track++ {
|
||||||
|
for sector := byte(0); sector < sd.Sectors(); sector++ {
|
||||||
|
if sm.FileForSector(track, sector) == file {
|
||||||
|
if err := sd.WritePhysicalSector(track, sector, cts[i*256:(i+1)*256]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
if i == sectorsNeeded {
|
||||||
|
break OUTER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := sm.Persist(sd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Symbol represents a single Super-Mon symbol.
|
// Symbol represents a single Super-Mon symbol.
|
||||||
type Symbol struct {
|
type Symbol struct {
|
||||||
// Address is the memory address the symbol points to, or 0 for an
|
// Address is the memory address the symbol points to, or 0 for an
|
||||||
|
Loading…
x
Reference in New Issue
Block a user