From fe96da5d48372ac2b147ecda980df05791f00df5 Mon Sep 17 00:00:00 2001 From: Zellyn Hunter Date: Thu, 3 Nov 2016 20:49:49 -0400 Subject: [PATCH] Add initial support for dos33 disk .dsk files --- lib/disk/disk.go | 82 +++++++++ lib/disk/marshal.go | 49 +++++ lib/dos33/dos33.go | 296 +++++++++++++++++++++++++++---- lib/dos33/dos33_test.go | 114 ++++++++++-- lib/dos33/testdata/dos33test.dsk | Bin 0 -> 143360 bytes 5 files changed, 494 insertions(+), 47 deletions(-) create mode 100644 lib/disk/disk.go create mode 100644 lib/disk/marshal.go create mode 100644 lib/dos33/testdata/dos33test.dsk diff --git a/lib/disk/disk.go b/lib/disk/disk.go new file mode 100644 index 0000000..5f772ea --- /dev/null +++ b/lib/disk/disk.go @@ -0,0 +1,82 @@ +// Copyright © 2016 Zellyn Hunter + +// Package disk contains routines for reading and writing various disk +// file formats. +package disk + +import ( + "fmt" + "io/ioutil" +) + +type SectorDisk 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 +} + +const ( + DOS33Tracks = 35 // Tracks per disk + 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 +) + +// DSK represents a .dsk disk image. +type DSK struct { + data [DOS33DiskBytes]byte +} + +var _ SectorDisk = (*DSK)(nil) + +// LoadDSK loads a .dsk image from a file. +func LoadDSK(filename string) (DSK, error) { + d := DSK{} + bb, err := ioutil.ReadFile(filename) + if err != nil { + return d, err + } + if len(bb) != DOS33DiskBytes { + return d, fmt.Errorf("Expected file %q to contain %d bytes, but got %d.", filename, DOS33DiskBytes, len(bb)) + } + copy(d.data[:], bb) + return d, nil +} + +// ReadLogicalSector reads a single logical sector from the disk. It +// always returns 256 byes. +func (d DSK) ReadLogicalSector(track byte, sector byte) ([]byte, error) { + if track < 0 || track >= DOS33Tracks { + return nil, fmt.Errorf("Expected track between 0 and %d; got %d", DOS33Tracks-1, track) + } + if sector < 0 || sector >= DOS33Sectors { + return nil, fmt.Errorf("Expected sector between 0 and %d; got %d", DOS33Sectors-1, sector) + } + + start := int(track)*DOS33TrackBytes + 256*int(sector) + buf := make([]byte, 256) + copy(buf, d.data[start:start+256]) + return buf, nil +} + +// WriteLogicalSector writes a single logical sector to a disk. It +// expects exactly 256 bytes. +func (d DSK) WriteLogicalSector(track byte, sector byte, data []byte) error { + if track < 0 || track >= DOS33Tracks { + return fmt.Errorf("Expected track between 0 and %d; got %d", DOS33Tracks-1, track) + } + if sector < 0 || sector >= DOS33Sectors { + return fmt.Errorf("Expected sector between 0 and %d; got %d", DOS33Sectors-1, sector) + } + if len(data) != 256 { + return fmt.Errorf("WriteLogicalSector expects data of length 256; got %d", len(data)) + } + + start := int(track)*DOS33TrackBytes + 256*int(sector) + copy(d.data[start:start+256], data) + return nil +} diff --git a/lib/disk/marshal.go b/lib/disk/marshal.go new file mode 100644 index 0000000..ba14422 --- /dev/null +++ b/lib/disk/marshal.go @@ -0,0 +1,49 @@ +// Copyright © 2016 Zellyn Hunter + +// marshal.go contains helpers for marshaling sector structs to/from +// disk. + +package disk + +// 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 + // 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) + // 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 SectorDisk, ss SectorSink, track, sector byte) error { + bytes, err := d.ReadLogicalSector(track, sector) + if err != nil { + return err + } + ss.FromSector(bytes) + ss.SetTrack(track) + ss.SetSector(sector) + return nil +} + +// MarshalLogicalSector marshals a SectorSource to its sector on a +// SectorDisk. +func MarshalLogicalSector(d SectorDisk, ss SectorSource) error { + track := ss.GetTrack() + sector := ss.GetSector() + bytes := ss.ToSector() + return d.WriteLogicalSector(track, sector, bytes) +} diff --git a/lib/dos33/dos33.go b/lib/dos33/dos33.go index 6239bb6..495d5cf 100644 --- a/lib/dos33/dos33.go +++ b/lib/dos33/dos33.go @@ -6,13 +6,72 @@ package dos33 import ( "encoding/binary" "fmt" + "strings" + + "github.com/zellyn/diskii/lib/disk" ) -type FreeSectorMap [4]byte // Bit map of free sectors in a track +const ( + // VTOCTrack is the track on a DOS3.3 that holds the VTOC. + VTOCTrack = 17 + // VTOCSector is the sector on a DOS3.3 that holds the VTOC. + VTOCSector = 0 +) + +type DiskSector struct { + Track byte + Sector byte +} + +// GetTrack returns the track that a DiskSector was loaded from. +func (ds DiskSector) GetTrack() byte { + return ds.Track +} + +// SetTrack sets the track that a DiskSector was loaded from. +func (ds DiskSector) SetTrack(track byte) { + ds.Track = track +} + +// GetSector returns the sector that a DiskSector was loaded from. +func (ds DiskSector) GetSector() byte { + return ds.Sector +} + +// SetSector sets the sector that a DiskSector was loaded from. +func (ds DiskSector) SetSector(sector byte) { + ds.Sector = sector +} + +// TrackFreeSectors maps the free sectors in a single track. +type TrackFreeSectors [4]byte // Bit map of free sectors in a track + +// IsFree returns true if the given sector on a track is free (or if +// sector > 15). +func (t TrackFreeSectors) IsFree(sector byte) bool { + if sector >= 16 { + return false + } + bits := byte(1) << (sector % 8) + if sector < 8 { + return t[1]&bits > 0 + } + return t[0]&bits > 0 +} + +// UnusedClear returns true if the unused bytes of the free sector map +// for a track are zeroes (as they're supposed to be). +func (t TrackFreeSectors) UnusedClear() bool { + return t[2] == 0 && t[3] == 0 +} + +// DiskFreeSectors maps the free sectors on a disk. +type DiskFreeSectors [50]TrackFreeSectors // VTOC is the struct used to hold the DOS 3.3 VTOC structure. // See page 4-2 of Beneath Apple DOS. type VTOC struct { + DiskSector Unused1 byte // Not used CatalogTrack byte // Track number of first catalog sector CatalogSector byte // Sector number of first catalog sector @@ -30,11 +89,42 @@ type VTOC struct { NumTracks byte // Number of tracks per diskette (normally 35) NumSectors byte // Number of sectors per track (13 or 16) BytesPerSector uint16 // Number of bytes per sector (LO/HI format) - FreeSectors [50]FreeSectorMap + FreeSectors DiskFreeSectors } -// MarshalBinary marshals the VTOC sector to bytes. Error is always nil. -func (v VTOC) MarshalBinary() (data []byte, err error) { +// Validate checks a VTOC sector to make sure it looks normal. +func (v *VTOC) Validate() error { + if v.Volume == 255 { + return fmt.Errorf("expected volume to be 0-254, but got 255") + } + if v.DOSRelease != 3 { + return fmt.Errorf("expected DOS release number to be 3; got %d", v.DOSRelease) + } + if v.TrackDirection != 1 && v.TrackDirection != -1 { + return fmt.Errorf("expected track direction to be 1 or -1; got %d", v.TrackDirection) + } + if v.NumTracks != 35 { + return fmt.Errorf("expected number of tracks to be 35; got %d", v.NumTracks) + } + if v.NumSectors != 13 && v.NumSectors != 16 { + return fmt.Errorf("expected number of sectors per track to be 13 or 16; got %d", v.NumSectors) + } + if v.BytesPerSector != 256 { + return fmt.Errorf("expected 256 bytes per sector; got %d", v.BytesPerSector) + } + if v.TrackSectorListMaxSize != 122 { + return fmt.Errorf("expected 122 track/sector pairs per track/sector list sector; got %d", v.TrackSectorListMaxSize) + } + for i, tf := range v.FreeSectors { + if !tf.UnusedClear() { + return fmt.Errorf("unused bytes of free-sector list for track %d are not zeroes", i) + } + } + return nil +} + +// ToSector marshals the VTOC sector to bytes. +func (v VTOC) ToSector() []byte { buf := make([]byte, 256) buf[0x00] = v.Unused1 buf[0x01] = v.CatalogTrack @@ -54,7 +144,7 @@ func (v VTOC) MarshalBinary() (data []byte, err error) { for i, m := range v.FreeSectors { copyBytes(buf[0x38+4*i:0x38+4*i+4], m[:]) } - return buf, nil + return buf } // copyBytes is just like the builtin copy, but just for byte slices, @@ -66,11 +156,11 @@ func copyBytes(dst, src []byte) int { return copy(dst, src) } -// UnmarshalBinary unmarshals the VTOC sector from bytes. Input is +// FromSector unmarshals the VTOC sector from bytes. Input is // expected to be exactly 256 bytes. -func (v *VTOC) UnmarshalBinary(data []byte) error { +func (v *VTOC) FromSector(data []byte) { if len(data) != 256 { - return fmt.Errorf("VTOC.UnmarshalBinary expects exactly 256 bytes; got %d", len(data)) + panic(fmt.Sprintf("VTOC.FromSector expects exactly 256 bytes; got %d", len(data))) } v.Unused1 = data[0x00] @@ -91,8 +181,6 @@ func (v *VTOC) UnmarshalBinary(data []byte) error { for i := range v.FreeSectors { copyBytes(v.FreeSectors[i][:], data[0x38+4*i:0x38+4*i+4]) } - - return nil } func DefaultVTOC() VTOC { @@ -109,9 +197,9 @@ func DefaultVTOC() VTOC { BytesPerSector: 0x100, } for i := range v.FreeSectors { - v.FreeSectors[i] = FreeSectorMap{} + v.FreeSectors[i] = TrackFreeSectors{} if i < 35 { - v.FreeSectors[i] = FreeSectorMap([4]byte{0xff, 0xff, 0x00, 0x00}) + v.FreeSectors[i] = TrackFreeSectors([4]byte{0xff, 0xff, 0x00, 0x00}) } } return v @@ -120,6 +208,7 @@ func DefaultVTOC() VTOC { // CatalogSector is the struct used to hold the DOS 3.3 Catalog // sector. type CatalogSector struct { + DiskSector Unused1 byte // Not used NextTrack byte // Track number of next catalog sector (usually 11 hex) NextSector byte // Sector number of next catalog sector @@ -127,25 +216,25 @@ type CatalogSector struct { FileDescs [7]FileDesc // File descriptive entries } -// MarshalBinary marshals the CatalogSector to bytes. Error is always nil. -func (cs CatalogSector) MarshalBinary() (data []byte, err error) { +// ToSector marshals the CatalogSector to bytes. +func (cs CatalogSector) ToSector() []byte { buf := make([]byte, 256) buf[0x00] = cs.Unused1 buf[0x01] = cs.NextTrack buf[0x02] = cs.NextSector copyBytes(buf[0x03:0x0b], cs.Unused2[:]) for i, fd := range cs.FileDescs { - fdBytes, _ := fd.MarshalBinary() + fdBytes := fd.ToBytes() copyBytes(buf[0x0b+35*i:0x0b+35*(i+1)], fdBytes) } - return buf, nil + return buf } -// UnmarshalBinary unmarshals the CatalogSector from bytes. Input is +// FromSector unmarshals the CatalogSector from bytes. Input is // expected to be exactly 256 bytes. -func (cs *CatalogSector) UnmarshalBinary(data []byte) error { +func (cs *CatalogSector) FromSector(data []byte) { if len(data) != 256 { - return fmt.Errorf("CatalogSector.UnmarshalBinary expects exactly 256 bytes; got %d", len(data)) + panic(fmt.Sprintf("CatalogSector.FromSector expects exactly 256 bytes; got %d", len(data))) } cs.Unused1 = data[0x00] @@ -154,12 +243,8 @@ func (cs *CatalogSector) UnmarshalBinary(data []byte) error { copyBytes(cs.Unused2[:], data[0x03:0x0b]) for i := range cs.FileDescs { - if err := cs.FileDescs[i].UnmarshalBinary(data[0x0b+35*i : 0x0b+35*(i+1)]); err != nil { - return err - } + cs.FileDescs[i].FromBytes(data[0x0b+35*i : 0x0b+35*(i+1)]) } - - return nil } type Filetype byte @@ -179,6 +264,14 @@ const ( FileTypeB Filetype = 0x40 // B type file ) +type FileDescStatus int + +const ( + FileDescStatusNormal FileDescStatus = iota + FileDescStatusDeleted + FileDescStatusUnused +) + // FileDesc is the struct used to represent the DOS 3.3 File // Descriptive entry. type FileDesc struct { @@ -199,8 +292,8 @@ type FileDesc struct { SectorCount uint16 } -// MarshalBinary marshals the FileDesc to bytes. Error is always nil. -func (fd FileDesc) MarshalBinary() (data []byte, err error) { +// ToBytes marshals the FileDesc to bytes. +func (fd FileDesc) ToBytes() []byte { buf := make([]byte, 35) buf[0x00] = fd.TrackSectorListTrack buf[0x01] = fd.TrackSectorListSector @@ -208,21 +301,158 @@ func (fd FileDesc) MarshalBinary() (data []byte, err error) { copyBytes(buf[0x03:0x21], fd.Filename[:]) binary.LittleEndian.PutUint16(buf[0x21:0x23], fd.SectorCount) - return buf, nil + return buf } -// UnmarshalBinary unmarshals the FileDesc from bytes. Input is +// FromBytes unmarshals the FileDesc from bytes. Input is // expected to be exactly 35 bytes. -func (fd *FileDesc) UnmarshalBinary(data []byte) error { +func (fd *FileDesc) FromBytes(data []byte) { if len(data) != 35 { - return fmt.Errorf("FileDesc.UnmarshalBinary expects exactly 35 bytes; got %d", len(data)) + panic(fmt.Sprintf("FileDesc.FromBytes expects exactly 35 bytes; got %d", len(data))) } fd.TrackSectorListTrack = data[0x00] fd.TrackSectorListSector = data[0x01] fd.Filetype = Filetype(data[0x02]) - copyBytes(data[0x03:0x21], fd.Filename[:]) + copyBytes(fd.Filename[:], data[0x03:0x21]) fd.SectorCount = binary.LittleEndian.Uint16(data[0x21:0x23]) - - return nil +} + +// Status returns whether the FileDesc describes a deleted file, a +// normal file, or has never been used. +func (fd *FileDesc) Status() FileDescStatus { + switch fd.TrackSectorListTrack { + case 0: + return FileDescStatusUnused // Never been used. + case 0xff: + return FileDescStatusDeleted + default: + return FileDescStatusNormal + } +} + +// FilenameString returns the filename of a FileDesc as a normal +// string. +func (fd *FileDesc) FilenameString() string { + var slice []byte + if fd.Status() == FileDescStatusDeleted { + slice = append(slice, fd.Filename[0:len(fd.Filename)-1]...) + } else { + slice = append(slice, fd.Filename[:]...) + } + for i := range slice { + slice[i] -= 0x80 + } + return strings.TrimRight(string(slice), " ") +} + +type TrackSector struct { + Track byte + Sector byte +} + +// TrackSectorList is the struct used to represent DOS 3.3 +// Track/Sector List sectors. +type TrackSectorList struct { + DiskSector + Unused1 byte // Not used + NextTrack byte // Track number of next T/S List sector if one was needed or zero if no more T/S List sectors. + NextSector byte // Sector number of next T/S List sector (if present). + Unused2 [2]byte // Not used + SectorOffset uint16 // Sector offset in file of the first sector described by this list. + Unused3 [5]byte // Not used + TrackSectors [122]TrackSector +} + +// ToSector marshals the TrackSectorList to bytes. +func (tsl TrackSectorList) ToSector() []byte { + buf := make([]byte, 256) + buf[0x00] = tsl.Unused1 + buf[0x01] = tsl.NextTrack + buf[0x02] = tsl.NextSector + copyBytes(buf[0x03:0x05], tsl.Unused2[:]) + binary.LittleEndian.PutUint16(buf[0x05:0x07], tsl.SectorOffset) + copyBytes(buf[0x07:0x0C], tsl.Unused3[:]) + + for i, ts := range tsl.TrackSectors { + buf[0x0C+i*2] = ts.Track + buf[0x0D+i*2] = ts.Sector + } + return buf +} + +// FromSector unmarshals the TrackSectorList from bytes. Input is +// expected to be exactly 256 bytes. +func (tsl *TrackSectorList) FromSector(data []byte) { + if len(data) != 256 { + panic(fmt.Sprintf("TrackSectorList.FromSector expects exactly 256 bytes; got %d", len(data))) + } + + tsl.Unused1 = data[0x00] + tsl.NextTrack = data[0x01] + tsl.NextSector = data[0x02] + copyBytes(tsl.Unused2[:], data[0x03:0x05]) + tsl.SectorOffset = binary.LittleEndian.Uint16(data[0x05:0x07]) + copyBytes(tsl.Unused3[:], data[0x07:0x0C]) + + for i := range tsl.TrackSectors { + tsl.TrackSectors[i].Track = data[0x0C+i*2] + tsl.TrackSectors[i].Sector = data[0x0D+i*2] + } +} + +// readCatalogSectors reads the raw CatalogSector structs from a DOS +// 3.3 disk. +func readCatalogSectors(d disk.SectorDisk) ([]CatalogSector, error) { + v := &VTOC{} + err := disk.UnmarshalLogicalSector(d, v, VTOCTrack, VTOCSector) + if err != nil { + return nil, err + } + if err := v.Validate(); err != nil { + return nil, fmt.Errorf("Invalid VTOC sector: %v", err) + } + + nextTrack := v.CatalogTrack + nextSector := v.CatalogSector + css := []CatalogSector{} + for nextTrack != 0 || nextSector != 0 { + if nextTrack >= v.NumTracks { + return nil, fmt.Errorf("catalog sectors can't be in track %d: disk only has %d tracks", nextTrack, v.NumTracks) + } + if nextSector >= v.NumSectors { + 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) + if err != nil { + return nil, err + } + css = append(css, cs) + nextTrack = cs.NextTrack + nextSector = cs.NextSector + } + return css, nil +} + +// ReadCatalog reads the catalog of a DOS 3.3 disk. +func ReadCatalog(d disk.SectorDisk) (files, deleted []FileDesc, err error) { + css, err := readCatalogSectors(d) + if err != nil { + return nil, nil, err + } + + for _, cs := range css { + for _, fd := range cs.FileDescs { + switch fd.Status() { + case FileDescStatusUnused: + // skip + case FileDescStatusDeleted: + deleted = append(deleted, fd) + case FileDescStatusNormal: + files = append(files, fd) + } + } + } + return files, deleted, nil } diff --git a/lib/dos33/dos33_test.go b/lib/dos33/dos33_test.go index 6d6c2fa..169b146 100644 --- a/lib/dos33/dos33_test.go +++ b/lib/dos33/dos33_test.go @@ -4,24 +4,24 @@ import ( "crypto/rand" "reflect" "testing" + + "github.com/zellyn/diskii/lib/disk" ) // TestVTOCMarshalRoundtrip checks a simple roundtrip of VTOC data. func TestVTOCMarshalRoundtrip(t *testing.T) { buf := make([]byte, 256) rand.Read(buf) + buf1 := make([]byte, 256) + copy(buf1, buf) vtoc1 := &VTOC{} - if err := vtoc1.UnmarshalBinary(buf); err != nil { - t.Fatal(err) - } - buf2, _ := vtoc1.MarshalBinary() + vtoc1.FromSector(buf1) + buf2 := vtoc1.ToSector() if !reflect.DeepEqual(buf, buf2) { t.Errorf("Buffers differ: %v != %v", buf, buf2) } vtoc2 := &VTOC{} - if err := vtoc2.UnmarshalBinary(buf2); err != nil { - t.Fatal(err) - } + vtoc2.FromSector(buf2) if *vtoc1 != *vtoc2 { t.Errorf("Structs differ: %v != %v", vtoc1, vtoc2) } @@ -31,19 +31,105 @@ func TestVTOCMarshalRoundtrip(t *testing.T) { func TestCatalogSectorMarshalRoundtrip(t *testing.T) { buf := make([]byte, 256) rand.Read(buf) + buf1 := make([]byte, 256) + copy(buf1, buf) cs1 := &CatalogSector{} - if err := cs1.UnmarshalBinary(buf); err != nil { - t.Fatal(err) - } - buf2, _ := cs1.MarshalBinary() + cs1.FromSector(buf1) + buf2 := cs1.ToSector() if !reflect.DeepEqual(buf, buf2) { t.Errorf("Buffers differ: %v != %v", buf, buf2) } cs2 := &CatalogSector{} - if err := cs2.UnmarshalBinary(buf2); err != nil { - t.Fatal(err) - } + cs2.FromSector(buf2) if *cs1 != *cs2 { t.Errorf("Structs differ: %v != %v", cs1, cs2) } } + +// TestTrackSectorListMarshalRoundtrip checks a simple roundtrip of TrackSectorList data. +func TestTrackSectorListMarshalRoundtrip(t *testing.T) { + buf := make([]byte, 256) + rand.Read(buf) + buf1 := make([]byte, 256) + copy(buf1, buf) + cs1 := &TrackSectorList{} + cs1.FromSector(buf1) + buf2 := cs1.ToSector() + if !reflect.DeepEqual(buf, buf2) { + t.Errorf("Buffers differ: %v != %v", buf, buf2) + } + cs2 := &TrackSectorList{} + cs2.FromSector(buf2) + if *cs1 != *cs2 { + t.Errorf("Structs differ: %v != %v", cs1, cs2) + } +} + +// TestReadCatalog tests the reading of the catalog of a test disk. +func TestReadCatalog(t *testing.T) { + dsk, err := disk.LoadDSK("testdata/dos33test.dsk") + if err != nil { + t.Fatal(err) + } + fds, deleted, err := ReadCatalog(dsk) + + fdsWant := []struct { + locked bool + typ string + size int + name string + }{ + {true, "A", 3, "HELLO"}, + {true, "I", 3, "APPLESOFT"}, + {true, "B", 6, "LOADER.OBJ0"}, + {true, "B", 42, "FPBASIC"}, + {true, "B", 42, "INTBASIC"}, + {true, "A", 3, "MASTER"}, + {true, "B", 9, "MASTER CREATE"}, + {true, "I", 9, "COPY"}, + {true, "B", 3, "COPY.OBJ0"}, + {true, "A", 9, "COPYA"}, + {true, "B", 3, "CHAIN"}, + {true, "A", 14, "RENUMBER"}, + {true, "A", 3, "FILEM"}, + {true, "B", 20, "FID"}, + {true, "A", 3, "CONVERT13"}, + {true, "B", 27, "MUFFIN"}, + {true, "A", 3, "START13"}, + {true, "B", 7, "BOOT13"}, + {true, "A", 4, "SLOT#"}, + {false, "A", 3, "EXAMPLE"}, + } + + deletedWant := []struct { + locked bool + typ string + size int + name string + }{ + {false, "A", 3, "EXAMPLE2"}, + {false, "I", 3, "EXAMPLE3"}, + } + + if len(fdsWant) != len(fds) { + t.Fatalf("Want %d undeleted files; got %d", len(fdsWant), len(fds)) + } + + if len(deletedWant) != len(deleted) { + t.Fatalf("Want %d deleted files; got %d", len(deletedWant), len(deleted)) + } + + for i, wantInfo := range fdsWant { + if want, got := wantInfo.name, fds[i].FilenameString(); want != got { + t.Errorf("Want filename %d to be %q; got %q", i+1, want, got) + } + } + + for i, wantInfo := range deletedWant { + if want, got := wantInfo.name, deleted[i].FilenameString(); want != got { + t.Errorf("Want deleted filename %d to be %q; got %q", i+1, want, got) + } + } + + // TODO(zellyn): Check type, size, locked status. +} diff --git a/lib/dos33/testdata/dos33test.dsk b/lib/dos33/testdata/dos33test.dsk new file mode 100644 index 0000000000000000000000000000000000000000..647e2c32d47c58797b51ad7ac8077bc6f4d533a9 GIT binary patch literal 143360 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�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 z zQ$vhF@vqpT@rY@X)342b=L#o~CQWiN5_QUo#(jxy>6U5p)tPn_G(JL9tsa27WP!Px0 z7QeGFBO`s0FJnd9n)^2(=D^l%)I*WqCwa@&yrql!wY>Fs=l%J}r>TutT0yhetgOvj zk*%OztTHT>O?k@Z6`M&nX9KoGh+^p6#;XbNrCde5)lCo{J>!3#i}wl=Om;?@6n&Kt{boV z&$P_qZ7=dJN#OGp>bPkoa&PjX-Y{(-OJogVAgogdbjN*bzLD-AO3$9RbZt5n9k~TI z8JMotzxH-dV7J4oP{BXJ$uY^%$+ME9lFiAH$)@BG{vRxy&~-=xAqj*e5RyPh0wD>6 zBoLB7NCF`Vge346E`b-h=RAen3!Wcx`#d_XoNWW9-CkJ!Li-ct``Vu@-#g&{HPWQL zTvcuPgi92R9iQphCImqJ6ya0-W(4pw;?}49#`A4>2rzJWvHxLsyu%}h#9(Wu^4;Y> zoWQA~{D;oR+YOH&H$2{Hc>I(h|Lo{%zdQebeo^%9^JDojr(-{-A7=hF`T3|nQV%A* zm*D?AtrvBjc~j-a0n2AHbrCQAM~P9L-3E8N0nk2s(BO&Sekv8#KE}CS74JTdSd!oK zhqG?I|0Ax_C1Bz|l`3n6cfYShc%MMb-YGpPhd1rrh+W|};a`3wS4mC+CoHs#?M_#4 zBT(kT@O(GtE<;e=+KP7tG+XIE#@3FjdnH@XH{w-eoI-(qCjTxI>v zf&$@eu26)nTkaelbgBMoUKc&3sHzSX8lS4&Kqf;v6su6L!rl!%>TCLTrMon6( zM#XAWtU<+UQqkE#?aJ|K9$PFQIX^t^LNJ#TE<}LtU(sUBoJ`N0RGifMyp0>UrpA^N zy~Jc~Qgwb6I;hDPxtf-+{>x?I!UBv~atr!bC7)FBYpLb1)M#lbdq<5_evkx=ha6hC z#{`{++Vg0!<#&RUt#ReLisUg@^l6v>lgyg!(vC@8Z{hf3E#d0?Nqls!3XcW4)+&Dl z!k|~>W^+;%w?-1VwelGkmnENdajT^5+)8N&cdz>MPLj8idf;STjrBPYCchTV}3mpo`8r=`IURzl7ysMuAa5Jh!Xcy z`Wlqay28somZb1nf1+)_K%rP=gU>_d3wtVEl?ZzO3WoBi-;n$4GZ>tN!PRC;?nxbg z+$B{^Qv3f@DMwGS7y;{sPBxw*RW zYCM2eaP{LgSbf#Stx!A(817aKKK}>7lPG!0=YJztcuJhIweKje_@uU6obZ1V804hB zC05u6Z4lR2=P+eg(RA+u)mPCcs15J8B7EyH`EAeOf^(BY1)Jr9B-|(}Rp5X$QptHISM#v0x8D?XDv`NB23LAa0r%MvNi z)Khird{^K!ZQ_Eys1fqU4kn?se|ELRKs}APC<_U!XS$z12#Osx8BiMxOG>$B8C9D_&^-PIof#Td;MNwsu;DRl>s*7q+vTTw6f&LtnZYt_ut3>Bk zbENuWg~l{Q!-amAKN?Dy=-=rN7e>&~ZgV|y{Khgf3Vi}S)Z>32M!DL$eeT-&eH9nU z{!D&%8k8eaRk)~x3zu*w8rmN%mk_eg)rgpVlFwU-!?@7$bt38y0?N|zo~rXfV_gRS z$5OSbJgG)Kp``zgoBta4Y|=j$&gE8eS<=50>bQGtg(hy5@ORUdN zb|7&FmM*u3|E+;rjjep`BvSZK4P3Ug27AidzBN)7&a3*eq?O(*>E7{G2uv2ynzd)m z(JdFq3DFuqF<^ULjfj&qOS<%mrFFHf&|-2X#HWTmtM_N-uSVP1*fFv*CruxG zYEVWbeSd6AjK{z~Z1Q}}f7g_m`^}i#Z=NOo*#1PHXTwfr&!ghaFNVqQEzAa?Wm)e| zYN5F{aQo^=#05ZSBV?==}sM#&paGvo#jm=0;&q${}HzzG9 z0d&7KW08-XmM$6q_rbR;1CI&IpUz%!ERT4JPl;R;M))^*^X^%(540yOb$w(m8JEf~ z2uvD2J*OE--^$Lte|_E}2lbDU-%^J^pZ&JR2+2tQ4*P9_abpbRDvwo9>$S(S??6P6 zPPN9S^>~tWQ1y|IX$|Dyv5t5@oPNj)JT^MO2G|jH49|_oSL=|+$Lk8c7Wr>s;?iYc zGF*u)Msdya;|%=*Ri+;p@3`X*$30ZIc`E9wrq2y+_XdBmre(b{I2G5_N|P~+ke4b} zc))?7zGbq6<$>Zb9|Vnzbg(Hzu#7U&!NVytC54F?2eKf}3_{~l@%Oy@Hh?Y@upg2| zBu(mzcLr)Irg>rD;RI?DLeo`F!Hp;c#6N6ML)3?+JHo`}T4O6j5U13ExmPrTx{*$q zA~VCD%2qPEm))(Y8a6QVNr_2`PMMVwm10hbOfjWIq!?4eQ^HaVDf*crp^K0NLJ|l` zAS8j11VR!BNgyPFkOV>!2uUC$fxl1*+#uH9`fFnSZP>W())D^xCMd$+kN=(xBDjX|A=tO|DmU+OVLls9sWWIeZo#N_*87hr5To)UI7{zk8;yufM0?JA7Ig z@(zuRs_s5V&&+t)2f zYg%Go$Eu z#$~bQIkj7W%hZ`Ny5U2s)U*@hZYTgc98$<6P6-Jo6DAUQ?#`6+F7&Y_(9J3^696gi|md)m1Z@M*WxvV$&vk!aLRz&;;?v z&8wc6;VgE@JA4LyRN;~NoS^w+4)!I>Q+)Rz@%(yD)7)6Iz*DEsDP93pyM^KNS8~S; zBEt@uo0FO6MXFS0*f~+TF(z#SICcxdaZTA;61C;Dw=%^z{s#hCa?5?dd}@y1}PUz>LobhXtVncWo~T zKOZB>>Ntd=w$`>oFSQ>&a>zsS---v%8{*m|}#TUmv8$X|UJN}V`?Frvxp0}4Sv6no{C@*>< z`Pocv4V|+)XMYZm=hgPkREE#8cg|t>Rd(6N@Y#0R&hTsOT{^#B(3fnqH@(Nm?=x_s zQWoQx;*%Kp8+NS?Im^!H+T~Stev`eRzM!GNi8goVu=fz(F2A=42_2Vhd#GZ|XY5&n zNl0j=4qUe3Zedxp9A@t~`i)vM>{l(QTVLR0ORumirtp<#GyRcDifDnp7T?BL5OjvW zY-9hP_JnI^F-f_zKTHV|ueDFcsFD7{L2#$%;q1MU1s?3!P(9xH`Dd863HqS zIf?P>obtO2zuqp7GyDeohi(Snj_)ShA5QkqWh>+4bUSZj4t#gEyu{AinF9~c7AUyA zvCtoGu%n^D3PyRwDZin%aDlYoi9>nF$Ecj2vf&+U0o+|5ZEWY&P@HGEVq4(rFS=4N}ovH9^q` z%Ml~U!Hxs_I+>$&LOM8y@KMA5VzLyH zKF_U;{i5+Z#dy|lMxOQ+=XCC1&?@+wxhrCY#UAQ_#a?W=EMrAa+2pwlPub;ihCP2p zoQ+Q8{p3=9PEANgf^&ZkY)7PuJv!TCWw5dw7}#eZgm`pMlrwxeQ zNAwr3Df3O3QS`QCg1L`I41yq`fqhXVG)U@ZgwX)J8Fp0SlBXtyTMPTXd;7(HF&O!hpd+{~EkeH{Z# zPBA$+(fy*Gexs^Y=gfYk&Iemry2%p}*utihuI_HytUbo7i?oReq|FMhR8ZidI0pim z;WrHfgp!~gC}lsRt~f3ZGMpXb8+6%~Pvw28y7_rn1)cXN!A2*1T`9`P*lSf2mm3&= z8myZb-mrfajL+8psy{Mde9W||lZ7ESG5tN*3^75cVri~q20FJUrAI*UjZCIfOo7VO zg<*5b0>f7`auvhlC)YO%;)Rge*JqWjT3pYhFK-r^rdo#mbXM6Caz7vW6QwmwsamY0 zj+7+nF)i;k)nPAyerlMq_qXUXop1mqpsKGJy7XTzsfEH5qg(8n-ZTYIpczs}Q}A^5 zfO4f+`K)Lj!oDp)L@?~F+TziEwia8uL>q<=whQLz6s86yd^w#5vE3A0ILIi!aTYjd ztoVmfO_fX+r5M@WQDxXLjzyJy$UYP;dl-KdDfBkmZqEH?l(zYCadMuW&r6cG+4*fr z&{ZYll=G6Jw(2?23M5~ z#16ikA@_T;=Hw-*XZ+|sF{_}Vg`{1I?=YBltd4m+mr6c_HbDYBXfN6%0T*g zY(RQ(&cr~v;t?)jyZY?}*2VPJg>iZqzJVdTR;S;DZL9&?Sgp2=HTm6cvP{5>nnJM& z-=N5py*E%=#o(z*V2B)2#b~V~&8TP?)wDr9VMeV6Mhw@a-T#6TUQmF?FzL1&P_b@f zyMHH|k%b6-xO9q9S}~#&an{vq^)Umn-X<6>taFm#!oj!*14I9VD?a77+7F}pd_$~w z$Sh2WQ!?Yf3!_>brLZ2|5bhT7cmli!vGDjbMowY)IgHFQ{9Hz{c=RMcQp;zHBAwV? zv>yPS5=CazS{BxSw9F(runXtj6S*jYXBqrTU03E1%A}Dp50f$}uvM%%{q^N$+S*0R z&1FQx^<`$-Y9wXmFheN}BJ<5|LKFD0OABWt_k?2hO!sO?;4W|2OcAbge zOCC97=2&Sm!~Vp?o;P7pi-|-ok?h}@V8^*xCid6r_39|O5v_``WHjotvS%mvBkmlx zEK?peOh!zmq{I9l{9H^x0rGUM>zvD&@o}fZ*gj(4FceW7;sY9r^qc|Dcc&xhIyJhkZCu18*si&5_K^ObSMz+u;BIXJZh>auyrKn%PL!#73|PBglra23F7N zSjre>G#ew0*F+2qt{u7#NgyPFkOV>!2uUC$fsh135(r5kB!Q3wLK67jECG*`>HZBHHg3K(5#VowhycZZ5D}o^mPCNVUmyYi_xXSS9Qm{0|NKqx|A1I$ zC;(zG1t5?~b=;T*aQfyffDdlQ0cR^@jz4aRfLf%6+*H&-eI7M#j7XSP8&KRW!bDWN>igH3GSh0JI(%9^-i` zfPn+@4S>BpBf|i+&v*q&!`=r8Cjo4Rp3@_vV?y7k7bJ(7+cRUx1*-vZegD^U9cEY# zy(447q2@NiML5)a2x1?G>JUg1+WC@Phil6X5kf{F*6Lpe*8vK@j_VTtn|NbFT*88c zI}=tVY)SZ0f;I7Q;zj1w#5WTEGx2wcDb@_@J=WFM2ds}+|6%68r>uXGT!$NRU2Y7F z-$?@soFPVhjV8p1K3e-@?@mw@G#-Pnb1;|~fmF~ST7>Q?P$uxz_zXA)5hHLnEVPUW zEyqEkI5W+o7y}VwC+HEBaHd=EqD9t3{t?<0-w=N~{u1Eu zlUBgtO>}9ewK?8adcs=LNUL;+JL%lcxM@1XkhOCK&A(#pTu$?YRyl*_hpqBbnjf(S z=n!YEO&4kTZTg}Pc*8kE?swu?Dn%tmETiSuti0Nq{EC%7XO#!7{CR6IG2$EKFW^71 zf*7&OdMzvVbS9DExs>mB?{ND87uP!2+eI7|~dM7V@;Fa;Fvj9hl{iPgv3AfoMmd*AK_6 zXlU>VP3RD3)fQeOEr1S@L6`zdX?AX0fDX}V9X?^z=nyBZ8XcmMhVrh`Ax>C9hp^fX zSZ$i1nw#i}ON=c*hp^iClhzKKjXz}t91e|^SmjKb=dE%U&6ipU9YPfvp+g*|L5Da( z6OHTAh{pA4NL@xlp&A|HoR!ca&RYo`;+&PxAkZYxoHg%xU-@1^-;R_F?J zh(=nYLuiGF87hExrVZ~8p+l^r5AZbT5bNkKLx)&L2j~#=R)sB{RowOGafsZ@ghAE%2;PSHX5|4F*}1byi^4gCN6^bG!giVooa z-88}f)mwu9chegFkF$pV|C}cH|0oUo9|t&AxeCs+b7I*&vGPjVuhJoUqH|x2*6u)u z2+CMvA^MBgl=&viC|aKeI>bk@Djj04B|wMxZFI2mK!-SCRp}7%C|BS-O{~xEDPSG0vkNf$^pD695OVwf}U8LkyKa~pn{}g7Z;{U4N;*hAAC(sP36O8|VpZ;U;e;?LY!37_!;s2@;BK-dy8u93o+%4kqprhjdD{1*InqN-Kchh_(t>XX4kJR$N9R7bdeQW&xF4*dq!T&SqTjT%B z>7l!5;QyKQ(A~6(|F5J~{C_1jaY7Ee0seo*M(}@`{Kodt$4b9O2k?I{4U*(d@c&-4 zdUO2$w)8LJ|CzLk|F3|teG&g(8OweO$3J{8{XgRWKKgq6Uw literal 0 HcmV?d00001