mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
127 lines
3.4 KiB
Go
127 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/safing/portbase/container"
|
|
"github.com/safing/portbase/database/record"
|
|
"github.com/safing/portbase/formats/dsd"
|
|
"github.com/safing/portbase/info"
|
|
)
|
|
|
|
func initializeLogFile(logFilePath string, identifier string, version string) *os.File {
|
|
logFile, err := os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE, 0o0440) //nolint:gosec // As desired.
|
|
if err != nil {
|
|
log.Printf("failed to create log file %s: %s\n", logFilePath, err)
|
|
return nil
|
|
}
|
|
|
|
// create header, so that the portmaster can view log files as a database
|
|
meta := record.Meta{}
|
|
meta.Update()
|
|
meta.SetAbsoluteExpiry(time.Now().Add(720 * time.Hour).Unix()) // one month
|
|
|
|
// manually marshal
|
|
// version
|
|
c := container.New([]byte{1})
|
|
// meta
|
|
metaSection, err := dsd.Dump(meta, dsd.JSON)
|
|
if err != nil {
|
|
log.Printf("failed to serialize header for log file %s: %s\n", logFilePath, err)
|
|
finalizeLogFile(logFile)
|
|
return nil
|
|
}
|
|
c.AppendAsBlock(metaSection)
|
|
// log file data type (string) and newline for better manual viewing
|
|
c.Append([]byte("S\n"))
|
|
c.Append([]byte(fmt.Sprintf("executing %s version %s on %s %s\n", identifier, version, runtime.GOOS, runtime.GOARCH)))
|
|
|
|
_, err = logFile.Write(c.CompileData())
|
|
if err != nil {
|
|
log.Printf("failed to write header for log file %s: %s\n", logFilePath, err)
|
|
finalizeLogFile(logFile)
|
|
return nil
|
|
}
|
|
|
|
return logFile
|
|
}
|
|
|
|
func finalizeLogFile(logFile *os.File) {
|
|
logFilePath := logFile.Name()
|
|
|
|
err := logFile.Close()
|
|
if err != nil {
|
|
log.Printf("failed to close log file %s: %s\n", logFilePath, err)
|
|
}
|
|
|
|
// check file size
|
|
stat, err := os.Stat(logFilePath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// delete if file is smaller than
|
|
if stat.Size() >= 200 { // header + info is about 150 bytes
|
|
return
|
|
}
|
|
|
|
if err := os.Remove(logFilePath); err != nil {
|
|
log.Printf("failed to delete empty log file %s: %s\n", logFilePath, err)
|
|
}
|
|
}
|
|
|
|
func getLogFile(options *Options, version, ext string) *os.File {
|
|
// check logging dir
|
|
logFileBasePath := filepath.Join(logsRoot.Path, options.ShortIdentifier)
|
|
err := logsRoot.EnsureAbsPath(logFileBasePath)
|
|
if err != nil {
|
|
log.Printf("failed to check/create log file folder %s: %s\n", logFileBasePath, err)
|
|
}
|
|
|
|
// open log file
|
|
logFilePath := filepath.Join(logFileBasePath, fmt.Sprintf("%s%s", time.Now().UTC().Format("2006-01-02-15-04-05"), ext))
|
|
return initializeLogFile(logFilePath, options.Identifier, version)
|
|
}
|
|
|
|
func getPmStartLogFile(ext string) *os.File {
|
|
return getLogFile(&Options{
|
|
ShortIdentifier: "start",
|
|
Identifier: "start/portmaster-start",
|
|
}, info.Version(), ext)
|
|
}
|
|
|
|
//nolint:unused // false positive on linux, currently used by windows only. TODO: move to a _windows file.
|
|
func logControlError(cErr error) {
|
|
// check if error present
|
|
if cErr == nil {
|
|
return
|
|
}
|
|
|
|
errorFile := getPmStartLogFile(".error.log")
|
|
if errorFile == nil {
|
|
return
|
|
}
|
|
defer func() {
|
|
_ = errorFile.Close()
|
|
}()
|
|
|
|
fmt.Fprintln(errorFile, cErr.Error())
|
|
}
|
|
|
|
//nolint:deadcode,unused // false positive on linux, currently used by windows only. TODO: move to a _windows file.
|
|
func runAndLogControlError(wrappedFunc func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error {
|
|
return func(cmd *cobra.Command, args []string) error {
|
|
err := wrappedFunc(cmd, args)
|
|
if err != nil {
|
|
logControlError(err)
|
|
}
|
|
return err
|
|
}
|
|
}
|