-
Notifications
You must be signed in to change notification settings - Fork 0
/
fsutil.go
152 lines (131 loc) · 3.55 KB
/
fsutil.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
143
144
145
146
147
148
149
150
151
152
package fsutil
import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"time"
)
var (
isNotExist = os.IsNotExist
abs = filepath.Abs
rel = filepath.Rel
errFileSysInfoIsNil = errors.New("file sys info is nil")
)
// StatFunc the function prototype of os.Stat
type StatFunc func(name string) (fs.FileInfo, error)
// GetFileTimeFunc the function prototype of GetFileTime
type GetFileTimeFunc func(path string) (cTime time.Time, aTime time.Time, mTime time.Time, err error)
// IsDirFunc the function prototype of IsDir
type IsDirFunc func(path string) (bool, error)
// FileExist is file Exist
func FileExist(path string) (exist bool, err error) {
_, err = os.Stat(path)
if err != nil && isNotExist(err) {
return false, nil
}
if err != nil {
return false, err
}
return true, nil
}
// CreateFile create a file without truncate
func CreateFile(name string) (*os.File, error) {
return os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666)
}
// OpenRWFile open a file with read write mode
func OpenRWFile(name string) (*os.File, error) {
return os.OpenFile(name, os.O_RDWR, 0666)
}
// IsDir the path is directory or not
func IsDir(path string) (bool, error) {
f, err := os.Stat(path)
if err != nil {
return false, err
}
return f.IsDir(), nil
}
// IsEOF whether the error is io.EOF
func IsEOF(err error) bool {
return err != nil && errors.Is(err, io.EOF)
}
// IsNonEOF whether the error is not io.EOF and is not nil
func IsNonEOF(err error) bool {
return err != nil && !errors.Is(err, io.EOF)
}
// GetFileTime get the creation time, last access time, last modify time of the path
func GetFileTime(path string) (cTime time.Time, aTime time.Time, mTime time.Time, err error) {
stat, err := os.Lstat(path)
if err != nil {
return
}
return GetFileTimeBySys(stat.Sys())
}
// IsSub whether it is a subdirectory of the parent
func IsSub(parent, child string) (bool, error) {
pAbs, err := abs(parent)
if err != nil {
return false, err
}
cAbs, err := abs(child)
if err != nil {
return false, err
}
relPath, err := rel(pAbs, cAbs)
if err != nil {
return false, err
}
relPath = filepath.ToSlash(relPath)
return relPath != ".." && !strings.HasPrefix(relPath, "../"), nil
}
// SafePath encode some special characters for the path like "?", "#" etc.
func SafePath(path string) string {
if len(path) == 0 {
return path
}
filterRule := []struct {
old string
new string
}{
{"%", "%25"}, // stay in the first position
{"?", "%3F"},
{"#", "%23"},
}
for _, r := range filterRule {
path = strings.ReplaceAll(path, r.old, r.new)
}
return path
}
// IsSymlink the path is a symbolic link or not
func IsSymlink(path string) (bool, error) {
fi, err := os.Lstat(path)
if err != nil {
return false, err
}
return IsSymlinkMode(fi.Mode()), nil
}
// IsSymlinkMode check the mode is a symbolic link or not
func IsSymlinkMode(mode fs.FileMode) bool {
return mode&fs.ModeSymlink != 0
}
// IsSymlinkSupported checks if the system supports symbolic links
func IsSymlinkSupported() bool {
symlink := filepath.Join(os.TempDir(), fmt.Sprintf("%d.symlink_detect", time.Now().UnixNano()))
defer os.RemoveAll(symlink)
return Symlink(os.Args[0], symlink) == nil
}
// Symlink create a symbolic link
func Symlink(oldname, newname string) error {
return os.Symlink(oldname, newname)
}
// Readlink returns the destination of the named symbolic link
func Readlink(name string) (string, error) {
return os.Readlink(name)
}
// SymlinkText build custom symlink text content
func SymlinkText(realPath string) string {
return fmt.Sprintf("# symlink\n%s", realPath)
}