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