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 }