github.com/stolowski/snapd@v0.0.0-20210407085831-115137ce5a22/osutil/stat.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2014-2015 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package osutil
    21  
    22  import (
    23  	"os"
    24  	"os/exec"
    25  	"syscall"
    26  )
    27  
    28  // FileExists return true if given path can be stat()ed by us. Note that
    29  // it may return false on e.g. permission issues.
    30  func FileExists(path string) bool {
    31  	_, err := os.Stat(path)
    32  	return err == nil
    33  }
    34  
    35  // IsDirectory return true if the given path can be stat()ed by us and
    36  // is a directory. Note that it may return false on e.g. permission issues.
    37  func IsDirectory(path string) bool {
    38  	fileInfo, err := os.Stat(path)
    39  	if err != nil {
    40  		return false
    41  	}
    42  
    43  	return fileInfo.IsDir()
    44  }
    45  
    46  // IsDevice checks if the given os.FileMode coresponds to a device (char/block)
    47  func IsDevice(mode os.FileMode) bool {
    48  	return (mode & (os.ModeDevice | os.ModeCharDevice)) != 0
    49  }
    50  
    51  // IsSymlink returns true if the given file is a symlink
    52  func IsSymlink(path string) bool {
    53  	fileInfo, err := os.Lstat(path)
    54  	if err != nil {
    55  		return false
    56  	}
    57  
    58  	return (fileInfo.Mode() & os.ModeSymlink) != 0
    59  }
    60  
    61  // IsExecutable returns true when given path points to an executable file
    62  func IsExecutable(path string) bool {
    63  	stat, err := os.Stat(path)
    64  	if err != nil {
    65  		return false
    66  	}
    67  	return !stat.IsDir() && (stat.Mode().Perm()&0111 != 0)
    68  }
    69  
    70  // ExecutableExists returns whether there an exists an executable with the given name somewhere on $PATH.
    71  func ExecutableExists(name string) bool {
    72  	_, err := exec.LookPath(name)
    73  
    74  	return err == nil
    75  }
    76  
    77  var lookPath func(name string) (string, error) = exec.LookPath
    78  
    79  // LookPathDefault searches for a given command name in all directories
    80  // listed in the environment variable PATH and returns the found path or the
    81  // provided default path.
    82  func LookPathDefault(name string, defaultPath string) string {
    83  	p, err := lookPath(name)
    84  	if err != nil {
    85  		return defaultPath
    86  	}
    87  	return p
    88  }
    89  
    90  // IsWritable checks if the given file/directory can be written by
    91  // the current user
    92  func IsWritable(path string) bool {
    93  	// from "fcntl.h"
    94  	const W_OK = 2
    95  
    96  	err := syscall.Access(path, W_OK)
    97  	return err == nil
    98  }
    99  
   100  // IsDirNotExist tells you whether the given error is due to a directory not existing.
   101  func IsDirNotExist(err error) bool {
   102  	switch pe := err.(type) {
   103  	case nil:
   104  		return false
   105  	case *os.PathError:
   106  		err = pe.Err
   107  	case *os.LinkError:
   108  		err = pe.Err
   109  	case *os.SyscallError:
   110  		err = pe.Err
   111  	}
   112  
   113  	return err == syscall.ENOTDIR || err == syscall.ENOENT || err == os.ErrNotExist
   114  }
   115  
   116  // DirExists checks whether a given path exists, and if so whether it is a directory.
   117  func DirExists(fn string) (exists bool, isDir bool, err error) {
   118  	st, err := os.Stat(fn)
   119  	if err != nil {
   120  		if IsDirNotExist(err) {
   121  			return false, false, nil
   122  		}
   123  		return false, false, err
   124  	}
   125  	return true, st.IsDir(), nil
   126  }
   127  
   128  // RegularFileExists checks whether a given path exists, and if so whether it is a regular file.
   129  func RegularFileExists(fn string) (exists, isReg bool, err error) {
   130  	fileStat, err := os.Lstat(fn)
   131  	if err != nil {
   132  		return false, false, err
   133  	}
   134  	return true, fileStat.Mode().IsRegular(), nil
   135  }