...

Source file src/golang.conradwood.net/go-easyops/linux/copydir.go

Documentation: golang.conradwood.net/go-easyops/linux

     1  package linux
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"syscall"
    10  )
    11  
    12  func CopyDir(srcDir, dest string) error {
    13  	err := os.MkdirAll(dest, 0777)
    14  	if err != nil {
    15  		return err
    16  	}
    17  	c := copy{permIgnore: true}
    18  	err = c.copyDirInternal(srcDir, dest)
    19  	return err
    20  }
    21  
    22  type copy struct {
    23  	permIgnore bool
    24  }
    25  
    26  func (c *copy) copyDirInternal(srcDir, dest string) error {
    27  	entries, err := ioutil.ReadDir(srcDir)
    28  	if err != nil {
    29  		return err
    30  	}
    31  	for _, entry := range entries {
    32  		sourcePath := filepath.Join(srcDir, entry.Name())
    33  		destPath := filepath.Join(dest, entry.Name())
    34  
    35  		fileInfo, err := os.Stat(sourcePath)
    36  		if err != nil {
    37  			return fmt.Errorf("stat(%s) failed: %s", sourcePath, err)
    38  		}
    39  
    40  		stat, ok := fileInfo.Sys().(*syscall.Stat_t)
    41  		if !ok {
    42  			return fmt.Errorf("failed to get raw syscall.Stat_t data for '%s'", sourcePath)
    43  		}
    44  
    45  		switch fileInfo.Mode() & os.ModeType {
    46  		case os.ModeDir:
    47  			if err := CreateIfNotExists(destPath, 0755); err != nil {
    48  				return err
    49  			}
    50  			if err := c.copyDirInternal(sourcePath, destPath); err != nil {
    51  				return err
    52  			}
    53  		case os.ModeSymlink:
    54  			if err := CopySymLink(sourcePath, destPath); err != nil {
    55  				return err
    56  			}
    57  		default:
    58  			if err := Copy(sourcePath, destPath); err != nil {
    59  				return err
    60  			}
    61  		}
    62  
    63  		// requires root:
    64  		err = os.Lchown(destPath, int(stat.Uid), int(stat.Gid))
    65  		if !c.permIgnore && err != nil {
    66  			return fmt.Errorf("lchown(file=%s,uid=%d,gid=%d) failed: %s", destPath, stat.Uid, stat.Gid, err)
    67  		}
    68  		isSymlink := entry.Mode()&os.ModeSymlink != 0
    69  		if !isSymlink {
    70  			err := os.Chmod(destPath, entry.Mode())
    71  			if !c.permIgnore && err != nil {
    72  				return fmt.Errorf("chmod(%s) failed: %s", destPath, err)
    73  			}
    74  		}
    75  	}
    76  	return nil
    77  }
    78  
    79  func Copy(srcFile, dstFile string) error {
    80  	out, err := os.Create(dstFile)
    81  	if err != nil {
    82  		return fmt.Errorf("failed to create(%s): %s", dstFile, err)
    83  	}
    84  
    85  	defer out.Close()
    86  
    87  	in, err := os.Open(srcFile)
    88  	if err != nil {
    89  		return fmt.Errorf("failed to open(%s): %s", srcFile, err)
    90  	}
    91  	defer in.Close()
    92  
    93  	_, err = io.Copy(out, in)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	return nil
    99  }
   100  
   101  func Exists(filePath string) bool {
   102  	if _, err := os.Stat(filePath); os.IsNotExist(err) {
   103  		return false
   104  	}
   105  
   106  	return true
   107  }
   108  
   109  func CreateIfNotExists(dir string, perm os.FileMode) error {
   110  	if Exists(dir) {
   111  		return nil
   112  	}
   113  
   114  	if err := os.MkdirAll(dir, perm); err != nil {
   115  		return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error())
   116  	}
   117  
   118  	return nil
   119  }
   120  
   121  func CopySymLink(source, dest string) error {
   122  	link, err := os.Readlink(source)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	return os.Symlink(link, dest)
   127  }
   128  

View as plain text