mirror of https://github.com/zellyn/diskii.git
add a couple disks
This commit is contained in:
parent
f09e8f47f1
commit
9c66e2c5e6
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"filewatcher.commands": [
|
||||
{
|
||||
"match": "\\.go",
|
||||
"cmd": "echo '${file} changed'",
|
||||
"event": "onFileChange",
|
||||
},
|
||||
]
|
||||
}
|
57
README.md
57
README.md
|
@ -32,7 +32,7 @@ Discussion/support is in
|
|||
[#apple2 on the retrocomputing Slack](https://retrocomputing.slack.com/messages/apple2/)
|
||||
(invites [here](https://retrocomputing.herokuapp.com)).
|
||||
|
||||
### Goals
|
||||
# Goals
|
||||
|
||||
Eventually, it aims to be a comprehensive disk image manipulation
|
||||
tool, but for now only some parts work.
|
||||
|
@ -59,7 +59,7 @@ Current disk operations supported:
|
|||
| init | ✗ | ✗ | ✗ |
|
||||
| defrag | ✗ | ✗ | ✗ |
|
||||
|
||||
### Installing/updating
|
||||
# Installing/updating
|
||||
Assuming you have Go installed, run `go get -u github.com/zellyn/diskii`
|
||||
|
||||
You can also download automatically-built binaries from the
|
||||
|
@ -68,7 +68,7 @@ page](https://github.com/zellyn/diskii/releases/latest). If you
|
|||
need binaries for a different architecture, please send a pull
|
||||
request or open an issue.
|
||||
|
||||
### Short-term TODOs/roadmap/easy ways to contribute
|
||||
# Short-term TODOs/roadmap/easy ways to contribute
|
||||
|
||||
My rough TODO list (apart from anything marked (✗) in the disk
|
||||
operations matrix is listed below. Anything that an actual user needs
|
||||
|
@ -86,7 +86,7 @@ will be likely to get priority.
|
|||
- [ ] Add basic ProDOS structures
|
||||
- [ ] Add ProDOS support
|
||||
|
||||
### Related tools
|
||||
# Related tools
|
||||
|
||||
- http://a2ciderpress.com/ - the great grandaddy of them all. Windows only, unless you Wine
|
||||
- http://retrocomputingaustralia.com/rca-downloads/ Michael Mulhern's MacOS package of CiderPress
|
||||
|
@ -107,3 +107,52 @@ will be likely to get priority.
|
|||
- https://github.com/slotek/apple2-disk-util - ruby
|
||||
- https://github.com/slotek/dsk2nib - C
|
||||
- https://github.com/robmcmullen/atrcopy - dos3.3, python
|
||||
|
||||
# Notes
|
||||
|
||||
## Disk formats
|
||||
|
||||
- `.do`
|
||||
- `.po`
|
||||
- `.dsk` - could be DO or PO.
|
||||
|
||||
DOS 3.2.1: the 13 sectors are physically skewed on disk.
|
||||
|
||||
DOS 3.3+: the 16 physical sectors are stored in ascending order on disk, not physically skewed at all. The
|
||||
|
||||
|
||||
| Logical Sector | DOS 3.3 Physical Sector | ProDOS Physical Sector |
|
||||
| --------------- | -------------- | ------------- |
|
||||
| 0 | 0 | x |
|
||||
| 1 | D | x |
|
||||
| 2 | B | x |
|
||||
| 3 | 9 | x |
|
||||
| 4 | 7 | x |
|
||||
| 5 | 5 | x |
|
||||
| 6 | 3 | x |
|
||||
| 7 | 1 | x |
|
||||
| 8 | E | x |
|
||||
| 9 | C | x |
|
||||
| A | A | x |
|
||||
| B | 8 | x |
|
||||
| C | 6 | x |
|
||||
| D | 4 | x |
|
||||
| E | 2 | x |
|
||||
| F | F | x |
|
||||
|
||||
### RWTS - DOS
|
||||
|
||||
Sector mapping:
|
||||
http://www.textfiles.com/apple/ANATOMY/rwts.s.txt and search for INTRLEAV
|
||||
|
||||
Mapping from specified sector to physical sector (the reverse of what the comment says):
|
||||
|
||||
`00 0D 0B 09 07 05 03 01 0E 0C 0A 08 06 04 02 0F`
|
||||
|
||||
So if you write to "T0S1" with DOS RWTS, it ends up in physical sector 0D.
|
||||
|
||||
## Commandline examples for thinking about how it should work
|
||||
|
||||
diskii ls dos33.dsk
|
||||
diskii --order=do ls dos33.dsk
|
||||
diskii --order=do --system=nakedos ls nakedos.dsk
|
||||
|
|
|
@ -5,7 +5,7 @@ package applesoft
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/zellyn/diskii/lib/basic"
|
||||
"github.com/zellyn/diskii/basic"
|
||||
)
|
||||
|
||||
// helloBinary is a simple basic program used for testing. Listing
|
|
@ -5,7 +5,7 @@ package integer
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/zellyn/diskii/lib/basic"
|
||||
"github.com/zellyn/diskii/basic"
|
||||
)
|
||||
|
||||
// helloBinary is a simple basic program used for testing. Listing
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
export ACME="$HOME/gh/acme/ACME_Lib"
|
||||
ACME_BIN="$HOME/gh/acme/acme"
|
||||
|
||||
|
||||
$ACME_BIN -o writetest.o -r writetest.lst writetest.asm
|
||||
|
||||
# cp data/disks/dos33mst.dsk writetest.dsk
|
||||
# diskii put -f writetest.dsk writetest writetest.o
|
||||
|
||||
# Also run mame? (set MAMEDIR and MAMEBIN to your local variant)
|
||||
[[ -z "${MAMEDIR-}" ]] && MAMEDIR="/Users/zellyn/Library/Application Support/Ample"
|
||||
[[ -z "${MAMEBIN-}" ]] && MAMEBIN="/Applications/Ample.app/Contents/MacOS/mame64"
|
||||
|
||||
# Write audit.o into an OpenEmulator config?
|
||||
[[ -z "${TMPLS-}" ]] && TMPLS=~/gh/OpenEmulator-OSX/modules/libemulation/res/templates
|
||||
|
||||
DSK=$(realpath ./audit.dsk)
|
||||
|
||||
case "${1-none}" in
|
||||
"2ee")
|
||||
# mame64 apple2ee -skip_gameinfo -nosamples -window -resolution 1120x840 -flop1 /Users/zellyn/gh/a2audit/audit/audit.dsk
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2ee -window -flop1 "$DSK" -skip_gameinfo)
|
||||
;;
|
||||
"2e")
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2e -window -flop1 "$DSK" -skip_gameinfo)
|
||||
;;
|
||||
"2p")
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2p -window -flop1 "$DSK" -skip_gameinfo)
|
||||
;;
|
||||
"2")
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2 -window -flop1 "$DSK" -skip_gameinfo)
|
||||
;;
|
||||
"2ee-d")
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2ee -window -flop1 "$DSK" -skip_gameinfo -debug)
|
||||
;;
|
||||
"2e-d")
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2e -window -flop1 "$DSK" -skip_gameinfo -debug)
|
||||
;;
|
||||
"2p-d")
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2p -window -flop1 "$DSK" -skip_gameinfo -debug)
|
||||
;;
|
||||
"2-d")
|
||||
(cd "$MAMEDIR"; "$MAMEBIN" apple2 -window -flop1 "$DSK" -skip_gameinfo -debug)
|
||||
;;
|
||||
"oe")
|
||||
(head -c 24576 /dev/zero; cat audit.o; head -c 65536 /dev/zero) | head -c 65536 > $TMPLS/Apple\ II/Apple\ IIe-test.emulation/appleIIe.mainRam.bin
|
||||
sed -e 's|<property name="pc" value="0x...."/>|<property name="pc" value="0x6000"/>|' $TMPLS/Apple\ II/Apple\ IIe.xml > $TMPLS/Apple\ II/Apple\ IIe-test.emulation/info.xml
|
||||
;;
|
||||
"none")
|
||||
;;
|
||||
*)
|
||||
echo Options: 2ee, 2e, 2p, 2, 2ee-d, 2e-d, 2p-d, 2-d
|
||||
esac
|
||||
|
||||
true # Signal success (since we had a bunch of conditionals that can return false status).
|
|
@ -7,9 +7,9 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/basic"
|
||||
"github.com/zellyn/diskii/lib/basic/applesoft"
|
||||
"github.com/zellyn/diskii/lib/helpers"
|
||||
"github.com/zellyn/diskii/basic"
|
||||
"github.com/zellyn/diskii/basic/applesoft"
|
||||
"github.com/zellyn/diskii/helpers"
|
||||
)
|
||||
|
||||
// applesoftCmd represents the applesoft command
|
||||
|
|
|
@ -6,54 +6,34 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/disk"
|
||||
"github.com/zellyn/diskii/types"
|
||||
)
|
||||
|
||||
var shortnames bool // flag for whether to print short filenames
|
||||
var debug bool
|
||||
|
||||
// catalogCmd represents the cat command, used to catalog a disk or
|
||||
// directory.
|
||||
var catalogCmd = &cobra.Command{
|
||||
Use: "catalog",
|
||||
Aliases: []string{"cat", "ls"},
|
||||
Short: "print a list of files",
|
||||
Long: `Catalog a disk or subdirectory.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runCat(args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(-1)
|
||||
}
|
||||
},
|
||||
type LsCmd struct {
|
||||
ShortNames bool `kong:"short='s',help='Whether to print short filenames (only makes a difference on Super-Mon disks).'"`
|
||||
Image *os.File `kong:"arg,required,help='Disk/device image to read.'"`
|
||||
Directory string `kong:"arg,optional,help='Directory to list (ProDOS only).'"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(catalogCmd)
|
||||
catalogCmd.Flags().BoolVarP(&shortnames, "shortnames", "s", false, "whether to print short filenames (only makes a difference on Super-Mon disks)")
|
||||
catalogCmd.Flags().BoolVarP(&debug, "debug", "d", false, "pring debug information")
|
||||
}
|
||||
|
||||
// runCat performs the actual catalog logic.
|
||||
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")
|
||||
}
|
||||
op, err := disk.Open(args[0])
|
||||
func (l *LsCmd) Run(globals *types.Globals) error {
|
||||
op, order, err := disk.OpenImage(l.Image, globals)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if debug {
|
||||
fmt.Printf("Got disk of type %q with underlying sector/block order %q.\n", op.Name(), op.Order())
|
||||
if globals.Debug {
|
||||
fmt.Fprintf(os.Stderr, "Opened disk with order %q, system %q\n", order, op.Name())
|
||||
}
|
||||
subdir := ""
|
||||
if len(args) == 2 {
|
||||
|
||||
if l.Directory != "" {
|
||||
if !op.HasSubdirs() {
|
||||
return fmt.Errorf("Disks of type %q cannot have subdirectories", op.Name())
|
||||
}
|
||||
subdir = args[1]
|
||||
}
|
||||
fds, err := op.Catalog(subdir)
|
||||
fds, err := op.Catalog(l.Directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,14 +2,7 @@
|
|||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
)
|
||||
|
||||
/*
|
||||
var missingok bool // flag for whether to consider deleting a nonexistent file okay
|
||||
|
||||
// deleteCmd represents the delete command, used to delete a file.
|
||||
|
@ -62,3 +55,4 @@ func runDelete(args []string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
|
10
cmd/dump.go
10
cmd/dump.go
|
@ -2,14 +2,7 @@
|
|||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
)
|
||||
|
||||
/*
|
||||
// dumpCmd represents the dump command, used to dump the raw contents
|
||||
// of a file.
|
||||
var dumpCmd = &cobra.Command{
|
||||
|
@ -48,3 +41,4 @@ func runDump(args []string) error {
|
|||
os.Stdout.Write(file.Data)
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/types"
|
||||
)
|
||||
|
||||
var all bool // flag for whether to show all filetypes
|
||||
|
@ -36,7 +36,7 @@ func runFiletypes(args []string) error {
|
|||
if len(args) != 0 {
|
||||
return fmt.Errorf("filetypes expects no arguments")
|
||||
}
|
||||
for _, typ := range disk.FiletypeNames(all) {
|
||||
for _, typ := range types.FiletypeNames(all) {
|
||||
fmt.Println(typ)
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -2,15 +2,7 @@
|
|||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/lib/supermon"
|
||||
)
|
||||
|
||||
/*
|
||||
// nakedosCmd represents the nakedos command
|
||||
var nakedosCmd = &cobra.Command{
|
||||
Use: "nakedos",
|
||||
|
@ -123,3 +115,4 @@ func runMkhello(args []string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
|
11
cmd/put.go
11
cmd/put.go
|
@ -2,15 +2,7 @@
|
|||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/lib/helpers"
|
||||
)
|
||||
|
||||
/*
|
||||
var filetypeName string // flag for file type
|
||||
var overwrite bool // flag for whether to overwrite
|
||||
|
||||
|
@ -81,3 +73,4 @@ func runPut(args []string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
|
30
cmd/root.go
30
cmd/root.go
|
@ -7,7 +7,6 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
@ -30,32 +29,3 @@ func Execute() {
|
|||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports Persistent Flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
|
||||
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.diskii.yaml)")
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
// RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
func initConfig() {
|
||||
if cfgFile != "" { // enable ability to specify config file via flag
|
||||
viper.SetConfigFile(cfgFile)
|
||||
}
|
||||
|
||||
viper.SetConfigName(".diskii") // name of config file (without extension)
|
||||
viper.AddConfigPath("$HOME") // adding home directory as first search path
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
||||
|
|
19
cmd/sd.go
19
cmd/sd.go
|
@ -7,8 +7,8 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/lib/helpers"
|
||||
"github.com/zellyn/diskii/disk"
|
||||
"github.com/zellyn/diskii/helpers"
|
||||
)
|
||||
|
||||
var sdAddress uint16 // flag for address to load at
|
||||
|
@ -87,16 +87,16 @@ func runMkSd(args []string) error {
|
|||
contents = append(contents, 0)
|
||||
}
|
||||
|
||||
sd := disk.Empty()
|
||||
diskbytes := make([]byte, disk.FloppyDiskBytes)
|
||||
|
||||
var track, sector byte
|
||||
for i := 0; i < len(contents); i += 256 {
|
||||
sector += 2
|
||||
if sector >= sd.Sectors() {
|
||||
sector = (sd.Sectors() + 1) - sector
|
||||
if sector >= disk.FloppySectors {
|
||||
sector = (disk.FloppySectors + 1) - sector
|
||||
if sector == 0 {
|
||||
track++
|
||||
if track >= sd.Tracks() {
|
||||
if track >= disk.FloppyTracks {
|
||||
return fmt.Errorf("ran out of tracks")
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ func runMkSd(args []string) error {
|
|||
|
||||
address := int(sdAddress) + i
|
||||
loader = append(loader, byte(address>>8))
|
||||
if err := sd.WritePhysicalSector(track, sector, contents[i:i+256]); err != nil {
|
||||
if err := disk.WriteSector(diskbytes, track, sector, contents[i:i+256]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ func runMkSd(args []string) error {
|
|||
loader = append(loader, 0)
|
||||
}
|
||||
|
||||
if err := sd.WritePhysicalSector(0, 0, loader); err != nil {
|
||||
if err := disk.WriteSector(diskbytes, 0, 0, loader); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,8 @@ func runMkSd(args []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = sd.Write(f)
|
||||
return fmt.Errorf("write not implemented")
|
||||
//_, err = sd.Write(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
319
data/data.go
319
data/data.go
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -10,14 +10,15 @@ import (
|
|||
"io/ioutil"
|
||||
)
|
||||
|
||||
// A ProDOS block.
|
||||
type Block [256]byte
|
||||
|
||||
// Dev represents a .po disk image.
|
||||
type Dev struct {
|
||||
data []byte // The actual data in the file
|
||||
blocks uint16 // Number of blocks
|
||||
}
|
||||
|
||||
var _ BlockDevice = (*Dev)(nil)
|
||||
|
||||
// LoadDev loads a .po image from a file.
|
||||
func LoadDev(filename string) (Dev, error) {
|
||||
bb, err := ioutil.ReadFile(filename)
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// Package disk contains routines for reading and writing various disk
|
||||
// file formats.
|
||||
package disk
|
||||
|
||||
// Various DOS33 disk characteristics.
|
||||
const (
|
||||
FloppyTracks = 35
|
||||
FloppySectors = 16 // Sectors per track
|
||||
// FloppyDiskBytes is the number of bytes on a DOS 3.3 disk.
|
||||
FloppyDiskBytes = 143360 // 35 tracks * 16 sectors * 256 bytes
|
||||
FloppyTrackBytes = 256 * FloppySectors // Bytes per track
|
||||
)
|
||||
|
||||
// Dos33LogicalToPhysicalSectorMap maps logical sector numbers to physical ones.
|
||||
// See [UtA2 9-42 - Read Routines].
|
||||
var Dos33LogicalToPhysicalSectorMap = []int{
|
||||
0x00, 0x0D, 0x0B, 0x09, 0x07, 0x05, 0x03, 0x01,
|
||||
0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x0F,
|
||||
}
|
||||
|
||||
// Dos33PhysicalToLogicalSectorMap maps physical sector numbers to logical ones.
|
||||
// See [UtA2 9-42 - Read Routines].
|
||||
var Dos33PhysicalToLogicalSectorMap = []int{
|
||||
0x00, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04,
|
||||
0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x0F,
|
||||
}
|
||||
|
||||
// ProDOSLogicalToPhysicalSectorMap maps logical sector numbers to pysical ones.
|
||||
// See [UtA2e 9-43 - Sectors vs. Blocks].
|
||||
var ProDOSLogicalToPhysicalSectorMap = []int{
|
||||
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
|
||||
0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
|
||||
}
|
||||
|
||||
// ProDosPhysicalToLogicalSectorMap maps physical sector numbers to logical ones.
|
||||
// See [UtA2e 9-43 - Sectors vs. Blocks].
|
||||
var ProDosPhysicalToLogicalSectorMap = []int{
|
||||
0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B,
|
||||
0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F,
|
||||
}
|
||||
|
||||
// TrackSector is a pair of track/sector bytes.
|
||||
type TrackSector struct {
|
||||
Track byte
|
||||
Sector byte
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// marshal.go contains helpers for marshaling sector structs to/from
|
||||
// disk and block structs to/from devices.
|
||||
|
||||
package disk
|
||||
|
||||
import "fmt"
|
||||
|
||||
// BlockDevice is the interface used to read and write devices by
|
||||
// logical block number.
|
||||
|
||||
// SectorSource is the interface for types that can marshal to sectors.
|
||||
type SectorSource interface {
|
||||
// ToSector marshals the sector struct to exactly 256 bytes.
|
||||
ToSector() ([]byte, error)
|
||||
// GetTrack returns the track that a sector struct was loaded from.
|
||||
GetTrack() byte
|
||||
// GetSector returns the sector that a sector struct was loaded from.
|
||||
GetSector() byte
|
||||
}
|
||||
|
||||
// SectorSink is the interface for types that can unmarshal from sectors.
|
||||
type SectorSink interface {
|
||||
// FromSector unmarshals the sector struct from bytes. Input is
|
||||
// expected to be exactly 256 bytes.
|
||||
FromSector(data []byte) error
|
||||
// SetTrack sets the track that a sector struct was loaded from.
|
||||
SetTrack(track byte)
|
||||
// SetSector sets the sector that a sector struct was loaded from.
|
||||
SetSector(sector byte)
|
||||
}
|
||||
|
||||
// UnmarshalLogicalSector reads a sector from a disk image, and unmarshals it
|
||||
// into a SectorSink, setting its track and sector.
|
||||
func UnmarshalLogicalSector(diskbytes []byte, ss SectorSink, track, sector byte) error {
|
||||
bytes, err := ReadSector(diskbytes, track, sector)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ss.FromSector(bytes); err != nil {
|
||||
return err
|
||||
}
|
||||
ss.SetTrack(track)
|
||||
ss.SetSector(sector)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadSector just reads 256 bytes from the given track and sector.
|
||||
func ReadSector(diskbytes []byte, track, sector byte) ([]byte, error) {
|
||||
start := int(track)*FloppyTrackBytes + int(sector)*256
|
||||
end := start + 256
|
||||
if len(diskbytes) < end {
|
||||
return nil, fmt.Errorf("cannot read track %d/sector %d (bytes %d-%d) from disk of length %d", track, sector, start, end, len(diskbytes))
|
||||
}
|
||||
bytes := make([]byte, 256)
|
||||
copy(bytes, diskbytes[start:end])
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
// MarshalLogicalSector marshals a SectorSource to its track/sector on a disk
|
||||
// image.
|
||||
func MarshalLogicalSector(diskbytes []byte, ss SectorSource) error {
|
||||
track := ss.GetTrack()
|
||||
sector := ss.GetSector()
|
||||
bytes, err := ss.ToSector()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return WriteSector(diskbytes, track, sector, bytes)
|
||||
}
|
||||
|
||||
// WriteSector writes 256 bytes to the given track and sector.
|
||||
func WriteSector(diskbytes []byte, track, sector byte, data []byte) error {
|
||||
if len(data) != 256 {
|
||||
return fmt.Errorf("call to writeSector with len(data)==%d; want 256", len(data))
|
||||
}
|
||||
start := int(track)*FloppyTrackBytes + int(sector)*256
|
||||
end := start + 256
|
||||
if len(diskbytes) < end {
|
||||
return fmt.Errorf("cannot write track %d/sector %d (bytes %d-%d) to disk of length %d", track, sector, start, end, len(diskbytes))
|
||||
}
|
||||
copy(diskbytes[start:end], data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 block device, and unmarshals it into a
|
||||
// BlockSink, setting its index.
|
||||
func UnmarshalBlock(diskbytes []byte, bs BlockSink, index uint16) error {
|
||||
start := int(index) * 512
|
||||
end := start + 512
|
||||
if len(diskbytes) < end {
|
||||
return fmt.Errorf("device too small to read block %d", index)
|
||||
}
|
||||
var block Block
|
||||
copy(block[:], diskbytes[start:end])
|
||||
if err := bs.FromBlock(block); err != nil {
|
||||
return err
|
||||
}
|
||||
bs.SetBlock(index)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBlock marshals a BlockSource to its block on a block device.
|
||||
func MarshalBlock(diskbytes []byte, bs BlockSource) error {
|
||||
index := bs.GetBlock()
|
||||
block, err := bs.ToBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
start := int(index) * 512
|
||||
end := start + 512
|
||||
if len(diskbytes) < end {
|
||||
return fmt.Errorf("device too small to write block %d", index)
|
||||
}
|
||||
copy(diskbytes[start:end], block[:])
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/zellyn/diskii/types"
|
||||
)
|
||||
|
||||
var diskOrdersByName map[string][]int = map[string][]int{
|
||||
"do": Dos33LogicalToPhysicalSectorMap,
|
||||
"po": ProDOSLogicalToPhysicalSectorMap,
|
||||
"raw": {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF},
|
||||
}
|
||||
|
||||
// OpenImage attempts to open an image on disk, using the provided ordering and system type.
|
||||
func OpenImage(file *os.File, globals *types.Globals) (types.Operator, string, error) {
|
||||
bb, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if len(bb) == FloppyDiskBytes {
|
||||
return openDoOrPo(bb, globals, strings.ToLower(path.Ext(file.Name())))
|
||||
}
|
||||
return nil, "", fmt.Errorf("OpenImage not implemented yet for non-disk-sized images")
|
||||
}
|
||||
|
||||
func openDoOrPo(diskbytes []byte, globals *types.Globals, ext string) (types.Operator, string, error) {
|
||||
var factories []types.OperatorFactory
|
||||
for _, factory := range globals.DiskOperatorFactories {
|
||||
if globals.System == "auto" || globals.System == factory.Name() {
|
||||
factories = append(factories, factory)
|
||||
}
|
||||
}
|
||||
if len(factories) == 0 {
|
||||
return nil, "", fmt.Errorf("cannot find disk system with name %q", globals.System)
|
||||
}
|
||||
orders := []string{globals.Order}
|
||||
switch globals.Order {
|
||||
case "do", "po":
|
||||
// nothing more
|
||||
case "auto":
|
||||
switch ext {
|
||||
case ".po":
|
||||
orders = []string{"po"}
|
||||
case ".do":
|
||||
orders = []string{"do"}
|
||||
case ".dsk", "":
|
||||
orders = []string{"do", "po"}
|
||||
default:
|
||||
return nil, "", fmt.Errorf("unknown disk image extension: %q", ext)
|
||||
}
|
||||
default:
|
||||
return nil, "", fmt.Errorf("disk order %q invalid for %d-byte disk images", globals.Order, FloppyDiskBytes)
|
||||
}
|
||||
|
||||
for _, order := range orders {
|
||||
swizzled, err := Swizzle(diskbytes, diskOrdersByName[order])
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
for _, factory := range factories {
|
||||
if len(orders) == 1 && globals.System != "auto" {
|
||||
if globals.Debug {
|
||||
fmt.Fprintf(os.Stderr, "Attempting to open with order=%s, system=%s.\n", order, factory.Name())
|
||||
}
|
||||
op, err := factory.Operator(swizzled, globals.Debug)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return op, order, nil
|
||||
}
|
||||
|
||||
if globals.Debug {
|
||||
fmt.Fprintf(os.Stderr, "Testing whether order=%s, system=%s seems to match.\n", order, factory.Name())
|
||||
}
|
||||
if factory.SeemsToMatch(swizzled, globals.Debug) {
|
||||
op, err := factory.Operator(swizzled, globals.Debug)
|
||||
if err == nil {
|
||||
return op, order, nil
|
||||
}
|
||||
if globals.Debug {
|
||||
fmt.Fprintf(os.Stderr, "Got error opening with order=%s, system=%s: %v\n", order, factory.Name(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, "", fmt.Errorf("openDoOrPo not implemented yet")
|
||||
}
|
||||
|
||||
// Swizzle changes the sector ordering according to the order parameter. If
|
||||
// order is nil, it leaves the order unchanged.
|
||||
func Swizzle(diskimage []byte, order []int) ([]byte, error) {
|
||||
if len(diskimage) != FloppyDiskBytes {
|
||||
return nil, fmt.Errorf("swizzling only works on disk images of %d bytes; got %d", FloppyDiskBytes, len(diskimage))
|
||||
}
|
||||
if err := validateOrder(order); err != nil {
|
||||
return nil, fmt.Errorf("called Swizzle with weird order: %w", err)
|
||||
}
|
||||
|
||||
result := make([]byte, FloppyDiskBytes)
|
||||
for track := 0; track < FloppyTracks; track++ {
|
||||
for sector := 0; sector < FloppySectors; sector++ {
|
||||
data, err := ReadSector(diskimage, byte(track), byte(sector))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = WriteSector(result, byte(track), byte(order[sector]), data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func UnSwizzle(diskimage []byte, order []int) ([]byte, error) {
|
||||
if err := validateOrder(order); err != nil {
|
||||
return nil, fmt.Errorf("called UnSwizzle with weird order: %w", err)
|
||||
}
|
||||
reverseOrder := make([]int, FloppySectors)
|
||||
for index, mapping := range order {
|
||||
reverseOrder[mapping] = index
|
||||
}
|
||||
return Swizzle(diskimage, reverseOrder)
|
||||
}
|
||||
|
||||
// validateOrder validates that an order mapping is valid, and maps [0,15] onto
|
||||
// [0,15] without repeats.
|
||||
func validateOrder(order []int) error {
|
||||
if len(order) != FloppySectors {
|
||||
return fmt.Errorf("len=%d; want %d: %v", len(order), FloppySectors, order)
|
||||
}
|
||||
seen := make(map[int]bool)
|
||||
for i, mapping := range order {
|
||||
if mapping < 0 || mapping > 15 {
|
||||
return fmt.Errorf("mapping %d:%d is not in [0,15]: %v", i, mapping, order)
|
||||
}
|
||||
if seen[mapping] {
|
||||
return fmt.Errorf("mapping %d:%d is a repeat: %v", i, mapping, order)
|
||||
}
|
||||
seen[mapping] = true
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -7,10 +7,11 @@ package dos3
|
|||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/disk"
|
||||
"github.com/zellyn/diskii/types"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -356,11 +357,11 @@ func (fd *FileDesc) FilenameString() string {
|
|||
return strings.TrimRight(string(slice), " ")
|
||||
}
|
||||
|
||||
// descriptor returns a disk.Descriptor for a FileDesc, but with the
|
||||
// descriptor returns a types.Descriptor for a FileDesc, but with the
|
||||
// length set to -1, since we can't know it without reading the file
|
||||
// contents.
|
||||
func (fd FileDesc) descriptor() disk.Descriptor {
|
||||
desc := disk.Descriptor{
|
||||
func (fd FileDesc) descriptor() types.Descriptor {
|
||||
desc := types.Descriptor{
|
||||
Name: fd.FilenameString(),
|
||||
Sectors: int(fd.SectorCount),
|
||||
Length: -1,
|
||||
|
@ -368,28 +369,28 @@ func (fd FileDesc) descriptor() disk.Descriptor {
|
|||
}
|
||||
switch fd.Filetype & 0x7f {
|
||||
case FiletypeText: // Text file
|
||||
desc.Type = disk.FiletypeASCIIText
|
||||
desc.Type = types.FiletypeASCIIText
|
||||
case FiletypeInteger: // INTEGER BASIC file
|
||||
desc.Type = disk.FiletypeIntegerBASIC
|
||||
desc.Type = types.FiletypeIntegerBASIC
|
||||
case FiletypeApplesoft: // APPLESOFT BASIC file
|
||||
desc.Type = disk.FiletypeApplesoftBASIC
|
||||
desc.Type = types.FiletypeApplesoftBASIC
|
||||
case FiletypeBinary: // BINARY file
|
||||
desc.Type = disk.FiletypeBinary
|
||||
desc.Type = types.FiletypeBinary
|
||||
case FiletypeS: // S type file
|
||||
desc.Type = disk.FiletypeS
|
||||
desc.Type = types.FiletypeS
|
||||
case FiletypeRelocatable: // RELOCATABLE object module file
|
||||
desc.Type = disk.FiletypeRelocatable
|
||||
desc.Type = types.FiletypeRelocatable
|
||||
case FiletypeA: // A type file
|
||||
desc.Type = disk.FiletypeNewA
|
||||
desc.Type = types.FiletypeNewA
|
||||
case FiletypeB: // B type file
|
||||
desc.Type = disk.FiletypeNewB
|
||||
desc.Type = types.FiletypeNewB
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
// Contents returns the on-disk contents of a file represented by a
|
||||
// FileDesc.
|
||||
func (fd *FileDesc) Contents(lsd disk.LogicalSectorDisk) ([]byte, error) {
|
||||
func (fd *FileDesc) Contents(diskbytes []byte) ([]byte, error) {
|
||||
tsls := []TrackSectorList{}
|
||||
nextTrack := fd.TrackSectorListTrack
|
||||
nextSector := fd.TrackSectorListSector
|
||||
|
@ -401,7 +402,7 @@ func (fd *FileDesc) Contents(lsd disk.LogicalSectorDisk) ([]byte, error) {
|
|||
}
|
||||
seen[ts] = true
|
||||
tsl := TrackSectorList{}
|
||||
if err := disk.UnmarshalLogicalSector(lsd, &tsl, nextTrack, nextSector); err != nil {
|
||||
if err := disk.UnmarshalLogicalSector(diskbytes, &tsl, nextTrack, nextSector); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tsls = append(tsls, tsl)
|
||||
|
@ -426,7 +427,7 @@ func (fd *FileDesc) Contents(lsd disk.LogicalSectorDisk) ([]byte, error) {
|
|||
data = append(data, 0)
|
||||
}
|
||||
} else {
|
||||
contents, err := lsd.ReadLogicalSector(ts.Track, ts.Sector)
|
||||
contents, err := disk.ReadSector(diskbytes, ts.Track, ts.Sector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -490,15 +491,18 @@ func (tsl *TrackSectorList) FromSector(data []byte) error {
|
|||
|
||||
// readCatalogSectors reads the raw CatalogSector structs from a DOS
|
||||
// 3.3 disk.
|
||||
func readCatalogSectors(d disk.LogicalSectorDisk) ([]CatalogSector, error) {
|
||||
func readCatalogSectors(diskbytes []byte, debug bool) ([]CatalogSector, error) {
|
||||
v := &VTOC{}
|
||||
err := disk.UnmarshalLogicalSector(d, v, VTOCTrack, VTOCSector)
|
||||
err := disk.UnmarshalLogicalSector(diskbytes, v, VTOCTrack, VTOCSector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := v.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("Invalid VTOC sector: %v", err)
|
||||
}
|
||||
if debug {
|
||||
fmt.Fprintf(os.Stderr, "Read VTOC sector: %#v\n", v)
|
||||
}
|
||||
|
||||
nextTrack := v.CatalogTrack
|
||||
nextSector := v.CatalogSector
|
||||
|
@ -516,7 +520,7 @@ func readCatalogSectors(d disk.LogicalSectorDisk) ([]CatalogSector, error) {
|
|||
return nil, fmt.Errorf("catalog sectors can't be in sector %d: disk only has %d sectors", nextSector, v.NumSectors)
|
||||
}
|
||||
cs := CatalogSector{}
|
||||
err := disk.UnmarshalLogicalSector(d, &cs, nextTrack, nextSector)
|
||||
err := disk.UnmarshalLogicalSector(diskbytes, &cs, nextTrack, nextSector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -528,8 +532,8 @@ func readCatalogSectors(d disk.LogicalSectorDisk) ([]CatalogSector, error) {
|
|||
}
|
||||
|
||||
// ReadCatalog reads the catalog of a DOS 3.3 disk.
|
||||
func ReadCatalog(d disk.LogicalSectorDisk) (files, deleted []FileDesc, err error) {
|
||||
css, err := readCatalogSectors(d)
|
||||
func ReadCatalog(diskbytes []byte, debug bool) (files, deleted []FileDesc, err error) {
|
||||
css, err := readCatalogSectors(diskbytes, debug)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -549,13 +553,14 @@ func ReadCatalog(d disk.LogicalSectorDisk) (files, deleted []FileDesc, err error
|
|||
return files, deleted, nil
|
||||
}
|
||||
|
||||
// operator is a disk.Operator - an interface for performing
|
||||
// operator is a types.Operator - an interface for performing
|
||||
// high-level operations on files and directories.
|
||||
type operator struct {
|
||||
lsd disk.LogicalSectorDisk
|
||||
data []byte
|
||||
debug bool
|
||||
}
|
||||
|
||||
var _ disk.Operator = operator{}
|
||||
var _ types.Operator = operator{}
|
||||
|
||||
// operatorName is the keyword name for the operator that undestands
|
||||
// dos3 disks.
|
||||
|
@ -566,11 +571,6 @@ func (o operator) Name() string {
|
|||
return operatorName
|
||||
}
|
||||
|
||||
// Order returns the sector or block order of the underlying storage.
|
||||
func (o operator) Order() string {
|
||||
return o.lsd.Order()
|
||||
}
|
||||
|
||||
// HasSubdirs returns true if the underlying operating system on the
|
||||
// disk allows subdirectories.
|
||||
func (o operator) HasSubdirs() bool {
|
||||
|
@ -579,12 +579,12 @@ func (o operator) HasSubdirs() bool {
|
|||
|
||||
// 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) {
|
||||
fds, _, err := ReadCatalog(o.lsd)
|
||||
func (o operator) Catalog(subdir string) ([]types.Descriptor, error) {
|
||||
fds, _, err := ReadCatalog(o.data, o.debug)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
descs := make([]disk.Descriptor, 0, len(fds))
|
||||
descs := make([]types.Descriptor, 0, len(fds))
|
||||
for _, fd := range fds {
|
||||
descs = append(descs, fd.descriptor())
|
||||
}
|
||||
|
@ -594,7 +594,7 @@ func (o operator) Catalog(subdir string) ([]disk.Descriptor, error) {
|
|||
// fileForFilename returns the FileDesc corresponding to the given
|
||||
// filename, or an error.
|
||||
func (o operator) fileForFilename(filename string) (FileDesc, error) {
|
||||
fds, _, err := ReadCatalog(o.lsd)
|
||||
fds, _, err := ReadCatalog(o.data, o.debug)
|
||||
if err != nil {
|
||||
return FileDesc{}, err
|
||||
}
|
||||
|
@ -607,18 +607,18 @@ func (o operator) fileForFilename(filename string) (FileDesc, error) {
|
|||
}
|
||||
|
||||
// GetFile retrieves a file by name.
|
||||
func (o operator) GetFile(filename string) (disk.FileInfo, error) {
|
||||
func (o operator) GetFile(filename string) (types.FileInfo, error) {
|
||||
fd, err := o.fileForFilename(filename)
|
||||
if err != nil {
|
||||
return disk.FileInfo{}, err
|
||||
return types.FileInfo{}, err
|
||||
}
|
||||
desc := fd.descriptor()
|
||||
data, err := fd.Contents(o.lsd)
|
||||
data, err := fd.Contents(o.data)
|
||||
if err != nil {
|
||||
return disk.FileInfo{}, err
|
||||
return types.FileInfo{}, err
|
||||
}
|
||||
|
||||
fi := disk.FileInfo{
|
||||
fi := types.FileInfo{
|
||||
Descriptor: desc,
|
||||
Data: data,
|
||||
}
|
||||
|
@ -659,7 +659,7 @@ func (o operator) GetFile(filename string) (disk.FileInfo, error) {
|
|||
errType = "B"
|
||||
}
|
||||
|
||||
return disk.FileInfo{}, fmt.Errorf("%s does not yet implement `GetFile` for filetype %s", operatorName, errType)
|
||||
return types.FileInfo{}, fmt.Errorf("%s does not yet implement `GetFile` for filetype %s", operatorName, errType)
|
||||
}
|
||||
|
||||
// Delete deletes a file by name. It returns true if the file was
|
||||
|
@ -671,29 +671,31 @@ func (o operator) Delete(filename string) (bool, error) {
|
|||
// 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) {
|
||||
func (o operator) PutFile(fileInfo types.FileInfo, overwrite bool) (existed bool, err error) {
|
||||
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 a types.OperatorFactory for DOS 3.3 disks.
|
||||
type OperatorFactory struct {
|
||||
}
|
||||
|
||||
// operatorFactory is the factory that returns dos3 operators given
|
||||
// disk images.
|
||||
func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
||||
lsd, err := disk.NewMappedDisk(sd, disk.Dos33LogicalToPhysicalSectorMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _, err = ReadCatalog(lsd)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cannot read catalog. Underlying error: %v", err)
|
||||
}
|
||||
return operator{lsd: lsd}, nil
|
||||
// Name returns the name of the operator.
|
||||
func (of OperatorFactory) Name() string {
|
||||
return operatorName
|
||||
}
|
||||
|
||||
func init() {
|
||||
disk.RegisterDiskOperatorFactory(operatorName, operatorFactory)
|
||||
// SeemsToMatch returns true if the []byte disk image seems to match the
|
||||
// system of this operator.
|
||||
func (of OperatorFactory) SeemsToMatch(diskbytes []byte, debug bool) bool {
|
||||
// For now, just return true if we can run Catalog successfully.
|
||||
_, _, err := ReadCatalog(diskbytes, debug)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Operator returns an Operator for the []byte disk image.
|
||||
func (of OperatorFactory) Operator(diskbytes []byte, debug bool) (types.Operator, error) {
|
||||
return operator{data: diskbytes, debug: debug}, nil
|
||||
}
|
|
@ -2,10 +2,9 @@ package dos3
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
)
|
||||
|
||||
// TestVTOCMarshalRoundtrip checks a simple roundtrip of VTOC data.
|
||||
|
@ -76,15 +75,11 @@ func TestTrackSectorListMarshalRoundtrip(t *testing.T) {
|
|||
|
||||
// TestReadCatalog tests the reading of the catalog of a test disk.
|
||||
func TestReadCatalog(t *testing.T) {
|
||||
sd, err := disk.LoadDSK("testdata/dos33test.dsk")
|
||||
diskbytes, err := os.ReadFile("testdata/dos33test.dsk")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
dsk, err := disk.NewMappedDisk(sd, disk.Dos33LogicalToPhysicalSectorMap)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fds, deleted, err := ReadCatalog(dsk)
|
||||
fds, deleted, err := ReadCatalog(diskbytes, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
module github.com/zellyn/diskii
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/alecthomas/kong v0.2.17 // indirect
|
||||
github.com/kr/pretty v0.2.1
|
||||
github.com/spf13/cobra v1.1.3
|
||||
github.com/spf13/viper v1.8.1
|
||||
)
|
|
@ -0,0 +1,673 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alecthomas/kong v0.2.17 h1:URDISCI96MIgcIlQyoCAlhOmrSw6pZScBNkctg8r0W0=
|
||||
github.com/alecthomas/kong v0.2.17/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
|
||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
304
lib/disk/disk.go
304
lib/disk/disk.go
|
@ -1,304 +0,0 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// Package disk contains routines for reading and writing various disk
|
||||
// file formats.
|
||||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Various DOS33 disk characteristics.
|
||||
const (
|
||||
DOS33Tracks = 35
|
||||
DOS33Sectors = 16 // Sectors per track
|
||||
// DOS33DiskBytes is the number of bytes on a DOS 3.3 disk.
|
||||
DOS33DiskBytes = 143360 // 35 tracks * 16 sectors * 256 bytes
|
||||
DOS33TrackBytes = 256 * DOS33Sectors // Bytes per track
|
||||
)
|
||||
|
||||
// Dos33LogicalToPhysicalSectorMap maps logical sector numbers to physical ones.
|
||||
// See [UtA2 9-42 - Read Routines].
|
||||
var Dos33LogicalToPhysicalSectorMap = []byte{
|
||||
0x00, 0x0D, 0x0B, 0x09, 0x07, 0x05, 0x03, 0x01,
|
||||
0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x0F,
|
||||
}
|
||||
|
||||
// Dos33PhysicalToLogicalSectorMap maps physical sector numbers to logical ones.
|
||||
// See [UtA2 9-42 - Read Routines].
|
||||
var Dos33PhysicalToLogicalSectorMap = []byte{
|
||||
0x00, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04,
|
||||
0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x0F,
|
||||
}
|
||||
|
||||
// ProDOSLogicalToPhysicalSectorMap maps logical sector numbers to pysical ones.
|
||||
// See [UtA2e 9-43 - Sectors vs. Blocks].
|
||||
var ProDOSLogicalToPhysicalSectorMap = []byte{
|
||||
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
|
||||
0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
|
||||
}
|
||||
|
||||
// ProDosPhysicalToLogicalSectorMap maps physical sector numbers to logical ones.
|
||||
// See [UtA2e 9-43 - Sectors vs. Blocks].
|
||||
var ProDosPhysicalToLogicalSectorMap = []byte{
|
||||
0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B,
|
||||
0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F,
|
||||
}
|
||||
|
||||
// TrackSector is a pair of track/sector bytes.
|
||||
type TrackSector struct {
|
||||
Track byte
|
||||
Sector byte
|
||||
}
|
||||
|
||||
// SectorDisk is the interface used to read and write disks by
|
||||
// physical (matches sector header) sector number.
|
||||
type SectorDisk interface {
|
||||
// ReadPhysicalSector reads a single physical sector from the disk. It
|
||||
// always returns 256 byes.
|
||||
ReadPhysicalSector(track byte, sector byte) ([]byte, error)
|
||||
// WritePhysicalSector writes a single physical sector to a disk. It
|
||||
// expects exactly 256 bytes.
|
||||
WritePhysicalSector(track byte, sector byte, data []byte) error
|
||||
// Sectors returns the number of sectors on the SectorDisk
|
||||
Sectors() byte
|
||||
// Tracks returns the number of tracks on the SectorDisk
|
||||
Tracks() byte
|
||||
// Write writes the disk contents to the given file.
|
||||
Write(io.Writer) (int, error)
|
||||
// Order returns the sector order.
|
||||
Order() string
|
||||
}
|
||||
|
||||
// LogicalSectorDisk is the interface used to read and write a disk by
|
||||
// *logical* sector number.
|
||||
type LogicalSectorDisk interface {
|
||||
// ReadLogicalSector reads a single logical sector from the disk. It
|
||||
// always returns 256 byes.
|
||||
ReadLogicalSector(track byte, sector byte) ([]byte, error)
|
||||
// WriteLogicalSector writes a single logical sector to a disk. It
|
||||
// expects exactly 256 bytes.
|
||||
WriteLogicalSector(track byte, sector byte, data []byte) error
|
||||
// Sectors returns the number of sectors on the SectorDisk
|
||||
Sectors() byte
|
||||
// Tracks returns the number of tracks on the SectorDisk
|
||||
Tracks() byte
|
||||
// Write writes the disk contents to the given file.
|
||||
Write(io.Writer) (int, error)
|
||||
// Order returns the underlying sector ordering.
|
||||
Order() string
|
||||
}
|
||||
|
||||
// MappedDisk wraps a SectorDisk as a LogicalSectorDisk, handling the
|
||||
// logical-to-physical sector mapping.
|
||||
type MappedDisk struct {
|
||||
sectorDisk SectorDisk // The underlying physical sector disk.
|
||||
logicalToPhysical []byte // The mapping of logical to physical sectors.
|
||||
}
|
||||
|
||||
var _ LogicalSectorDisk = MappedDisk{}
|
||||
|
||||
// NewMappedDisk returns a MappedDisk with the given
|
||||
// logical-to-physical sector mapping.
|
||||
func NewMappedDisk(sd SectorDisk, logicalToPhysical []byte) (MappedDisk, error) {
|
||||
if logicalToPhysical != nil && len(logicalToPhysical) != int(sd.Sectors()) {
|
||||
return MappedDisk{}, fmt.Errorf("NewMappedDisk called on a disk image with %d sectors per track, but a mapping of length %d", sd.Sectors(), len(logicalToPhysical))
|
||||
}
|
||||
if logicalToPhysical == nil {
|
||||
logicalToPhysical = make([]byte, int(sd.Sectors()))
|
||||
for i := range logicalToPhysical {
|
||||
logicalToPhysical[i] = byte(i)
|
||||
}
|
||||
}
|
||||
return MappedDisk{
|
||||
sectorDisk: sd,
|
||||
logicalToPhysical: logicalToPhysical,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ReadLogicalSector reads a single logical sector from the disk. It
|
||||
// always returns 256 byes.
|
||||
func (md MappedDisk) ReadLogicalSector(track byte, sector byte) ([]byte, error) {
|
||||
if track >= md.sectorDisk.Tracks() {
|
||||
return nil, fmt.Errorf("ReadLogicalSector expected track between 0 and %d; got %d", md.sectorDisk.Tracks()-1, track)
|
||||
}
|
||||
if sector >= md.sectorDisk.Sectors() {
|
||||
return nil, fmt.Errorf("ReadLogicalSector expected sector between 0 and %d; got %d", md.sectorDisk.Sectors()-1, sector)
|
||||
}
|
||||
physicalSector := md.logicalToPhysical[int(sector)]
|
||||
return md.sectorDisk.ReadPhysicalSector(track, physicalSector)
|
||||
}
|
||||
|
||||
// WriteLogicalSector writes a single logical sector to a disk. It
|
||||
// expects exactly 256 bytes.
|
||||
func (md MappedDisk) WriteLogicalSector(track byte, sector byte, data []byte) error {
|
||||
if track >= md.sectorDisk.Tracks() {
|
||||
return fmt.Errorf("WriteLogicalSector expected track between 0 and %d; got %d", md.sectorDisk.Tracks()-1, track)
|
||||
}
|
||||
if sector >= md.sectorDisk.Sectors() {
|
||||
return fmt.Errorf("WriteLogicalSector expected sector between 0 and %d; got %d", md.sectorDisk.Sectors()-1, sector)
|
||||
}
|
||||
physicalSector := md.logicalToPhysical[int(sector)]
|
||||
return md.sectorDisk.WritePhysicalSector(track, physicalSector, data)
|
||||
}
|
||||
|
||||
// Sectors returns the number of sectors in the disk image.
|
||||
func (md MappedDisk) Sectors() byte {
|
||||
return md.sectorDisk.Sectors()
|
||||
}
|
||||
|
||||
// Tracks returns the number of tracks in the disk image.
|
||||
func (md MappedDisk) Tracks() byte {
|
||||
return md.sectorDisk.Tracks()
|
||||
}
|
||||
|
||||
// Write writes the disk contents to the given file.
|
||||
func (md MappedDisk) Write(w io.Writer) (n int, err error) {
|
||||
return md.sectorDisk.Write(w)
|
||||
}
|
||||
|
||||
// Order returns the sector order of the underlying sector disk.
|
||||
func (md MappedDisk) Order() string {
|
||||
return md.sectorDisk.Order()
|
||||
}
|
||||
|
||||
// OpenDisk opens a disk image by filename.
|
||||
func OpenDisk(filename string) (SectorDisk, error) {
|
||||
ext := strings.ToLower(path.Ext(filename))
|
||||
switch ext {
|
||||
case ".dsk":
|
||||
return LoadDSK(filename)
|
||||
}
|
||||
return nil, fmt.Errorf("Unimplemented/unknown disk file extension %q", ext)
|
||||
}
|
||||
|
||||
// OpenDev opens a device image by filename.
|
||||
func OpenDev(filename string) (BlockDevice, error) {
|
||||
ext := strings.ToLower(path.Ext(filename))
|
||||
switch ext {
|
||||
case ".po":
|
||||
return LoadDev(filename)
|
||||
}
|
||||
return nil, fmt.Errorf("Unimplemented/unknown device 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 {
|
||||
var op Operator
|
||||
op, err = OperatorForDisk(sd)
|
||||
if err == nil {
|
||||
return op, nil
|
||||
}
|
||||
}
|
||||
|
||||
dev, err2 := OpenDev(filename)
|
||||
if err2 == nil {
|
||||
var op Operator
|
||||
op, err2 = OperatorForDevice(dev)
|
||||
if err2 != nil {
|
||||
return nil, err2
|
||||
}
|
||||
return op, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type DiskBlockDevice struct {
|
||||
lsd LogicalSectorDisk
|
||||
blocks uint16
|
||||
}
|
||||
|
||||
// BlockDeviceFromSectorDisk creates a ProDOS block device from a
|
||||
// SectorDisk. It reads maps ProDOS to physical sectors.
|
||||
func BlockDeviceFromSectorDisk(sd SectorDisk) (BlockDevice, error) {
|
||||
lsd, err := NewMappedDisk(sd, ProDOSLogicalToPhysicalSectorMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return DiskBlockDevice{
|
||||
lsd: lsd,
|
||||
blocks: uint16(lsd.Tracks()) / 2 * uint16(lsd.Sectors()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ReadBlock reads a single block from the device. It always returns
|
||||
// 512 byes.
|
||||
func (dbv DiskBlockDevice) ReadBlock(index uint16) (Block, error) {
|
||||
var b Block
|
||||
if index >= dbv.blocks {
|
||||
return b, fmt.Errorf("device has %d blocks; tried to read block %d (index=%d)", dbv.blocks, index+1, index)
|
||||
}
|
||||
i := int(index) * 2
|
||||
sectors := int(dbv.lsd.Sectors())
|
||||
|
||||
track0 := i / sectors
|
||||
sector0 := i % sectors
|
||||
sector1 := sector0 + 1
|
||||
track1 := track0
|
||||
if sector1 == sectors {
|
||||
sector1 = 0
|
||||
track1++
|
||||
}
|
||||
|
||||
b0, err := dbv.lsd.ReadLogicalSector(byte(track0), byte(sector0))
|
||||
if err != nil {
|
||||
return b, fmt.Errorf("error reading first half of block %d (t:%d s:%d): %v", index, track0, sector0, err)
|
||||
}
|
||||
b1, err := dbv.lsd.ReadLogicalSector(byte(track1), byte(sector1))
|
||||
if err != nil {
|
||||
return b, fmt.Errorf("error reading second half of block %d (t:%d s:%d): %v", index, track1, sector1, err)
|
||||
}
|
||||
copy(b[:256], b0)
|
||||
copy(b[256:], b1)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// WriteBlock writes a single block to a device. It expects exactly
|
||||
// 512 bytes.
|
||||
func (dbv DiskBlockDevice) WriteBlock(index uint16, data Block) error {
|
||||
if index >= dbv.blocks {
|
||||
return fmt.Errorf("device has %d blocks; tried to read block %d (index=%d)", dbv.blocks, index+1, index)
|
||||
}
|
||||
i := int(index) * 2
|
||||
sectors := int(dbv.lsd.Sectors())
|
||||
|
||||
track0 := i / sectors
|
||||
sector0 := i % sectors
|
||||
sector1 := sector0 + 1
|
||||
track1 := track0
|
||||
if sector1 == sectors {
|
||||
sector1 = 0
|
||||
track1++
|
||||
}
|
||||
|
||||
if err := dbv.lsd.WriteLogicalSector(byte(track0), byte(sector0), data[:256]); err != nil {
|
||||
return fmt.Errorf("error writing first half of block %d (t:%d s:%d): %v", index, track0, sector0, err)
|
||||
}
|
||||
if err := dbv.lsd.WriteLogicalSector(byte(track1), byte(sector1), data[256:]); err != nil {
|
||||
return fmt.Errorf("error writing second half of block %d (t:%d s:%d): %v", index, track1, sector1, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Blocks returns the number of blocks on the device.
|
||||
func (dbv DiskBlockDevice) Blocks() uint16 {
|
||||
return dbv.blocks
|
||||
}
|
||||
|
||||
// Order returns the underlying sector or block order of the storage.
|
||||
func (dbv DiskBlockDevice) Order() string {
|
||||
return dbv.lsd.Order()
|
||||
}
|
||||
|
||||
// Write writes the device contents to the given Writer.
|
||||
func (dbv DiskBlockDevice) Write(w io.Writer) (int, error) {
|
||||
return dbv.lsd.Write(w)
|
||||
}
|
111
lib/disk/dsk.go
111
lib/disk/dsk.go
|
@ -1,111 +0,0 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// dsk.go contains logic for reading ".dsk" disk images.
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// DSK represents a .dsk disk image.
|
||||
type DSK struct {
|
||||
data []byte // The actual data in the file
|
||||
sectors byte // Number of sectors per track
|
||||
physicalToStored []byte // Map of physical on-disk sector numbers to sectors in the disk image
|
||||
bytesPerTrack int // Number of bytes per track
|
||||
tracks byte // Number of tracks
|
||||
order string // Underlying sector order.
|
||||
}
|
||||
|
||||
var _ SectorDisk = (*DSK)(nil)
|
||||
|
||||
// LoadDSK loads a .dsk image from a file.
|
||||
func LoadDSK(filename string) (DSK, error) {
|
||||
bb, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return DSK{}, err
|
||||
}
|
||||
// TODO(zellyn): handle 13-sector disks.
|
||||
if len(bb) != DOS33DiskBytes {
|
||||
return DSK{}, fmt.Errorf("expected file %q to contain %d bytes, but got %d", filename, DOS33DiskBytes, len(bb))
|
||||
}
|
||||
return DSK{
|
||||
data: bb,
|
||||
sectors: 16,
|
||||
physicalToStored: Dos33PhysicalToLogicalSectorMap,
|
||||
bytesPerTrack: 16 * 256,
|
||||
tracks: DOS33Tracks,
|
||||
order: "dos33",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Empty creates a .dsk image that is all zeros.
|
||||
func Empty() DSK {
|
||||
return DSK{
|
||||
data: make([]byte, DOS33DiskBytes),
|
||||
sectors: 16,
|
||||
physicalToStored: Dos33PhysicalToLogicalSectorMap,
|
||||
bytesPerTrack: 16 * 256,
|
||||
tracks: DOS33Tracks,
|
||||
order: "dos33",
|
||||
}
|
||||
}
|
||||
|
||||
// ReadPhysicalSector reads a single physical sector from the disk. It
|
||||
// always returns 256 byes.
|
||||
func (d DSK) ReadPhysicalSector(track byte, sector byte) ([]byte, error) {
|
||||
if track >= d.tracks {
|
||||
return nil, fmt.Errorf("ReadPhysicalSector expected track between 0 and %d; got %d", d.tracks-1, track)
|
||||
}
|
||||
if sector >= d.sectors {
|
||||
return nil, fmt.Errorf("ReadPhysicalSector expected sector between 0 and %d; got %d", d.sectors-1, sector)
|
||||
}
|
||||
|
||||
storedSector := d.physicalToStored[int(sector)]
|
||||
start := int(track)*d.bytesPerTrack + 256*int(storedSector)
|
||||
buf := make([]byte, 256)
|
||||
copy(buf, d.data[start:start+256])
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// WritePhysicalSector writes a single physical sector to a disk. It
|
||||
// expects exactly 256 bytes.
|
||||
func (d DSK) WritePhysicalSector(track byte, sector byte, data []byte) error {
|
||||
if track >= d.tracks {
|
||||
return fmt.Errorf("WritePhysicalSector expected track between 0 and %d; got %d", d.tracks-1, track)
|
||||
}
|
||||
if sector >= d.sectors {
|
||||
return fmt.Errorf("WritePhysicalSector expected sector between 0 and %d; got %d", d.sectors-1, sector)
|
||||
}
|
||||
if len(data) != 256 {
|
||||
return fmt.Errorf("WritePhysicalSector expects data of length 256; got %d", len(data))
|
||||
}
|
||||
|
||||
storedSector := d.physicalToStored[int(sector)]
|
||||
start := int(track)*d.bytesPerTrack + 256*int(storedSector)
|
||||
copy(d.data[start:start+256], data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sectors returns the number of sectors on the DSK image.
|
||||
func (d DSK) Sectors() byte {
|
||||
return d.sectors
|
||||
}
|
||||
|
||||
// Tracks returns the number of tracks on the DSK image.
|
||||
func (d DSK) Tracks() byte {
|
||||
return d.tracks
|
||||
}
|
||||
|
||||
// Order returns the sector order name.
|
||||
func (d DSK) Order() string {
|
||||
return d.order
|
||||
}
|
||||
|
||||
// Write writes the disk contents to the given file.
|
||||
func (d DSK) Write(w io.Writer) (n int, err error) {
|
||||
return w.Write(d.data)
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// marshal.go contains helpers for marshaling sector structs to/from
|
||||
// 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)
|
||||
// Order returns the sector or block order of the underlying device.
|
||||
Order() string
|
||||
}
|
||||
|
||||
// SectorSource is the interface for types that can marshal to sectors.
|
||||
type SectorSource interface {
|
||||
// ToSector marshals the sector struct to exactly 256 bytes.
|
||||
ToSector() ([]byte, error)
|
||||
// GetTrack returns the track that a sector struct was loaded from.
|
||||
GetTrack() byte
|
||||
// GetSector returns the sector that a sector struct was loaded from.
|
||||
GetSector() byte
|
||||
}
|
||||
|
||||
// SectorSink is the interface for types that can unmarshal from sectors.
|
||||
type SectorSink interface {
|
||||
// FromSector unmarshals the sector struct from bytes. Input is
|
||||
// expected to be exactly 256 bytes.
|
||||
FromSector(data []byte) error
|
||||
// SetTrack sets the track that a sector struct was loaded from.
|
||||
SetTrack(track byte)
|
||||
// SetSector sets the sector that a sector struct was loaded from.
|
||||
SetSector(sector byte)
|
||||
}
|
||||
|
||||
// UnmarshalLogicalSector reads a sector from a SectorDisk, and
|
||||
// unmarshals it into a SectorSink, setting its track and sector.
|
||||
func UnmarshalLogicalSector(d LogicalSectorDisk, ss SectorSink, track, sector byte) error {
|
||||
bytes, err := d.ReadLogicalSector(track, sector)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ss.FromSector(bytes); err != nil {
|
||||
return err
|
||||
}
|
||||
ss.SetTrack(track)
|
||||
ss.SetSector(sector)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalLogicalSector marshals a SectorSource to its sector on a
|
||||
// SectorDisk.
|
||||
func MarshalLogicalSector(d LogicalSectorDisk, ss SectorSource) error {
|
||||
track := ss.GetTrack()
|
||||
sector := ss.GetSector()
|
||||
bytes, err := ss.ToSector()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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)
|
||||
}
|
134
lib/disk/ops.go
134
lib/disk/ops.go
|
@ -1,134 +0,0 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// ops.go contains the interfaces and helper functions for operating
|
||||
// on disk images logically: catalog, rename, delete, create files,
|
||||
// etc.
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Descriptor describes a file's characteristics.
|
||||
type Descriptor struct {
|
||||
Name string
|
||||
Fullname string // If there's a more complete filename (eg. Super-Mon), put it here.
|
||||
Sectors int
|
||||
Blocks int
|
||||
Length int
|
||||
Locked bool
|
||||
Type Filetype
|
||||
}
|
||||
|
||||
// Operator is the interface that can operate on disks.
|
||||
type Operator interface {
|
||||
// Name returns the name of the operator.
|
||||
Name() string
|
||||
// Order returns the sector or block order name.
|
||||
Order() string
|
||||
// HasSubdirs returns true if the underlying operating system on the
|
||||
// disk allows subdirectories.
|
||||
HasSubdirs() bool
|
||||
// Catalog returns a catalog of disk entries. subdir should be empty
|
||||
// for operating systems that do not support subdirectories.
|
||||
Catalog(subdir string) ([]Descriptor, error)
|
||||
// GetFile retrieves a file by name.
|
||||
GetFile(filename string) (FileInfo, error)
|
||||
// Delete deletes a file by name. It returns true if the file was
|
||||
// deleted, false if it didn't exist.
|
||||
Delete(filename string) (bool, error)
|
||||
// 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.
|
||||
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.
|
||||
type FileInfo struct {
|
||||
Descriptor Descriptor
|
||||
Data []byte
|
||||
StartAddress uint16
|
||||
}
|
||||
|
||||
// diskOperatorFactory is the type of functions that accept a SectorDisk,
|
||||
// and may return an Operator interface to operate on it.
|
||||
type diskOperatorFactory func(SectorDisk) (Operator, error)
|
||||
|
||||
// diskOperatorFactories is the map of currently-registered disk
|
||||
// operator factories.
|
||||
var diskOperatorFactories map[string]diskOperatorFactory
|
||||
|
||||
func init() {
|
||||
diskOperatorFactories = make(map[string]diskOperatorFactory)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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 diskOperatorFactories {
|
||||
if operator, err := factory(sd); err == nil {
|
||||
return operator, nil
|
||||
}
|
||||
}
|
||||
names := make([]string, 0, len(diskOperatorFactories))
|
||||
for name := range diskOperatorFactories {
|
||||
names = append(names, `"`+name+`"`)
|
||||
}
|
||||
sort.Strings(names)
|
||||
return nil, fmt.Errorf("Cannot find a disk operator matching the given disk image (tried %s)", strings.Join(names, ", "))
|
||||
}
|
||||
|
||||
// deviceOperatorFactory is the type of functions that accept a BlockDevice,
|
||||
// and may return an Operator interface to operate on it.
|
||||
type deviceOperatorFactory func(BlockDevice) (Operator, error)
|
||||
|
||||
// deviceOperatorFactories is the map of currently-registered device
|
||||
// operator factories.
|
||||
var deviceOperatorFactories map[string]deviceOperatorFactory
|
||||
|
||||
func init() {
|
||||
deviceOperatorFactories = make(map[string]deviceOperatorFactory)
|
||||
}
|
||||
|
||||
// RegisterDeviceOperatorFactory registers a device operator factory with
|
||||
// the given name: a function that accepts a BlockDevice, and may
|
||||
// return an Operator. It doesn't lock deviceOperatorFactories: it is
|
||||
// expected to be called only from package `init` functions.
|
||||
func RegisterDeviceOperatorFactory(name string, factory deviceOperatorFactory) {
|
||||
deviceOperatorFactories[name] = factory
|
||||
}
|
||||
|
||||
// OperatorForDevice returns an Operator for the given BlockDevice, if possible.
|
||||
func OperatorForDevice(sd BlockDevice) (Operator, error) {
|
||||
if len(deviceOperatorFactories) == 0 {
|
||||
return nil, errors.New("Cannot find an operator matching the given device image (none registered)")
|
||||
}
|
||||
for _, factory := range deviceOperatorFactories {
|
||||
if operator, err := factory(sd); err == nil {
|
||||
return operator, nil
|
||||
}
|
||||
}
|
||||
names := make([]string, 0, len(deviceOperatorFactories))
|
||||
for name := range deviceOperatorFactories {
|
||||
names = append(names, `"`+name+`"`)
|
||||
}
|
||||
sort.Strings(names)
|
||||
return nil, fmt.Errorf("Cannot find a device operator matching the given device image (tried %s)", strings.Join(names, ", "))
|
||||
}
|
54
main.go
54
main.go
|
@ -1,16 +1,56 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
// Copyright ©2021 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/zellyn/diskii/cmd"
|
||||
"github.com/zellyn/diskii/dos3"
|
||||
"github.com/zellyn/diskii/types"
|
||||
|
||||
// Import disk operator factories for DOS3 and Super-Mon
|
||||
_ "github.com/zellyn/diskii/lib/dos3"
|
||||
_ "github.com/zellyn/diskii/lib/prodos"
|
||||
_ "github.com/zellyn/diskii/lib/supermon"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
var cli struct {
|
||||
Debug bool `kong:"short='v',help='Enable debug mode.'"`
|
||||
Order string `kong:"default='auto',enum='auto,raw,do,po',help='Logical-to-physical sector order.'"`
|
||||
System string `kong:"default='auto',enum='auto,dos3',help='DOS system used for image.'"`
|
||||
|
||||
Ls cmd.LsCmd `cmd:"" aliases:"cat,catalog" help:"List paths."`
|
||||
}
|
||||
|
||||
func run() error {
|
||||
|
||||
ctx := kong.Parse(&cli,
|
||||
kong.Name("diskii"),
|
||||
kong.Description("A commandline tool for working with Apple II disk images."),
|
||||
kong.UsageOnError(),
|
||||
kong.ConfigureHelp(kong.HelpOptions{
|
||||
Compact: true,
|
||||
Summary: true,
|
||||
}),
|
||||
)
|
||||
|
||||
globals := &types.Globals{
|
||||
Debug: cli.Debug,
|
||||
Order: cli.Order,
|
||||
System: cli.System,
|
||||
DiskOperatorFactories: []types.OperatorFactory{
|
||||
dos3.OperatorFactory{},
|
||||
// supermon.OperatorFactory,
|
||||
// prodos.DiskOperatorFactory,
|
||||
},
|
||||
}
|
||||
// Call the Run() method of the selected parsed command.
|
||||
return ctx.Run(globals)
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/disk"
|
||||
)
|
||||
|
||||
// Storage types.
|
||||
|
@ -875,9 +875,9 @@ func deviceOperatorFactory(bd disk.BlockDevice) (disk.Operator, error) {
|
|||
return op, nil
|
||||
}
|
||||
|
||||
// diskOperatorFactory is the factory that returns dos3 operators
|
||||
// DiskOperatorFactory is the factory that returns dos3 operators
|
||||
// given disk images.
|
||||
func diskOperatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
||||
func DiskOperatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
||||
bd, err := disk.BlockDeviceFromSectorDisk(sd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -887,5 +887,5 @@ func diskOperatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
|||
|
||||
func init() {
|
||||
disk.RegisterDeviceOperatorFactory(operatorName, deviceOperatorFactory)
|
||||
disk.RegisterDiskOperatorFactory(operatorName, diskOperatorFactory)
|
||||
disk.RegisterDiskOperatorFactory(operatorName, DiskOperatorFactory)
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/disk"
|
||||
)
|
||||
|
||||
func randomBlock() disk.Block {
|
|
@ -7,12 +7,11 @@ package supermon
|
|||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/lib/errors"
|
||||
"github.com/zellyn/diskii/disk"
|
||||
"github.com/zellyn/diskii/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -29,17 +28,17 @@ const (
|
|||
type SectorMap []byte
|
||||
|
||||
// LoadSectorMap loads a NakedOS sector map.
|
||||
func LoadSectorMap(sd disk.SectorDisk) (SectorMap, error) {
|
||||
func LoadSectorMap(diskbytes []byte) (SectorMap, error) {
|
||||
sm := SectorMap(make([]byte, 560))
|
||||
sector09, err := sd.ReadPhysicalSector(0, 9)
|
||||
sector09, err := disk.ReadSector(diskbytes, 0, 9)
|
||||
if err != nil {
|
||||
return sm, err
|
||||
}
|
||||
sector0A, err := sd.ReadPhysicalSector(0, 0xA)
|
||||
sector0A, err := disk.ReadSector(diskbytes, 0, 0xA)
|
||||
if err != nil {
|
||||
return sm, err
|
||||
}
|
||||
sector0B, err := sd.ReadPhysicalSector(0, 0xB)
|
||||
sector0B, err := disk.ReadSector(diskbytes, 0, 0xB)
|
||||
if err != nil {
|
||||
return sm, err
|
||||
}
|
||||
|
@ -63,19 +62,19 @@ func (sm SectorMap) FirstFreeFile() byte {
|
|||
|
||||
// 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)
|
||||
func (sm SectorMap) Persist(diskbytes []byte) error {
|
||||
sector09, err := disk.ReadSector(diskbytes, 0, 9)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(sector09[0xd0:], sm[0:0x30])
|
||||
if err := sd.WritePhysicalSector(0, 9, sector09); err != nil {
|
||||
if err := disk.WriteSector(diskbytes, 0, 9, sector09); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := sd.WritePhysicalSector(0, 0xA, sm[0x30:0x130]); err != nil {
|
||||
if err := disk.WriteSector(diskbytes, 0, 0xA, sm[0x30:0x130]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := sd.WritePhysicalSector(0, 0xB, sm[0x130:0x230]); err != nil {
|
||||
if err := disk.WriteSector(diskbytes, 0, 0xB, sm[0x130:0x230]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -167,10 +166,10 @@ func (sm SectorMap) SectorsByFile() map[byte][]disk.TrackSector {
|
|||
}
|
||||
|
||||
// ReadFile reads the contents of a file.
|
||||
func (sm SectorMap) ReadFile(sd disk.SectorDisk, file byte) ([]byte, error) {
|
||||
func (sm SectorMap) ReadFile(diskbytes []byte, file byte) ([]byte, error) {
|
||||
var result []byte
|
||||
for _, ts := range sm.SectorsForFile(file) {
|
||||
bytes, err := sd.ReadPhysicalSector(ts.Track, ts.Sector)
|
||||
bytes, err := disk.ReadSector(diskbytes, ts.Track, ts.Sector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -190,7 +189,7 @@ func (sm SectorMap) Delete(file byte) {
|
|||
|
||||
// WriteFile writes the contents of a file. It returns true if the
|
||||
// file already existed.
|
||||
func (sm SectorMap) WriteFile(sd disk.SectorDisk, file byte, contents []byte, overwrite bool) (bool, error) {
|
||||
func (sm SectorMap) WriteFile(diskbytes []byte, file byte, contents []byte, overwrite bool) (bool, error) {
|
||||
sectorsNeeded := (len(contents) + 255) / 256
|
||||
cts := make([]byte, 256*sectorsNeeded)
|
||||
copy(cts, contents)
|
||||
|
@ -209,10 +208,10 @@ func (sm SectorMap) WriteFile(sd disk.SectorDisk, file byte, contents []byte, ov
|
|||
|
||||
i := 0
|
||||
OUTER:
|
||||
for track := byte(0); track < sd.Tracks(); track++ {
|
||||
for sector := byte(0); sector < sd.Sectors(); sector++ {
|
||||
for track := byte(0); track < disk.FloppyTracks; track++ {
|
||||
for sector := byte(0); sector < disk.FloppySectors; sector++ {
|
||||
if sm.FileForSector(track, sector) == FileFree {
|
||||
if err := sd.WritePhysicalSector(track, sector, cts[i*256:(i+1)*256]); err != nil {
|
||||
if err := disk.WriteSector(diskbytes, track, sector, cts[i*256:(i+1)*256]); err != nil {
|
||||
return existed, err
|
||||
}
|
||||
if err := sm.SetFileForSector(track, sector, file); err != nil {
|
||||
|
@ -225,7 +224,7 @@ OUTER:
|
|||
}
|
||||
}
|
||||
}
|
||||
if err := sm.Persist(sd); err != nil {
|
||||
if err := sm.Persist(diskbytes); err != nil {
|
||||
return existed, err
|
||||
}
|
||||
return existed, nil
|
||||
|
@ -317,16 +316,16 @@ type SymbolTable []Symbol
|
|||
// ReadSymbolTable reads the symbol table from a disk. If there are
|
||||
// problems with the symbol table (like it doesn't exist, or the link
|
||||
// pointers are problematic), it'll return nil and an error.
|
||||
func (sm SectorMap) ReadSymbolTable(sd disk.SectorDisk) (SymbolTable, error) {
|
||||
func (sm SectorMap) ReadSymbolTable(diskbytes []byte) (SymbolTable, error) {
|
||||
table := make(SymbolTable, 0, 819)
|
||||
symtbl1, err := sm.ReadFile(sd, 3)
|
||||
symtbl1, err := sm.ReadFile(diskbytes, 3)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(symtbl1) != 0x1000 {
|
||||
return nil, fmt.Errorf("expected file FSYMTBL1(0x3) to be 0x1000 bytes long; got 0x%04X", len(symtbl1))
|
||||
}
|
||||
symtbl2, err := sm.ReadFile(sd, 4)
|
||||
symtbl2, err := sm.ReadFile(diskbytes, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -380,7 +379,7 @@ func (sm SectorMap) ReadSymbolTable(sd disk.SectorDisk) (SymbolTable, error) {
|
|||
}
|
||||
|
||||
// WriteSymbolTable writes a symbol table to a disk.
|
||||
func (sm SectorMap) WriteSymbolTable(sd disk.SectorDisk, st SymbolTable) error {
|
||||
func (sm SectorMap) WriteSymbolTable(diskbytes []byte, st SymbolTable) error {
|
||||
symtbl1 := make([]byte, 0x1000)
|
||||
symtbl2 := make([]byte, 0x1000)
|
||||
for i, sym := range st {
|
||||
|
@ -400,10 +399,10 @@ func (sm SectorMap) WriteSymbolTable(sd disk.SectorDisk, st SymbolTable) error {
|
|||
symtbl1[offset+4] = six[5]
|
||||
copy(symtbl2[offset:offset+5], six)
|
||||
}
|
||||
if _, err := sm.WriteFile(sd, 3, symtbl1, true); err != nil {
|
||||
if _, err := sm.WriteFile(diskbytes, 3, symtbl1, true); err != nil {
|
||||
return fmt.Errorf("unable to write first half of symbol table: %v", err)
|
||||
}
|
||||
if _, err := sm.WriteFile(sd, 4, symtbl2, true); err != nil {
|
||||
if _, err := sm.WriteFile(diskbytes, 4, symtbl2, true); err != nil {
|
||||
return fmt.Errorf("unable to write first second of symbol table: %v", err)
|
||||
}
|
||||
return nil
|
||||
|
@ -643,9 +642,9 @@ func (st SymbolTable) FilesForCompoundName(filename string) (numFile byte, named
|
|||
// Operator is a disk.Operator - an interface for performing
|
||||
// high-level operations on files and directories.
|
||||
type Operator struct {
|
||||
SD disk.SectorDisk
|
||||
SM SectorMap
|
||||
ST SymbolTable
|
||||
data []byte
|
||||
SM SectorMap
|
||||
ST SymbolTable
|
||||
}
|
||||
|
||||
var _ disk.Operator = Operator{}
|
||||
|
@ -659,11 +658,6 @@ func (o Operator) Name() string {
|
|||
return operatorName
|
||||
}
|
||||
|
||||
// Order returns the sector or block order of the Operator.
|
||||
func (o Operator) Order() string {
|
||||
return o.SD.Order()
|
||||
}
|
||||
|
||||
// HasSubdirs returns true if the underlying operating system on the
|
||||
// disk allows subdirectories.
|
||||
func (o Operator) HasSubdirs() bool {
|
||||
|
@ -698,7 +692,7 @@ func (o Operator) GetFile(filename string) (disk.FileInfo, error) {
|
|||
if err != nil {
|
||||
return disk.FileInfo{}, err
|
||||
}
|
||||
data, err := o.SM.ReadFile(o.SD, file)
|
||||
data, err := o.SM.ReadFile(o.data, file)
|
||||
if err != nil {
|
||||
return disk.FileInfo{}, fmt.Errorf("error reading file DF%02x: %v", file, err)
|
||||
}
|
||||
|
@ -731,13 +725,13 @@ func (o Operator) Delete(filename string) (bool, error) {
|
|||
}
|
||||
existed := len(o.SM.SectorsForFile(file)) > 0
|
||||
o.SM.Delete(file)
|
||||
if err := o.SM.Persist(o.SD); err != nil {
|
||||
if err := o.SM.Persist(o.data); err != nil {
|
||||
return existed, err
|
||||
}
|
||||
if o.ST != nil {
|
||||
changed := o.ST.DeleteSymbol(filename)
|
||||
if changed {
|
||||
if err := o.SM.WriteSymbolTable(o.SD, o.ST); err != nil {
|
||||
if err := o.SM.WriteSymbolTable(o.data, o.ST); err != nil {
|
||||
return existed, err
|
||||
}
|
||||
}
|
||||
|
@ -774,7 +768,7 @@ func (o Operator) PutFile(fileInfo disk.FileInfo, overwrite bool) (existed bool,
|
|||
return false, fmt.Errorf("all files already used")
|
||||
}
|
||||
}
|
||||
existed, err = o.SM.WriteFile(o.SD, numFile, fileInfo.Data, overwrite)
|
||||
existed, err = o.SM.WriteFile(o.data, numFile, fileInfo.Data, overwrite)
|
||||
if err != nil {
|
||||
return existed, err
|
||||
}
|
||||
|
@ -782,22 +776,17 @@ func (o Operator) PutFile(fileInfo disk.FileInfo, overwrite bool) (existed bool,
|
|||
if err := o.ST.AddSymbol(symbol, 0xDF00+uint16(numFile)); err != nil {
|
||||
return existed, err
|
||||
}
|
||||
if err := o.SM.WriteSymbolTable(o.SD, o.ST); err != nil {
|
||||
if err := o.SM.WriteSymbolTable(o.data, o.ST); err != nil {
|
||||
return existed, err
|
||||
}
|
||||
}
|
||||
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
|
||||
// OperatorFactory is the factory that returns supermon operators
|
||||
// given disk images.
|
||||
func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
||||
sm, err := LoadSectorMap(sd)
|
||||
func OperatorFactory(diskbytes []byte) (disk.Operator, error) {
|
||||
sm, err := LoadSectorMap(diskbytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -805,16 +794,12 @@ func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
op := Operator{SD: sd, SM: sm}
|
||||
op := Operator{data: diskbytes, SM: sm}
|
||||
|
||||
st, err := sm.ReadSymbolTable(sd)
|
||||
st, err := sm.ReadSymbolTable(diskbytes)
|
||||
if err == nil {
|
||||
op.ST = st
|
||||
}
|
||||
|
||||
return op, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
disk.RegisterDiskOperatorFactory(operatorName, operatorFactory)
|
||||
}
|
|
@ -8,7 +8,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"github.com/zellyn/diskii/lib/disk"
|
||||
"github.com/zellyn/diskii/disk"
|
||||
)
|
||||
|
||||
const testDisk = "testdata/chacha20.dsk"
|
|
@ -3,7 +3,7 @@
|
|||
// filetype.go contains the Filetype type, along with routines for
|
||||
// converting to and from strings.
|
||||
|
||||
package disk
|
||||
package types
|
||||
|
||||
import "fmt"
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright © 2016 Zellyn Hunter <zellyn@gmail.com>
|
||||
|
||||
// ops.go contains the interfaces and helper functions for operating
|
||||
// on disk images logically: catalog, rename, delete, create files,
|
||||
// etc.
|
||||
|
||||
package types
|
||||
|
||||
// Descriptor describes a file's characteristics.
|
||||
type Descriptor struct {
|
||||
Name string
|
||||
Fullname string // If there's a more complete filename (eg. Super-Mon), put it here.
|
||||
Sectors int
|
||||
Blocks int
|
||||
Length int
|
||||
Locked bool
|
||||
Type Filetype
|
||||
}
|
||||
|
||||
// OperatorFactory is the interface for getting operators, and finding out a bit
|
||||
// about them before getting them.
|
||||
type OperatorFactory interface {
|
||||
// Name returns the name of the operator.
|
||||
Name() string
|
||||
// SeemsToMatch returns true if the []byte disk image seems to match the
|
||||
// system of this operator.
|
||||
SeemsToMatch(diskbytes []byte, debug bool) bool
|
||||
// Operator returns an Operator for the []byte disk image.
|
||||
Operator(diskbytes []byte, debug bool) (Operator, error)
|
||||
}
|
||||
|
||||
// Operator is the interface that can operate on disks.
|
||||
type Operator interface {
|
||||
// Name returns the name of the operator.
|
||||
Name() string
|
||||
// HasSubdirs returns true if the underlying operating system on the
|
||||
// disk allows subdirectories.
|
||||
HasSubdirs() bool
|
||||
// Catalog returns a catalog of disk entries. subdir should be empty
|
||||
// for operating systems that do not support subdirectories.
|
||||
Catalog(subdir string) ([]Descriptor, error)
|
||||
// GetFile retrieves a file by name.
|
||||
GetFile(filename string) (FileInfo, error)
|
||||
// Delete deletes a file by name. It returns true if the file was
|
||||
// deleted, false if it didn't exist.
|
||||
Delete(filename string) (bool, error)
|
||||
// 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.
|
||||
PutFile(fileInfo FileInfo, overwrite bool) (existed bool, err error)
|
||||
}
|
||||
|
||||
// FileInfo represents a file descriptor plus the content.
|
||||
type FileInfo struct {
|
||||
Descriptor Descriptor
|
||||
Data []byte
|
||||
StartAddress uint16
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package types
|
||||
|
||||
// Globals holds flags and configuration that are shared globally.
|
||||
type Globals struct {
|
||||
Debug bool
|
||||
Order string //Logical-to-physical sector order
|
||||
System string // DOS system used for image
|
||||
|
||||
DiskOperatorFactories []OperatorFactory
|
||||
}
|
|
@ -5,7 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/zellyn/diskii/data"
|
||||
"github.com/zellyn/diskii/lib/woz"
|
||||
"github.com/zellyn/diskii/woz"
|
||||
)
|
||||
|
||||
func TestBasicLoad(t *testing.T) {
|
|
@ -0,0 +1,64 @@
|
|||
* = $6000
|
||||
START = *
|
||||
|
||||
;; Free addresses: 6, 7, 8, 9
|
||||
|
||||
IOB = $6
|
||||
RWTS = $3D9
|
||||
GET_IOB = $3E3
|
||||
BUF = $6100
|
||||
|
||||
start:
|
||||
; set up IOB address
|
||||
jsr GET_IOB
|
||||
sta IOB+1
|
||||
sty IOB
|
||||
|
||||
lda #$f
|
||||
outer:
|
||||
ldy #0
|
||||
inner:
|
||||
sta BUF,Y
|
||||
iny
|
||||
bne inner
|
||||
pha
|
||||
jsr write
|
||||
pla
|
||||
tax
|
||||
dex
|
||||
txa
|
||||
bpl outer
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
write:
|
||||
ldy #$5 ; sector number
|
||||
sta ($6), Y
|
||||
ldy #$2 ; drive number
|
||||
lda #$2 ; drive 2
|
||||
sta ($6), Y
|
||||
iny ; 3: volume
|
||||
lda #0 ; any volume
|
||||
sta ($6), Y
|
||||
iny ; 4: track
|
||||
sta ($6), Y
|
||||
ldy #$8 ; LO of buffer
|
||||
lda #<BUF
|
||||
sta ($6), Y
|
||||
iny ; $9: HI of buffer
|
||||
lda #>BUF
|
||||
sta ($6), Y
|
||||
iny ; $A: unused
|
||||
iny ; $B: Byte count
|
||||
lda #0
|
||||
sta ($6),Y
|
||||
iny ; $C: command
|
||||
lda #$02 ; write
|
||||
sta ($6),Y
|
||||
lda IOB+1
|
||||
ldy IOB
|
||||
jsr RWTS
|
||||
rts
|
|
@ -0,0 +1 @@
|
|||
6000:20 e3 03 85 07 84 06 a9 0f a0 00 99 00 61 c8 d0 fa 48 20 1c 60 68 aa ca 8a 10 ee 60 a0 05 91 06 a0 02 a9 02 91 06 c8 a9 00 91 06 c8 91 06 a0 08 a9 00 91 06 c8 a9 61 91 06 c8 c8 a9 00 91 06 c8 a9 02 91 06 a5 07 a4 06 20 d9 03 60
|
Loading…
Reference in New Issue