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

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