From 8027e3a27b90ed1b101a85b5f9e8c8aa8bd62c42 Mon Sep 17 00:00:00 2001 From: Ludwig Date: Wed, 3 Jul 2024 11:28:31 +0200 Subject: [PATCH 1/7] feat: implement remove and rename feature for fat32, add new unit-tests --- filesystem/ext4/ext4.go | 8 + filesystem/fat32/directory.go | 72 +++++++- filesystem/fat32/fat32.go | 120 +++++++++++++- filesystem/fat32/fat32_test.go | 283 ++++++++++++++++++++++++++++++++ filesystem/filesystem.go | 4 + filesystem/iso9660/iso9660.go | 8 + filesystem/squashfs/squashfs.go | 8 + 7 files changed, 501 insertions(+), 2 deletions(-) diff --git a/filesystem/ext4/ext4.go b/filesystem/ext4/ext4.go index 660c3c1d..00538951 100644 --- a/filesystem/ext4/ext4.go +++ b/filesystem/ext4/ext4.go @@ -804,6 +804,14 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { }, nil } +func (fs *FileSystem) RemoveFile(p string) error { + return fmt.Errorf("not implemented") +} + +func (fs *FileSystem) RenameFile(p, newFileName string) error { + return fmt.Errorf("not implemented") +} + // Label read the volume label func (fs *FileSystem) Label() string { if fs.superblock == nil { diff --git a/filesystem/fat32/directory.go b/filesystem/fat32/directory.go index bd917b75..5c4652df 100644 --- a/filesystem/fat32/directory.go +++ b/filesystem/fat32/directory.go @@ -1,6 +1,7 @@ package fat32 import ( + "fmt" "time" ) @@ -41,7 +42,7 @@ func (d *Directory) entriesToBytes(bytesPerCluster int) ([]byte, error) { func (d *Directory) createEntry(name string, cluster uint32, dir bool) (*directoryEntry, error) { // is it a long filename or a short filename? var isLFN bool - // TODO: convertLfnSfn does not calculate if the short name conflicts and thus shoukld increment the last character + // TODO: convertLfnSfn does not calculate if the short name conflicts and thus should increment the last character // that should happen here, once we can look in the directory entry shortName, extension, isLFN, _ := convertLfnSfn(name) lfn := "" @@ -70,6 +71,75 @@ func (d *Directory) createEntry(name string, cluster uint32, dir bool) (*directo return &entry, nil } +// removeEntry removes an entry in the given directory +func (d *Directory) removeEntry(name string) error { + // is it a long filename or a short filename? + var isLFN bool + // TODO: convertLfnSfn does not calculate if the short name conflicts and thus should increment the last character + // that should happen here, once we can look in the directory entry + _, _, isLFN, _ = convertLfnSfn(name) + lfn := "" + if isLFN { + lfn = name + } + + removeEntryIndex := -1 + for i, entry := range d.entries { + if entry.filenameLong == lfn { // || entry.filenameShort == shortName do not compare SFN, since it is not incremented correctly + removeEntryIndex = i + } + } + + if removeEntryIndex == -1 { + return fmt.Errorf("cannot find entry for name %s", name) + } + + // remove the entry from the list + d.entries = append(d.entries[:removeEntryIndex], d.entries[removeEntryIndex+1:]...) + + return nil +} + +// renameEntry renames an entry in the given directory, and returns the handle to it +func (d *Directory) renameEntry(oldFileName, newFileName string) error { + // is it a long filename or a short filename? + var isLFN bool + // TODO: convertLfnSfn does not calculate if the short name conflicts and thus should increment the last character + // that should happen here, once we can look in the directory entry + _, _, isLFN, _ = convertLfnSfn(oldFileName) + lfn := "" + if isLFN { + lfn = oldFileName + } + + var newEntries []*directoryEntry + var isReplaced = false + for _, entry := range d.entries { + if entry.filenameLong == newFileName { + return fmt.Errorf("file with name %s already exists", newFileName) + } + if entry.filenameLong == lfn { // || entry.filenameShort == shortName do not compare SFN, since it is not incremented correctly + shortName, extension, isLFN, _ := convertLfnSfn(newFileName) + if isLFN { + lfn = newFileName + } + entry.filenameLong = lfn + entry.filenameShort = shortName + entry.fileExtension = extension + entry.modifyTime = time.Now() + isReplaced = true + } + newEntries = append(newEntries, entry) + } + if !isReplaced { + return fmt.Errorf("cannot find file entry for %s", oldFileName) + } + + d.entries = newEntries + + return nil +} + // createVolumeLabel create a volume label entry in the given directory, and return the handle to it func (d *Directory) createVolumeLabel(name string) (*directoryEntry, error) { // allocate a slot for the new filename in the existing directory diff --git a/filesystem/fat32/fat32.go b/filesystem/fat32/fat32.go index acb68ed1..4601ae76 100644 --- a/filesystem/fat32/fat32.go +++ b/filesystem/fat32/fat32.go @@ -599,6 +599,124 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { }, nil } +// RemoveFile removes a file from the filesystem +// +// returns an error if the file does not exist or cannot be removed +func (fs *FileSystem) RemoveFile(p string) error { + // get the path + dir := path.Dir(p) + filename := path.Base(p) + // if the dir == filename, then it is just / + if dir == filename { + return fmt.Errorf("cannot remove directory %s as file", p) + } + // get the directory entries + parentDir, entries, err := fs.readDirWithMkdir(dir, false) + if err != nil { + return fmt.Errorf("could not read directory entries for %s", dir) + } + // we now know that the directory exists, see if the file exists + var targetEntry *directoryEntry + for _, e := range entries { + shortName := e.filenameShort + if e.fileExtension != "" { + shortName += "." + e.fileExtension + } + if e.filenameLong != filename && shortName != filename { + continue + } + // cannot do anything with directories + if e.isSubdirectory { + return fmt.Errorf("cannot open directory %s as file", p) + } + // if we got this far, we have found the file + targetEntry = e + } + + // see if the file exists + // if the file does not exist, and is not opened for os.O_CREATE, return an error + if targetEntry == nil { + return fmt.Errorf("target file %s does not exist", p) + } + err = parentDir.removeEntry(filename) + if err != nil { + return fmt.Errorf("failed to remove file %s: %v", p, err) + } + + // we need to make sure that clusters are removed which may not be used anymore + _, err = fs.allocateSpace(uint64(parentDir.fileSize), parentDir.clusterLocation) + if err != nil { + return fmt.Errorf("failed to allocate clusters: %v", err) + } + + // write the directory entries to disk + err = fs.writeDirectoryEntries(parentDir) + if err != nil { + return fmt.Errorf("error writing directory file %s to disk: %v", p, err) + } + + return nil +} + +// RenameFile removes a file from the filesystem +// +// returns an error if the file does not exist or cannot be renamed +func (fs *FileSystem) RenameFile(p, newFileName string) error { + // get the path + dir := path.Dir(p) + filename := path.Base(p) + // if the dir == filename, then it is just / + if dir == filename { + return fmt.Errorf("cannot rename directory %s as file", p) + } + // get the directory entries + parentDir, entries, err := fs.readDirWithMkdir(dir, false) + if err != nil { + return fmt.Errorf("could not read directory entries for %s", dir) + } + // we now know that the directory exists, see if the file exists + var targetEntry *directoryEntry + for _, e := range entries { + shortName := e.filenameShort + if e.fileExtension != "" { + shortName += "." + e.fileExtension + } + if e.filenameLong != filename && shortName != filename { + continue + } + // cannot do anything with directories + if e.isSubdirectory { + return fmt.Errorf("cannot open directory %s as file", p) + } + // if we got this far, we have found the file + targetEntry = e + } + + // see if the file exists + // if the file does not exist, and is not opened for os.O_CREATE, return an error + if targetEntry == nil { + return fmt.Errorf("target file %s does not exist", p) + } + err = parentDir.renameEntry(filename, newFileName) + if err != nil { + return fmt.Errorf("failed to rename file %s: %v", p, err) + } + + // we need to make sure that clusters are removed which may not be used anymore + _, err = fs.allocateSpace(uint64(parentDir.fileSize), parentDir.clusterLocation) + if err != nil { + return fmt.Errorf("failed to allocate clusters: %v", err) + } + + // write the directory entries to disk + err = fs.writeDirectoryEntries(parentDir) + if err != nil { + return fmt.Errorf("error writing directory file %s to disk: %v", p, err) + } + + return nil +} + // Label get the label of the filesystem from the secial file in the root directory. // The label stored in the boot sector is ignored to mimic Windows behavior which // only stores and reads the label from the special file in the root directory. @@ -748,7 +866,7 @@ func (fs *FileSystem) mkSubdir(parent *Directory, name string) (*directoryEntry, } func (fs *FileSystem) writeDirectoryEntries(dir *Directory) error { - // we need to save the entries of theparent + // we need to save the entries of the parent b, err := dir.entriesToBytes(fs.bytesPerCluster) if err != nil { return fmt.Errorf("could not create a valid byte stream for a FAT32 Entries: %v", err) diff --git a/filesystem/fat32/fat32_test.go b/filesystem/fat32/fat32_test.go index 5b1bca19..674890a6 100644 --- a/filesystem/fat32/fat32_test.go +++ b/filesystem/fat32/fat32_test.go @@ -11,6 +11,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strings" "testing" @@ -947,3 +948,285 @@ func TestFat32Label(t *testing.T) { } }) } + +func Test_RenameFile(t *testing.T) { + workingPath := "/" + oldFileName := "old.txt" + newFileName := "new.txt" + createFile := func(t *testing.T, fs *fat32.FileSystem, name, content string) { + origFile, err := fs.OpenFile(filepath.Join(workingPath, name), os.O_CREATE|os.O_RDWR) + if err != nil { + t.Fatalf("Could not create file %s: %+v", name, err) + } + defer origFile.Close() + // write test file + _, err = origFile.Write([]byte(content)) + if err != nil { + t.Fatalf("Could not Write file %s, %+v", name, err) + } + } + readFile := func(t *testing.T, fs *fat32.FileSystem, name string) string { + file, err := fs.OpenFile(filepath.Join(workingPath, name), os.O_RDONLY) + if err != nil { + t.Fatalf("file %s does not exist: %+v", name, err) + } + defer file.Close() + buf := &bytes.Buffer{} + _, err = io.Copy(buf, file) + if err != nil { + t.Fatalf("Could not read file %s: %+v", name, err) + } + return buf.String() + } + tests := []struct { + name string + hasError bool + pre func(t *testing.T, fs *fat32.FileSystem) + post func(t *testing.T, fs *fat32.FileSystem) + }{ + { + name: "simple renaming works without errors", + hasError: false, + pre: func(t *testing.T, fs *fat32.FileSystem) { + createFile(t, fs, oldFileName, "FooBar") + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + //check if original file is there -> should not be the case + origFile, err := fs.OpenFile(oldFileName, os.O_RDONLY) + if err == nil { + defer origFile.Close() + t.Fatal("Original file is still there") + } + // check if new file is there -> should be the case + content := readFile(t, fs, newFileName) + if content != "FooBar" { + t.Fatalf("Content should be '%s', but is '%s'", "FooBar", content) + } + }, + }, + { + name: "destination file already exists", + hasError: true, + pre: func(t *testing.T, fs *fat32.FileSystem) { + createFile(t, fs, oldFileName, "FooBar") + //create destination file + createFile(t, fs, newFileName, "This should keep") + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + // new file is not touched + content := readFile(t, fs, newFileName) + if content != "This should keep" { + t.Fatalf("Content should be '%s', but is '%s'", "This should keep", content) + } + + // old file is still there + content = readFile(t, fs, oldFileName) + if content != "FooBar" { + t.Fatalf("Content should be '%s', but is '%s'", "FooBar", content) + } + }, + }, + { + name: "source file does not exist", + hasError: true, + pre: func(t *testing.T, fs *fat32.FileSystem) { + // do not create orig file + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + + }, + }, + { + name: "renaming long file to short file", + hasError: false, + pre: func(t *testing.T, fs *fat32.FileSystem) { + var s string + for i := 0; i < 255; i++ { + s += "a" + } + oldFileName = s + createFile(t, fs, s, "orig") + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + oldFileName = "old.txt" + }, + }, + { + name: "renaming short file to long file", + hasError: false, + pre: func(t *testing.T, fs *fat32.FileSystem) { + var s string + for i := 0; i < 255; i++ { + s += "a" + } + newFileName = s + createFile(t, fs, oldFileName, "orig") + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + newFileName = "new.txt" + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // get a mock filesystem image + f, err := tmpFat32(false, 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) + } + + // create an empty filesystem + fs, err := fat32.Create(f, fileInfo.Size(), 0, 512, "go-diskfs") + if err != nil { + t.Fatalf("error creating fat32 filesystem: %v", err) + } + + test.pre(t, fs) + + err = fs.RenameFile(filepath.Join(workingPath, oldFileName), newFileName) + + if test.hasError { + if err == nil { + t.Fatal("No Error renaming file", err) + } + } else { + if err != nil { + t.Fatal("Error renaming file", err) + } + } + + test.post(t, fs) + }) + } +} + +func Test_RemoveFile(t *testing.T) { + workingPath := "/" + fileToRemove := "fileToRemove.txt" + createFile := func(t *testing.T, fs *fat32.FileSystem, name, content string) { + origFile, err := fs.OpenFile(filepath.Join(workingPath, name), os.O_CREATE|os.O_RDWR) + if err != nil { + t.Fatalf("Could not create file %s: %+v", name, err) + } + defer origFile.Close() + // write test file + _, err = origFile.Write([]byte(content)) + if err != nil { + t.Fatalf("Could not Write file %s, %+v", name, err) + } + } + tests := []struct { + name string + hasError bool + errorMsg string + pre func(t *testing.T, fs *fat32.FileSystem) + post func(t *testing.T, fs *fat32.FileSystem) + }{ + { + name: "simple remove works without", + hasError: false, + pre: func(t *testing.T, fs *fat32.FileSystem) { + createFile(t, fs, fileToRemove, "FooBar") + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + //check if original file is there -> should not be the case + origFile, err := fs.OpenFile(fileToRemove, os.O_RDONLY) + if err == nil { + defer origFile.Close() + t.Fatal("Original file is still there") + } + }, + }, + { + name: "file to remove does not exist", + hasError: true, + errorMsg: "target file /fileToRemove.txt does not exist", + pre: func(t *testing.T, fs *fat32.FileSystem) { + // do not create any file + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + + }, + }, + { + name: "removing multiple files", + hasError: false, + pre: func(t *testing.T, fs *fat32.FileSystem) { + var s string + for i := 0; i < 10240; i++ { + s += "this is a big file\n" + } + for i := 0; i < 50; i++ { + createFile(t, fs, fmt.Sprintf("file%d.txt", i), "small file") + } + createFile(t, fs, fileToRemove, s) + for i := 50; i < 100; i++ { + createFile(t, fs, fmt.Sprintf("file%d.txt", i), "small file") + } + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + for i := 0; i < 100; i++ { + err := fs.RemoveFile(fmt.Sprintf("/file%d.txt", i)) + if err != nil { + t.Fatalf("expected no error, but got %v", err) + } + } + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // get a mock filesystem image + f, err := tmpFat32(false, 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) + } + + // create an empty filesystem + fs, err := fat32.Create(f, fileInfo.Size(), 0, 512, "go-diskfs") + if err != nil { + t.Fatalf("error creating fat32 filesystem: %v", err) + } + + test.pre(t, fs) + + err = fs.RemoveFile(filepath.Join(workingPath, fileToRemove)) + + if test.hasError { + if err == nil { + t.Fatal("No Error renaming file", err) + } else if !strings.Contains(err.Error(), test.errorMsg) { + t.Fatalf("Error does not contain expected msg: %s. Original error: %v", test.errorMsg, err) + } + } else { + if err != nil { + t.Fatal("Error renaming file", err) + } + } + + test.post(t, fs) + }) + } +} diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 2c1acfa6..cc1bfb45 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -16,6 +16,10 @@ type FileSystem interface { ReadDir(string) ([]os.FileInfo, error) // OpenFile open a handle to read or write to a file OpenFile(string, int) (File, error) + // RemoveFile removes a file from the filesystem + RemoveFile(p string) error + // RenameFile renames a file from the filesystem + RenameFile(p, newFileName string) error // Label get the label for the filesystem, or "" if none. Be careful to trim it, as it may contain // leading or following whitespace. The label is passed as-is and not cleaned up at all. Label() string diff --git a/filesystem/iso9660/iso9660.go b/filesystem/iso9660/iso9660.go index 64b28ed2..91367f01 100644 --- a/filesystem/iso9660/iso9660.go +++ b/filesystem/iso9660/iso9660.go @@ -414,6 +414,14 @@ func (fsm *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { return f, nil } +func (fs *FileSystem) RemoveFile(p string) error { + return fmt.Errorf("not implemented") +} + +func (fs *FileSystem) RenameFile(p, newFileName string) error { + return fmt.Errorf("not implemented") +} + // readDirectory - read directory entry on iso only (not workspace) func (fsm *FileSystem) readDirectory(p string) ([]*directoryEntry, error) { var ( diff --git a/filesystem/squashfs/squashfs.go b/filesystem/squashfs/squashfs.go index bdd8d5a7..55cf436d 100644 --- a/filesystem/squashfs/squashfs.go +++ b/filesystem/squashfs/squashfs.go @@ -379,6 +379,14 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { return f, nil } +func (fs *FileSystem) RemoveFile(p string) error { + return fmt.Errorf("not implemented") +} + +func (fs *FileSystem) RenameFile(p, newFileName string) error { + return fmt.Errorf("not implemented") +} + // readDirectory - read directory entry on squashfs only (not workspace) func (fs *FileSystem) readDirectory(p string) ([]*directoryEntry, error) { // use the root inode to find the location of the root direectory in the table From afb98269fd985f438672b21b69f3399087fae9b5 Mon Sep 17 00:00:00 2001 From: Ludwig Date: Fri, 15 Nov 2024 10:57:11 +0100 Subject: [PATCH 2/7] task: transform RemoveFile() method into Remove() for interface compatibility --- filesystem/ext4/ext4.go | 4 ---- filesystem/fat32/fat32.go | 28 +++++++++++------------ filesystem/fat32/fat32_test.go | 40 +++++++++++++++++++++++++++++---- filesystem/filesystem.go | 2 -- filesystem/iso9660/iso9660.go | 4 ---- filesystem/squashfs/squashfs.go | 4 ---- 6 files changed, 50 insertions(+), 32 deletions(-) diff --git a/filesystem/ext4/ext4.go b/filesystem/ext4/ext4.go index 422720ec..89eaac86 100644 --- a/filesystem/ext4/ext4.go +++ b/filesystem/ext4/ext4.go @@ -841,10 +841,6 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { }, nil } -func (fs *FileSystem) RemoveFile(p string) error { - return fmt.Errorf("not implemented") -} - func (fs *FileSystem) RenameFile(p, newFileName string) error { return fmt.Errorf("not implemented") } diff --git a/filesystem/fat32/fat32.go b/filesystem/fat32/fat32.go index 3d418d24..2b348443 100644 --- a/filesystem/fat32/fat32.go +++ b/filesystem/fat32/fat32.go @@ -648,19 +648,12 @@ func (fs *FileSystem) Rename(oldpath, newpath string) error { // //nolint:revive // parameters will be used eventually func (fs *FileSystem) Remove(pathname string) error { - return filesystem.ErrNotImplemented -} - -// RemoveFile removes a file from the filesystem -// -// returns an error if the file does not exist or cannot be removed -func (fs *FileSystem) RemoveFile(p string) error { // get the path - dir := path.Dir(p) - filename := path.Base(p) + dir := path.Dir(pathname) + filename := path.Base(pathname) // if the dir == filename, then it is just / if dir == filename { - return fmt.Errorf("cannot remove directory %s as file", p) + return fmt.Errorf("cannot remove directory %s as file", pathname) } // get the directory entries parentDir, entries, err := fs.readDirWithMkdir(dir, false) @@ -679,7 +672,14 @@ func (fs *FileSystem) RemoveFile(p string) error { } // cannot do anything with directories if e.isSubdirectory { - return fmt.Errorf("cannot open directory %s as file", p) + content, err := fs.ReadDir(pathname) + if err != nil { + return fmt.Errorf("error while checking if file to delete is empty: %+v", err) + } + // '.' & '..' are always present in directory + if len(content) > 2 { + return fmt.Errorf("cannot remove non-empty directory %s", pathname) + } } // if we got this far, we have found the file targetEntry = e @@ -688,11 +688,11 @@ func (fs *FileSystem) RemoveFile(p string) error { // see if the file exists // if the file does not exist, and is not opened for os.O_CREATE, return an error if targetEntry == nil { - return fmt.Errorf("target file %s does not exist", p) + return fmt.Errorf("target file %s does not exist", pathname) } err = parentDir.removeEntry(filename) if err != nil { - return fmt.Errorf("failed to remove file %s: %v", p, err) + return fmt.Errorf("failed to remove file %s: %v", pathname, err) } // we need to make sure that clusters are removed which may not be used anymore @@ -704,7 +704,7 @@ func (fs *FileSystem) RemoveFile(p string) error { // write the directory entries to disk err = fs.writeDirectoryEntries(parentDir) if err != nil { - return fmt.Errorf("error writing directory file %s to disk: %v", p, err) + return fmt.Errorf("error writing directory file %s to disk: %v", pathname, err) } return nil diff --git a/filesystem/fat32/fat32_test.go b/filesystem/fat32/fat32_test.go index 976839e1..451a2448 100644 --- a/filesystem/fat32/fat32_test.go +++ b/filesystem/fat32/fat32_test.go @@ -1307,7 +1307,7 @@ func Test_RenameFile(t *testing.T) { } } -func Test_RemoveFile(t *testing.T) { +func Test_Remove(t *testing.T) { workingPath := "/" fileToRemove := "fileToRemove.txt" createFile := func(t *testing.T, fs *fat32.FileSystem, name, content string) { @@ -1373,13 +1373,45 @@ func Test_RemoveFile(t *testing.T) { }, post: func(t *testing.T, fs *fat32.FileSystem) { for i := 0; i < 100; i++ { - err := fs.RemoveFile(fmt.Sprintf("/file%d.txt", i)) + err := fs.Remove(fmt.Sprintf("/file%d.txt", i)) if err != nil { t.Fatalf("expected no error, but got %v", err) } } }, }, + { + name: "removing empty dir", + hasError: false, + pre: func(t *testing.T, fs *fat32.FileSystem) { + if err := fs.Mkdir(filepath.Join(workingPath, fileToRemove)); err != nil { + t.Fatalf("could not create test directory: %+v", err) + } + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + _, err := fs.ReadDir(filepath.Join(workingPath, fileToRemove)) + if err == nil { + t.Fatalf("Expected that dir cannot be read, but is still there") + } + }, + }, + { + name: "cannot delete dir with content", + hasError: true, + pre: func(t *testing.T, fs *fat32.FileSystem) { + if err := fs.Mkdir(filepath.Join(workingPath, fileToRemove)); err != nil { + t.Fatalf("could not create test directory: %+v", err) + } + // file within dir to remove + createFile(t, fs, filepath.Join(workingPath, fileToRemove, "test"), "foo") + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + _, err := fs.ReadDir(filepath.Join(workingPath, fileToRemove)) + if err != nil { + t.Fatalf("Expected that dir can be read, but has error: %+v", err) + } + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -1408,7 +1440,7 @@ func Test_RemoveFile(t *testing.T) { test.pre(t, fs) - err = fs.RemoveFile(filepath.Join(workingPath, fileToRemove)) + err = fs.Remove(filepath.Join(workingPath, fileToRemove)) if test.hasError { if err == nil { @@ -1418,7 +1450,7 @@ func Test_RemoveFile(t *testing.T) { } } else { if err != nil { - t.Fatal("Error renaming file", err) + t.Fatal("Error removing file", err) } } diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 03d2ab72..e90ad9f3 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -40,8 +40,6 @@ type FileSystem interface { Rename(oldpath, newpath string) error // removes the named file or (empty) directory. Remove(pathname string) error - // RemoveFile removes a file from the filesystem - RemoveFile(p string) error // RenameFile renames a file from the filesystem RenameFile(p, newFileName string) error // Label get the label for the filesystem, or "" if none. Be careful to trim it, as it may contain diff --git a/filesystem/iso9660/iso9660.go b/filesystem/iso9660/iso9660.go index 4750cdb3..857699aa 100644 --- a/filesystem/iso9660/iso9660.go +++ b/filesystem/iso9660/iso9660.go @@ -476,10 +476,6 @@ func (fsm *FileSystem) Remove(p string) error { return os.Remove(path.Join(fsm.workspace, p)) } -func (fs *FileSystem) RemoveFile(p string) error { - return fmt.Errorf("not implemented") -} - func (fs *FileSystem) RenameFile(p, newFileName string) error { return fmt.Errorf("not implemented") } diff --git a/filesystem/squashfs/squashfs.go b/filesystem/squashfs/squashfs.go index bae1f45a..f92e0725 100644 --- a/filesystem/squashfs/squashfs.go +++ b/filesystem/squashfs/squashfs.go @@ -441,10 +441,6 @@ func (fs *FileSystem) Remove(p string) error { return os.Remove(path.Join(fs.workspace, p)) } -func (fs *FileSystem) RemoveFile(p string) error { - return fmt.Errorf("not implemented") -} - func (fs *FileSystem) RenameFile(p, newFileName string) error { return fmt.Errorf("not implemented") } From 96aacec96b92030273727ff07ec39a3e4f3409d3 Mon Sep 17 00:00:00 2001 From: Ludwig Date: Fri, 15 Nov 2024 14:21:32 +0100 Subject: [PATCH 3/7] task: transform RenameFile() method into Rename() for interface compatibility --- filesystem/ext4/ext4.go | 4 --- filesystem/fat32/directory.go | 2 +- filesystem/fat32/fat32.go | 36 +++++++++++++------------- filesystem/fat32/fat32_test.go | 45 ++++++++++++++++----------------- filesystem/filesystem.go | 2 -- filesystem/iso9660/iso9660.go | 4 --- filesystem/squashfs/squashfs.go | 4 --- 7 files changed, 40 insertions(+), 57 deletions(-) diff --git a/filesystem/ext4/ext4.go b/filesystem/ext4/ext4.go index 89eaac86..8f326e6b 100644 --- a/filesystem/ext4/ext4.go +++ b/filesystem/ext4/ext4.go @@ -841,10 +841,6 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { }, nil } -func (fs *FileSystem) RenameFile(p, newFileName string) error { - return fmt.Errorf("not implemented") -} - // Label read the volume label func (fs *FileSystem) Label() string { if fs.superblock == nil { diff --git a/filesystem/fat32/directory.go b/filesystem/fat32/directory.go index 5c4652df..7c37921b 100644 --- a/filesystem/fat32/directory.go +++ b/filesystem/fat32/directory.go @@ -116,7 +116,7 @@ func (d *Directory) renameEntry(oldFileName, newFileName string) error { var isReplaced = false for _, entry := range d.entries { if entry.filenameLong == newFileName { - return fmt.Errorf("file with name %s already exists", newFileName) + continue // skip adding already existing file, will be overwritten } if entry.filenameLong == lfn { // || entry.filenameShort == shortName do not compare SFN, since it is not incremented correctly shortName, extension, isLFN, _ := convertLfnSfn(newFileName) diff --git a/filesystem/fat32/fat32.go b/filesystem/fat32/fat32.go index 2b348443..18d499da 100644 --- a/filesystem/fat32/fat32.go +++ b/filesystem/fat32/fat32.go @@ -637,13 +637,6 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { }, nil } -// Rename renames (moves) oldpath to newpath. If newpath already exists and is not a directory, Rename replaces it. -// -//nolint:revive // parameters will be used eventually -func (fs *FileSystem) Rename(oldpath, newpath string) error { - return filesystem.ErrNotImplemented -} - // removes the named file or (empty) directory. // //nolint:revive // parameters will be used eventually @@ -710,16 +703,21 @@ func (fs *FileSystem) Remove(pathname string) error { return nil } -// RenameFile removes a file from the filesystem -// -// returns an error if the file does not exist or cannot be renamed -func (fs *FileSystem) RenameFile(p, newFileName string) error { +// Rename renames (moves) oldpath to newpath. If newpath already exists and is not a directory, Rename replaces it. +func (fs *FileSystem) Rename(oldpath, newpath string) error { // get the path - dir := path.Dir(p) - filename := path.Base(p) + dir := path.Dir(oldpath) + filename := path.Base(oldpath) + + newDir := path.Dir(newpath) + newname := path.Base(newpath) + if dir != newDir { + return errors.New("can only rename files within the same directory") + } + // if the dir == filename, then it is just / if dir == filename { - return fmt.Errorf("cannot rename directory %s as file", p) + return fmt.Errorf("cannot rename directory %s as file", oldpath) } // get the directory entries parentDir, entries, err := fs.readDirWithMkdir(dir, false) @@ -738,7 +736,7 @@ func (fs *FileSystem) RenameFile(p, newFileName string) error { } // cannot do anything with directories if e.isSubdirectory { - return fmt.Errorf("cannot open directory %s as file", p) + return fmt.Errorf("cannot open directory %s as file", oldpath) } // if we got this far, we have found the file targetEntry = e @@ -747,11 +745,11 @@ func (fs *FileSystem) RenameFile(p, newFileName string) error { // see if the file exists // if the file does not exist, and is not opened for os.O_CREATE, return an error if targetEntry == nil { - return fmt.Errorf("target file %s does not exist", p) + return fmt.Errorf("target file %s does not exist", oldpath) } - err = parentDir.renameEntry(filename, newFileName) + err = parentDir.renameEntry(filename, newname) if err != nil { - return fmt.Errorf("failed to rename file %s: %v", p, err) + return fmt.Errorf("failed to rename file %s: %v", oldpath, err) } // we need to make sure that clusters are removed which may not be used anymore @@ -763,7 +761,7 @@ func (fs *FileSystem) RenameFile(p, newFileName string) error { // write the directory entries to disk err = fs.writeDirectoryEntries(parentDir) if err != nil { - return fmt.Errorf("error writing directory file %s to disk: %v", p, err) + return fmt.Errorf("error writing directory file %s to disk: %v", oldpath, err) } return nil diff --git a/filesystem/fat32/fat32_test.go b/filesystem/fat32/fat32_test.go index 451a2448..647230c6 100644 --- a/filesystem/fat32/fat32_test.go +++ b/filesystem/fat32/fat32_test.go @@ -1145,10 +1145,10 @@ func TestCreateFileTree(t *testing.T) { } } -func Test_RenameFile(t *testing.T) { +func Test_Rename(t *testing.T) { workingPath := "/" - oldFileName := "old.txt" - newFileName := "new.txt" + srcFile := "old.txt" + dstFile := "new.txt" createFile := func(t *testing.T, fs *fat32.FileSystem, name, content string) { origFile, err := fs.OpenFile(filepath.Join(workingPath, name), os.O_CREATE|os.O_RDWR) if err != nil { @@ -1184,39 +1184,38 @@ func Test_RenameFile(t *testing.T) { name: "simple renaming works without errors", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { - createFile(t, fs, oldFileName, "FooBar") + createFile(t, fs, srcFile, "FooBar") }, post: func(t *testing.T, fs *fat32.FileSystem) { //check if original file is there -> should not be the case - origFile, err := fs.OpenFile(oldFileName, os.O_RDONLY) + origFile, err := fs.OpenFile(srcFile, os.O_RDONLY) if err == nil { defer origFile.Close() t.Fatal("Original file is still there") } // check if new file is there -> should be the case - content := readFile(t, fs, newFileName) + content := readFile(t, fs, dstFile) if content != "FooBar" { t.Fatalf("Content should be '%s', but is '%s'", "FooBar", content) } }, }, { - name: "destination file already exists", - hasError: true, + name: "destination file already exists and gets overwritten", + hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { - createFile(t, fs, oldFileName, "FooBar") + createFile(t, fs, srcFile, "FooBar") //create destination file - createFile(t, fs, newFileName, "This should keep") + createFile(t, fs, dstFile, "This should be overwritten") }, post: func(t *testing.T, fs *fat32.FileSystem) { - // new file is not touched - content := readFile(t, fs, newFileName) - if content != "This should keep" { - t.Fatalf("Content should be '%s', but is '%s'", "This should keep", content) + origFile, err := fs.OpenFile(filepath.Join(workingPath, srcFile), os.O_RDONLY) + if err == nil { + defer origFile.Close() + t.Fatal("Original file is still there") } - - // old file is still there - content = readFile(t, fs, oldFileName) + // check if new file is there -> should be the case + content := readFile(t, fs, dstFile) if content != "FooBar" { t.Fatalf("Content should be '%s', but is '%s'", "FooBar", content) } @@ -1240,11 +1239,11 @@ func Test_RenameFile(t *testing.T) { for i := 0; i < 255; i++ { s += "a" } - oldFileName = s + srcFile = s createFile(t, fs, s, "orig") }, post: func(t *testing.T, fs *fat32.FileSystem) { - oldFileName = "old.txt" + srcFile = "old.txt" }, }, { @@ -1255,11 +1254,11 @@ func Test_RenameFile(t *testing.T) { for i := 0; i < 255; i++ { s += "a" } - newFileName = s - createFile(t, fs, oldFileName, "orig") + dstFile = s + createFile(t, fs, srcFile, "orig") }, post: func(t *testing.T, fs *fat32.FileSystem) { - newFileName = "new.txt" + dstFile = "new.txt" }, }, } @@ -1290,7 +1289,7 @@ func Test_RenameFile(t *testing.T) { test.pre(t, fs) - err = fs.RenameFile(filepath.Join(workingPath, oldFileName), newFileName) + err = fs.Rename(filepath.Join(workingPath, srcFile), filepath.Join(workingPath, dstFile)) if test.hasError { if err == nil { diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index e90ad9f3..bf309d39 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -40,8 +40,6 @@ type FileSystem interface { Rename(oldpath, newpath string) error // removes the named file or (empty) directory. Remove(pathname string) error - // RenameFile renames a file from the filesystem - RenameFile(p, newFileName string) error // Label get the label for the filesystem, or "" if none. Be careful to trim it, as it may contain // leading or following whitespace. The label is passed as-is and not cleaned up at all. Label() string diff --git a/filesystem/iso9660/iso9660.go b/filesystem/iso9660/iso9660.go index 857699aa..6cb56df1 100644 --- a/filesystem/iso9660/iso9660.go +++ b/filesystem/iso9660/iso9660.go @@ -476,10 +476,6 @@ func (fsm *FileSystem) Remove(p string) error { return os.Remove(path.Join(fsm.workspace, p)) } -func (fs *FileSystem) RenameFile(p, newFileName string) error { - return fmt.Errorf("not implemented") -} - // readDirectory - read directory entry on iso only (not workspace) func (fsm *FileSystem) readDirectory(p string) ([]*directoryEntry, error) { var ( diff --git a/filesystem/squashfs/squashfs.go b/filesystem/squashfs/squashfs.go index f92e0725..8b769deb 100644 --- a/filesystem/squashfs/squashfs.go +++ b/filesystem/squashfs/squashfs.go @@ -441,10 +441,6 @@ func (fs *FileSystem) Remove(p string) error { return os.Remove(path.Join(fs.workspace, p)) } -func (fs *FileSystem) RenameFile(p, newFileName string) error { - return fmt.Errorf("not implemented") -} - // readDirectory - read directory entry on squashfs only (not workspace) func (fs *FileSystem) readDirectory(p string) ([]*directoryEntry, error) { // use the root inode to find the location of the root direectory in the table From a6044054c78f042d059c99aaf05b6390126d4577 Mon Sep 17 00:00:00 2001 From: Ludwig Date: Fri, 15 Nov 2024 15:00:01 +0100 Subject: [PATCH 4/7] task: support renaming of directories (in same dir) --- filesystem/fat32/fat32.go | 4 ---- filesystem/fat32/fat32_test.go | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/filesystem/fat32/fat32.go b/filesystem/fat32/fat32.go index 18d499da..2d3947c2 100644 --- a/filesystem/fat32/fat32.go +++ b/filesystem/fat32/fat32.go @@ -734,10 +734,6 @@ func (fs *FileSystem) Rename(oldpath, newpath string) error { if e.filenameLong != filename && shortName != filename { continue } - // cannot do anything with directories - if e.isSubdirectory { - return fmt.Errorf("cannot open directory %s as file", oldpath) - } // if we got this far, we have found the file targetEntry = e } diff --git a/filesystem/fat32/fat32_test.go b/filesystem/fat32/fat32_test.go index 647230c6..f2cca794 100644 --- a/filesystem/fat32/fat32_test.go +++ b/filesystem/fat32/fat32_test.go @@ -1261,6 +1261,29 @@ func Test_Rename(t *testing.T) { dstFile = "new.txt" }, }, + { + name: "rename a non empty directory", + hasError: false, + pre: func(t *testing.T, fs *fat32.FileSystem) { + fs.Mkdir(filepath.Join(workingPath, srcFile)) + // create file in directory which is going to be moved + createFile(t, fs, filepath.Join(srcFile, "/test.txt"), "FooBar") + }, + post: func(t *testing.T, fs *fat32.FileSystem) { + _, err := fs.ReadDir(filepath.Join(workingPath, srcFile)) + if err == nil { + t.Fatalf("source directory does exist: %+v", err) + } + _, err = fs.ReadDir(filepath.Join(workingPath, dstFile)) + if err != nil { + t.Fatalf("destination directory does not exist: %+v", err) + } + content := readFile(t, fs, filepath.Join(dstFile, "/test.txt")) + if content != "FooBar" { + t.Fatalf("Content should be '%s', but is '%s'", "FooBar", content) + } + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { From 737ccd7cf44bf11af7cc5d657bf73c9f94ab5de2 Mon Sep 17 00:00:00 2001 From: Ludwig Date: Sun, 17 Nov 2024 11:31:45 +0100 Subject: [PATCH 5/7] remove nolint comment --- filesystem/fat32/fat32.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/filesystem/fat32/fat32.go b/filesystem/fat32/fat32.go index 2d3947c2..5c17bffa 100644 --- a/filesystem/fat32/fat32.go +++ b/filesystem/fat32/fat32.go @@ -638,8 +638,6 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) { } // removes the named file or (empty) directory. -// -//nolint:revive // parameters will be used eventually func (fs *FileSystem) Remove(pathname string) error { // get the path dir := path.Dir(pathname) From a3bfd1ea68f6db6e6680478e69cfb558b1943789 Mon Sep 17 00:00:00 2001 From: Ludwig Date: Sun, 17 Nov 2024 16:38:10 +0100 Subject: [PATCH 6/7] fix: linter findings --- filesystem/fat32/directory.go | 27 ++++++--------------------- filesystem/fat32/fat32_test.go | 24 +++++++++++++++--------- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/filesystem/fat32/directory.go b/filesystem/fat32/directory.go index 7c37921b..2996ae28 100644 --- a/filesystem/fat32/directory.go +++ b/filesystem/fat32/directory.go @@ -73,19 +73,11 @@ func (d *Directory) createEntry(name string, cluster uint32, dir bool) (*directo // removeEntry removes an entry in the given directory func (d *Directory) removeEntry(name string) error { - // is it a long filename or a short filename? - var isLFN bool - // TODO: convertLfnSfn does not calculate if the short name conflicts and thus should increment the last character - // that should happen here, once we can look in the directory entry - _, _, isLFN, _ = convertLfnSfn(name) - lfn := "" - if isLFN { - lfn = name - } + // TODO implement check for long/short filename after increment of sfn is correctly implemented removeEntryIndex := -1 for i, entry := range d.entries { - if entry.filenameLong == lfn { // || entry.filenameShort == shortName do not compare SFN, since it is not incremented correctly + if entry.filenameLong == name { // || entry.filenameShort == shortName do not compare SFN, since it is not incremented correctly removeEntryIndex = i } } @@ -102,23 +94,16 @@ func (d *Directory) removeEntry(name string) error { // renameEntry renames an entry in the given directory, and returns the handle to it func (d *Directory) renameEntry(oldFileName, newFileName string) error { - // is it a long filename or a short filename? - var isLFN bool - // TODO: convertLfnSfn does not calculate if the short name conflicts and thus should increment the last character - // that should happen here, once we can look in the directory entry - _, _, isLFN, _ = convertLfnSfn(oldFileName) - lfn := "" - if isLFN { - lfn = oldFileName - } + // TODO implement check for long/short filename after increment of sfn is correctly implemented - var newEntries []*directoryEntry + newEntries := make([]*directoryEntry, 0, len(d.entries)) var isReplaced = false for _, entry := range d.entries { if entry.filenameLong == newFileName { continue // skip adding already existing file, will be overwritten } - if entry.filenameLong == lfn { // || entry.filenameShort == shortName do not compare SFN, since it is not incremented correctly + if entry.filenameLong == oldFileName { // || entry.filenameShort == shortName do not compare SFN, since it is not incremented correctly + var lfn string shortName, extension, isLFN, _ := convertLfnSfn(newFileName) if isLFN { lfn = newFileName diff --git a/filesystem/fat32/fat32_test.go b/filesystem/fat32/fat32_test.go index f2cca794..426812ce 100644 --- a/filesystem/fat32/fat32_test.go +++ b/filesystem/fat32/fat32_test.go @@ -1150,6 +1150,7 @@ func Test_Rename(t *testing.T) { srcFile := "old.txt" dstFile := "new.txt" createFile := func(t *testing.T, fs *fat32.FileSystem, name, content string) { + t.Helper() origFile, err := fs.OpenFile(filepath.Join(workingPath, name), os.O_CREATE|os.O_RDWR) if err != nil { t.Fatalf("Could not create file %s: %+v", name, err) @@ -1162,6 +1163,7 @@ func Test_Rename(t *testing.T) { } } readFile := func(t *testing.T, fs *fat32.FileSystem, name string) string { + t.Helper() file, err := fs.OpenFile(filepath.Join(workingPath, name), os.O_RDONLY) if err != nil { t.Fatalf("file %s does not exist: %+v", name, err) @@ -1184,10 +1186,11 @@ func Test_Rename(t *testing.T) { name: "simple renaming works without errors", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() createFile(t, fs, srcFile, "FooBar") }, post: func(t *testing.T, fs *fat32.FileSystem) { - //check if original file is there -> should not be the case + // check if original file is there -> should not be the case origFile, err := fs.OpenFile(srcFile, os.O_RDONLY) if err == nil { defer origFile.Close() @@ -1205,7 +1208,7 @@ func Test_Rename(t *testing.T) { hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { createFile(t, fs, srcFile, "FooBar") - //create destination file + // create destination file createFile(t, fs, dstFile, "This should be overwritten") }, post: func(t *testing.T, fs *fat32.FileSystem) { @@ -1224,10 +1227,10 @@ func Test_Rename(t *testing.T) { { name: "source file does not exist", hasError: true, - pre: func(t *testing.T, fs *fat32.FileSystem) { + pre: func(_ *testing.T, fs *fat32.FileSystem) { // do not create orig file }, - post: func(t *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, fs *fat32.FileSystem) { }, }, @@ -1242,7 +1245,7 @@ func Test_Rename(t *testing.T) { srcFile = s createFile(t, fs, s, "orig") }, - post: func(t *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, fs *fat32.FileSystem) { srcFile = "old.txt" }, }, @@ -1265,9 +1268,12 @@ func Test_Rename(t *testing.T) { name: "rename a non empty directory", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { - fs.Mkdir(filepath.Join(workingPath, srcFile)) + err := fs.Mkdir(filepath.Join(workingPath, srcFile)) + if err != nil { + t.Fatalf("Could not create directory %s: %+v", srcFile, err) + } // create file in directory which is going to be moved - createFile(t, fs, filepath.Join(srcFile, "/test.txt"), "FooBar") + createFile(t, fs, filepath.Join(srcFile, "test.txt"), "FooBar") }, post: func(t *testing.T, fs *fat32.FileSystem) { _, err := fs.ReadDir(filepath.Join(workingPath, srcFile)) @@ -1278,7 +1284,7 @@ func Test_Rename(t *testing.T) { if err != nil { t.Fatalf("destination directory does not exist: %+v", err) } - content := readFile(t, fs, filepath.Join(dstFile, "/test.txt")) + content := readFile(t, fs, filepath.Join(dstFile, "test.txt")) if content != "FooBar" { t.Fatalf("Content should be '%s', but is '%s'", "FooBar", content) } @@ -1358,7 +1364,7 @@ func Test_Remove(t *testing.T) { createFile(t, fs, fileToRemove, "FooBar") }, post: func(t *testing.T, fs *fat32.FileSystem) { - //check if original file is there -> should not be the case + // check if original file is there -> should not be the case origFile, err := fs.OpenFile(fileToRemove, os.O_RDONLY) if err == nil { defer origFile.Close() From 9e1a13c21ca5734a3f766f685e288419fa24bc53 Mon Sep 17 00:00:00 2001 From: Ludwig Date: Sun, 17 Nov 2024 16:44:07 +0100 Subject: [PATCH 7/7] fix: linter findings --- filesystem/fat32/fat32_test.go | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/filesystem/fat32/fat32_test.go b/filesystem/fat32/fat32_test.go index 426812ce..70e822f8 100644 --- a/filesystem/fat32/fat32_test.go +++ b/filesystem/fat32/fat32_test.go @@ -1189,7 +1189,7 @@ func Test_Rename(t *testing.T) { t.Helper() createFile(t, fs, srcFile, "FooBar") }, - post: func(t *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, fs *fat32.FileSystem) { // check if original file is there -> should not be the case origFile, err := fs.OpenFile(srcFile, os.O_RDONLY) if err == nil { @@ -1206,12 +1206,12 @@ func Test_Rename(t *testing.T) { { name: "destination file already exists and gets overwritten", hasError: false, - pre: func(t *testing.T, fs *fat32.FileSystem) { + pre: func(_ *testing.T, fs *fat32.FileSystem) { createFile(t, fs, srcFile, "FooBar") // create destination file createFile(t, fs, dstFile, "This should be overwritten") }, - post: func(t *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, fs *fat32.FileSystem) { origFile, err := fs.OpenFile(filepath.Join(workingPath, srcFile), os.O_RDONLY) if err == nil { defer origFile.Close() @@ -1227,10 +1227,10 @@ func Test_Rename(t *testing.T) { { name: "source file does not exist", hasError: true, - pre: func(_ *testing.T, fs *fat32.FileSystem) { + pre: func(_ *testing.T, _ *fat32.FileSystem) { // do not create orig file }, - post: func(_ *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, _ *fat32.FileSystem) { }, }, @@ -1238,6 +1238,7 @@ func Test_Rename(t *testing.T) { name: "renaming long file to short file", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() var s string for i := 0; i < 255; i++ { s += "a" @@ -1245,7 +1246,7 @@ func Test_Rename(t *testing.T) { srcFile = s createFile(t, fs, s, "orig") }, - post: func(_ *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, _ *fat32.FileSystem) { srcFile = "old.txt" }, }, @@ -1253,6 +1254,7 @@ func Test_Rename(t *testing.T) { name: "renaming short file to long file", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() var s string for i := 0; i < 255; i++ { s += "a" @@ -1260,7 +1262,7 @@ func Test_Rename(t *testing.T) { dstFile = s createFile(t, fs, srcFile, "orig") }, - post: func(t *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, _ *fat32.FileSystem) { dstFile = "new.txt" }, }, @@ -1268,6 +1270,7 @@ func Test_Rename(t *testing.T) { name: "rename a non empty directory", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() err := fs.Mkdir(filepath.Join(workingPath, srcFile)) if err != nil { t.Fatalf("Could not create directory %s: %+v", srcFile, err) @@ -1276,6 +1279,7 @@ func Test_Rename(t *testing.T) { createFile(t, fs, filepath.Join(srcFile, "test.txt"), "FooBar") }, post: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() _, err := fs.ReadDir(filepath.Join(workingPath, srcFile)) if err == nil { t.Fatalf("source directory does exist: %+v", err) @@ -1339,6 +1343,7 @@ func Test_Remove(t *testing.T) { workingPath := "/" fileToRemove := "fileToRemove.txt" createFile := func(t *testing.T, fs *fat32.FileSystem, name, content string) { + t.Helper() origFile, err := fs.OpenFile(filepath.Join(workingPath, name), os.O_CREATE|os.O_RDWR) if err != nil { t.Fatalf("Could not create file %s: %+v", name, err) @@ -1361,9 +1366,11 @@ func Test_Remove(t *testing.T) { name: "simple remove works without", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() createFile(t, fs, fileToRemove, "FooBar") }, post: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() // check if original file is there -> should not be the case origFile, err := fs.OpenFile(fileToRemove, os.O_RDONLY) if err == nil { @@ -1376,10 +1383,10 @@ func Test_Remove(t *testing.T) { name: "file to remove does not exist", hasError: true, errorMsg: "target file /fileToRemove.txt does not exist", - pre: func(t *testing.T, fs *fat32.FileSystem) { + pre: func(_ *testing.T, _ *fat32.FileSystem) { // do not create any file }, - post: func(t *testing.T, fs *fat32.FileSystem) { + post: func(_ *testing.T, _ *fat32.FileSystem) { }, }, @@ -1387,6 +1394,7 @@ func Test_Remove(t *testing.T) { name: "removing multiple files", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() var s string for i := 0; i < 10240; i++ { s += "this is a big file\n" @@ -1400,6 +1408,7 @@ func Test_Remove(t *testing.T) { } }, post: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() for i := 0; i < 100; i++ { err := fs.Remove(fmt.Sprintf("/file%d.txt", i)) if err != nil { @@ -1412,11 +1421,13 @@ func Test_Remove(t *testing.T) { name: "removing empty dir", hasError: false, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() if err := fs.Mkdir(filepath.Join(workingPath, fileToRemove)); err != nil { t.Fatalf("could not create test directory: %+v", err) } }, post: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() _, err := fs.ReadDir(filepath.Join(workingPath, fileToRemove)) if err == nil { t.Fatalf("Expected that dir cannot be read, but is still there") @@ -1427,6 +1438,7 @@ func Test_Remove(t *testing.T) { name: "cannot delete dir with content", hasError: true, pre: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() if err := fs.Mkdir(filepath.Join(workingPath, fileToRemove)); err != nil { t.Fatalf("could not create test directory: %+v", err) } @@ -1434,6 +1446,7 @@ func Test_Remove(t *testing.T) { createFile(t, fs, filepath.Join(workingPath, fileToRemove, "test"), "foo") }, post: func(t *testing.T, fs *fat32.FileSystem) { + t.Helper() _, err := fs.ReadDir(filepath.Join(workingPath, fileToRemove)) if err != nil { t.Fatalf("Expected that dir can be read, but has error: %+v", err)