github.com/rumpl/bof@v23.0.0-rc.2+incompatible/pkg/directory/directory_unix.go (about) 1 //go:build linux || freebsd || darwin 2 // +build linux freebsd darwin 3 4 package directory // import "github.com/docker/docker/pkg/directory" 5 6 import ( 7 "context" 8 "os" 9 "path/filepath" 10 "syscall" 11 ) 12 13 // calcSize walks a directory tree and returns its total size in bytes. 14 func calcSize(ctx context.Context, dir string) (int64, error) { 15 var size int64 16 data := make(map[uint64]struct{}) 17 err := filepath.Walk(dir, func(d string, fileInfo os.FileInfo, err error) error { 18 if err != nil { 19 // if dir/x disappeared while walking, Size() ignores dir/x. 20 // if dir does not exist, Size() returns the error. 21 if d != dir && os.IsNotExist(err) { 22 return nil 23 } 24 return err 25 } 26 select { 27 case <-ctx.Done(): 28 return ctx.Err() 29 default: 30 } 31 32 // Ignore directory sizes 33 if fileInfo == nil { 34 return nil 35 } 36 37 s := fileInfo.Size() 38 if fileInfo.IsDir() || s == 0 { 39 return nil 40 } 41 42 // Check inode to handle hard links correctly 43 inode := fileInfo.Sys().(*syscall.Stat_t).Ino 44 //nolint:unconvert // inode is not an uint64 on all platforms. 45 if _, exists := data[uint64(inode)]; exists { 46 return nil 47 } 48 49 data[uint64(inode)] = struct{}{} //nolint:unconvert // inode is not an uint64 on all platforms. 50 51 size += s 52 53 return nil 54 }) 55 return size, err 56 }