diff --git a/filesystem/fat32/directoryentry.go b/filesystem/fat32/directoryentry.go index 08cb2ec4..86f119f2 100644 --- a/filesystem/fat32/directoryentry.go +++ b/filesystem/fat32/directoryentry.go @@ -103,7 +103,7 @@ func (de *directoryEntry) toBytes() ([]byte, error) { } if de.lowercaseExtension { - dosBytes[12] |= 0x04 + dosBytes[12] |= 0x10 } if de.lowercaseShortname { dosBytes[12] |= 0x08 @@ -161,7 +161,7 @@ byteLoop: isArchiveDirty := b[i+11]&0x20 == 0x20 isVolumeLabel := b[i+11]&0x08 == 0x08 lowercaseShortname := b[i+12]&0x08 == 0x08 - lowercaseExtension := b[i+12]&0x04 == 0x04 + lowercaseExtension := b[i+12]&0x10 == 0x10 entry := directoryEntry{ filenameLong: lfn, diff --git a/filesystem/fat32/fat32.go b/filesystem/fat32/fat32.go index b13c42aa..6e5a7463 100644 --- a/filesystem/fat32/fat32.go +++ b/filesystem/fat32/fat32.go @@ -511,7 +511,7 @@ func (fs *FileSystem) ReadDir(p string) ([]os.FileInfo, error) { } fileExtension := e.fileExtension if e.lowercaseExtension { - shortName = strings.ToLower(fileExtension) + fileExtension = strings.ToLower(fileExtension) } if fileExtension != "" { shortName = fmt.Sprintf("%s.%s", shortName, fileExtension) @@ -553,7 +553,7 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { if e.fileExtension != "" { shortName += "." + e.fileExtension } - if e.filenameLong != filename && shortName != filename { + if !strings.EqualFold(e.filenameLong, filename) && !strings.EqualFold(shortName, filename) { continue } // cannot do anything with directories @@ -840,7 +840,7 @@ func (fs *FileSystem) readDirWithMkdir(p string, doMake bool) (*Directory, []*di // match is determined by any one of: // - long filename == provided name // - uppercase(short filename) == uppercase(provided name) - if e.filenameLong != subp && !strings.EqualFold(e.filenameShort, subp) { + if !strings.EqualFold(e.filenameLong, subp) && !strings.EqualFold(e.filenameShort, subp) { continue } if !e.isSubdirectory { diff --git a/filesystem/fat32/fat32_test.go b/filesystem/fat32/fat32_test.go index 62c6e3ad..1bc189e0 100644 --- a/filesystem/fat32/fat32_test.go +++ b/filesystem/fat32/fat32_test.go @@ -977,3 +977,84 @@ func TestFat32MkdirCases(t *testing.T) { t.Fatalf("expected 1 file, found %d", len(files)) } } + +func Test83Lowercase(t *testing.T) { + // get a temporary working file + f, err := tmpFat32(true, 0, 0) + if err != nil { + t.Fatal(err) + } + if keepTmpFiles == "" { + defer os.Remove(f.Name()) + } else { + fmt.Println(f.Name()) + } + fileInfo, err := f.Stat() + if err != nil { + t.Fatalf("error getting file info for tmpfile %s: %v", f.Name(), err) + } + fs, err := fat32.Read(f, fileInfo.Size(), 0, 512) + if err != nil { + t.Fatalf("error reading fat32 filesystem from %s: %v", f.Name(), err) + } + + // Ensure using correct masks for lowercase shortname and extension (bits 3 and 4, zero-based) + files, err := fs.ReadDir("/lower83") + if err != nil { + t.Fatal(err) + } + expected := []string{"lower.low", "lower.UPP", "UPPER.low"} + i := 0 + for _, file := range files { + if file.Name() == "." || file.Name() == ".." { + continue + } + if file.Name() != expected[i] { + t.Errorf("got %q, expected %q", file.Name(), expected[i]) + } + i++ + } +} + +func TestOpenFileCaseInsensitive(t *testing.T) { + // get a temporary working file + f, err := tmpFat32(true, 0, 0) + if err != nil { + t.Fatal(err) + } + if keepTmpFiles == "" { + defer os.Remove(f.Name()) + } else { + fmt.Println(f.Name()) + } + fileInfo, err := f.Stat() + if err != nil { + t.Fatalf("error getting file info for tmpfile %s: %v", f.Name(), err) + } + fs, err := fat32.Read(f, fileInfo.Size(), 0, 512) + if err != nil { + t.Fatalf("error reading fat32 filesystem from %s: %v", f.Name(), err) + } + + // Ensure openfile is case-insensitive for the 8.3 name as well as the long name + paths := []string{ + // The actual name + "/lower83/lower.low", + // Same name but different extension case + "/lower83/lower.LOW", + // Same name but different base case + "/lower83/LOWER.LOW", + // Actual name/case of non-8.3 file + "/tercer_archivo", + // Same name but uppercase + "/TERCER_ARCHIVO", + } + for _, path := range paths { + file, err := fs.OpenFile(path, os.O_RDONLY) + if err != nil { + t.Errorf("error opening %s: %v\n", path, err) + } else { + file.Close() + } + } +} diff --git a/filesystem/fat32/testdata/mkfat32.sh b/filesystem/fat32/testdata/mkfat32.sh index b235e2bf..5beeee57 100755 --- a/filesystem/fat32/testdata/mkfat32.sh +++ b/filesystem/fat32/testdata/mkfat32.sh @@ -28,6 +28,10 @@ mcopy -i /data/fat32.img /CORTO1.TXT ::/ mcopy -i /data/fat32.img '/Un archivo con nombre largo.dat' ::/ mcopy -i /data/fat32.img '/tercer_archivo' ::/ mcopy -i /data/fat32.img '/some_long_embedded_nameŚ' ::/foo/bar +mmd -i /data/fat32.img ::/lower83 +mcopy -i /data/fat32.img /CORTO1.TXT ::/lower83/lower.low +mcopy -i /data/fat32.img /CORTO1.TXT ::/lower83/lower.UPP +mcopy -i /data/fat32.img /CORTO1.TXT ::/lower83/UPPER.low i=0 until [ $i -gt 75 ]; do mmd -i /data/fat32.img ::/foo/dir${i}; i=$(( $i+1 )); done