pkg.re/essentialkaos/ek@v12.36.0+incompatible/fsutil/helpers.go (about)

     1  // +build !windows
     2  
     3  package fsutil
     4  
     5  // ////////////////////////////////////////////////////////////////////////////////// //
     6  //                                                                                    //
     7  //                         Copyright (c) 2021 ESSENTIAL KAOS                          //
     8  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
     9  //                                                                                    //
    10  // ////////////////////////////////////////////////////////////////////////////////// //
    11  
    12  import (
    13  	"bufio"
    14  	"errors"
    15  	"io"
    16  	"os"
    17  	"path"
    18  )
    19  
    20  // ////////////////////////////////////////////////////////////////////////////////// //
    21  
    22  var _disableCopyFileChecks bool // Flag for testing purposes only
    23  var _disableMoveFileChecks bool // Flag for testing purposes only
    24  var _disableCopyDirChecks bool  // Flag for testing purposes only
    25  
    26  // ////////////////////////////////////////////////////////////////////////////////// //
    27  
    28  // CopyFile copies file using bufio
    29  func CopyFile(from, to string, perms ...os.FileMode) error {
    30  	var targetExist = IsExist(to)
    31  
    32  	if !_disableCopyFileChecks {
    33  		dir := path.Dir(to)
    34  
    35  		switch {
    36  		case from == "":
    37  			return errors.New("Source file can't be blank")
    38  		case to == "":
    39  			return errors.New("Target file can't be blank")
    40  
    41  		case !IsExist(from):
    42  			return errors.New("File " + from + " does not exists")
    43  		case !IsRegular(from):
    44  			return errors.New("File " + from + " is not a regular file")
    45  		case !IsReadable(from):
    46  			return errors.New("File " + from + " is not readable")
    47  
    48  		case !targetExist && !IsExist(dir):
    49  			return errors.New("Directory " + dir + " does not exists")
    50  		case !targetExist && !IsWritable(dir):
    51  			return errors.New("Directory " + dir + " is not writable")
    52  
    53  		case targetExist && !IsWritable(to):
    54  			return errors.New("Target file " + to + " is not writable")
    55  		case targetExist && !IsRegular(to):
    56  			return errors.New("Target is not a file")
    57  		}
    58  	}
    59  
    60  	return copyFile(from, to, perms)
    61  }
    62  
    63  // MoveFile moves file
    64  func MoveFile(from, to string, perms ...os.FileMode) error {
    65  	if !_disableMoveFileChecks {
    66  		targetExist := IsExist(to)
    67  		dir := path.Dir(to)
    68  
    69  		switch {
    70  		case from == "":
    71  			return errors.New("Source file can't be blank")
    72  		case to == "":
    73  			return errors.New("Target file can't be blank")
    74  
    75  		case !IsExist(from):
    76  			return errors.New("File " + from + " does not exists")
    77  		case !IsRegular(from):
    78  			return errors.New("File " + from + " is not a regular file")
    79  		case !IsReadable(from):
    80  			return errors.New("File " + from + " is not readable")
    81  
    82  		case !targetExist && !IsExist(dir):
    83  			return errors.New("Directory " + dir + " does not exists")
    84  		case !targetExist && !IsWritable(dir):
    85  			return errors.New("Directory " + dir + " is not writable")
    86  		}
    87  	}
    88  
    89  	return moveFile(from, to, perms)
    90  }
    91  
    92  // CopyDir copies directory content recursively to target directory
    93  func CopyDir(from, to string) error {
    94  	if !_disableCopyDirChecks {
    95  		switch {
    96  		case from == "":
    97  			return errors.New("Source directory can't be blank")
    98  		case to == "":
    99  			return errors.New("Target directory can't be blank")
   100  
   101  		case !IsExist(from):
   102  			return errors.New("Directory " + from + " does not exists")
   103  		case !IsDir(from):
   104  			return errors.New("Target " + from + " is not a directory")
   105  		case !IsReadable(from):
   106  			return errors.New("Directory " + from + " is not readable")
   107  		case IsExist(to) && !IsDir(to):
   108  			return errors.New("Target " + to + " is not a directory")
   109  		case IsExist(to) && !IsWritable(to):
   110  			return errors.New("Directory " + to + " is not writable")
   111  		}
   112  	}
   113  
   114  	if !IsExist(to) {
   115  		err := os.Mkdir(to, GetMode(from))
   116  
   117  		if err != nil {
   118  			return err
   119  		}
   120  	}
   121  
   122  	return copyDir(from, to)
   123  }
   124  
   125  // TouchFile creates empty file
   126  func TouchFile(path string, perm os.FileMode) error {
   127  	fd, err := os.OpenFile(path, os.O_CREATE, perm)
   128  
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	return fd.Close()
   134  }
   135  
   136  // ////////////////////////////////////////////////////////////////////////////////// //
   137  
   138  func copyFile(from, to string, perms []os.FileMode) error {
   139  	var targetExist bool
   140  	var perm os.FileMode
   141  
   142  	if IsExist(to) {
   143  		targetExist = true
   144  	}
   145  
   146  	if len(perms) == 0 {
   147  		perm = GetMode(from)
   148  	} else {
   149  		perm = perms[0]
   150  	}
   151  
   152  	ffd, err := os.OpenFile(from, os.O_RDONLY, 0)
   153  
   154  	if err != nil {
   155  		return err
   156  	}
   157  
   158  	defer ffd.Close()
   159  
   160  	tfd, err := os.OpenFile(to, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, perm)
   161  
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	defer tfd.Close()
   167  
   168  	reader := bufio.NewReader(ffd)
   169  
   170  	_, err = io.Copy(tfd, reader)
   171  
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	if targetExist {
   177  		return os.Chmod(to, perm)
   178  	}
   179  
   180  	return nil
   181  }
   182  
   183  func moveFile(from, to string, perms []os.FileMode) error {
   184  	err := os.Rename(from, to)
   185  
   186  	if err != nil {
   187  		return err
   188  	}
   189  
   190  	if len(perms) == 0 {
   191  		return nil
   192  	}
   193  
   194  	return os.Chmod(to, perms[0])
   195  }
   196  
   197  func copyDir(from, to string) error {
   198  	var err error
   199  
   200  	for _, target := range List(from, false) {
   201  		fp := from + "/" + target
   202  		tp := to + "/" + target
   203  
   204  		if IsDir(fp) {
   205  			err = os.Mkdir(tp, GetMode(fp))
   206  
   207  			if err != nil {
   208  				return err
   209  			}
   210  
   211  			err = copyDir(fp, tp)
   212  
   213  			if err != nil {
   214  				return err
   215  			}
   216  		} else {
   217  			err = CopyFile(fp, tp)
   218  
   219  			if err != nil {
   220  				return err
   221  			}
   222  		}
   223  	}
   224  
   225  	return nil
   226  }