Skip to content

Commit

Permalink
Loading dbf files now verifies expected encoded byte size versus actual.
Browse files Browse the repository at this point in the history
Includes applying footer byte only if one is not found in cached dataStore.
  • Loading branch information
LindsayBradford committed Mar 16, 2022
1 parent aa6cee3 commit f6bb03d
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 2 deletions.
23 changes: 21 additions & 2 deletions godbf/dbfio.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,23 @@ func createDbfTable(s []byte, fileEncoding string) (table *DbfTable, err error)
return nil, fieldErr
}

if verifyErr := verifyHeaderAgainstByteArray(s, dt); verifyErr != nil {
return nil, verifyErr
}

finaliseSchema(s, dt)
return dt, nil
}

func verifyHeaderAgainstByteArray(s []byte, dt *DbfTable) error {
expectedSize := uint32(dt.numberOfBytesInHeader) + dt.numberOfRecords*uint32(dt.lengthOfEachRecord) + 1
actualSize := uint32(len(s))
if actualSize != expectedSize {
return fmt.Errorf("encoded content is %d bytes, but header expected %d", actualSize, expectedSize)
}
return nil
}

func finaliseSchema(s []byte, dt *DbfTable) {
dt.dataEntryStarted = true // Schema changes no longer permitted
dt.dataStore = s // TODO: Deprecate?
Expand Down Expand Up @@ -148,7 +161,7 @@ func writeContent(dt *DbfTable, f *os.File) error {
if dsErr := writeDataStore(dt, f); dsErr != nil {
return dsErr
}
if footerErr := writeFooter(f); footerErr != nil {
if footerErr := writeFooter(dt, f); footerErr != nil {
return footerErr
}
return nil
Expand All @@ -163,8 +176,14 @@ func writeDataStore(dt *DbfTable, f *os.File) error {

const EofMarker byte = 0x1A

func writeFooter(f *os.File) error {
func writeFooter(dt *DbfTable, f *os.File) error {
eofBytes := []byte{EofMarker}

dataStoreLength := len(dt.dataStore)
if dt.dataStore[dataStoreLength-1] == EofMarker {
return nil
}

if _, footerErr := f.Write(eofBytes); footerErr != nil {
return footerErr
}
Expand Down
11 changes: 11 additions & 0 deletions godbf/dbfio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
)

const validTestFile = "testdata/validFile.dbf"
const lessThanActualRecordsFile = "testdata/lessThanActualRecords.dbf"

const realFile = "testdata/122016B1.DBF"

// For reference: https://en.wikipedia.org/wiki/.dbf#File_format_of_Level_5_DOS_dBASE
Expand Down Expand Up @@ -88,6 +90,15 @@ func TestDbfTable_EndOfFieldMarkerMissing_TableParsingError(t *testing.T) {
g.Expect(byteArrayErr.Error()).To(ContainSubstring("end-of-field marker missing"))
}

func TestDbfTable_NewFromLessThanActualRecords_Errors(t *testing.T) {
g := NewGomegaWithT(t)

_, readError := NewFromFile(lessThanActualRecordsFile, testEncoding)

g.Expect(readError).ToNot(BeNil())
t.Log(readError)
}

func verifyTableIsCorrect(tableUnderTest *DbfTable, g *GomegaWithT) {
verifyFieldDescriptorsAreCorrect(tableUnderTest, g)
verifyRecordsAreCorrect(tableUnderTest, g)
Expand Down
Binary file added godbf/testdata/lessThanActualRecords.dbf
Binary file not shown.
Binary file modified godbf/testdata/validFile.dbf
Binary file not shown.

0 comments on commit f6bb03d

Please sign in to comment.