feat: add tray control, priority restoration and session logging
This commit is contained in:
1 parent
4f8f6218ad
commit
4880aa46dc
25 files changed
+3072
-676
No files matched your search
@@ -0,0 +1,108 @@
|
||||
//go:build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const truncatedLogRecord = "\n[Слишком длинная запись сокращена]\n"
|
||||
|
||||
type rotatingLog struct {
|
||||
file *os.File
|
||||
path string
|
||||
limit, size int64
|
||||
}
|
||||
|
||||
func openRotatingLog(path string, limit int64) (*rotatingLog, error) {
|
||||
if limit < int64(len(truncatedLogRecord)+16) {
|
||||
return nil, fmt.Errorf("log size limit is too small")
|
||||
}
|
||||
for _, name := range []string{path, path + ".1"} {
|
||||
info, err := os.Lstat(name)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
return nil, fmt.Errorf("log target is not a regular file")
|
||||
}
|
||||
if name != path {
|
||||
if err = os.Remove(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rotatingLog{file: f, path: path, limit: limit}, nil
|
||||
}
|
||||
func (w *rotatingLog) Write(text string) error {
|
||||
if w.file == nil {
|
||||
return os.ErrClosed
|
||||
}
|
||||
if text == "" {
|
||||
return nil
|
||||
}
|
||||
if !utf8.ValidString(text) {
|
||||
text = strings.ToValidUTF8(text, "?")
|
||||
}
|
||||
if int64(len(text)) > w.limit {
|
||||
end := int(w.limit) - len(truncatedLogRecord)
|
||||
for end > 0 && !utf8.ValidString(text[:end]) {
|
||||
end--
|
||||
}
|
||||
text = text[:end] + truncatedLogRecord
|
||||
}
|
||||
if w.size > 0 && w.size+int64(len(text)) > w.limit {
|
||||
if err := w.rotate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
n, err := w.file.WriteString(text)
|
||||
w.size += int64(n)
|
||||
if err == nil && n != len(text) {
|
||||
return io.ErrShortWrite
|
||||
}
|
||||
return err
|
||||
}
|
||||
func (w *rotatingLog) rotate() error {
|
||||
err := w.file.Close()
|
||||
w.file = nil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info, e := os.Lstat(w.path + ".1"); e == nil {
|
||||
if !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("log archive is not a regular file")
|
||||
}
|
||||
if e = os.Remove(w.path + ".1"); e != nil {
|
||||
return e
|
||||
}
|
||||
} else if !errors.Is(e, os.ErrNotExist) {
|
||||
return e
|
||||
}
|
||||
if err = os.Rename(w.path, w.path+".1"); err != nil {
|
||||
return err
|
||||
}
|
||||
w.file, err = os.OpenFile(w.path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600)
|
||||
w.size = 0
|
||||
return err
|
||||
}
|
||||
func (w *rotatingLog) Close() error {
|
||||
if w.file == nil {
|
||||
return nil
|
||||
}
|
||||
e := errors.Join(w.file.Sync(), w.file.Close())
|
||||
w.file = nil
|
||||
return e
|
||||
}
|
||||
Reference in new issue
Block a user