Files
v2ray_simple/utils/path.go

113 lines
3.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package utils
import (
"errors"
"os"
"path/filepath"
"runtime"
"strings"
)
const (
ProjectName = "v2ray_simple"
ProjectPath = ProjectName + "/"
)
var (
ExtraSearchPath = "" //若给出,则会优先在此路径里查找
)
func FileExist(path string) bool {
_, err := os.Lstat(path)
return !os.IsNotExist(err)
}
func DirExist(dirname string) bool {
fi, err := os.Stat(dirname)
return (err == nil || os.IsExist(err)) && fi.IsDir()
}
//判断一个字符串是否是合法的文件名, 注意本函数不实际检查是否存在该文件
func IsFilePath(s string) error {
//https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names
if runtime.GOOS == "windows" {
if strings.ContainsAny(s, ":<>\"/\\|?*") {
return errors.New("contain illegal characters")
}
if strings.ContainsAny(s, string([]byte{0, 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})) {
return errors.New("contain illegal ASCII control characters")
}
} else {
if strings.Contains(s, string([]byte{0})) {
return errors.New("contain illegal characters")
}
}
return nil
}
// Function that search the specified file in the following directories:
// -1. If starts with '/', or is an empty string, return directly
// 0. If starts with string similar to "C:/", "D:\\", or "e:/", return directly
// 1. Search in ExtraSearchPath
// 2. Same folder with exec file
// 3. Same folder of the source file, 一种可能 是 用于 go test等情况
// 4. Same folder of working folder
func GetFilePath(fileName string) string {
if len(fileName) < 1 {
return ""
}
fb := fileName[0]
if fb == '/' && len(fileName) > 1 {
return fileName
}
if len(fileName) > 3 && (fb >= 'C' && fb <= 'Z' || fb >= 'c' && fb <= 'z') && fileName[1] == ':' && (fileName[2] == '/' || fileName[2] == '\\') {
return fileName
}
if ExtraSearchPath != "" {
p := filepath.Join(filepath.Dir(ExtraSearchPath), fileName)
if _, err := os.Stat(p); err == nil {
return p
}
}
if execFile, err := os.Executable(); err == nil {
p := filepath.Join(filepath.Dir(execFile), fileName)
if _, err := os.Stat(p); err == nil {
return p
}
}
// 下面的 runtime.Caller 查找调用函数对应的源文件所在目录。只适合普通go build的情况如果是release版因为使用了 trimpath参数
// 就找不到源文件的路径了。不过一般使用发布版的人 也不是 git clone的而是直接下载的所以本来也找不到, 所以无所谓。
if _, srcFile, _, ok := runtime.Caller(0); ok {
p := filepath.Join(filepath.Dir(srcFile), fileName)
if _, err := os.Stat(p); err == nil {
return p
}
//有可能是在项目子目录进行 go test的情况此时可以试图在项目根目录寻找
projectRootIdx := strings.Index(p, ProjectPath)
if projectRootIdx >= 0 {
p = p[:projectRootIdx+len(ProjectPath)] + fileName
if _, err := os.Stat(p); err == nil {
return p
}
}
}
if workingDir, err := os.Getwd(); err == nil {
p := filepath.Join(workingDir, fileName)
if _, err := os.Stat(p); err == nil {
return p
}
}
return fileName
}