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