Init basesystem source codes.
[staging/basesystem.git] / systemservice / logger_service / server / src / ss_logger_error_event_archive.cpp
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
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
17 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup  tag_SS_LoggerService
19 /// \brief    This file supports error event logging.
20 ///
21 ///////////////////////////////////////////////////////////////////////////////
22 #include "ss_logger_error_event_archive.h"
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <dirent.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <libtar_listhash.h>
31 #include <libtar.h>
32 #include <zlib.h>
33 #include <stdio.h>
34 #include <boost/bind.hpp>
35 #include <native_service/frameworkunified_framework_if.h>
36 #include <system_service/ss_services.h>
37 #include <system_service/ss_templates.h>
38 #include <iostream>
39 #include <fstream>
40 #include <string>
41 #include <vector>
42 #include "ss_logger_util.h"
43 #include "loggerservicedebug_loggerservicelog.h"
44 #include "ss_logger_fs_directory.h"
45
46 // GZF save variables
47 static gzFile g_gzFile;
48
49 CErrorEventArchive::CErrorEventArchive(void) {
50   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
51   m_pTarInfo = NULL;
52   g_gzFile = NULL;
53   m_gztype.openfunc = (openfunc_t) &CErrorEventArchive::gzOpenArchive;
54   m_gztype.closefunc = (closefunc_t) &CErrorEventArchive::gzCloseArchive;
55   m_gztype.readfunc = (readfunc_t) &CErrorEventArchive::gzReadArchive;
56   m_gztype.writefunc = (writefunc_t) &CErrorEventArchive::gzWriteArchive;
57   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
58 }
59
60 CErrorEventArchive::~CErrorEventArchive(void) {
61   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
62   if (NULL != m_pTarInfo) {  // LCOV_EXCL_BR_LINE 6: it will close after close
63     // LCOV_EXCL_START 6: it will close after close
64     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
65     (void) closeArchive();
66     m_pTarInfo = NULL;
67     // LCOV_EXCL_STOP
68   }
69   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
70 }
71
72 EFrameworkunifiedStatus CErrorEventArchive::openArchive(std::string f_pathAndName) {
73   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
74   EFrameworkunifiedStatus l_eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
75
76   if (NULL == m_pTarInfo) {  // LCOV_EXCL_BR_LINE 6: closeArchive will be set to null
77     m_pathAndName = f_pathAndName;
78
79     /* check if directory exists */
80     size_t l_found = f_pathAndName.find_last_of('/');
81     std::string l_path = f_pathAndName.substr(0, l_found);
82
83     if (0 != access(l_path.c_str(), F_OK)) {
84       FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Directory does not exist. Creating...");
85       l_eFrameworkunifiedStatus = CFSDirectory::CreateDirectory(l_path);
86     }
87
88     /* create archive in tmp */
89     m_tmpName = "/tmp/log.tar.gz";
90
91     int l_tarRetVal = tar_open(&m_pTarInfo, const_cast<char*>(m_tmpName.c_str()),
92                                 &m_gztype,
93                                 O_WRONLY | O_CREAT,
94                                 TARMODE,
95                                 TAR_GNU);
96
97     if ((l_tarRetVal != 0) || (m_pTarInfo == NULL) || (g_gzFile == NULL)) {  // LCOV_EXCL_BR_LINE 5: tar_open's error case.  // NOLINT[whitespace/line_length]
98       // LCOV_EXCL_START 5: tar_open's error case.
99       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
100       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Could not open TAR-Archive!");
101       l_eFrameworkunifiedStatus = eFrameworkunifiedStatusAccessError;
102       // LCOV_EXCL_STOP
103     }
104   } else {
105     // LCOV_EXCL_START 6: closeArchive will be set to null
106     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
107     FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "Tar is still open");
108     l_eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
109     // LCOV_EXCL_STOP
110   }
111
112   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
113   return (l_eFrameworkunifiedStatus);
114 }
115
116 EFrameworkunifiedStatus CErrorEventArchive::addToArchive(std::string f_filePathAndName,
117                                             std::string f_destinationName,
118                                             UI_8 f_depth) {
119   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
120   EFrameworkunifiedStatus l_eFrameworkunifiedStatus = eFrameworkunifiedStatusFileLoadError;
121   struct stat l_stat;
122   int l_statRetVal;
123
124   if (0 != access(f_filePathAndName.c_str(), F_OK)) {  // LCOV_EXCL_BR_LINE 200: file is aways exist
125     // LCOV_EXCL_START 200: file is aways exist
126     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
127     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
128            " Error. The specified file path and name does not exist: %s",
129            f_filePathAndName.c_str());
130     // LCOV_EXCL_STOP
131   } else if (0 != (l_statRetVal = stat(f_filePathAndName.c_str(), &l_stat))) {  // LCOV_EXCL_BR_LINE 5: stat's error case.  // NOLINT[whitespace/line_length]
132     // LCOV_EXCL_START 5: stat's error case.
133     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
134     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
135            " Error. stat() for file or directory returned error: %s -> %d",
136            f_filePathAndName.c_str(), l_statRetVal);
137     // LCOV_EXCL_STOP
138   } else if (0 != S_ISDIR(l_stat.st_mode)) {
139     if (0 < f_depth) {  // LCOV_EXCL_BR_LINE 6: it aways 4
140       l_eFrameworkunifiedStatus = addDirectoryToArchive(f_filePathAndName, f_destinationName,
141                                            f_depth);
142     } else {
143       // LCOV_EXCL_START 6: it aways 4
144       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
145       FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__,
146              "Maximum recursive depth reached! File %s not added to archive.",
147              f_filePathAndName.c_str());
148       // LCOV_EXCL_STOP
149     }
150   } else if (0 != S_ISREG(l_stat.st_mode)) {  // LCOV_EXCL_BR_LINE 200: it can not be a symbolic link
151     l_eFrameworkunifiedStatus = addFileToArchive(f_filePathAndName, f_destinationName);
152   } else {
153     // LCOV_EXCL_START 200: it can not be a symbolic link
154     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
155     FRAMEWORKUNIFIEDLOG(
156         ZONE_ERR,
157         __FUNCTION__,
158         " Error. specified file may be a symbolic link or other non 'regular' type. File: %s, mode: 0x%04X.",
159         f_filePathAndName.c_str(), l_stat.st_mode);
160     // LCOV_EXCL_STOP
161   }
162
163   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
164   return (l_eFrameworkunifiedStatus);
165 }
166
167 // LCOV_EXCL_START 8: can not be called
168 EFrameworkunifiedStatus CErrorEventArchive::addToArchive(
169     std::vector<std::string> f_filePathAndNameList) {
170   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
171   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
172   EFrameworkunifiedStatus l_eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
173
174   std::vector<std::string>::iterator l_vIter = f_filePathAndNameList.begin();
175   while ((eFrameworkunifiedStatusOK == l_eFrameworkunifiedStatus)
176       && (l_vIter != f_filePathAndNameList.end())) {
177     l_eFrameworkunifiedStatus = addToArchive(*l_vIter, *l_vIter);
178     l_vIter++;
179   }
180
181   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
182   return (l_eFrameworkunifiedStatus);
183 }
184 // LCOV_EXCL_STOP
185
186 EFrameworkunifiedStatus CErrorEventArchive::closeArchive(void) {
187   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
188   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
189
190   if (0 != tar_append_eof(m_pTarInfo)) {  // LCOV_EXCL_BR_LINE 5: tar_append_eof's error case.
191     // LCOV_EXCL_START 5: tar_append_eof's error case.
192     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
193     FRAMEWORKUNIFIEDLOG(ZONE_INFO, __PRETTY_FUNCTION__, "tar_append_eof()");
194     l_eStatus = eFrameworkunifiedStatusFail;
195     // LCOV_EXCL_STOP
196   }
197   if (0 != tar_close(m_pTarInfo)) {  // LCOV_EXCL_BR_LINE 5: tar_close's error case.
198     // LCOV_EXCL_START 5: tar_close's error case.
199     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
200     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Could not close archive");
201     l_eStatus = eFrameworkunifiedStatusFail;
202     // LCOV_EXCL_STOP
203   } else {
204     m_pTarInfo = NULL;
205     g_gzFile = NULL;
206   }
207
208   if (eFrameworkunifiedStatusOK == l_eStatus) {  // LCOV_EXCL_BR_LINE 6: it aways be ok
209 #ifdef RELEASE_BUILD
210     l_eStatus = CLoggerUtil::PathCheckAndCopyFile(m_tmpName, m_pathAndName);
211 #else
212     l_eStatus = CLoggerUtil::CopyFile(m_tmpName, m_pathAndName);
213 #endif  // RELEASE_BUILD
214     if (eFrameworkunifiedStatusOK == l_eStatus) {
215       l_eStatus =
216           (0 == remove(m_tmpName.c_str())) ? eFrameworkunifiedStatusOK : eFrameworkunifiedStatusFault;
217       if (eFrameworkunifiedStatusOK != l_eStatus) {  // LCOV_EXCL_BR_LINE 5: remove's error case.
218         // LCOV_EXCL_START 5: remove's error case.
219         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
220         FRAMEWORKUNIFIEDLOG(
221             ZONE_WARN,
222             __FUNCTION__,
223             " Warning. Failed to remove temporary archive. Will overwrite on next event");
224         // LCOV_EXCL_STOP
225       }
226     } else if (eFrameworkunifiedStatusErrNoEAGAIN == l_eStatus) {  // LCOV_EXCL_BR_LINE 200: write can not be ErrNoEAGAIN
227       // LCOV_EXCL_START 200: write can not be ErrNoEAGAIN
228       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
229       // disk space full
230       struct stat st_buf;
231       size_t req_size;
232       if (stat(m_tmpName.c_str(), &st_buf) != -1) {  // LCOV_EXCL_BR_LINE 5: stat's error case.
233         req_size = st_buf.st_size;
234         if (eFrameworkunifiedStatusOK
235             == CLoggerUtil::forceDeleteOldLog(m_pathAndName, req_size)) {
236 #ifdef RELEASE_BUILD
237           l_eStatus = CLoggerUtil::PathCheckAndCopyFile(m_tmpName, m_pathAndName);
238 #else
239           l_eStatus = CLoggerUtil::CopyFile(m_tmpName, m_pathAndName);
240 #endif  // RELEASE_BUILD
241           if (eFrameworkunifiedStatusOK != l_eStatus) {  // LCOV_EXCL_BR_LINE 200: PathCheckAndCopyFile can not be fail
242             FRAMEWORKUNIFIEDLOG(
243                 ZONE_ERR,
244                 __FUNCTION__,
245                 "Try Again but Error. Failed to copy to destination.%s, size=%d",
246                 m_pathAndName.c_str(), req_size);
247           }
248         } else {
249           FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
250                  "Error. force delete failed.%s, size=%d",
251                  m_pathAndName.c_str(), req_size);
252         }
253         FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, " emmc full: dest=%s, size=%d",
254                m_pathAndName.c_str(), req_size);
255       } else {
256         // LCOV_EXCL_START 5: stat's error case.
257         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
258         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
259                "Warning. Failed to get tmp log file stat. dest=%s",
260                m_pathAndName.c_str());
261         // LCOV_EXCL_STOP
262       }
263       // LCOV_EXCL_STOP
264     } else {
265       /*should we copy lost archive to emmc??*/
266       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
267              " Error. Failed to copy to destination. %s", m_pathAndName.c_str());
268     }
269     remove(m_tmpName.c_str());
270     m_tmpName = "";
271   }
272
273   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
274   return (l_eStatus);
275 }
276
277 EFrameworkunifiedStatus CErrorEventArchive::addFileToArchive(std::string f_filename,
278                                                 std::string f_destinationName) {
279   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
280   EFrameworkunifiedStatus l_eFrameworkunifiedStatus = eFrameworkunifiedStatusOK; /*check if Tar is open and if file can be read */
281
282   char path[PATH_MAX];
283
284   if ((NULL != m_pTarInfo) && (0 != f_destinationName.length())  // LCOV_EXCL_BR_LINE 200: it will awalys be true
285       && (realpath(f_filename.c_str(), path) != NULL)) {
286     int l_tarRetVal = tar_append_file(m_pTarInfo, path,
287                                       const_cast<char*>(f_destinationName. c_str()));
288     if (0 != l_tarRetVal) {  // LCOV_EXCL_BR_LINE 5: tar_append_file's error case.
289       // LCOV_EXCL_START 5: tar_append_file's error case.
290       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
291       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
292              "Could not add file \'%s\' to tar archive.", f_filename.c_str());
293       l_eFrameworkunifiedStatus = eFrameworkunifiedStatusAccessError;
294       // LCOV_EXCL_STOP
295     }
296   } else {
297     // LCOV_EXCL_START 200: it will awalys be true
298     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
299     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
300            "Archive not opened or could not access file: \"%s\"",
301            f_filename.c_str());
302     l_eFrameworkunifiedStatus = eFrameworkunifiedStatusInvldParam;
303     // LCOV_EXCL_STOP
304   }
305
306   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
307   return (l_eFrameworkunifiedStatus);
308 }
309
310 EFrameworkunifiedStatus CErrorEventArchive::addDirectoryToArchive(
311     std::string f_path, std::string f_destinationName, UI_8 f_depth) {
312   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
313   EFrameworkunifiedStatus l_eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
314   struct dirent l_pDirent;
315   struct dirent* next;
316
317   DIR *l_pDir = opendir(f_path.c_str());
318   if (l_pDir != NULL) {  // LCOV_EXCL_BR_LINE 5: opendir's error case.
319     while (0 == readdir_r(l_pDir, &l_pDirent, &next) && next != NULL) {
320       if ((0 != strcmp(l_pDirent.d_name, ".")) && /* Ignore special  . directory.                     */
321       (0 != strcmp(l_pDirent.d_name, "..")) && /* Ignore special .. directory.                     */
322       (0 != strcmp(l_pDirent.d_name, "lost+found")) && /* Ignore lost+found.                     */
323       ('.' != l_pDirent.d_name[0])) {  /* Ignore hidden files                              */
324         std::string l_extension = "/";
325         std::string l_fileName = f_path;
326         std::string l_destName = f_destinationName;
327         l_extension.append(l_pDirent.d_name);
328         l_fileName.append(l_extension);
329         l_destName.append(l_extension);
330         l_eFrameworkunifiedStatus = addToArchive(l_fileName, l_destName, static_cast<UI_8>(f_depth - 1));
331       }
332     }
333
334     closedir(l_pDir);
335   }
336
337   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
338   return (l_eFrameworkunifiedStatus);
339 }
340
341 SI_32 CErrorEventArchive::gzOpenArchive(PCHAR f_pcPathname, SI_32 f_siOflags,
342                                         SI_32 f_siMode) {
343   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
344   SI_32 l_siFileDescriptor = -1;
345
346   if (f_pcPathname) {  // LCOV_EXCL_BR_LINE 6: Pathname is awalys be set
347     PCHAR l_pcGzoflags;
348
349     switch (f_siOflags & O_ACCMODE) {  // LCOV_EXCL_BR_LINE 6: only O_WRONLY be set
350       case O_WRONLY: {
351         l_pcGzoflags = (PCHAR) "wb";
352         break;
353       }
354       // LCOV_EXCL_START 6: only O_WRONLY be set
355       case O_RDONLY: {
356         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
357         l_pcGzoflags = (PCHAR) "rb";
358         break;
359       }
360       // LCOV_EXCL_STOP
361       case O_RDWR:
362       default: {
363         return -1;
364       }
365     }
366
367     if (-1 == (l_siFileDescriptor =  // LCOV_EXCL_BR_LINE 5: open's error case.
368         open(f_pcPathname, f_siOflags, f_siMode))) {
369       // LCOV_EXCL_START 5: open's error case.
370       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
371       FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
372       return -1;
373       // LCOV_EXCL_STOP
374     }
375
376     if ((f_siOflags & O_CREAT)  // LCOV_EXCL_BR_LINE 5: fchmod's error case.
377         && fchmod(l_siFileDescriptor, f_siMode)) {
378       // LCOV_EXCL_START 5: fchmod's error case.
379       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
380       close(l_siFileDescriptor);
381       FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
382       return -1;
383       // LCOV_EXCL_STOP
384     }
385
386     g_gzFile = gzdopen(l_siFileDescriptor, l_pcGzoflags);
387     if (!g_gzFile) {  // LCOV_EXCL_BR_LINE 5: gzdopen's error case.
388       // LCOV_EXCL_START 5: gzdopen's error case.
389       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
390       close(l_siFileDescriptor);
391       FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
392       return -1;
393       // LCOV_EXCL_STOP
394     }
395   } else {
396     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Source Path empty.");
397   }
398
399   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
400   return (SI_32) l_siFileDescriptor;
401 }
402 SI_32 CErrorEventArchive::gzCloseArchive() {
403   return gzclose(g_gzFile);
404 }
405
406 ssize_t CErrorEventArchive::gzWriteArchive(int fd, const void* buf,
407                                            size_t count) {
408   return gzwrite(g_gzFile, const_cast<void*>(buf), (unsigned int) count);
409 }
410
411 ssize_t CErrorEventArchive::gzReadArchive(int fd, void* buf, size_t count) {
412   return gzread(g_gzFile, buf, (unsigned int) count);
413 }