github.com/snyk/vervet/v4@v4.27.2/internal/files/copy.go (about)

     1  package files
     2  
     3  import (
     4  	"io"
     5  	"io/fs"
     6  	"os"
     7  	"path/filepath"
     8  )
     9  
    10  // CopyItem copies a file or directory from src to dst.
    11  func CopyItem(dst, src string, force bool) error {
    12  	if st, err := os.Stat(src); err == nil && st.IsDir() {
    13  		return CopyDir(dst, src, force)
    14  	} else if err == nil {
    15  		return CopyFile(dst, src, force)
    16  	} else {
    17  		return err
    18  	}
    19  }
    20  
    21  // CopyDir recursively copies a directory from src to dst.
    22  func CopyDir(dst, src string, force bool) error {
    23  	return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error {
    24  		if err != nil {
    25  			return nil
    26  		}
    27  		name, err := filepath.Rel(src, path)
    28  		if err != nil {
    29  			return err
    30  		}
    31  		if d.IsDir() {
    32  			return nil
    33  		}
    34  		return CopyFile(filepath.Join(dst, name), path, force)
    35  	})
    36  }
    37  
    38  // CopyFile copies a file from src to dst. If there are missing directories in
    39  // dst, they are created.
    40  func CopyFile(dst, src string, force bool) error {
    41  	srcf, err := os.Open(src)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	defer srcf.Close()
    46  	flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC
    47  	if !force {
    48  		flags = flags | os.O_EXCL
    49  	}
    50  
    51  	dstDir := filepath.Dir(dst)
    52  	if dstDir != "." {
    53  		err = os.MkdirAll(dstDir, 0777) // leave it to umask
    54  		if err != nil {
    55  			return err
    56  		}
    57  	}
    58  
    59  	dstf, err := os.OpenFile(dst, flags, 0666) // leave it to umask
    60  	if err != nil {
    61  		return err
    62  	}
    63  	defer dstf.Close()
    64  
    65  	_, err = io.Copy(dstf, srcf)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	return nil
    70  }