github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/pkg/directory/directory_unix.go (about)

     1  // +build linux freebsd
     2  
     3  package directory
     4  
     5  import (
     6  	"os"
     7  	"path/filepath"
     8  	"syscall"
     9  )
    10  
    11  // Size walks a directory tree and returns its total size in bytes.
    12  func Size(dir string) (size int64, err error) {
    13  	data := make(map[uint64]struct{})
    14  	err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, err error) error {
    15  		if err != nil {
    16  			// if dir does not exist, Size() returns the error.
    17  			// if dir/x disappeared while walking, Size() ignores dir/x.
    18  			if os.IsNotExist(err) && d != dir {
    19  				return nil
    20  			}
    21  			return err
    22  		}
    23  
    24  		// Ignore directory sizes
    25  		if fileInfo == nil {
    26  			return nil
    27  		}
    28  
    29  		s := fileInfo.Size()
    30  		if fileInfo.IsDir() || s == 0 {
    31  			return nil
    32  		}
    33  
    34  		// Check inode to handle hard links correctly
    35  		inode := fileInfo.Sys().(*syscall.Stat_t).Ino
    36  		// inode is not a uint64 on all platforms. Cast it to avoid issues.
    37  		if _, exists := data[inode]; exists {
    38  			return nil
    39  		}
    40  		// inode is not a uint64 on all platforms. Cast it to avoid issues.
    41  		data[inode] = struct{}{}
    42  
    43  		size += s
    44  
    45  		return nil
    46  	})
    47  	return
    48  }