70f120c584d50aaa625764c8eb0ec46c99c263cc
[staging/basesystem.git] / service / system / version_library / library / src / ss_ver.cc
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 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <sys/file.h>
20 #include <dirent.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23
24 #include <native_service/ns_logger_if.h>
25 #include <system_service/ss_templates.h>
26
27 #include <system_service/ss_ver.h>
28
29 // For DEBUG
30 #define ZONE_INIT    ZONEMASK(10)
31 #define ZONE_FUNC    ZONEMASK(11)
32 #define ZONE_MEM     ZONEMASK(12)
33 #define ZONE_INFO    ZONEMASK(29)
34 #define ZONE_WARN    ZONEMASK(30)
35 #define ZONE_ERR     ZONEMASK(31)
36
37 #define ZONE_DEFAULT ZONE_FUNC
38
39 #define SSVER_TMPDIR "/tmp/ssver"
40
41 // FILE IO
42 class CPkgInfoIo {
43  private:
44   int m_fd;
45   std::string m_path;
46   static std::map<std::string, int> m_dbgCnt;  // Debug information for exclusive leakage check
47
48   void openFD(const int32_t mode) {
49     m_fd = open(m_path.c_str(), mode, 0664);  // LCOV_EXCL_BR_LINE 11:except,C++ STL
50     if (m_fd == -1) {
51       SS_ASERT_ERRNO(0);  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h
52       throw eFrameworkunifiedStatusFail;
53     }
54
55     // File lock to protect file accesses
56     SS_ASERT_ERRNO(0 == flock(m_fd, LOCK_EX));  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h
57     // LCOV_EXCL_BR_START 11:Unexpected branch
58     m_dbgCnt[m_path]++;
59     SS_ASERT_LOG(m_dbgCnt[m_path] == 1, "%s:%d", m_path.c_str(),  // LCOV_EXCL_BR_LINE 15: marco define @ss_templates.h
60                  m_dbgCnt[m_path]);
61     // LCOV_EXCL_BR_STOP
62   }
63
64 public:
65   CPkgInfoIo(const std::string& pkgName)
66     : m_fd(-1),
67       m_path(SSVER_TMPDIR) {  // LCOV_EXCL_BR_LINE 11:Unexpected branch
68     FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT,__FUNCTION__,"+:%s",pkgName.c_str());
69     m_path += "/";
70     m_path += pkgName;
71  
72      FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT,__FUNCTION__,"-");
73    }
74
75   ~CPkgInfoIo() {
76     FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "+");
77
78     // LCOV_EXCL_BR_START 11:Unexpected branch
79     m_dbgCnt[m_path]--;
80     SS_ASERT_LOG(m_dbgCnt[m_path] == 0, "%s:%d", m_path.c_str(),  // LCOV_EXCL_BR_LINE 15: marco define @ss_templates.h
81                  m_dbgCnt[m_path]);
82     SS_ASERT_ERRNO(0 == flock(m_fd, LOCK_UN));  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h
83
84     if (m_fd != -1) {
85       SS_ASERT_ERRNO(0 == close(m_fd));  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h
86     }
87     // LCOV_EXCL_BR_STOP
88     FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "-");
89   }
90
91   void putData(SSVER_PkgInfo &info) {  //  NOLINT (readability/nolint)
92     FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "+");
93     openFD(O_RDWR|O_CREAT|O_CLOEXEC);
94     ssize_t wsz;
95     wsz = write(m_fd, &info, sizeof(info));
96     if (wsz != sizeof(info)) {  // LCOV_EXCL_BR_LINE 5:std c lib error process
97       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
98
99       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed write(). wsz=%d size=%d errno=%d",  // LCOV_EXCL_LINE 5: glibc fail safe
100              wsz, sizeof(info), errno);  // LCOV_EXCL_LINE 5:std c lib error process
101       throw eFrameworkunifiedStatusFail;  // LCOV_EXCL_LINE 5:std c lib error process
102     }
103     FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "-");
104   }
105
106   void getData(SSVER_PkgInfo* p_info) {
107     FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "+");
108     openFD(O_RDONLY|O_CLOEXEC);
109
110     ssize_t rsz;
111     rsz = my_read(m_fd, p_info, sizeof(*p_info));
112     if (rsz != sizeof(*p_info)) {  // LCOV_EXCL_BR_LINE 5:std c lib error process
113       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
114
115       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed read(). rsz=%d size=%d", rsz,  // LCOV_EXCL_LINE 5:std c lib error process
116              sizeof(*p_info));  // LCOV_EXCL_LINE 5:std c lib error process
117       p_info->version[0] = '\0';  // LCOV_EXCL_LINE 5:std c lib error process
118       p_info->date[0] = '\0';  // LCOV_EXCL_LINE 5:std c lib error process
119       throw eFrameworkunifiedStatusFail;  // LCOV_EXCL_LINE 5:std c lib error process
120     }
121     FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "-");
122   }
123
124   int my_read(int fd, void* buf, int size) {
125     int done = 0;
126     char *buffer = reinterpret_cast<char*>(buf);
127     int sz = done;
128
129     while (size > 0) {
130       done = read(fd, buffer + done, size);
131       if (done < 0) {  // LCOV_EXCL_BR_LINE 5:std c lib error process
132         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
133
134         SS_ASERT_ERRNO(0);  // LCOV_EXCL_LINE 5:std c lib error process
135         if (errno == EINTR) {  // LCOV_EXCL_LINE 5:std c lib error process
136           continue;
137         } else {
138           return done;
139         }
140       } else if (done == 0) {  // LCOV_EXCL_BR_LINE 5:std c lib error process
141         return sz;
142       }
143       size -= done;
144       sz += done;
145     }
146     return sz;
147   }
148 };
149
150 std::map<std::string, int> CPkgInfoIo::m_dbgCnt;  // Actual status
151
152 //==================================================================
153 //                  private
154 //==================================================================
155 void CSSVer::dump(void) const {  // LCOV_EXCL_START 7:debugging process
156   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
157
158   std::string dumpStr;
159   dumpStr = "VERINFO DUMP\n";
160
161   for (SSVerPkgList::const_iterator ite = m_verList.begin();
162       ite != m_verList.end(); ite++) {
163     dumpStr += ite->first;
164     dumpStr += "\n";
165     dumpStr += ite->second.version;
166     dumpStr += "\n";
167     dumpStr += ite->second.date;
168     dumpStr += "\n";
169   }
170
171   FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "%s", dumpStr.c_str());
172 }
173 // LCOV_EXCL_STOP
174
175 //==================================================================
176 //                  PUBLIC
177 //==================================================================
178 CSSVer::CSSVer() {
179   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "+");
180   DIR *dir = NULL;
181   struct dirent dent, *next;
182   struct stat statbuf;
183
184   try {
185     if (stat(SSVER_TMPDIR, &statbuf) != 0) {
186       mkdir(SSVER_TMPDIR, 0775);
187       // Because this process is not locked, if multiple processes process at the same time,
188       // although it may have been created and fail, do not ASSERT it because it is harmless.
189     }
190
191     // Linux dependency codes
192     if ((dir = opendir(SSVER_TMPDIR)) == NULL) {  // LCOV_EXCL_BR_LINE 5:std c lib error process
193       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
194
195       SS_ASERT_ERRNO(0);  // LCOV_EXCL_LINE 5:std c lib error process
196       throw eFrameworkunifiedStatusFail;
197     }
198
199     // LCOV_EXCL_BR_START 11:Unexpected branch
200     while (0 == readdir_r(dir, &dent, &next) && next) {
201       if (DT_REG == dent.d_type) {
202         SSVER_PkgInfo info;
203         std::string name(dent.d_name);
204         std::string verInfo;
205
206         CPkgInfoIo pkgIo(name);
207         pkgIo.getData(&info);
208
209         verInfo += "\nPACKAGE :";
210         verInfo += name;
211         verInfo += "\n";
212         verInfo += "  VERSION:";
213         verInfo += info.version;
214         verInfo += "\n";
215         verInfo += "  DATE   :";
216         verInfo += info.date;
217         verInfo += "\n";
218         FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "%s", verInfo.c_str());
219
220         m_verList.insert(std::make_pair(name, info));
221       }
222     }
223     SS_ASERT_ERRNO(0 == closedir(dir));  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h
224     // LCOV_EXCL_BR_STOP
225   } catch (...) {  // LCOV_EXCL_START 6:unable to reach
226     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
227
228     if (dir) {
229       SS_ASERT_ERRNO(0 == closedir(dir));
230     }
231   }  // LCOV_EXCL_STOP
232   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "-");
233 }
234
235 CSSVer::~CSSVer() {
236   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "+");
237   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "-");
238 }
239
240 EFrameworkunifiedStatus CSSVer::getPkgInfo(const std::string &name, SSVER_PkgInfo* p_info) {
241   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "+");
242   EFrameworkunifiedStatus versionlibraryRet = eFrameworkunifiedStatusOK;
243   try {
244     if (p_info == NULL) {
245       SS_ASERT(0);  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h
246       throw eFrameworkunifiedStatusFail;
247     }
248
249     SSVerPkgList::iterator ite = m_verList.find(name);
250
251     if (ite != m_verList.end()) {
252       // cache hit
253       *p_info = ite->second;
254     } else {
255       // cache miss
256       std::string path(SSVER_TMPDIR);  // LCOV_EXCL_BR_LINE 11:except,C++ STL
257       path += "/";
258       path += name;
259
260       if (access(path.c_str(), F_OK) == 0) {
261         // cache refresh
262         CPkgInfoIo pkgIo(name);  // LCOV_EXCL_BR_LINE 11:Unexpected branch
263         pkgIo.getData(p_info);  // LCOV_EXCL_BR_LINE 11:except,C++ STL
264         m_verList.insert(std::make_pair(name, *p_info));  // LCOV_EXCL_BR_LINE 11:except,C++ STL
265       } else {
266         throw eFrameworkunifiedStatusFileLoadError;
267       }
268     }
269   } catch (EFrameworkunifiedStatus ee) {
270     versionlibraryRet = ee;
271   } catch (...) {  // LCOV_EXCL_START 6:unable to reach
272     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
273
274     versionlibraryRet = eFrameworkunifiedStatusFail;
275   }  // LCOV_EXCL_STOP
276   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "-");
277   return versionlibraryRet;
278 }
279
280 EFrameworkunifiedStatus CSSVer::setPkgInfo(const std::string &name, SSVER_PkgInfo &info) {
281   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "+");
282   EFrameworkunifiedStatus versionlibraryRet = eFrameworkunifiedStatusOK;
283   try {
284     // LCOV_EXCL_BR_START 11:Unexpected branch
285     SSVerPkgList::iterator ite = m_verList.find(name);
286
287     if (ite == m_verList.end()) {
288       m_verList.insert(std::make_pair(name, info));
289       CPkgInfoIo pkgIo(name);
290       pkgIo.putData(info);
291     } else {
292       ite->second = info;
293       CPkgInfoIo pkgIo(name);
294       pkgIo.putData(info);
295     }
296     // LCOV_EXCL_BR_STOP
297   } catch (EFrameworkunifiedStatus ee) {
298     versionlibraryRet = ee;
299   } catch (...) {  // LCOV_EXCL_START 6:unable to reach
300     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
301
302     SS_ASERT(0);  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h
303     versionlibraryRet = eFrameworkunifiedStatusFail;
304   }   // LCOV_EXCL_STOP
305
306   FRAMEWORKUNIFIEDLOG(ZONE_DEFAULT, __FUNCTION__, "-");
307   return versionlibraryRet;
308 }  // LCOV_EXCL_BR_LINE 10:for the last line
309