I have a program that is finding the larges files on a filesystem within the same directory. If I call FileDisplay.Delete
function and then re-run GetTopXFiles
on the directory, it returns files that had been deleted. Using ls while the program is still running, I can see that the files is no longer there. Interestingly, if I fallocate -l 251.2M file100
I can see my newly created file as being the largest file. If I then remove it using rm or the program, re-run the GetTopXFiles
it still returns. If I restart the program it recognizes the file is gone.
package fileFinder
import (
"fmt"
"io"
"io/fs"
"log"
"os"
"sort"
"sync"
"github.com/google/fscrypt/filesystem"
"github.com/sirupsen/logrus"
)
var device string
type fileDisplay struct {
sync.RWMutex
Files []FileDisplay
}
var files fileDisplay
type FileDisplay struct {
Size int64 `json:"size"`
Path string `json:"path"`
}
type bySize []FileDisplay
func (a bySize) Len() int { return len(a) }
func (a bySize) Less(i, j int) bool { return a[i].Size < a[j].Size }
func (a bySize) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func GetTopXFiles(mountpoint string, limit int) ([]FileDisplay, error) {
log.SetOutput(io.Discard)
if mountpoint == "" {
return nil, fmt.Errorf("Path cannot be empty")
}
if limit < 1 {
return nil, fmt.Errorf("Limit must be 1 or greater")
}
if mountpoint[len(mountpoint)-1:] != "/" {
mountpoint = mountpoint "/"
}
mount, err := filesystem.FindMount(mountpoint)
if err != nil {
return nil, err
}
device = mount.Device
entries, err := os.ReadDir(mountpoint)
if err != nil {
return nil, err
}
var wg sync.WaitGroup
getFiles(mountpoint, entries, &wg)
wg.Wait()
sort.Sort(bySize(files.Files))
var shortFiles []FileDisplay
if len(files.Files) > limit {
shortFiles = files.Files[len(files.Files)-limit:]
} else {
shortFiles = files.Files
}
return shortFiles, nil
}
func getFiles(start string, entries []fs.DirEntry, wg *sync.WaitGroup) {
for _, entry := range entries {
wg.Add(1)
go handleEntry(start, entry, wg)
}
}
func handleEntry(start string, entry fs.DirEntry, wg *sync.WaitGroup) {
defer wg.Done()
var file FileDisplay
mount, err := filesystem.FindMount(start entry.Name())
if err != nil {
logrus.Errorln(err, start entry.Name())
return
}
if mount.Device == device {
if entry.Type().IsRegular() {
fileInfo, err := os.Stat(start entry.Name())
if err != nil {
logrus.Errorln(err, start entry.Name())
return
}
file.Path = start entry.Name()
file.Size = fileInfo.Size()
files.Append(file)
} else if entry.IsDir() {
entries, err := os.ReadDir(start entry.Name())
if err != nil {
logrus.Errorln(err, start entry.Name())
return
}
logrus.Info("Searching ", start entry.Name())
getFiles(start entry.Name() "/", entries, wg)
}
}
}
func (f *FileDisplay) DisplaySizeIEC() string {
const unit = 1024
b := f.Size
if b < unit {
return fmt.Sprintf("