github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/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 // Size walks a directory tree and returns its total size in bytes. 14 func Size(ctx context.Context, dir string) (size int64, err error) { 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 does not exist, Size() returns the error. 19 // if dir/x disappeared while walking, Size() ignores dir/x. 20 if os.IsNotExist(err) && d != dir { 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 // inode is not a uint64 on all platforms. Cast it to avoid issues. 44 if _, exists := data[inode]; exists { 45 return nil 46 } 47 // inode is not a uint64 on all platforms. Cast it to avoid issues. 48 data[inode] = struct{}{} 49 50 size += s 51 52 return nil 53 }) 54 return 55 }