github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/util/fs/helper.go (about) 1 // Copyright (c) 2018, Sylabs Inc. All rights reserved. 2 // This software is licensed under a 3-clause BSD license. Please consult the 3 // LICENSE.md file distributed with the sources of this project regarding your 4 // rights to use or distribute this software. 5 6 package fs 7 8 import ( 9 "os" 10 "path/filepath" 11 "strings" 12 "syscall" 13 ) 14 15 // IsFile check if name component is regular file 16 func IsFile(name string) bool { 17 info, err := os.Stat(name) 18 if err != nil { 19 return false 20 } 21 return info.Mode().IsRegular() 22 } 23 24 // IsDir check if name component is a directory 25 func IsDir(name string) bool { 26 info, err := os.Stat(name) 27 if err != nil { 28 return false 29 } 30 return info.Mode().IsDir() 31 } 32 33 // IsLink check if name component is a symlink 34 func IsLink(name string) bool { 35 info, err := os.Lstat(name) 36 if err != nil { 37 return false 38 } 39 return (info.Mode()&os.ModeSymlink != 0) 40 } 41 42 // IsOwner check if name component is owned by user identified with uid 43 func IsOwner(name string, uid uint32) bool { 44 info, err := os.Stat(name) 45 if err != nil { 46 return false 47 } 48 return (info.Sys().(*syscall.Stat_t).Uid == uid) 49 } 50 51 // IsExec check if name component has executable bit permission set 52 func IsExec(name string) bool { 53 info, err := os.Stat(name) 54 if err != nil { 55 return false 56 } 57 return (info.Sys().(*syscall.Stat_t).Mode&syscall.S_IXUSR != 0) 58 } 59 60 // IsSuid check if name component has setuid bit permission set 61 func IsSuid(name string) bool { 62 info, err := os.Stat(name) 63 if err != nil { 64 return false 65 } 66 return (info.Sys().(*syscall.Stat_t).Mode&syscall.S_ISUID != 0) 67 } 68 69 // MkdirAll creates a directory and parents if it doesn't exist with 70 // mode after umask reset 71 func MkdirAll(path string, mode os.FileMode) error { 72 oldmask := syscall.Umask(0) 73 defer syscall.Umask(oldmask) 74 75 return os.MkdirAll(path, mode) 76 } 77 78 // Mkdir creates a directory if it doesn't exist with 79 // mode after umask reset 80 func Mkdir(path string, mode os.FileMode) error { 81 oldmask := syscall.Umask(0) 82 defer syscall.Umask(oldmask) 83 84 return os.Mkdir(path, mode) 85 } 86 87 // RootDir returns the root directory of path (rootdir of /my/path is /my). 88 // Returns "." if path is empty 89 func RootDir(path string) string { 90 if path == "" { 91 return "." 92 } 93 94 p := filepath.Clean(path) 95 iter := filepath.Dir(p) 96 for iter != "/" && iter != "." { 97 p = iter 98 iter = filepath.Dir(p) 99 } 100 101 return p 102 } 103 104 // EvalRelative evaluates symlinks in path relative to root path. This 105 // function doesn't return error but always returns an evaluated path 106 func EvalRelative(path string, root string) string { 107 splitted := strings.Split(filepath.Clean(path), string(os.PathSeparator)) 108 dest := string(os.PathSeparator) 109 110 for i := 1; i < len(splitted); i++ { 111 s := splitted[i : i+1][0] 112 dest = filepath.Join(dest, s) 113 114 if s != "" { 115 rootDestPath := filepath.Join(root, dest) 116 for { 117 target, err := filepath.EvalSymlinks(rootDestPath) 118 if err != nil { 119 break 120 } 121 if !strings.HasPrefix(target, root) { 122 rootDestPath = filepath.Join(root, target) 123 continue 124 } 125 dest = strings.Replace(target, root, "", 1) 126 break 127 } 128 } 129 } 130 131 return dest 132 } 133 134 // Touch behaves like touch command. 135 func Touch(path string) error { 136 f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644) 137 if err != nil { 138 return err 139 } 140 f.Close() 141 return nil 142 }