Merge pull request #8 from safing/develop

Release to master
This commit is contained in:
Daniel
2019-07-04 16:33:56 +02:00
committed by GitHub
15 changed files with 95 additions and 79 deletions

View File

@@ -31,7 +31,7 @@ func init() {
func main() { func main() {
// Set Info // Set Info
info.Set("Portmaster", "0.2.5", "AGPLv3", true) info.Set("Portmaster", "0.3.0", "AGPLv3", true)
// Start // Start
err := modules.Start() err := modules.Start()

View File

@@ -16,7 +16,7 @@ function check {
# get version # get version
version=$(grep "info.Set" main.go | cut -d'"' -f4) version=$(grep "info.Set" main.go | cut -d'"' -f4)
# build versioned file name # build versioned file name
filename="portmaster_v${version//./-}" filename="portmaster-core_v${version//./-}"
# platform # platform
platform="${GOOS}_${GOARCH}" platform="${GOOS}_${GOARCH}"
if [[ $GOOS == "windows" ]]; then if [[ $GOOS == "windows" ]]; then
@@ -40,7 +40,7 @@ function build {
# get version # get version
version=$(grep "info.Set" main.go | cut -d'"' -f4) version=$(grep "info.Set" main.go | cut -d'"' -f4)
# build versioned file name # build versioned file name
filename="portmaster_v${version//./-}" filename="portmaster-core_v${version//./-}"
# platform # platform
platform="${GOOS}_${GOARCH}" platform="${GOOS}_${GOARCH}"
if [[ $GOOS == "windows" ]]; then if [[ $GOOS == "windows" ]]; then

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/safing/portbase/utils"
"github.com/safing/portmaster/updates" "github.com/safing/portmaster/updates"
) )
@@ -25,7 +26,7 @@ func getFile(identifier string) (*updates.File, error) {
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
// create dirs // create dirs
err = updates.CheckDir(updateStoragePath) err = utils.EnsureDirectory(updateStoragePath, 0755)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -14,7 +14,7 @@ import (
) )
const ( const (
logPrefix = "[pmctl]" logPrefix = "[control]"
) )
var ( var (
@@ -22,7 +22,7 @@ var (
databaseRootDir *string databaseRootDir *string
rootCmd = &cobra.Command{ rootCmd = &cobra.Command{
Use: "pmctl", Use: "portmaster-control",
Short: "contoller for all portmaster components", Short: "contoller for all portmaster components",
PersistentPreRunE: initPmCtl, PersistentPreRunE: initPmCtl,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
@@ -55,7 +55,7 @@ func main() {
// }() // }()
// set meta info // set meta info
info.Set("Portmaster Control", "0.1.3", "AGPLv3", true) info.Set("Portmaster Control", "0.2.0", "AGPLv3", true)
// check if meta info is ok // check if meta info is ok
err := info.CheckVersion() err := info.CheckVersion()
@@ -97,7 +97,7 @@ func initPmCtl(cmd *cobra.Command, args []string) error {
if err != nil { if err != nil {
return fmt.Errorf("%s failed to upgrade self: %s", logPrefix, err) return fmt.Errorf("%s failed to upgrade self: %s", logPrefix, err)
} }
fmt.Println("upgraded pmctl") fmt.Println("upgraded portmaster-control")
} }
return nil return nil

View File

@@ -8,7 +8,7 @@ COL_BOLD="\033[01;01m"
COL_RED="\033[31m" COL_RED="\033[31m"
destDirPart1="../dist" destDirPart1="../dist"
destDirPart2="pmctl" destDirPart2="control"
function check { function check {
# output # output
@@ -16,7 +16,7 @@ function check {
# get version # get version
version=$(grep "info.Set" main.go | cut -d'"' -f4) version=$(grep "info.Set" main.go | cut -d'"' -f4)
# build versioned file name # build versioned file name
filename="pmctl_v${version//./-}" filename="portmaster-control_v${version//./-}"
# platform # platform
platform="${GOOS}_${GOARCH}" platform="${GOOS}_${GOARCH}"
if [[ $GOOS == "windows" ]]; then if [[ $GOOS == "windows" ]]; then
@@ -28,9 +28,9 @@ function check {
# check if file exists # check if file exists
if [[ -f $destPath ]]; then if [[ -f $destPath ]]; then
echo "[pmctl] $platform $version already built" echo "[control] $platform $version already built"
else else
echo -e "${COL_BOLD}[pmctl] $platform $version${COL_OFF}" echo -e "${COL_BOLD}[control] $platform $version${COL_OFF}"
fi fi
} }
@@ -40,7 +40,7 @@ function build {
# get version # get version
version=$(grep "info.Set" main.go | cut -d'"' -f4) version=$(grep "info.Set" main.go | cut -d'"' -f4)
# build versioned file name # build versioned file name
filename="pmctl_v${version//./-}" filename="portmaster-control_v${version//./-}"
# platform # platform
platform="${GOOS}_${GOARCH}" platform="${GOOS}_${GOARCH}"
if [[ $GOOS == "windows" ]]; then if [[ $GOOS == "windows" ]]; then
@@ -52,19 +52,19 @@ function build {
# check if file exists # check if file exists
if [[ -f $destPath ]]; then if [[ -f $destPath ]]; then
echo "[pmctl] $platform already built in version $version, skipping..." echo "[control] $platform already built in version $version, skipping..."
return return
fi fi
# build # build
./build ./build
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
echo -e "\n${COL_BOLD}[pmctl] $platform: ${COL_RED}BUILD FAILED.${COL_OFF}" echo -e "\n${COL_BOLD}[control] $platform: ${COL_RED}BUILD FAILED.${COL_OFF}"
exit 1 exit 1
fi fi
mkdir -p $(dirname $destPath) mkdir -p $(dirname $destPath)
cp $output $destPath cp $output $destPath
echo -e "\n${COL_BOLD}[pmctl] $platform: successfully built.${COL_OFF}" echo -e "\n${COL_BOLD}[control] $platform: successfully built.${COL_OFF}"
} }
function check_all { function check_all {

View File

@@ -27,7 +27,7 @@ var runCore = &cobra.Command{
Use: "core", Use: "core",
Short: "Run the Portmaster Core", Short: "Run the Portmaster Core",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return run("core/portmaster", cmd, false) return run("core/portmaster-core", cmd, false)
}, },
FParseErrWhitelist: cobra.FParseErrWhitelist{ FParseErrWhitelist: cobra.FParseErrWhitelist{
// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags // UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags

View File

@@ -13,7 +13,7 @@ import (
func checkForUpgrade() (update *updates.File) { func checkForUpgrade() (update *updates.File) {
info := info.GetInfo() info := info.GetInfo()
file, err := updates.GetLocalPlatformFile("pmctl/pmctl") file, err := updates.GetLocalPlatformFile("control/portmaster-control")
if err != nil { if err != nil {
return nil return nil
} }
@@ -113,6 +113,6 @@ func removeOldBin() error {
return nil return nil
} }
fmt.Println("removed previous pmctl") fmt.Println("removed previous portmaster-control")
return nil return nil
} }

View File

@@ -11,7 +11,6 @@ import (
"sync" "sync"
resources "github.com/cookieo9/resources-go" resources "github.com/cookieo9/resources-go"
"github.com/gorilla/mux"
"github.com/safing/portbase/api" "github.com/safing/portbase/api"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
@@ -41,7 +40,7 @@ func ServeBundle(defaultModuleName string) func(w http.ResponseWriter, r *http.R
// log.Tracef("ui: request for %s", r.RequestURI) // log.Tracef("ui: request for %s", r.RequestURI)
vars := mux.Vars(r) vars := api.GetMuxVars(r)
moduleName, ok := vars["moduleName"] moduleName, ok := vars["moduleName"]
if !ok { if !ok {
moduleName = defaultModuleName moduleName = defaultModuleName
@@ -98,8 +97,13 @@ func ServeBundle(defaultModuleName string) func(w http.ResponseWriter, r *http.R
func ServeFileFromBundle(w http.ResponseWriter, r *http.Request, bundleName string, bundle *resources.BundleSequence, path string) { func ServeFileFromBundle(w http.ResponseWriter, r *http.Request, bundleName string, bundle *resources.BundleSequence, path string) {
readCloser, err := bundle.Open(path) readCloser, err := bundle.Open(path)
if err != nil { if err != nil {
if err == resources.ErrNotFound {
log.Tracef("ui: requested resource \"%s\" not found in bundle %s: %s", path, bundleName, err)
http.Error(w, err.Error(), http.StatusNotFound)
} else {
log.Tracef("ui: error opening module %s: %s", bundleName, err) log.Tracef("ui: error opening module %s: %s", bundleName, err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
}
return return
} }

View File

@@ -15,6 +15,7 @@ import (
"github.com/google/renameio" "github.com/google/renameio"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
"github.com/safing/portbase/utils"
) )
var ( var (
@@ -37,15 +38,15 @@ func fetchFile(realFilepath, updateFilepath string, tries int) error {
// check destination dir // check destination dir
dirPath := filepath.Dir(realFilepath) dirPath := filepath.Dir(realFilepath)
err = CheckDir(dirPath) err = utils.EnsureDirectory(dirPath, 0755)
if err != nil { if err != nil {
return fmt.Errorf("updates: could not create updates folder: %s", dirPath) return fmt.Errorf("could not create updates folder: %s", dirPath)
} }
// open file for writing // open file for writing
atomicFile, err := renameio.TempFile(filepath.Join(updateStoragePath, "tmp"), realFilepath) atomicFile, err := renameio.TempFile(downloadTmpPath, realFilepath)
if err != nil { if err != nil {
return fmt.Errorf("updates: could not create temp file for download: %s", err) return fmt.Errorf("could not create temp file for download: %s", err)
} }
defer atomicFile.Cleanup() defer atomicFile.Cleanup()
@@ -62,7 +63,7 @@ func fetchFile(realFilepath, updateFilepath string, tries int) error {
return fmt.Errorf("failed downloading %s: %s", downloadURL, err) return fmt.Errorf("failed downloading %s: %s", downloadURL, err)
} }
if resp.ContentLength != n { if resp.ContentLength != n {
return fmt.Errorf("download unfinished, written %d out of %d bytes.", n, resp.ContentLength) return fmt.Errorf("download unfinished, written %d out of %d bytes", n, resp.ContentLength)
} }
// finalize file // finalize file
@@ -72,7 +73,8 @@ func fetchFile(realFilepath, updateFilepath string, tries int) error {
} }
// set permissions // set permissions
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
err = os.Chmod(realFilepath, 0644) // FIXME: only set executable files to 0755, set other to 0644
err = os.Chmod(realFilepath, 0755)
if err != nil { if err != nil {
log.Warningf("updates: failed to set permissions on downloaded file %s: %s", realFilepath, err) log.Warningf("updates: failed to set permissions on downloaded file %s: %s", realFilepath, err)
} }
@@ -108,7 +110,7 @@ func fetchData(downloadPath string, tries int) ([]byte, error) {
return nil, fmt.Errorf("failed downloading %s: %s", downloadURL, err) return nil, fmt.Errorf("failed downloading %s: %s", downloadURL, err)
} }
if resp.ContentLength != n { if resp.ContentLength != n {
return nil, fmt.Errorf("download unfinished, written %d out of %d bytes.", n, resp.ContentLength) return nil, fmt.Errorf("download unfinished, written %d out of %d bytes", n, resp.ContentLength)
} }
return buf.Bytes(), nil return buf.Bytes(), nil

View File

@@ -7,6 +7,7 @@ type File struct {
stable bool stable bool
} }
// NewFile combines update file attributes into an easy to use object.
func NewFile(filepath string, version string, stable bool) *File { func NewFile(filepath string, version string, stable bool) *File {
return &File{ return &File{
filepath: filepath, filepath: filepath,

View File

@@ -8,6 +8,7 @@ import (
var versionRegex = regexp.MustCompile("_v[0-9]+-[0-9]+-[0-9]+b?") var versionRegex = regexp.MustCompile("_v[0-9]+-[0-9]+-[0-9]+b?")
// GetIdentifierAndVersion splits the given file path into its identifier and version.
func GetIdentifierAndVersion(versionedPath string) (identifier, version string, ok bool) { func GetIdentifierAndVersion(versionedPath string) (identifier, version string, ok bool) {
// extract version // extract version
rawVersion := versionRegex.FindString(versionedPath) rawVersion := versionRegex.FindString(versionedPath)
@@ -27,6 +28,7 @@ func GetIdentifierAndVersion(versionedPath string) (identifier, version string,
return versionedPath[:i] + versionedPath[i+len(rawVersion):], version, true return versionedPath[:i] + versionedPath[i+len(rawVersion):], version, true
} }
// GetVersionedPath combines the identifier and version and returns it as a file path.
func GetVersionedPath(identifier, version string) (versionedPath string) { func GetVersionedPath(identifier, version string) (versionedPath string) {
// split in half // split in half
splittedFilePath := strings.SplitN(identifier, ".", 2) splittedFilePath := strings.SplitN(identifier, ".", 2)

View File

@@ -9,8 +9,10 @@ import (
"runtime" "runtime"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
"github.com/safing/portbase/utils"
) )
// Errors
var ( var (
ErrNotFound = errors.New("the requested file could not be found") ErrNotFound = errors.New("the requested file could not be found")
ErrNotAvailableLocally = errors.New("the requested file is not available locally") ErrNotAvailableLocally = errors.New("the requested file is not available locally")
@@ -81,12 +83,12 @@ func loadOrFetchFile(identifier string, fetch bool) (*File, error) {
} }
// check download dir // check download dir
err := CheckDir(filepath.Join(updateStoragePath, "tmp")) err := utils.EnsureDirectory(downloadTmpPath, 0755)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not prepare tmp directory for download: %s", err) return nil, fmt.Errorf("could not prepare tmp directory for download: %s", err)
} }
if (!fetch) { if !fetch {
return nil, ErrNotAvailableLocally return nil, ErrNotAvailableLocally
} }

View File

@@ -62,6 +62,7 @@ func LoadLatest() error {
return nil return nil
} }
// ScanForLatest scan the local update directory and returns a map of the latest/newest component versions.
func ScanForLatest(baseDir string, hardFail bool) (latest map[string]string, lastError error) { func ScanForLatest(baseDir string, hardFail bool) (latest map[string]string, lastError error) {
var added int var added int
latest = make(map[string]string) latest = make(map[string]string)
@@ -117,6 +118,7 @@ func ScanForLatest(baseDir string, hardFail bool) (latest map[string]string, las
return latest, nil return latest, nil
} }
// LoadIndexes loads the current update indexes from disk.
func LoadIndexes() error { func LoadIndexes() error {
data, err := ioutil.ReadFile(filepath.Join(updateStoragePath, "stable.json")) data, err := ioutil.ReadFile(filepath.Join(updateStoragePath, "stable.json"))
if err != nil { if err != nil {

View File

@@ -2,7 +2,6 @@ package updates
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
@@ -10,21 +9,24 @@ import (
"github.com/safing/portbase/info" "github.com/safing/portbase/info"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
"github.com/safing/portbase/modules" "github.com/safing/portbase/modules"
"github.com/safing/portbase/utils"
) )
var ( var (
updateStoragePath string updateStoragePath string
downloadTmpPath string
) )
// SetDatabaseRoot tells the updates module where the database is - and where to put its stuff. // SetDatabaseRoot tells the updates module where the database is - and where to put its stuff.
func SetDatabaseRoot(path string) { func SetDatabaseRoot(path string) {
if updateStoragePath == "" { if updateStoragePath == "" {
updateStoragePath = filepath.Join(path, "updates") updateStoragePath = filepath.Join(path, "updates")
downloadTmpPath = filepath.Join(updateStoragePath, "tmp")
} }
} }
func init() { func init() {
modules.Register("updates", prep, start, nil, "core") modules.Register("updates", prep, start, stop, "core")
} }
func prep() error { func prep() error {
@@ -33,8 +35,14 @@ func prep() error {
return errors.New("database root is not set") return errors.New("database root is not set")
} }
updateStoragePath = filepath.Join(dbRoot, "updates") updateStoragePath = filepath.Join(dbRoot, "updates")
downloadTmpPath = filepath.Join(updateStoragePath, "tmp")
err := CheckDir(updateStoragePath) err := utils.EnsureDirectory(updateStoragePath, 0755)
if err != nil {
return err
}
err = utils.EnsureDirectory(downloadTmpPath, 0700)
if err != nil { if err != nil {
return err return err
} }
@@ -70,34 +78,6 @@ func start() error {
} }
func stop() error { func stop() error {
return os.RemoveAll(filepath.Join(updateStoragePath, "tmp")) // delete download tmp dir
} return os.RemoveAll(downloadTmpPath)
func CheckDir(dirPath string) error {
f, err := os.Stat(dirPath)
if err == nil {
// file exists
if f.IsDir() {
return nil
}
err = os.Remove(dirPath)
if err != nil {
return fmt.Errorf("could not remove file %s to place dir: %s", dirPath, err)
}
err = os.MkdirAll(dirPath, 0755)
if err != nil {
return fmt.Errorf("could not create dir %s: %s", dirPath, err)
}
return nil
}
// file does not exist
if os.IsNotExist(err) {
err = os.MkdirAll(dirPath, 0755)
if err != nil {
return fmt.Errorf("could not create dir %s: %s", dirPath, err)
}
return nil
}
// other error
return fmt.Errorf("failed to access %s: %s", dirPath, err)
} }

View File

@@ -3,7 +3,9 @@ package updates
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"io/ioutil" "io/ioutil"
"path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"time" "time"
@@ -22,19 +24,25 @@ func updater() {
} }
} }
func CheckForUpdates() error { func markFileForDownload(identifier string) {
// get file
_, ok := localUpdates[identifier]
// only mark if it does not yet exist
if !ok {
localUpdates[identifier] = "loading..."
}
}
// ensure core components are updated func markPlatformFileForDownload(identifier string) {
var err error // add platform prefix
if runtime.GOOS == "windows" { identifier = path.Join(fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH), identifier)
_, err = GetPlatformFile("pmctl/pmctl.exe") // mark file
} else { markFileForDownload(identifier)
_, err = GetPlatformFile("pmctl/pmctl")
}
if err != nil {
log.Errorf("updates: failed to mark pmctl/pmctl as used to ensure updates: %s", err)
} }
// CheckForUpdates checks if updates are available and downloads updates of used components.
func CheckForUpdates() (err error) {
// download new index // download new index
var data []byte var data []byte
for tries := 0; tries < 3; tries++ { for tries := 0; tries < 3; tries++ {
@@ -60,6 +68,19 @@ func CheckForUpdates() error {
// FIXME IN STABLE: correct log line // FIXME IN STABLE: correct log line
log.Infof("updates: downloaded new update index: stable.json (alpha until we actually reach stable)") log.Infof("updates: downloaded new update index: stable.json (alpha until we actually reach stable)")
// ensure important components are always updated
updatesLock.Lock()
if runtime.GOOS == "windows" {
markPlatformFileForDownload("control/portmaster-control.exe")
markPlatformFileForDownload("app/portmaster-app.exe")
markPlatformFileForDownload("notifier/portmaster-notifier.exe")
} else {
markPlatformFileForDownload("control/portmaster-control")
markPlatformFileForDownload("app/portmaster-app")
markPlatformFileForDownload("notifier/portmaster-notifier")
}
updatesLock.Unlock()
// update existing files // update existing files
log.Tracef("updates: updating existing files") log.Tracef("updates: updating existing files")
updatesLock.RLock() updatesLock.RLock()
@@ -67,16 +88,17 @@ func CheckForUpdates() error {
oldVersion, ok := localUpdates[identifier] oldVersion, ok := localUpdates[identifier]
if ok && newVersion != oldVersion { if ok && newVersion != oldVersion {
log.Tracef("updates: updating %s to %s", identifier, newVersion)
filePath := GetVersionedPath(identifier, newVersion) filePath := GetVersionedPath(identifier, newVersion)
realFilePath := filepath.Join(updateStoragePath, filePath) realFilePath := filepath.Join(updateStoragePath, filePath)
for tries := 0; tries < 3; tries++ { for tries := 0; tries < 3; tries++ {
err := fetchFile(realFilePath, filePath, tries) err = fetchFile(realFilePath, filePath, tries)
if err == nil { if err == nil {
break break
} }
} }
if err != nil { if err != nil {
log.Warningf("failed to update %s to %s: %s", identifier, newVersion, err) log.Warningf("updates: failed to update %s to %s: %s", identifier, newVersion, err)
} }
} }