Fix write build error
[platform/core/security/ode.git] / server / file-sink.cpp
1 /*
2  *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 #ifndef _GNU_SOURCE
17 #define _GNU_SOURCE
18 #endif
19
20 #include <iostream>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <chrono>
26 #include <errno.h>
27
28 #include "file-sink.h"
29
30 namespace ode {
31
32 #define MAX_LOG_LEN 16
33
34 namespace {
35 std::string getFileName(const std::string &path)
36 {
37         std::string name;
38         auto pos = path.rfind('/');
39         pos = (pos == std::string::npos) ? 0 : pos + 1;
40         name = path.substr(pos, path.size());
41         return name;
42 }
43 } //namespace
44
45 FileLogSink::FileLogSink(const std::string& name)
46         : path("/opt/var/log/"), fd(-1)
47 {
48         path.append(getFileName(name));
49         fd = ::open(path.c_str(), O_CREAT | O_RDWR | O_APPEND | O_SYNC, 0664);
50 }
51
52 FileLogSink::~FileLogSink()
53 {
54         ::close(fd);
55 }
56
57 void FileLogSink::resize()
58 {
59         std::lock_guard<std::recursive_mutex> lock(mtx);
60         struct stat st;
61         int ret = 0;
62         int blkcnt = MAX_LOG_LEN;
63         size_t blksize = 0;
64
65         if (::lstat(path.c_str(), &st) < 0) {
66                 std::cerr << "Invalid log file" << std::endl;
67                 return;
68         }
69
70         blksize = st.st_blksize;
71         if (blksize > 0)
72                 blkcnt = (st.st_size / blksize) + 1;
73
74         if (blkcnt <= MAX_LOG_LEN)
75                 return;
76
77         ret = ::fallocate(fd, FALLOC_FL_COLLAPSE_RANGE, 0, blksize*(blkcnt-MAX_LOG_LEN));
78         if (ret < 0)
79                 std::cerr << "Failed to collapse the log file : " << errno << std::endl;
80 }
81
82 void FileLogSink::write(const std::string &message)
83 {
84         std::lock_guard<std::recursive_mutex> lock(mtx);
85         resize();
86
87         auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
88         std::tm tm = *std::localtime(&now);
89         std::string log("[" + std::to_string(tm.tm_hour)
90                         + ":"
91                         + std::to_string(tm.tm_min)
92                         + ":"
93                         + std::to_string(tm.tm_sec) + "] ");
94
95         log.append(message);
96
97         size_t written = 0, size = log.size();
98         const char *data = log.c_str();
99
100         while (written < size) {
101                 int bytes = ::write(fd, data + written, size-written);
102                 if (bytes >= 0) {
103                         written += bytes;
104                 } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
105                         continue;
106                 } else {
107                         std::cerr << "Failed to write log" << std::endl;
108                         break;
109                 }
110         }
111         ::sync();
112 }
113
114 void FileLogSink::sink(const std::string &message)
115 {
116         auto level = message.substr(0, message.find('<'));
117         auto subMsg = message.substr(message.find(':') + 1);
118         std::string log;
119
120         switch (audit::StringToLogLevel(level)) {
121         case audit::LogLevel::Error:
122                 log.append("[" + this->tag + " ERROR] : " + subMsg);
123                 break;
124         case audit::LogLevel::Warning:
125                 log.append("[" + this->tag + " WARN] : " + subMsg);
126                 break;
127         case audit::LogLevel::Debug:
128                 log.append("[" + this->tag + " DEBUG] : " + subMsg);
129                 break;
130         case audit::LogLevel::Info:
131                 log.append("[" + this->tag + " INFO] : " + subMsg);
132                 break;
133         case audit::LogLevel::Trace:
134                 log.append("[" + this->tag + " TRACE] : " + subMsg);
135                 break;
136         default:
137                 log.append("[" + this->tag + " SILENT] : " + subMsg);
138                 break;
139         }
140
141         write(log);
142 }
143
144 } //namespace ode