2021-07-12 20:27:13 +00:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/zellyn/diskii/disk"
|
|
|
|
"github.com/zellyn/diskii/helpers"
|
|
|
|
"github.com/zellyn/diskii/types"
|
|
|
|
)
|
|
|
|
|
2021-08-01 03:49:22 +00:00
|
|
|
// ReorderCmd is the kong `reorder` command.
|
2021-07-12 20:27:13 +00:00
|
|
|
type ReorderCmd struct {
|
2021-08-01 02:10:44 +00:00
|
|
|
Order types.DiskOrder `kong:"default='auto',enum='auto,do,po',help='Logical-to-physical sector order.'"`
|
|
|
|
NewOrder types.DiskOrder `kong:"default='auto',enum='auto,do,po',help='New Logical-to-physical sector order.'"`
|
|
|
|
Overwrite bool `kong:"short='f',help='Overwrite existing file?'"`
|
2021-07-12 20:27:13 +00:00
|
|
|
|
|
|
|
DiskImage string `kong:"arg,required,type='existingfile',help='Disk image to read.'"`
|
|
|
|
NewDiskImage string `kong:"arg,optional,type='path',help='Disk image to write, if different.'"`
|
|
|
|
}
|
|
|
|
|
2021-08-01 03:49:22 +00:00
|
|
|
// Run the `reorder` command.
|
2021-07-12 20:27:13 +00:00
|
|
|
func (r *ReorderCmd) Run(globals *types.Globals) error {
|
|
|
|
fromOrderName, toOrderName, err := getOrders(r.DiskImage, r.Order, r.NewDiskImage, r.NewOrder)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
frombytes, err := helpers.FileContentsOrStdIn(r.DiskImage)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
fromOrder, ok := disk.LogicalToPhysicalByName[fromOrderName]
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("internal error: disk order '%s' not found", fromOrderName)
|
|
|
|
}
|
|
|
|
toOrder, ok := disk.PhysicalToLogicalByName[toOrderName]
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("internal error: disk order '%s' not found", toOrderName)
|
|
|
|
}
|
|
|
|
rawbytes, err := disk.Swizzle(frombytes, fromOrder)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
tobytes, err := disk.Swizzle(rawbytes, toOrder)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-08-01 02:10:44 +00:00
|
|
|
|
|
|
|
overwrite := r.Overwrite
|
|
|
|
filename := r.NewDiskImage
|
|
|
|
if filename == "" {
|
|
|
|
filename = r.DiskImage
|
|
|
|
overwrite = true
|
|
|
|
}
|
|
|
|
return helpers.WriteOutput(filename, tobytes, overwrite)
|
2021-07-12 20:27:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getOrders returns the input order, and the output order.
|
2021-08-01 02:10:44 +00:00
|
|
|
func getOrders(inFilename string, inOrder types.DiskOrder, outFilename string, outOrder types.DiskOrder) (types.DiskOrder, types.DiskOrder, error) {
|
2021-07-12 20:27:13 +00:00
|
|
|
if inOrder == "auto" && outOrder != "auto" {
|
|
|
|
return oppositeOrder(outOrder), outOrder, nil
|
|
|
|
}
|
|
|
|
if outOrder == "auto" && inOrder != "auto" {
|
|
|
|
return inOrder, oppositeOrder(inOrder), nil
|
|
|
|
}
|
|
|
|
if inOrder != outOrder {
|
|
|
|
return inOrder, outOrder, nil
|
|
|
|
}
|
|
|
|
if inOrder != "auto" {
|
|
|
|
return "", "", fmt.Errorf("identical order and new-order")
|
|
|
|
}
|
|
|
|
|
2021-08-01 02:10:44 +00:00
|
|
|
inGuess, outGuess := disk.OrderFromFilename(inFilename, types.DiskOrderUnknown), disk.OrderFromFilename(outFilename, types.DiskOrderUnknown)
|
2021-07-12 20:27:13 +00:00
|
|
|
if inGuess == outGuess {
|
2021-08-01 02:10:44 +00:00
|
|
|
if inGuess == types.DiskOrderUnknown {
|
2021-07-12 20:27:13 +00:00
|
|
|
return "", "", fmt.Errorf("cannot determine input or output order from file extensions")
|
|
|
|
}
|
|
|
|
return "", "", fmt.Errorf("guessed order (%s) from file %q is the same as guessed order (%s) from file %q", inGuess, inFilename, outGuess, outFilename)
|
|
|
|
}
|
|
|
|
|
2021-08-01 02:10:44 +00:00
|
|
|
if inGuess == types.DiskOrderUnknown {
|
2021-07-12 20:27:13 +00:00
|
|
|
return oppositeOrder(outGuess), outGuess, nil
|
|
|
|
}
|
2021-08-01 02:10:44 +00:00
|
|
|
if outGuess == types.DiskOrderUnknown {
|
2021-07-12 20:27:13 +00:00
|
|
|
return inGuess, oppositeOrder(inGuess), nil
|
|
|
|
}
|
|
|
|
return inGuess, outGuess, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// oppositeOrder returns the opposite order from the input.
|
2021-08-01 02:10:44 +00:00
|
|
|
func oppositeOrder(order types.DiskOrder) types.DiskOrder {
|
|
|
|
if order == types.DiskOrderDO {
|
|
|
|
return types.DiskOrderPO
|
2021-07-12 20:27:13 +00:00
|
|
|
}
|
2021-08-01 02:10:44 +00:00
|
|
|
return types.DiskOrderDO
|
2021-07-12 20:27:13 +00:00
|
|
|
}
|