2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup tag_NPService
19 /// \brief This file contains the API to store and retrieve immediate
20 /// notification data from and to persistent storage.
24 ///////////////////////////////////////////////////////////////////////////////
26 ///////////////////////////////////////////////////////////////////////////////
28 ///////////////////////////////////////////////////////////////////////////////
33 #include <semaphore.h>
36 #include <native_service/ns_np_service.h>
37 #include <native_service/ns_np_service_protocol.h>
38 #include <native_service/ns_np_service_if.h>
39 #include <native_service/ns_message_center_if.h>
40 #include <native_service/ns_util_directory.h>
41 #include <native_service/ns_np_service_nor_persistence.h>
42 #include <native_service/frameworkunified_framework_types.h>
46 #include <native_service/ns_np_service_nor_persistence_internal.h>
47 #include <native_service/ns_np_types.h>
48 #include <native_service/ns_mc_system_info.h>
50 sem_t g_FileAccessSemaphore;
52 ////////////////////////////////////////////////////////////////////////////////////////////////////
53 /// NPSynchronousReadPersistentData
54 /// Read immediate persistent data from the persistent memory
55 ////////////////////////////////////////////////////////////////////////////////////////////////////
56 EFrameworkunifiedStatus NPSynchronousReadPersistentData(PCSTR pAppName,
60 const EFrameworkunifiedPersistCategory ePersistCategory) {
61 EFrameworkunifiedStatus eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
62 NC_NorPersistentData l_tNorPersistentData = {};
64 if (NULL != pAppName && NULL != notif_name && NULL != pData) {
65 if (eFrameworkunifiedStatusOK != NPSynchronousGetPersistentData(pAppName, notif_name, pData, uiDataSize, l_tNorPersistentData,
67 eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
70 eFrameworkunifiedStatus = eFrameworkunifiedStatusInvldParam;
73 return eFrameworkunifiedStatus;
76 ////////////////////////////////////////////////////////////////////////////////////////////////////
77 /// NPSynchronousGetPersistentData
78 /// Get the notification data from the persistent storage
79 ////////////////////////////////////////////////////////////////////////////////////////////////////
80 EFrameworkunifiedStatus NPSynchronousGetPersistentData(PCSTR pAppName,
84 NC_NorPersistentData &ptImmediatePersistentData, // NOLINT (readability/nolint)
85 const EFrameworkunifiedPersistCategory ePersistCategory) {
86 EFrameworkunifiedStatus eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
88 if (NULL != notif_name && NULL != pData && 0 < uiDataSize) {
89 FILE *l_fFilePtr = NULL;
91 if (0 == sem_init(&g_FileAccessSemaphore, 1, 1)) { // LCOV_EXCL_BR_LINE 5: sem_init's error case
92 if (sem_wait(&g_FileAccessSemaphore) == 0) { // LCOV_EXCL_BR_LINE 5: sem_wait's error case
93 // Create unique filename
94 std::string l_cTempPath = notif_name;
95 size_t l_uiTempPathSize = 0;
97 std::string l_cPath = "";
98 std::string l_cNewPath = IMMEDIATE_PERSISTENCE_STORAGE_V2;
99 std::string l_cOldPath = IMMEDIATE_PERSISTENCE_STORAGE_V1;
101 // replace all '/' by '_'
102 l_uiTempPathSize = l_cTempPath.find_first_of("/");
103 while (std::string::npos != l_uiTempPathSize) {
104 l_cTempPath[l_uiTempPathSize] = '_';
105 l_uiTempPathSize = l_cTempPath.find_first_of("/", l_uiTempPathSize + 1);
108 switch (ePersistCategory) {
109 case eFrameworkunifiedFactoryData: {
110 l_cNewPath.append(FACTORYDATADIR);
114 case eFrameworkunifiedFactoryCustomerData: {
115 l_cNewPath.append(FACTORYCUSTOMERDATADIR);
119 case eFrameworkunifiedDealerData: {
120 l_cNewPath.append(DEALERDATADIR);
124 case eFrameworkunifiedUserData:
126 l_cNewPath.append(USERDATADIR);
127 l_cNewPath.append(ALLUSERAPPDATADIR);
132 l_cNewPath.append(IMMEDIATEDATADIR);
133 l_cNewPath.append(l_cTempPath);
135 if (NULL != pAppName) { // LCOV_EXCL_BR_LINE 6: pAppName was checed in NPSynchronousReadPersistentData
136 l_cNewPath.append(pAppName);
139 if (0 == access(l_cNewPath.c_str(), F_OK)) {
140 l_cPath.assign(l_cNewPath);
142 l_cOldPath.append(l_cTempPath);
143 if (NULL != pAppName) { // LCOV_EXCL_BR_LINE 6: pAppName was checed in NPSynchronousReadPersistentData
144 l_cOldPath.append(pAppName);
147 if (0 == access(l_cOldPath.c_str(), F_OK)) {
148 l_cPath.assign(l_cOldPath);
150 eFrameworkunifiedStatus = eFrameworkunifiedStatusFileLoadError;
154 if (eFrameworkunifiedStatusOK == eFrameworkunifiedStatus) {
156 // Open and read from a file
157 l_fFilePtr = fopen(l_cPath.c_str(), "re");
158 if (NULL != l_fFilePtr) {
159 // read notification info structure
160 if (fread(&ptImmediatePersistentData, 1, sizeof(ptImmediatePersistentData),
161 l_fFilePtr) == sizeof(ptImmediatePersistentData)) {
162 if (0 == feof(l_fFilePtr)) {
164 PersistData = fread(pData, 1, uiDataSize, l_fFilePtr);
165 if (PersistData != uiDataSize) {
166 eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
169 eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
172 eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
176 eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
180 sem_post(&g_FileAccessSemaphore);
182 eFrameworkunifiedStatus = eFrameworkunifiedStatusErrOther;
184 sem_destroy(&g_FileAccessSemaphore);
186 eFrameworkunifiedStatus = eFrameworkunifiedStatusErrOther;
189 eFrameworkunifiedStatus = eFrameworkunifiedStatusInvldParam;
191 return eFrameworkunifiedStatus;
194 ////////////////////////////////////////////////////////////////////////////////////////////////////
195 /// NPSynchronousWritePersistentData
196 /// Store the notification data on the persistent memory
197 ////////////////////////////////////////////////////////////////////////////////////////////////////
198 EFrameworkunifiedStatus NPSynchronousWritePersistentData(PCSTR pAppName,
201 const UI_32 uiDataSize,
202 const EFrameworkunifiedPersistCategory ePersistCategory) {
203 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
205 HANDLE l_hReceiverMq = NULL;
207 // if this API is used to write the data directly then max data size will be same as data write size
208 l_eStatus = SynchronousWritePersistentData(pAppName, notif_name, pData, uiDataSize, 0, uiDataSize, ePersistCategory);
210 l_hReceiverMq = McOpenSender(FRAMEWORKUNIFIED_NS_NPSERVICE);
212 if (NULL != l_hReceiverMq) {
213 (VOID)McSendWithSysInfo(l_hReceiverMq,
215 NPS_SYNCHRONOUS_WRITE_NOTIFY_REQ,
221 McClose(l_hReceiverMq);
227 ////////////////////////////////////////////////////////////////////////////////////////////////////
228 /// SynchronousWritePersistentData
229 /// Store the notification data on the persistent memory
230 ////////////////////////////////////////////////////////////////////////////////////////////////////
231 EFrameworkunifiedStatus SynchronousWritePersistentData(PCSTR pAppName,
234 const UI_32 uiDataSize,
236 const UI_32 uiMaxSize,
237 const EFrameworkunifiedPersistCategory ePersistCategory) {
238 EFrameworkunifiedStatus eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
239 FILE *l_fFilePtr = NULL;
240 NC_NorPersistentData l_tImmediatePersistentData = {};
242 if (NULL != notif_name && NULL != pAppName && NULL != pData) {
243 if (strlen(notif_name) < MAX_STRING_SIZE_NOTIFICATION && strlen(pAppName) < MAX_NAME_SIZE_APP) {
244 // Create unique filename
245 std::string l_cTempPath = notif_name;
246 size_t l_uiTempPathSize = 0;
248 // replace all '/' by '_'
249 l_uiTempPathSize = l_cTempPath.find_first_of("/");
250 while (std::string::npos != l_uiTempPathSize) {
251 l_cTempPath[l_uiTempPathSize] = '_';
252 l_uiTempPathSize = l_cTempPath.find_first_of("/", l_uiTempPathSize + 1);
255 strncpy(l_tImmediatePersistentData.notificationName, notif_name,
256 sizeof(l_tImmediatePersistentData.notificationName) - 1);
257 strncpy(l_tImmediatePersistentData.pPublisherName, pAppName,
258 sizeof(l_tImmediatePersistentData.pPublisherName) - 1);
259 l_tImmediatePersistentData.dataSize = uiDataSize;
260 l_tImmediatePersistentData.uiDelay = uiDelay;
261 l_tImmediatePersistentData.uiMaxSize = uiMaxSize;
263 if (0 == sem_init(&g_FileAccessSemaphore, 1, 1)) { // LCOV_EXCL_BR_LINE 5: sem_init's error case
264 if (sem_wait(&g_FileAccessSemaphore) == 0) { // LCOV_EXCL_BR_LINE 5: sem_wait's error case
265 std::string l_cPath = IMMEDIATE_PERSISTENCE_STORAGE_V2;
267 switch (ePersistCategory) {
268 case eFrameworkunifiedFactoryData: {
269 l_cPath.append(FACTORYDATADIR);
273 case eFrameworkunifiedFactoryCustomerData: {
274 l_cPath.append(FACTORYCUSTOMERDATADIR);
278 case eFrameworkunifiedDealerData: {
279 l_cPath.append(DEALERDATADIR);
283 case eFrameworkunifiedUserData:
285 l_cPath.append(USERDATADIR);
286 l_cPath.append(ALLUSERAPPDATADIR);
291 l_cPath.append(IMMEDIATEDATADIR);
293 if (!DoesDirecotryExist(l_cPath)) {
294 eFrameworkunifiedStatus = CreateDirectory(l_cPath);
297 if (eFrameworkunifiedStatusOK == eFrameworkunifiedStatus) {
298 l_cPath.append(l_cTempPath);
300 l_cPath.append(pAppName);
302 l_fFilePtr = fopen(l_cPath.c_str(), "we");
303 if (NULL != l_fFilePtr) {
305 fwrite(&l_tImmediatePersistentData , 1 , sizeof(l_tImmediatePersistentData) , l_fFilePtr);
306 if (0 == ferror(l_fFilePtr)) {
308 fwrite(pData , 1 , uiDataSize , l_fFilePtr);
309 if (0 != ferror(l_fFilePtr)) {
310 eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
313 fsync(fileno(l_fFilePtr));
318 sem_post(&g_FileAccessSemaphore);
320 sem_destroy(&g_FileAccessSemaphore);
322 eFrameworkunifiedStatus = eFrameworkunifiedStatusErrOther;
325 eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
328 eFrameworkunifiedStatus = eFrameworkunifiedStatusInvldParam;
330 return eFrameworkunifiedStatus;
333 ////////////////////////////////////////////////////////////////////////////////////////////////////
334 /// NPSynchronousGetPersistentDataSize
335 /// Get the size of the notification data stored in the persistent memory
336 ////////////////////////////////////////////////////////////////////////////////////////////////////
337 EFrameworkunifiedStatus NPSynchronousGetPersistentDataSize(PCSTR notif_name, PUI_32 uiDataSize,
338 const EFrameworkunifiedPersistCategory ePersistCategory) {
339 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
341 if (NULL != notif_name && NULL != uiDataSize) {
342 FILE *l_fFilePtr = NULL;
343 NC_NorPersistentData l_ptImmediatePersistentData = {};
347 if (0 == sem_init(&g_FileAccessSemaphore, 1, 1)) { // LCOV_EXCL_BR_LINE 5: sem_init's error case
348 if (sem_wait(&g_FileAccessSemaphore) == 0) { // LCOV_EXCL_BR_LINE 5: sem_wait's error case
349 // Create unique filename
350 std::string l_cTempPath = notif_name;
351 size_t l_uiTempPathSize = 0;
353 std::string l_cPath = "";
354 std::string l_cNewPath = IMMEDIATE_PERSISTENCE_STORAGE_V2;
355 std::string l_cOldPath = IMMEDIATE_PERSISTENCE_STORAGE_V1;
357 // replace all '/' by '_'
358 l_uiTempPathSize = l_cTempPath.find_first_of("/");
359 while (std::string::npos != l_uiTempPathSize) {
360 l_cTempPath[l_uiTempPathSize] = '_';
361 l_uiTempPathSize = l_cTempPath.find_first_of("/", l_uiTempPathSize + 1);
364 switch (ePersistCategory) {
365 case eFrameworkunifiedFactoryData: {
366 l_cNewPath.append(FACTORYDATADIR);
370 case eFrameworkunifiedFactoryCustomerData: {
371 l_cNewPath.append(FACTORYCUSTOMERDATADIR);
375 case eFrameworkunifiedDealerData: {
376 l_cNewPath.append(DEALERDATADIR);
380 case eFrameworkunifiedUserData:
382 l_cNewPath.append(USERDATADIR);
383 l_cNewPath.append(ALLUSERAPPDATADIR);
388 l_cNewPath.append(IMMEDIATEDATADIR);
389 l_cNewPath.append(l_cTempPath);
391 if (0 == access(l_cNewPath.c_str(), F_OK)) {
392 l_cPath.assign(l_cNewPath);
394 l_cOldPath.append(l_cTempPath);
396 if (0 == access(l_cOldPath.c_str(), F_OK)) {
397 l_cPath.assign(l_cOldPath);
399 l_eStatus = eFrameworkunifiedStatusFileLoadError;
403 if (eFrameworkunifiedStatusOK == l_eStatus) {
405 // Open and read from a file
406 l_fFilePtr = fopen(l_cPath.c_str(), "re");
407 if (NULL != l_fFilePtr) {
408 // read notification info structure
409 PersistData = fread(&l_ptImmediatePersistentData, 1, sizeof(l_ptImmediatePersistentData), l_fFilePtr);
410 if (PersistData == sizeof(l_ptImmediatePersistentData)) {
411 *uiDataSize = l_ptImmediatePersistentData.dataSize;
413 *uiDataSize = static_cast<UI_32>(PersistData);
419 sem_post(&g_FileAccessSemaphore);
421 l_eStatus = eFrameworkunifiedStatusErrOther;
424 sem_destroy(&g_FileAccessSemaphore);
426 l_eStatus = eFrameworkunifiedStatusErrOther;
429 l_eStatus = eFrameworkunifiedStatusInvldParam;
435 ////////////////////////////////////////////////////////////////////////////////////////////
436 /// SynchronousMovePersistentData
437 /// API to move all the immediate notification data from f_cSrcDir directory to
438 /// f_cDestDir directory
439 ////////////////////////////////////////////////////////////////////////////////////////////
440 EFrameworkunifiedStatus SynchronousMovePersistentData(PCSTR f_cSrcDir,
442 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
444 if (NULL != f_cSrcDir && NULL != f_cDestDir) {
445 if (0 == sem_init(&g_FileAccessSemaphore, 1, 1)) {
446 if (sem_wait(&g_FileAccessSemaphore) == 0) { // LCOV_EXCL_BR_LINE 5: sem_init's error case
447 if (DoesDirecotryExist(f_cSrcDir)) { // LCOV_EXCL_BR_LINE 5: sem_wait's error case
448 if (!DoesDirecotryExist(f_cDestDir)) {
449 l_eStatus = CreateDirectory(f_cDestDir);
452 if (eFrameworkunifiedStatusOK == l_eStatus) {
454 struct dirent *l_pdirent = NULL;
456 std::string l_cSrcPath = "";
457 std::string l_cDestPath = "";
459 if (NULL != (l_pDir = opendir(f_cSrcDir))) {
460 while (NULL != (l_pdirent = readdir(l_pDir))) {
461 if (0 != std::strcmp(l_pdirent->d_name, ".") &&
462 0 != std::strcmp(l_pdirent->d_name, "..")) {
463 l_cSrcPath.assign(f_cSrcDir);
464 l_cSrcPath.append(l_pdirent->d_name);
466 l_cDestPath.assign(f_cDestDir);
467 l_cDestPath.append(l_pdirent->d_name);
469 // move the old app user data to the UserData fodler
470 if (0 != rename(l_cSrcPath.c_str(), l_cDestPath.c_str())) {
471 l_eStatus = eFrameworkunifiedStatusFail;
479 l_eStatus = eFrameworkunifiedStatusFileLoadError;
484 sem_post(&g_FileAccessSemaphore);
486 l_eStatus = eFrameworkunifiedStatusFail;
489 sem_destroy(&g_FileAccessSemaphore);
491 l_eStatus = eFrameworkunifiedStatusFail;
494 l_eStatus = eFrameworkunifiedStatusInvldParam;