mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
162 lines
4.1 KiB
Go
162 lines
4.1 KiB
Go
package updates
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/safing/portbase/log"
|
|
"github.com/safing/portbase/utils"
|
|
)
|
|
|
|
func updater() {
|
|
time.Sleep(10 * time.Second)
|
|
for {
|
|
err := UpdateIndexes()
|
|
if err != nil {
|
|
log.Warningf("updates: updating index failed: %s", err)
|
|
}
|
|
err = DownloadUpdates()
|
|
if err != nil {
|
|
log.Warningf("updates: downloading updates failed: %s", err)
|
|
}
|
|
err = runFileUpgrades()
|
|
if err != nil {
|
|
log.Warningf("updates: failed to upgrade portmaster-control: %s", err)
|
|
}
|
|
err = cleanOldUpgradedFiles()
|
|
if err != nil {
|
|
log.Warningf("updates: failed to clean old upgraded files: %s", err)
|
|
}
|
|
time.Sleep(1 * time.Hour)
|
|
}
|
|
}
|
|
|
|
func markFileForDownload(identifier string) {
|
|
// get file
|
|
_, ok := localUpdates[identifier]
|
|
// only mark if it does not yet exist
|
|
if !ok {
|
|
localUpdates[identifier] = "loading..."
|
|
}
|
|
}
|
|
|
|
func markPlatformFileForDownload(identifier string) {
|
|
// add platform prefix
|
|
identifier = path.Join(fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH), identifier)
|
|
// mark file
|
|
markFileForDownload(identifier)
|
|
}
|
|
|
|
// UpdateIndexes downloads the current update indexes.
|
|
func UpdateIndexes() (err error) {
|
|
// download new indexes
|
|
var data []byte
|
|
for tries := 0; tries < 3; tries++ {
|
|
data, err = fetchData("stable.json", tries)
|
|
if err == nil {
|
|
break
|
|
}
|
|
}
|
|
if err != nil {
|
|
return fmt.Errorf("failed to download: %s", err)
|
|
}
|
|
|
|
newStableUpdates := make(map[string]string)
|
|
err = json.Unmarshal(data, &newStableUpdates)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse: %s", err)
|
|
}
|
|
|
|
if len(newStableUpdates) == 0 {
|
|
return errors.New("index is empty")
|
|
}
|
|
|
|
// update stable index
|
|
updatesLock.Lock()
|
|
stableUpdates = newStableUpdates
|
|
updatesLock.Unlock()
|
|
|
|
// check dir
|
|
err = utils.EnsureDirectory(updateStoragePath, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// save stable index
|
|
err = ioutil.WriteFile(filepath.Join(updateStoragePath, "stable.json"), data, 0644)
|
|
if err != nil {
|
|
log.Warningf("updates: failed to save new version of stable.json: %s", err)
|
|
}
|
|
|
|
// update version status
|
|
updatesLock.RLock()
|
|
updateStatus(versionClassStable, stableUpdates)
|
|
updatesLock.RUnlock()
|
|
|
|
// FIXME IN STABLE: correct log line
|
|
log.Infof("updates: updated index stable.json (alpha/beta until we actually reach stable)")
|
|
|
|
return nil
|
|
}
|
|
|
|
// DownloadUpdates checks if updates are available and downloads updates of used components.
|
|
func DownloadUpdates() (err error) {
|
|
|
|
// ensure important components are always updated
|
|
updatesLock.Lock()
|
|
if runtime.GOOS == "windows" {
|
|
markPlatformFileForDownload("core/portmaster-core.exe")
|
|
markPlatformFileForDownload("control/portmaster-control.exe")
|
|
markPlatformFileForDownload("app/portmaster-app.exe")
|
|
markPlatformFileForDownload("notifier/portmaster-notifier.exe")
|
|
markPlatformFileForDownload("notifier/portmaster-snoretoast.exe")
|
|
} else {
|
|
markPlatformFileForDownload("core/portmaster-core")
|
|
markPlatformFileForDownload("control/portmaster-control")
|
|
markPlatformFileForDownload("app/portmaster-app")
|
|
markPlatformFileForDownload("notifier/portmaster-notifier")
|
|
}
|
|
updatesLock.Unlock()
|
|
|
|
// RLock for the remaining function
|
|
updatesLock.RLock()
|
|
defer updatesLock.RUnlock()
|
|
|
|
// update existing files
|
|
log.Tracef("updates: updating existing files")
|
|
for identifier, newVersion := range stableUpdates {
|
|
oldVersion, ok := localUpdates[identifier]
|
|
if ok && newVersion != oldVersion {
|
|
|
|
log.Tracef("updates: updating %s to %s", identifier, newVersion)
|
|
filePath := GetVersionedPath(identifier, newVersion)
|
|
realFilePath := filepath.Join(updateStoragePath, filePath)
|
|
for tries := 0; tries < 3; tries++ {
|
|
err = fetchFile(realFilePath, filePath, tries)
|
|
if err == nil {
|
|
break
|
|
}
|
|
}
|
|
if err != nil {
|
|
log.Warningf("updates: failed to update %s to %s: %s", identifier, newVersion, err)
|
|
}
|
|
|
|
}
|
|
}
|
|
log.Tracef("updates: finished updating existing files")
|
|
|
|
// remove tmp folder after we are finished
|
|
err = os.RemoveAll(downloadTmpPath)
|
|
if err != nil {
|
|
log.Tracef("updates: failed to remove tmp dir %s after downloading updates: %s", updateStoragePath, err)
|
|
}
|
|
|
|
return nil
|
|
}
|