mirror of https://github.com/zellyn/diskii.git
refactor to make more disk/device agnostic
This commit is contained in:
parent
5bd50043b9
commit
2d0d2773a4
|
@ -37,11 +37,7 @@ func runCat(args []string) error {
|
|||
if len(args) < 1 || len(args) > 2 {
|
||||
return fmt.Errorf("cat expects a disk image filename, and an optional subdirectory")
|
||||
}
|
||||
sd, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op, err := disk.OperatorFor(sd)
|
||||
op, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -38,11 +38,7 @@ func runDelete(args []string) error {
|
|||
if len(args) != 2 {
|
||||
return fmt.Errorf("delete expects a disk image filename, and a filename")
|
||||
}
|
||||
sd, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op, err := disk.OperatorFor(sd)
|
||||
op, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -57,7 +53,7 @@ func runDelete(args []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = sd.Write(f)
|
||||
_, err = op.Write(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -36,11 +36,7 @@ func runDump(args []string) error {
|
|||
if len(args) != 2 {
|
||||
return fmt.Errorf("dump expects a disk image filename, and a filename")
|
||||
}
|
||||
sd, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op, err := disk.OperatorFor(sd)
|
||||
op, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -68,11 +68,7 @@ func runMkhello(args []string) error {
|
|||
if start < address {
|
||||
return fmt.Errorf("start address %d (%04X) < load address %d (%04X)", start, start, address, address)
|
||||
}
|
||||
sd, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op, err := disk.OperatorFor(sd)
|
||||
op, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -118,7 +114,7 @@ func runMkhello(args []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = sd.Write(f)
|
||||
_, err = op.Write(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -42,11 +42,7 @@ func runPut(args []string) error {
|
|||
if len(args) != 3 {
|
||||
return fmt.Errorf("usage: put <disk image> <target filename> <source filename>")
|
||||
}
|
||||
sd, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op, err := disk.OperatorFor(sd)
|
||||
op, err := disk.Open(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -76,7 +72,7 @@ func runPut(args []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = sd.Write(f)
|
||||
_, err = op.Write(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -156,8 +156,8 @@ func (md MappedDisk) Write(w io.Writer) (n int, err error) {
|
|||
return md.sectorDisk.Write(w)
|
||||
}
|
||||
|
||||
// Open opens a disk image by filename.
|
||||
func Open(filename string) (SectorDisk, error) {
|
||||
// OpenDisk opens a disk image by filename.
|
||||
func OpenDisk(filename string) (SectorDisk, error) {
|
||||
ext := strings.ToLower(path.Ext(filename))
|
||||
switch ext {
|
||||
case ".dsk":
|
||||
|
@ -165,3 +165,16 @@ func Open(filename string) (SectorDisk, error) {
|
|||
}
|
||||
return nil, fmt.Errorf("Unimplemented/unknown disk file extension %q", ext)
|
||||
}
|
||||
|
||||
// Open opens a disk image by filename, returning an Operator.
|
||||
func Open(filename string) (Operator, error) {
|
||||
sd, err := OpenDisk(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
op, err := OperatorForDisk(sd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return op, nil
|
||||
}
|
||||
|
|
|
@ -1,10 +1,30 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// marshal.go contains helpers for marshaling sector structs to/from
|
||||
// disk.
|
||||
// disk and block structs to/from devices.
|
||||
|
||||
package disk
|
||||
|
||||
import "io"
|
||||
|
||||
// A ProDOS block.
|
||||
type Block [512]byte
|
||||
|
||||
// BlockDevice is the interface used to read and write devices by
|
||||
// logical block number.
|
||||
type BlockDevice interface {
|
||||
// ReadBlock reads a single block from the device. It always returns
|
||||
// 512 byes.
|
||||
ReadBlock(index uint16) (Block, error)
|
||||
// WriteBlock writes a single block to a device. It expects exactly
|
||||
// 512 bytes.
|
||||
WriteBlock(index uint16, data Block) error
|
||||
// Blocks returns the number of blocks on the device.
|
||||
Blocks() uint16
|
||||
// Write writes the device contents to the given Writer.
|
||||
Write(io.Writer) (int, error)
|
||||
}
|
||||
|
||||
// SectorSource is the interface for types that can marshal to sectors.
|
||||
type SectorSource interface {
|
||||
// ToSector marshals the sector struct to exactly 256 bytes.
|
||||
|
@ -52,3 +72,44 @@ func MarshalLogicalSector(d LogicalSectorDisk, ss SectorSource) error {
|
|||
}
|
||||
return d.WriteLogicalSector(track, sector, bytes)
|
||||
}
|
||||
|
||||
// BlockSource is the interface for types that can marshal to blocks.
|
||||
type BlockSource interface {
|
||||
// ToBlock marshals the block struct to exactly 512 bytes.
|
||||
ToBlock() (Block, error)
|
||||
// GetBlock returns the index that a block struct was loaded from.
|
||||
GetBlock() uint16
|
||||
}
|
||||
|
||||
// BlockSink is the interface for types that can unmarshal from blocks.
|
||||
type BlockSink interface {
|
||||
// FromBlock unmarshals the block struct from a Block. Input is
|
||||
// expected to be exactly 512 bytes.
|
||||
FromBlock(block Block) error
|
||||
// SetBlock sets the index that a block struct was loaded from.
|
||||
SetBlock(index uint16)
|
||||
}
|
||||
|
||||
// UnmarshalBlock reads a block from a BlockDevice, and unmarshals it
|
||||
// into a BlockSink, setting its index.
|
||||
func UnmarshalBlock(d BlockDevice, bs BlockSink, index uint16) error {
|
||||
block, err := d.ReadBlock(index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bs.FromBlock(block); err != nil {
|
||||
return err
|
||||
}
|
||||
bs.SetBlock(index)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBlock marshals a BlockSource to its block on a BlockDevice.
|
||||
func MarshalBlock(d BlockDevice, bs BlockSource) error {
|
||||
index := bs.GetBlock()
|
||||
block, err := bs.ToBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return d.WriteBlock(index, block)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package disk
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
@ -42,6 +43,8 @@ type Operator interface {
|
|||
// is false, it returns with an error. Otherwise it returns true if
|
||||
// an existing file was overwritten.
|
||||
PutFile(fileInfo FileInfo, overwrite bool) (existed bool, err error)
|
||||
// Write writes the underlying disk to the given writer.
|
||||
Write(io.Writer) (int, error)
|
||||
}
|
||||
|
||||
// FileInfo represents a file descriptor plus the content.
|
||||
|
@ -51,40 +54,40 @@ type FileInfo struct {
|
|||
StartAddress uint16
|
||||
}
|
||||
|
||||
// operatorFactory is the type of functions that accept a SectorDisk,
|
||||
// diskOperatorFactory is the type of functions that accept a SectorDisk,
|
||||
// and may return an Operator interface to operate on it.
|
||||
type operatorFactory func(SectorDisk) (Operator, error)
|
||||
type diskOperatorFactory func(SectorDisk) (Operator, error)
|
||||
|
||||
// operatorFactories is the map of currently-registered operator
|
||||
// factories.
|
||||
var operatorFactories map[string]operatorFactory
|
||||
// diskOperatorFactories is the map of currently-registered disk
|
||||
// operator factories.
|
||||
var diskOperatorFactories map[string]diskOperatorFactory
|
||||
|
||||
func init() {
|
||||
operatorFactories = make(map[string]operatorFactory)
|
||||
diskOperatorFactories = make(map[string]diskOperatorFactory)
|
||||
}
|
||||
|
||||
// RegisterOperatorFactory registers an operator factory with the
|
||||
// given name: a function that accepts a SectorDisk, and may return an
|
||||
// Operator. It doesn't lock operatorFactories: it is expected to be
|
||||
// called only from package `init` functions.
|
||||
func RegisterOperatorFactory(name string, factory operatorFactory) {
|
||||
operatorFactories[name] = factory
|
||||
// RegisterDiskOperatorFactory registers a disk operator factory with
|
||||
// the given name: a function that accepts a SectorDisk, and may
|
||||
// return an Operator. It doesn't lock diskOperatorFactories: it is
|
||||
// expected to be called only from package `init` functions.
|
||||
func RegisterDiskOperatorFactory(name string, factory diskOperatorFactory) {
|
||||
diskOperatorFactories[name] = factory
|
||||
}
|
||||
|
||||
// OperatorFor returns an Operator for the given SectorDisk, if possible.
|
||||
func OperatorFor(sd SectorDisk) (Operator, error) {
|
||||
if len(operatorFactories) == 0 {
|
||||
// OperatorForDisk returns an Operator for the given SectorDisk, if possible.
|
||||
func OperatorForDisk(sd SectorDisk) (Operator, error) {
|
||||
if len(diskOperatorFactories) == 0 {
|
||||
return nil, errors.New("Cannot find an operator matching the given disk image (none registered)")
|
||||
}
|
||||
for _, factory := range operatorFactories {
|
||||
for _, factory := range diskOperatorFactories {
|
||||
if operator, err := factory(sd); err == nil {
|
||||
return operator, nil
|
||||
}
|
||||
}
|
||||
names := make([]string, 0, len(operatorFactories))
|
||||
for name := range operatorFactories {
|
||||
names := make([]string, 0, len(diskOperatorFactories))
|
||||
for name := range diskOperatorFactories {
|
||||
names = append(names, `"`+name+`"`)
|
||||
}
|
||||
sort.Strings(names)
|
||||
return nil, fmt.Errorf("Cannot find an operator matching the given disk image (tried %s)", strings.Join(names, ", "))
|
||||
return nil, fmt.Errorf("Cannot find a disk operator matching the given disk image (tried %s)", strings.Join(names, ", "))
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package dos3
|
|||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
|
@ -669,6 +670,11 @@ func (o operator) PutFile(fileInfo disk.FileInfo, overwrite bool) (existed bool,
|
|||
return false, fmt.Errorf("%s does not implement PutFile yet", operatorName)
|
||||
}
|
||||
|
||||
// Write writes the underlying disk to the given writer.
|
||||
func (o operator) Write(w io.Writer) (int, error) {
|
||||
return o.lsd.Write(w)
|
||||
}
|
||||
|
||||
// operatorFactory is the factory that returns dos3 operators given
|
||||
// disk images.
|
||||
func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
||||
|
@ -684,5 +690,5 @@ func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
|||
}
|
||||
|
||||
func init() {
|
||||
disk.RegisterOperatorFactory(operatorName, operatorFactory)
|
||||
disk.RegisterDiskOperatorFactory(operatorName, operatorFactory)
|
||||
}
|
||||
|
|
|
@ -8,30 +8,14 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
)
|
||||
|
||||
// A single ProDOS block.
|
||||
type Block [512]byte
|
||||
|
||||
// BlockDevice is the interface used to read and write devices by
|
||||
// logical block number.
|
||||
type BlockDevice interface {
|
||||
// ReadBlock reads a single block from the device. It always returns
|
||||
// 512 byes.
|
||||
ReadBlock(index uint16) (Block, error)
|
||||
// WriteBlock writes a single block to a device. It expects exactly
|
||||
// 512 bytes.
|
||||
WriteBlock(index uint16, data Block) error
|
||||
// Blocks returns the number of blocks on the device.
|
||||
Blocks() uint16
|
||||
// Write writes the device contents to the given Writer.
|
||||
Write(io.Writer) (int, error)
|
||||
}
|
||||
|
||||
type VolumeBitMap []Block
|
||||
type VolumeBitMap []disk.Block
|
||||
|
||||
func NewVolumeBitMap(blocks uint16) VolumeBitMap {
|
||||
vbm := VolumeBitMap(make([]Block, (blocks+(512*8)-1)/(512*8)))
|
||||
vbm := VolumeBitMap(make([]disk.Block, (blocks+(512*8)-1)/(512*8)))
|
||||
for b := 0; b < int(blocks); b++ {
|
||||
vbm.MarkUnused(uint16(b))
|
||||
}
|
||||
|
@ -69,9 +53,9 @@ func (vbm VolumeBitMap) IsFree(block uint16) bool {
|
|||
}
|
||||
|
||||
// ReadVolumeBitMap
|
||||
func ReadVolumeBitMap(bd BlockDevice, startBlock uint16) (VolumeBitMap, error) {
|
||||
func ReadVolumeBitMap(bd disk.BlockDevice, startBlock uint16) (VolumeBitMap, error) {
|
||||
blocks := bd.Blocks() / 4096
|
||||
vbm := make([]Block, blocks)
|
||||
vbm := make([]disk.Block, blocks)
|
||||
for i := uint16(0); i < blocks; i++ {
|
||||
block, err := bd.ReadBlock(startBlock + i)
|
||||
if err != nil {
|
||||
|
@ -84,7 +68,7 @@ func ReadVolumeBitMap(bd BlockDevice, startBlock uint16) (VolumeBitMap, error) {
|
|||
|
||||
// Write writes the Volume Bit Map to a block device, starting at the
|
||||
// given block.
|
||||
func (vbm VolumeBitMap) Write(bd BlockDevice, startBlock uint16) error {
|
||||
func (vbm VolumeBitMap) Write(bd disk.BlockDevice, startBlock uint16) error {
|
||||
for i, block := range vbm {
|
||||
if err := bd.WriteBlock(startBlock+uint16(i), block); err != nil {
|
||||
return fmt.Errorf("cannot write block %d of Volume Bit Map: %v", err)
|
||||
|
@ -137,8 +121,8 @@ type VolumeDirectoryKeyBlock struct {
|
|||
}
|
||||
|
||||
// ToBlock marshals the VolumeDirectoryKeyBlock to a Block of bytes.
|
||||
func (vdkb VolumeDirectoryKeyBlock) ToBlock() Block {
|
||||
var block Block
|
||||
func (vdkb VolumeDirectoryKeyBlock) ToBlock() disk.Block {
|
||||
var block disk.Block
|
||||
binary.LittleEndian.PutUint16(block[0x0:0x2], vdkb.Prev)
|
||||
binary.LittleEndian.PutUint16(block[0x2:0x4], vdkb.Next)
|
||||
copyBytes(block[0x04:0x02b], vdkb.Header.toBytes())
|
||||
|
@ -150,7 +134,7 @@ func (vdkb VolumeDirectoryKeyBlock) ToBlock() Block {
|
|||
}
|
||||
|
||||
// FromBlock unmarshals a Block of bytes into a VolumeDirectoryKeyBlock.
|
||||
func (vdkb *VolumeDirectoryKeyBlock) FromBlock(block Block) {
|
||||
func (vdkb *VolumeDirectoryKeyBlock) FromBlock(block disk.Block) {
|
||||
vdkb.Prev = binary.LittleEndian.Uint16(block[0x0:0x2])
|
||||
vdkb.Next = binary.LittleEndian.Uint16(block[0x2:0x4])
|
||||
vdkb.Header.fromBytes(block[0x04:0x2b])
|
||||
|
@ -184,8 +168,8 @@ type VolumeDirectoryBlock struct {
|
|||
}
|
||||
|
||||
// ToBlock marshals a VolumeDirectoryBlock to a Block of bytes.
|
||||
func (vdb VolumeDirectoryBlock) ToBlock() Block {
|
||||
var block Block
|
||||
func (vdb VolumeDirectoryBlock) ToBlock() disk.Block {
|
||||
var block disk.Block
|
||||
binary.LittleEndian.PutUint16(block[0x0:0x2], vdb.Prev)
|
||||
binary.LittleEndian.PutUint16(block[0x2:0x4], vdb.Next)
|
||||
for i, desc := range vdb.Descriptors {
|
||||
|
@ -196,7 +180,7 @@ func (vdb VolumeDirectoryBlock) ToBlock() Block {
|
|||
}
|
||||
|
||||
// FromBlock unmarshals a Block of bytes into a VolumeDirectoryBlock.
|
||||
func (vdb *VolumeDirectoryBlock) FromBlock(block Block) {
|
||||
func (vdb *VolumeDirectoryBlock) FromBlock(block disk.Block) {
|
||||
vdb.Prev = binary.LittleEndian.Uint16(block[0x0:0x2])
|
||||
vdb.Next = binary.LittleEndian.Uint16(block[0x2:0x4])
|
||||
for i := range vdb.Descriptors {
|
||||
|
@ -360,7 +344,7 @@ func (fd FileDescriptor) Validate() (errors []error) {
|
|||
|
||||
// An index block contains 256 16-bit block numbers, pointing to other
|
||||
// blocks. The LSBs are stored in the first half, MSBs in the second.
|
||||
type IndexBlock Block
|
||||
type IndexBlock disk.Block
|
||||
|
||||
// Get the blockNum'th block number from an index block.
|
||||
func (i IndexBlock) Get(blockNum byte) uint16 {
|
||||
|
@ -384,8 +368,8 @@ type SubdirectoryKeyBlock struct {
|
|||
}
|
||||
|
||||
// ToBlock marshals the SubdirectoryKeyBlock to a Block of bytes.
|
||||
func (skb SubdirectoryKeyBlock) ToBlock() Block {
|
||||
var block Block
|
||||
func (skb SubdirectoryKeyBlock) ToBlock() disk.Block {
|
||||
var block disk.Block
|
||||
binary.LittleEndian.PutUint16(block[0x0:0x2], skb.Prev)
|
||||
binary.LittleEndian.PutUint16(block[0x2:0x4], skb.Next)
|
||||
copyBytes(block[0x04:0x02b], skb.Header.toBytes())
|
||||
|
@ -397,7 +381,7 @@ func (skb SubdirectoryKeyBlock) ToBlock() Block {
|
|||
}
|
||||
|
||||
// FromBlock unmarshals a Block of bytes into a SubdirectoryKeyBlock.
|
||||
func (skb *SubdirectoryKeyBlock) FromBlock(block Block) {
|
||||
func (skb *SubdirectoryKeyBlock) FromBlock(block disk.Block) {
|
||||
skb.Prev = binary.LittleEndian.Uint16(block[0x0:0x2])
|
||||
skb.Next = binary.LittleEndian.Uint16(block[0x2:0x4])
|
||||
skb.Header.fromBytes(block[0x04:0x2b])
|
||||
|
@ -431,8 +415,8 @@ type SubdirectoryBlock struct {
|
|||
}
|
||||
|
||||
// ToBlock marshals a SubdirectoryBlock to a Block of bytes.
|
||||
func (sb SubdirectoryBlock) ToBlock() Block {
|
||||
var block Block
|
||||
func (sb SubdirectoryBlock) ToBlock() disk.Block {
|
||||
var block disk.Block
|
||||
binary.LittleEndian.PutUint16(block[0x0:0x2], sb.Prev)
|
||||
binary.LittleEndian.PutUint16(block[0x2:0x4], sb.Next)
|
||||
for i, desc := range sb.Descriptors {
|
||||
|
@ -443,7 +427,7 @@ func (sb SubdirectoryBlock) ToBlock() Block {
|
|||
}
|
||||
|
||||
// FromBlock unmarshals a Block of bytes into a SubdirectoryBlock.
|
||||
func (sb *SubdirectoryBlock) FromBlock(block Block) {
|
||||
func (sb *SubdirectoryBlock) FromBlock(block disk.Block) {
|
||||
sb.Prev = binary.LittleEndian.Uint16(block[0x0:0x2])
|
||||
sb.Next = binary.LittleEndian.Uint16(block[0x2:0x4])
|
||||
for i := range sb.Descriptors {
|
||||
|
@ -543,3 +527,66 @@ func copyBytes(dst, src []byte) int {
|
|||
}
|
||||
return copy(dst, src)
|
||||
}
|
||||
|
||||
// operator is a disk.Operator - an interface for performing
|
||||
// high-level operations on files and directories.
|
||||
type operator struct {
|
||||
dev disk.BlockDevice
|
||||
}
|
||||
|
||||
var _ disk.Operator = operator{}
|
||||
|
||||
// operatorName is the keyword name for the operator that undestands
|
||||
// prodos disks/devices.
|
||||
const operatorName = "prodos"
|
||||
|
||||
// Name returns the name of the operator.
|
||||
func (o operator) Name() string {
|
||||
return operatorName
|
||||
}
|
||||
|
||||
// HasSubdirs returns true if the underlying operating system on the
|
||||
// disk allows subdirectories.
|
||||
func (o operator) HasSubdirs() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Catalog returns a catalog of disk entries. subdir should be empty
|
||||
// for operating systems that do not support subdirectories.
|
||||
func (o operator) Catalog(subdir string) ([]disk.Descriptor, error) {
|
||||
return nil, fmt.Errorf("%s doesn't implement Catalog yet", operatorName)
|
||||
/*
|
||||
fds, _, err := ReadCatalog(o.dev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
descs := make([]disk.Descriptor, 0, len(fds))
|
||||
for _, fd := range fds {
|
||||
descs = append(descs, fd.descriptor())
|
||||
}
|
||||
return descs, nil
|
||||
*/
|
||||
}
|
||||
|
||||
// GetFile retrieves a file by name.
|
||||
func (o operator) GetFile(filename string) (disk.FileInfo, error) {
|
||||
return disk.FileInfo{}, fmt.Errorf("%s doesn't implement GetFile yet", operatorName)
|
||||
}
|
||||
|
||||
// Delete deletes a file by name. It returns true if the file was
|
||||
// deleted, false if it didn't exist.
|
||||
func (o operator) Delete(filename string) (bool, error) {
|
||||
return false, fmt.Errorf("%s doesn't implement Delete yet", operatorName)
|
||||
}
|
||||
|
||||
// PutFile writes a file by name. If the file exists and overwrite
|
||||
// is false, it returns with an error. Otherwise it returns true if
|
||||
// an existing file was overwritten.
|
||||
func (o operator) PutFile(fileInfo disk.FileInfo, overwrite bool) (existed bool, err error) {
|
||||
return false, fmt.Errorf("%s doesn't implement PutFile yet", operatorName)
|
||||
}
|
||||
|
||||
// Write writes the underlying device blocks to the given writer.
|
||||
func (o operator) Write(w io.Writer) (int, error) {
|
||||
return o.dev.Write(w)
|
||||
}
|
||||
|
|
|
@ -6,10 +6,11 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
)
|
||||
|
||||
func randomBlock() Block {
|
||||
var b1 Block
|
||||
func randomBlock() disk.Block {
|
||||
var b1 disk.Block
|
||||
rand.Read(b1[:])
|
||||
return b1
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package supermon
|
|||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -783,6 +784,11 @@ func (o Operator) PutFile(fileInfo disk.FileInfo, overwrite bool) (existed bool,
|
|||
return existed, nil
|
||||
}
|
||||
|
||||
// Write writes the underlying disk to the given writer.
|
||||
func (o Operator) Write(w io.Writer) (int, error) {
|
||||
return o.SD.Write(w)
|
||||
}
|
||||
|
||||
// operatorFactory is the factory that returns supermon operators
|
||||
// given disk images.
|
||||
func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
||||
|
@ -805,5 +811,5 @@ func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
|||
}
|
||||
|
||||
func init() {
|
||||
disk.RegisterOperatorFactory(operatorName, operatorFactory)
|
||||
disk.RegisterDiskOperatorFactory(operatorName, operatorFactory)
|
||||
}
|
||||
|
|
|
@ -126,11 +126,11 @@ func TestReadSymbolTable(t *testing.T) {
|
|||
// TestGetFile tests the retrieval of a file's contents, using the
|
||||
// Operator interface.
|
||||
func TestGetFile(t *testing.T) {
|
||||
sd, err := disk.Open(testDisk)
|
||||
sd, err := disk.OpenDisk(testDisk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
op, err := disk.OperatorFor(sd)
|
||||
op, err := disk.OperatorForDisk(sd)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -213,11 +213,11 @@ func TestReadWriteSymbolTable(t *testing.T) {
|
|||
// TestPutFile tests the creation of a file, using the Operator
|
||||
// interface.
|
||||
func TestPutFile(t *testing.T) {
|
||||
sd, err := disk.Open(testDisk)
|
||||
sd, err := disk.OpenDisk(testDisk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
op, err := disk.OperatorFor(sd)
|
||||
op, err := disk.OperatorForDisk(sd)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue