diff --git a/common/platform/filesystem/file.go b/common/platform/filesystem/file.go index e4fe2a9a..ebe9b0f1 100644 --- a/common/platform/filesystem/file.go +++ b/common/platform/filesystem/file.go @@ -1,9 +1,12 @@ +//go:build !windows && !wasm + package filesystem import ( "io" "os" "path/filepath" + "syscall" "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/platform" @@ -16,6 +19,29 @@ var NewFileReader FileReaderFunc = func(path string) (io.ReadCloser, error) { } func ReadFile(path string) ([]byte, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + stat, err := file.Stat() + if err != nil { + return nil, err + } + + size := stat.Size() + if size == 0 { + return []byte{}, nil + } + + // use mmap to save RAM + bs, err := syscall.Mmap(int(file.Fd()), 0, int(size), syscall.PROT_READ, syscall.MAP_SHARED) + if err == nil { + return bs, nil + } + + // fallback reader, err := NewFileReader(path) if err != nil { return nil, err diff --git a/common/platform/filesystem/file_other.go b/common/platform/filesystem/file_other.go new file mode 100644 index 00000000..d3cbdcc7 --- /dev/null +++ b/common/platform/filesystem/file_other.go @@ -0,0 +1,54 @@ +//go:build windows || wasm + +package filesystem + +import ( + "io" + "os" + "path/filepath" + + "github.com/xtls/xray-core/common/buf" + "github.com/xtls/xray-core/common/platform" +) + +type FileReaderFunc func(path string) (io.ReadCloser, error) + +var NewFileReader FileReaderFunc = func(path string) (io.ReadCloser, error) { + return os.Open(path) +} + +func ReadFile(path string) ([]byte, error) { + reader, err := NewFileReader(path) + if err != nil { + return nil, err + } + defer reader.Close() + + return buf.ReadAllToBytes(reader) +} + +func ReadAsset(file string) ([]byte, error) { + return ReadFile(platform.GetAssetLocation(file)) +} + +func ReadCert(file string) ([]byte, error) { + if filepath.IsAbs(file) { + return ReadFile(file) + } + return ReadFile(platform.GetCertLocation(file)) +} + +func CopyFile(dst string, src string) error { + bytes, err := ReadFile(src) + if err != nil { + return err + } + f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0o644) + if err != nil { + return err + } + defer f.Close() + + _, err = f.Write(bytes) + return err +}