package app import ( "encoding/json" "fmt" "os" "strings" "time" ) func saveRoutesClearCache() (routesClearCacheMeta, error) { if err := os.MkdirAll(stateDir, 0o755); err != nil { return routesClearCacheMeta{}, err } routes, err := readCurrentRoutesTableLines() if err != nil { return routesClearCacheMeta{}, err } if err := writeLinesFile(routesCacheRT, routes); err != nil { return routesClearCacheMeta{}, err } var warns []string ipCount, err := snapshotNftSetToFile("agvpn4", routesCacheIPs) if err != nil { warns = append(warns, fmt.Sprintf("agvpn4 snapshot failed: %v", err)) _ = cacheCopyOrEmpty(stateDir+"/last-ips.txt", routesCacheIPs) ipCount = len(readNonEmptyLines(routesCacheIPs)) } dynIPCount, err := snapshotNftSetToFile("agvpn_dyn4", routesCacheDyn) if err != nil { warns = append(warns, fmt.Sprintf("agvpn_dyn4 snapshot failed: %v", err)) _ = os.WriteFile(routesCacheDyn, []byte{}, 0o644) dynIPCount = 0 } if err := cacheCopyOrEmpty(stateDir+"/last-ips-map.txt", routesCacheMap); err != nil { warns = append(warns, fmt.Sprintf("last-ips-map cache copy failed: %v", err)) } if err := cacheCopyOrEmpty(lastIPsMapDirect, routesCacheMapD); err != nil { warns = append(warns, fmt.Sprintf("last-ips-map-direct cache copy failed: %v", err)) } if err := cacheCopyOrEmpty(lastIPsMapDyn, routesCacheMapW); err != nil { warns = append(warns, fmt.Sprintf("last-ips-map-wildcard cache copy failed: %v", err)) } meta := routesClearCacheMeta{ CreatedAt: time.Now().UTC().Format(time.RFC3339), Iface: detectIfaceFromRoutes(routes), RouteCount: len(routes), IPCount: ipCount, DynIPCount: dynIPCount, HasIPMap: fileExists(routesCacheMap), } data, err := json.MarshalIndent(meta, "", " ") if err != nil { return routesClearCacheMeta{}, err } if err := os.WriteFile(routesCacheMeta, data, 0o644); err != nil { return routesClearCacheMeta{}, err } if len(warns) > 0 { return meta, fmt.Errorf("%s", strings.Join(warns, "; ")) } return meta, nil }