diff --git a/file.go b/file.go index 7a8014e..3eefe4c 100644 --- a/file.go +++ b/file.go @@ -82,7 +82,7 @@ func (r *Reader) setDirEntries() error { if r.header.numDirectorySectors > 0 { c = int(r.header.numDirectorySectors) } - fs, de := make([]*File, 0, c), make([]int, 0, c) + de := make([]*File, 0, c) cycles := make(map[uint32]bool) num := int(sectorSize / 128) sn := r.header.directorySectorLoc @@ -92,14 +92,11 @@ func (r *Reader) setDirEntries() error { return Error{ErrRead, "directory entries read error (" + err.Error() + ")", fileOffset(sn)} } for i := 0; i < num; i++ { - de = append(de, len(fs)) f := &File{r: r} f.directoryEntryFields = makeDirEntry(buf[i*128:]) - if f.directoryEntryFields.objectType != unknown { - fixFile(r.header.majorVersion, f) - f.readSector = f.startingSectorLoc - fs = append(fs, f) - } + fixFile(r.header.majorVersion, f) + f.readSector = f.startingSectorLoc + de = append(de, f) } nsn, err := r.findNext(sn, false) if err != nil { @@ -113,7 +110,7 @@ func (r *Reader) setDirEntries() error { } sn = nsn } - r.File, r.direntries = fs, de + r.direntries = de return nil } @@ -144,26 +141,24 @@ func fixName(f *File) { } func (r *Reader) traverse() error { - r.indexes = make([]int, len(r.File)) - var idx int + r.File = make([]*File, 0, len(r.direntries)) var recurse func(int, []string) var err error recurse = func(i int, path []string) { - if i < 0 || i >= len(r.direntries) || r.direntries[i] >= len(r.File) { + if i < 0 || i >= len(r.direntries) { err = Error{ErrTraverse, "illegal traversal index", int64(i)} return } - file := r.File[r.direntries[i]] + file := r.direntries[i] if file.leftSibID != noStream { recurse(int(file.leftSibID), path) } - if idx >= len(r.indexes) { + if len(r.File) >= cap(r.File) { err = Error{ErrTraverse, "traversal counter overflow", int64(i)} return } - r.indexes[idx] = r.direntries[i] + r.File = append(r.File, file) file.Path = path - idx++ if file.childID != noStream { if i > 0 { recurse(int(file.childID), append(path, file.Name)) @@ -177,7 +172,6 @@ func (r *Reader) traverse() error { return } recurse(0, []string{}) - r.indexes = r.indexes[:idx] return err } diff --git a/mscfb.go b/mscfb.go index d0178ae..2a5d1bf 100644 --- a/mscfb.go +++ b/mscfb.go @@ -184,7 +184,7 @@ func (r *Reader) setDifats() error { // set the ministream FAT and sector slices in the header func (r *Reader) setMiniStream() error { // do nothing if there is no ministream - if r.File[0].startingSectorLoc == endOfChain || r.header.miniFatSectorLoc == endOfChain || r.header.numMiniFatSectors == 0 { + if r.direntries[0].startingSectorLoc == endOfChain || r.header.miniFatSectorLoc == endOfChain || r.header.numMiniFatSectors == 0 { return nil } // build a slice of minifat sectors (akin to the DIFAT slice) @@ -201,7 +201,7 @@ func (r *Reader) setMiniStream() error { // build a slice of ministream sectors c = int(sectorSize / 4 * r.header.numMiniFatSectors) r.header.miniStreamLocs = make([]uint32, 0, c) - sn := r.File[0].startingSectorLoc + sn := r.direntries[0].startingSectorLoc var err error for sn != endOfChain { r.header.miniStreamLocs = append(r.header.miniStreamLocs, sn) @@ -273,11 +273,11 @@ type Reader struct { slicer bool buf []byte header *header - File []*File // File is a slice of directory entries. Not necessarily in correct order. Use Next() for order. + File []*File // File is an ordered slice of final directory entries. + direntries []*File // unordered raw directory entries entry int - indexes []int - direntries []int - ra io.ReaderAt + + ra io.ReaderAt } // New returns a MSCFB reader @@ -329,18 +329,18 @@ func (r *Reader) Modified() time.Time { // This isn't necessarily an adjacent *File within the File slice, but is based on the Left Sibling, Right Sibling and Child information in directory entries. func (r *Reader) Next() (*File, error) { r.entry++ - if r.entry >= len(r.indexes) { + if r.entry >= len(r.File) { return nil, io.EOF } - return r.File[r.indexes[r.entry]], nil + return r.File[r.entry], nil } // Read the current directory entry func (r *Reader) Read(b []byte) (n int, err error) { - if r.entry >= len(r.indexes) { + if r.entry >= len(r.File) { return 0, io.EOF } - return r.File[r.indexes[r.entry]].Read(b) + return r.File[r.entry].Read(b) } // Debug provides granular information from an mscfb file to assist with debugging diff --git a/mscfb_test.go b/mscfb_test.go index 088c345..1cbeb12 100644 --- a/mscfb_test.go +++ b/mscfb_test.go @@ -99,22 +99,27 @@ func testFile(t *testing.T, path string) { func TestTraverse(t *testing.T) { r := new(Reader) - r.File = testEntries - r.direntries = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} + r.direntries = testEntries if r.traverse() != nil { t.Error("Error traversing") } expect := []int{0, 1, 2, 4, 5, 8, 9, 11, 6, 3, 7, 10} - for i, v := range r.indexes { - if v != expect[i] { - t.Errorf("Error traversing: expecting %d at index %d; got %d", expect[i], i, v) + if len(r.File) != len(expect) { + t.Fatalf("Error traversing: expecting %d entries, got %d", len(expect), len(r.File)) + } + for i, v := range r.File { + if v != testEntries[expect[i]] { + t.Errorf("Error traversing: expecting %d at index %d; got %v", expect[i], i, v) } } - if r.File[10].Path[0] != "Charlie" { - t.Errorf("Error traversing: expecting Charlie got %s", r.File[10].Path[0]) + if len(r.File[len(r.File)-1].Path) != 2 { + t.Fatalf("Error traversing: expecting a path length of %d, got %d", 2, len(r.File[len(r.File)-1].Path)) + } + if r.File[len(r.File)-1].Path[0] != "Charlie" { + t.Errorf("Error traversing: expecting Charlie got %s", r.File[expect[10]].Path[0]) } - if r.File[10].Path[1] != "Golf" { - t.Errorf("Error traversing: expecting Golf got %s", r.File[10].Path[1]) + if r.File[len(r.File)-1].Path[1] != "Golf" { + t.Errorf("Error traversing: expecting Golf got %s", r.File[expect[10]].Path[1]) } }