diff --git a/pkg/storage/iface.go b/pkg/storage/iface.go index 3bb3461..f412fff 100644 --- a/pkg/storage/iface.go +++ b/pkg/storage/iface.go @@ -14,6 +14,7 @@ type Iface interface { Rename(oldName, newName string) error AppendFile(name string, data []byte) error EnsurePermissions(name string, mode fs.FileMode) error + FileInfo(name string) (fs.FileInfo, error) ReadWriter Seeker } diff --git a/pkg/storage/local/path.go b/pkg/storage/local/path.go index de52e4f..214b341 100644 --- a/pkg/storage/local/path.go +++ b/pkg/storage/local/path.go @@ -90,3 +90,7 @@ func (l *LocalStorage) Rename(oldName, newName string) error { func (l *LocalStorage) EnsurePermissions(name string, mode fs.FileMode) error { return os.Chmod(path.Join(l.path, name), mode) } + +func (l *LocalStorage) FileInfo(name string) (fs.FileInfo, error) { + return os.Stat(name) +} diff --git a/pkg/storage/memory/fileinfo.go b/pkg/storage/memory/fileinfo.go new file mode 100644 index 0000000..b9fc5dd --- /dev/null +++ b/pkg/storage/memory/fileinfo.go @@ -0,0 +1,34 @@ +package memorystorage + +import ( + "io/fs" + "time" +) + +type FileInfo struct { + NameOut string // base name of the file + SizeOut int64 // length in bytes for regular files; system-dependent for others + ModeOut fs.FileMode // file mode bits + ModTimeOut time.Time // modification time + IsDirOut bool // abbreviation for Mode().IsDir() + SysOut any // underlying data source (can return nil) +} + +func (f FileInfo) Name() string { + return f.NameOut +} +func (f FileInfo) Size() int64 { + return f.SizeOut +} +func (f FileInfo) Mode() fs.FileMode { + return f.ModeOut +} +func (f FileInfo) ModTime() time.Time { + return f.ModTimeOut +} +func (f FileInfo) IsDir() bool { + return f.IsDirOut +} +func (f FileInfo) Sys() any { + return nil +} diff --git a/pkg/storage/memory/storage.go b/pkg/storage/memory/storage.go index 74674f6..ef5734e 100644 --- a/pkg/storage/memory/storage.go +++ b/pkg/storage/memory/storage.go @@ -21,7 +21,8 @@ func (m *MockReadWriterData) Write(p []byte) (nn int, err error) { } type MockMemoryStorage struct { - Data map[string]*MockReadWriterData + FileInfoData map[string]*FileInfo + Data map[string]*MockReadWriterData } func (m *MockMemoryStorage) ConfigPath(filename string) string { @@ -151,3 +152,10 @@ func (m *MockMemoryStorage) OpenFileForAppending(name string) (io.WriteCloser, e func (m *MockMemoryStorage) EnsurePermissions(name string, mode fs.FileMode) error { return nil } +func (m *MockMemoryStorage) FileInfo(name string) (fs.FileInfo, error) { + val, ok := m.FileInfoData[name] + if !ok { + return FileInfo{}, fmt.Errorf("couldn't get file info for: %s", name) + } + return val, nil +} diff --git a/pkg/wireguard/packetlogger.go b/pkg/wireguard/packetlogger.go index f813ee5..978acfd 100644 --- a/pkg/wireguard/packetlogger.go +++ b/pkg/wireguard/packetlogger.go @@ -375,6 +375,10 @@ func PacketLoggerLogRotation(storage storage.Iface) { if err != nil { logging.ErrorLog(fmt.Errorf("packet logger log rotation error: %s", err)) } + err = packetLoggerRemoveTmpFiles(storage) + if err != nil { + logging.ErrorLog(fmt.Errorf("packet logger remove tmp files error: %s", err)) + } } } @@ -431,6 +435,28 @@ func packetLoggerLogRotation(storage storage.Iface) error { return nil } +func packetLoggerRemoveTmpFiles(storage storage.Iface) error { + files, err := storage.ReadDir(VPN_PACKETLOGGER_TMP_DIR) + if err != nil { + return fmt.Errorf("readDir error: %s", err) + } + for _, filename := range files { + if strings.HasSuffix(filename, ".log") { + fileInfo, err := storage.FileInfo(path.Join(VPN_PACKETLOGGER_TMP_DIR, filename)) + if err != nil { + return fmt.Errorf("file info error (%s): %s", filename, err) + } + if time.Since(fileInfo.ModTime()) > (24 * time.Hour) { + err = storage.Remove(path.Join(VPN_PACKETLOGGER_TMP_DIR, filename)) + if err != nil { + return fmt.Errorf("file remove error (%s): %s", filename, err) + } + } + } + } + return nil +} + func packetLoggerCompressLog(storage storage.Iface, filename string) error { reader, err := storage.OpenFile(path.Join(VPN_STATS_DIR, VPN_PACKETLOGGER_DIR, filename)) if err != nil { diff --git a/pkg/wireguard/packetlogger_test.go b/pkg/wireguard/packetlogger_test.go index 4936d4e..a89c047 100644 --- a/pkg/wireguard/packetlogger_test.go +++ b/pkg/wireguard/packetlogger_test.go @@ -432,6 +432,47 @@ func TestPacketLoggerLogRotationDeletion(t *testing.T) { } } +func TestPacketLoggerRemoveTmpFiles(t *testing.T) { + storage := &memorystorage.MockMemoryStorage{ + Data: map[string]*memorystorage.MockReadWriterData{}, + FileInfoData: map[string]*memorystorage.FileInfo{}, + } + for i := 0; i < 20; i++ { + timestamp := time.Now().AddDate(0, 0, -1*i) + suffix := ".log" + key1 := path.Join(VPN_PACKETLOGGER_TMP_DIR, fmt.Sprintf("1-2-3-4-%s%s", timestamp.Format("2006-01-02"), suffix)) + value1 := []byte(timestamp.Format(TIMESTAMP_FORMAT) + `,https,10.189.184.2,64.233.180.104,60496,443,www.google.com`) + err := storage.WriteFile(key1, value1) + if err != nil { + t.Fatalf("write file error: %s", err) + } + storage.FileInfoData[key1] = &memorystorage.FileInfo{ + ModTimeOut: timestamp, + } + } + + before, err := storage.ReadDir(VPN_PACKETLOGGER_TMP_DIR) + if err != nil { + t.Fatalf("readdir error: %s", err) + } + + err = packetLoggerRemoveTmpFiles(storage) + if err != nil { + t.Fatalf("packetLoggerRotation error: %s", err) + } + + after, err := storage.ReadDir(VPN_PACKETLOGGER_TMP_DIR) + if err != nil { + t.Fatalf("readdir error: %s", err) + } + if len(before) != 20 { + t.Fatalf("expected to have written 20 files. Got: %d", len(before)) + } + if len(after) != 1 { + t.Fatalf("only expected 1 tmp files. Got: %d", len(after)) + } +} + func TestParsePacketSwitchPacketLogTypes(t *testing.T) { storage := &memorystorage.MockMemoryStorage{} clientCache := &ClientCache{