mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
107 lines
3.3 KiB
Go
107 lines
3.3 KiB
Go
package updates
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/safing/portmaster/base/log"
|
|
)
|
|
|
|
const (
|
|
defaultFileMode = os.FileMode(0o0644)
|
|
executableFileMode = os.FileMode(0o0744)
|
|
defaultDirMode = os.FileMode(0o0755)
|
|
)
|
|
|
|
func switchFolders(updateIndex UpdateIndex, newBundle Bundle) error {
|
|
// Create purge dir.
|
|
err := os.MkdirAll(updateIndex.PurgeDirectory, defaultDirMode)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create directory: %w", err)
|
|
}
|
|
|
|
// Read all files in the current version folder.
|
|
files, err := os.ReadDir(updateIndex.Directory)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Move current version files into purge folder.
|
|
log.Debugf("updates: removing the old version")
|
|
for _, file := range files {
|
|
currentFilepath := filepath.Join(updateIndex.Directory, file.Name())
|
|
purgePath := filepath.Join(updateIndex.PurgeDirectory, file.Name())
|
|
err := os.Rename(currentFilepath, purgePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to move file %s: %w", currentFilepath, err)
|
|
}
|
|
}
|
|
|
|
// Move the new index file
|
|
log.Debugf("updates: installing the new version")
|
|
indexFile := filepath.Join(updateIndex.DownloadDirectory, updateIndex.IndexFile)
|
|
newIndexFile := filepath.Join(updateIndex.Directory, updateIndex.IndexFile)
|
|
err = os.Rename(indexFile, newIndexFile)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to move index file %s: %w", indexFile, err)
|
|
}
|
|
|
|
// Move downloaded files to the current version folder.
|
|
for _, artifact := range newBundle.Artifacts {
|
|
fromFilepath := filepath.Join(updateIndex.DownloadDirectory, artifact.Filename)
|
|
toFilepath := filepath.Join(updateIndex.Directory, artifact.Filename)
|
|
err = os.Rename(fromFilepath, toFilepath)
|
|
if err != nil {
|
|
log.Errorf("failed to move file %s: %s", fromFilepath, err)
|
|
} else {
|
|
log.Debugf("updates: %s moved", artifact.Filename)
|
|
}
|
|
|
|
// Special case for linux.
|
|
// When installed the portmaster ui path is `/usr/bin/portmaster`. During update the ui will be placed in `/usr/lib/portmaster/portmaster`
|
|
// After an update the original binary should be deleted and replaced by symlink
|
|
// `/usr/bin/portmaster` -> `/usr/lib/portmaster/portmaster`
|
|
if runtime.GOOS == "linux" && artifact.Filename == "portmaster" && artifact.Platform == currentPlatform {
|
|
err = makeSymlinkForUI(updateIndex.Directory)
|
|
if err != nil {
|
|
log.Errorf("failed to create symlink for the ui: %s", err)
|
|
} else {
|
|
log.Infof("ui symlink successfully created")
|
|
}
|
|
}
|
|
}
|
|
|
|
log.Debugf("updates: update complete")
|
|
|
|
return nil
|
|
}
|
|
|
|
func deleteUnfinishedDownloads(rootDir string) error {
|
|
entries, err := os.ReadDir(rootDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, e := range entries {
|
|
// Check if the current file has the download extension
|
|
if !e.IsDir() && strings.HasSuffix(e.Name(), ".download") {
|
|
path := filepath.Join(rootDir, e.Name())
|
|
log.Warningf("updates: deleting unfinished download file: %s\n", path)
|
|
err := os.Remove(path)
|
|
if err != nil {
|
|
log.Errorf("updates: failed to delete unfinished download file %s: %s", path, err)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func makeSymlinkForUI(directory string) error {
|
|
err := os.Symlink(filepath.Join(directory, "portmaster"), "/usr/bin/portmaster")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create symlink: %w", err)
|
|
}
|
|
return nil
|
|
}
|