Files
sing-box/experimental/libbox/report.go
2026-04-10 16:24:25 +08:00

98 lines
2.5 KiB
Go

//go:build darwin || linux || windows
package libbox
import (
"bytes"
"encoding/json"
"os"
"path/filepath"
"runtime"
"strconv"
"time"
C "github.com/sagernet/sing-box/constant"
E "github.com/sagernet/sing/common/exceptions"
)
type reportMetadata struct {
Source string `json:"source,omitempty"`
BundleIdentifier string `json:"bundleIdentifier,omitempty"`
ProcessName string `json:"processName,omitempty"`
ProcessPath string `json:"processPath,omitempty"`
StartedAt string `json:"startedAt,omitempty"`
AppVersion string `json:"appVersion,omitempty"`
AppMarketingVersion string `json:"appMarketingVersion,omitempty"`
CoreVersion string `json:"coreVersion,omitempty"`
GoVersion string `json:"goVersion,omitempty"`
}
func baseReportMetadata() reportMetadata {
processPath, _ := os.Executable()
processName := filepath.Base(processPath)
if processName == "." {
processName = ""
}
return reportMetadata{
Source: sCrashReportSource,
ProcessName: processName,
ProcessPath: processPath,
CoreVersion: C.Version,
GoVersion: GoVersion(),
}
}
func writeReportFile(destPath string, name string, content []byte) {
filePath := filepath.Join(destPath, name)
os.WriteFile(filePath, content, 0o666)
chownReport(filePath)
}
func writeReportMetadata(destPath string, metadata any) {
data, err := json.Marshal(metadata)
if err != nil {
return
}
writeReportFile(destPath, "metadata.json", data)
}
func copyConfigSnapshot(destPath string) {
snapshotPath := configSnapshotPath()
content, err := os.ReadFile(snapshotPath)
if err != nil {
return
}
if len(bytes.TrimSpace(content)) == 0 {
return
}
writeReportFile(destPath, "configuration.json", content)
}
func initReportDir(path string) {
os.MkdirAll(path, 0o777)
chownReport(path)
}
func chownReport(path string) {
if runtime.GOOS != "android" && runtime.GOOS != "windows" {
os.Chown(path, sUserID, sGroupID)
}
}
func nextAvailableReportPath(reportsDir string, timestamp time.Time) (string, error) {
destName := timestamp.Format("2006-01-02T15-04-05")
destPath := filepath.Join(reportsDir, destName)
_, err := os.Stat(destPath)
if os.IsNotExist(err) {
return destPath, nil
}
for i := 1; i <= 1000; i++ {
suffixedPath := filepath.Join(reportsDir, destName+"-"+strconv.Itoa(i))
_, err = os.Stat(suffixedPath)
if os.IsNotExist(err) {
return suffixedPath, nil
}
}
return "", E.New("no available report path for ", destName)
}