Re-organized sub-directory by category
[staging/basesystem.git] / service / native / framework_unified / client / NS_NPServiceIf / src / ns_np_service_nor_persistence.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_NPService
19 /// \brief    This file contains the API to store and retrieve immediate
20 ///           notification data from and to persistent storage.
21 ///
22 ///
23 ///
24 ///////////////////////////////////////////////////////////////////////////////
25
26 ///////////////////////////////////////////////////////////////////////////////
27 // Include Files
28 ///////////////////////////////////////////////////////////////////////////////
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <dirent.h>
33 #include <semaphore.h>
34 #include <aglpath.h>
35
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>
43
44 #include <string>
45
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>
49
50 sem_t g_FileAccessSemaphore;
51
52 ////////////////////////////////////////////////////////////////////////////////////////////////////
53 /// NPSynchronousReadPersistentData
54 /// Read immediate persistent data from the persistent memory
55 ////////////////////////////////////////////////////////////////////////////////////////////////////
56 EFrameworkunifiedStatus NPSynchronousReadPersistentData(PCSTR pAppName,
57                                            PCSTR notif_name,
58                                            PVOID pData,
59                                            UI_32 uiDataSize,
60                                            const EFrameworkunifiedPersistCategory ePersistCategory) {
61   EFrameworkunifiedStatus eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
62   NC_NorPersistentData l_tNorPersistentData = {};
63
64   if (NULL != pAppName && NULL != notif_name && NULL != pData) {
65     if (eFrameworkunifiedStatusOK != NPSynchronousGetPersistentData(pAppName, notif_name, pData, uiDataSize, l_tNorPersistentData,
66                                                        ePersistCategory)) {
67       eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
68     }
69   } else {
70     eFrameworkunifiedStatus = eFrameworkunifiedStatusInvldParam;
71   }
72
73   return eFrameworkunifiedStatus;
74 }
75
76 ////////////////////////////////////////////////////////////////////////////////////////////////////
77 /// NPSynchronousGetPersistentData
78 /// Get the notification data from the persistent storage
79 ////////////////////////////////////////////////////////////////////////////////////////////////////
80 EFrameworkunifiedStatus NPSynchronousGetPersistentData(PCSTR pAppName,
81                                   PCSTR notif_name,
82                                   PVOID pData,
83                                   UI_32 uiDataSize,
84                                   NC_NorPersistentData &ptImmediatePersistentData,  // NOLINT  (readability/nolint)
85                                   const EFrameworkunifiedPersistCategory ePersistCategory) {
86   EFrameworkunifiedStatus eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
87
88   if (NULL != notif_name && NULL != pData && 0 < uiDataSize) {
89     FILE *l_fFilePtr = NULL;
90
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;
96
97         std::string l_cPath = "";
98         std::string l_cNewPath = IMMEDIATE_PERSISTENCE_STORAGE_V2;
99         std::string l_cOldPath = IMMEDIATE_PERSISTENCE_STORAGE_V1;
100
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);
106         }
107
108         switch (ePersistCategory) {
109           case eFrameworkunifiedFactoryData: {
110               l_cNewPath.append(FACTORYDATADIR);
111             }
112             break;
113
114           case eFrameworkunifiedFactoryCustomerData: {
115               l_cNewPath.append(FACTORYCUSTOMERDATADIR);
116             }
117             break;
118
119           case eFrameworkunifiedDealerData: {
120               l_cNewPath.append(DEALERDATADIR);
121             }
122             break;
123
124           case eFrameworkunifiedUserData:
125           default: {
126               l_cNewPath.append(USERDATADIR);
127               l_cNewPath.append(ALLUSERAPPDATADIR);
128             }
129             break;
130         }
131
132         l_cNewPath.append(IMMEDIATEDATADIR);
133         l_cNewPath.append(l_cTempPath);
134
135         if (NULL != pAppName) {  // LCOV_EXCL_BR_LINE 6: pAppName was checed in NPSynchronousReadPersistentData
136           l_cNewPath.append(pAppName);
137         }
138
139         if (0 == access(l_cNewPath.c_str(), F_OK)) {
140           l_cPath.assign(l_cNewPath);
141         } else {
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);
145           }
146
147           if (0 == access(l_cOldPath.c_str(), F_OK)) {
148             l_cPath.assign(l_cOldPath);
149           } else {
150             eFrameworkunifiedStatus = eFrameworkunifiedStatusFileLoadError;
151           }
152         }
153
154         if (eFrameworkunifiedStatusOK ==  eFrameworkunifiedStatus) {
155           size_t PersistData;
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)) {
163                 // read data
164                 PersistData = fread(pData, 1, uiDataSize, l_fFilePtr);
165                 if (PersistData != uiDataSize) {
166                   eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
167                 }
168               } else {
169                 eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
170               }
171             } else {
172               eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
173             }
174             fclose(l_fFilePtr);
175           } else {
176             eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
177           }
178         }
179
180         sem_post(&g_FileAccessSemaphore);
181       } else {
182         eFrameworkunifiedStatus = eFrameworkunifiedStatusErrOther;
183       }
184       sem_destroy(&g_FileAccessSemaphore);
185     } else {
186       eFrameworkunifiedStatus = eFrameworkunifiedStatusErrOther;
187     }
188   } else {
189     eFrameworkunifiedStatus = eFrameworkunifiedStatusInvldParam;
190   }
191   return eFrameworkunifiedStatus;
192 }
193
194 ////////////////////////////////////////////////////////////////////////////////////////////////////
195 /// NPSynchronousWritePersistentData
196 /// Store the notification data on the persistent memory
197 ////////////////////////////////////////////////////////////////////////////////////////////////////
198 EFrameworkunifiedStatus NPSynchronousWritePersistentData(PCSTR pAppName,
199                                             PCSTR notif_name,
200                                             PVOID pData,
201                                             const UI_32 uiDataSize,
202                                             const EFrameworkunifiedPersistCategory ePersistCategory) {
203   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
204
205   HANDLE l_hReceiverMq = NULL;
206
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);
209
210   l_hReceiverMq = McOpenSender(FRAMEWORKUNIFIED_NS_NPSERVICE);
211
212   if (NULL != l_hReceiverMq) {
213     (VOID)McSendWithSysInfo(l_hReceiverMq,
214                             pAppName,
215                             NPS_SYNCHRONOUS_WRITE_NOTIFY_REQ,
216                             (PCHAR)notif_name,
217                             uiDataSize,
218                             pData,
219                             0);
220
221     McClose(l_hReceiverMq);
222   }
223
224   return l_eStatus;
225 }
226
227 ////////////////////////////////////////////////////////////////////////////////////////////////////
228 /// SynchronousWritePersistentData
229 /// Store the notification data on the persistent memory
230 ////////////////////////////////////////////////////////////////////////////////////////////////////
231 EFrameworkunifiedStatus SynchronousWritePersistentData(PCSTR pAppName,
232                                           PCSTR notif_name,
233                                           PVOID pData,
234                                           const UI_32 uiDataSize,
235                                           const UI_32 uiDelay,
236                                           const UI_32 uiMaxSize,
237                                           const EFrameworkunifiedPersistCategory ePersistCategory) {
238   EFrameworkunifiedStatus eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
239   FILE *l_fFilePtr = NULL;
240   NC_NorPersistentData l_tImmediatePersistentData = {};
241
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;
247
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);
253       }
254
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;
262
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;
266
267           switch (ePersistCategory) {
268             case eFrameworkunifiedFactoryData: {
269                 l_cPath.append(FACTORYDATADIR);
270               }
271               break;
272
273             case eFrameworkunifiedFactoryCustomerData: {
274                 l_cPath.append(FACTORYCUSTOMERDATADIR);
275               }
276               break;
277
278             case eFrameworkunifiedDealerData: {
279                 l_cPath.append(DEALERDATADIR);
280               }
281               break;
282
283             case eFrameworkunifiedUserData:
284             default: {
285                 l_cPath.append(USERDATADIR);
286                 l_cPath.append(ALLUSERAPPDATADIR);
287               }
288               break;
289           }
290
291           l_cPath.append(IMMEDIATEDATADIR);
292
293           if (!DoesDirecotryExist(l_cPath)) {
294             eFrameworkunifiedStatus = CreateDirectory(l_cPath);
295           }
296
297           if (eFrameworkunifiedStatusOK == eFrameworkunifiedStatus) {
298             l_cPath.append(l_cTempPath);
299
300             l_cPath.append(pAppName);
301
302             l_fFilePtr = fopen(l_cPath.c_str(), "we");
303             if (NULL != l_fFilePtr) {
304               // write header
305               fwrite(&l_tImmediatePersistentData , 1 , sizeof(l_tImmediatePersistentData) , l_fFilePtr);
306               if (0 == ferror(l_fFilePtr)) {
307                 // write data
308                 fwrite(pData , 1 , uiDataSize , l_fFilePtr);
309                 if (0 != ferror(l_fFilePtr)) {
310                   eFrameworkunifiedStatus = eFrameworkunifiedStatusOK;
311                 }
312               }
313               fsync(fileno(l_fFilePtr));
314               fclose(l_fFilePtr);
315             }
316           }
317
318           sem_post(&g_FileAccessSemaphore);
319         }
320         sem_destroy(&g_FileAccessSemaphore);
321       } else {
322         eFrameworkunifiedStatus = eFrameworkunifiedStatusErrOther;
323       }
324     } else {
325       eFrameworkunifiedStatus = eFrameworkunifiedStatusFail;
326     }
327   } else {
328     eFrameworkunifiedStatus = eFrameworkunifiedStatusInvldParam;
329   }
330   return eFrameworkunifiedStatus;
331 }
332
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;
340
341   if (NULL != notif_name && NULL != uiDataSize) {
342     FILE *l_fFilePtr = NULL;
343     NC_NorPersistentData l_ptImmediatePersistentData = {};
344
345     *uiDataSize = 0;
346
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;
352
353         std::string l_cPath = "";
354         std::string l_cNewPath = IMMEDIATE_PERSISTENCE_STORAGE_V2;
355         std::string l_cOldPath = IMMEDIATE_PERSISTENCE_STORAGE_V1;
356
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);
362         }
363
364         switch (ePersistCategory) {
365           case eFrameworkunifiedFactoryData: {
366               l_cNewPath.append(FACTORYDATADIR);
367             }
368             break;
369
370           case eFrameworkunifiedFactoryCustomerData: {
371               l_cNewPath.append(FACTORYCUSTOMERDATADIR);
372             }
373             break;
374
375           case eFrameworkunifiedDealerData: {
376               l_cNewPath.append(DEALERDATADIR);
377             }
378             break;
379
380           case eFrameworkunifiedUserData:
381           default: {
382               l_cNewPath.append(USERDATADIR);
383               l_cNewPath.append(ALLUSERAPPDATADIR);
384             }
385             break;
386         }
387
388         l_cNewPath.append(IMMEDIATEDATADIR);
389         l_cNewPath.append(l_cTempPath);
390
391         if (0 == access(l_cNewPath.c_str(), F_OK)) {
392           l_cPath.assign(l_cNewPath);
393         } else {
394           l_cOldPath.append(l_cTempPath);
395
396           if (0 == access(l_cOldPath.c_str(), F_OK)) {
397             l_cPath.assign(l_cOldPath);
398           } else {
399             l_eStatus = eFrameworkunifiedStatusFileLoadError;
400           }
401         }
402
403         if (eFrameworkunifiedStatusOK ==  l_eStatus) {
404           size_t PersistData;
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;
412             } else {
413               *uiDataSize = static_cast<UI_32>(PersistData);
414             }
415             fclose(l_fFilePtr);
416           }
417         }
418
419         sem_post(&g_FileAccessSemaphore);
420       } else {
421         l_eStatus = eFrameworkunifiedStatusErrOther;
422       }
423
424       sem_destroy(&g_FileAccessSemaphore);
425     } else {
426       l_eStatus = eFrameworkunifiedStatusErrOther;
427     }
428   } else {
429     l_eStatus = eFrameworkunifiedStatusInvldParam;
430   }
431
432   return l_eStatus;
433 }
434
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,
441                                          PCSTR f_cDestDir) {
442   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
443
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);
450           }
451
452           if (eFrameworkunifiedStatusOK == l_eStatus) {
453             DIR *l_pDir = NULL;
454             struct dirent *l_pdirent = NULL;
455
456             std::string l_cSrcPath = "";
457             std::string l_cDestPath = "";
458
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);
465
466                   l_cDestPath.assign(f_cDestDir);
467                   l_cDestPath.append(l_pdirent->d_name);
468
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;
472                   }
473                 }
474               }
475               closedir(l_pDir);
476
477               sync();
478             } else {
479               l_eStatus = eFrameworkunifiedStatusFileLoadError;
480             }
481           }
482         }
483
484         sem_post(&g_FileAccessSemaphore);
485       } else {
486         l_eStatus = eFrameworkunifiedStatusFail;
487       }
488
489       sem_destroy(&g_FileAccessSemaphore);
490     } else {
491       l_eStatus = eFrameworkunifiedStatusFail;
492     }
493   } else {
494     l_eStatus = eFrameworkunifiedStatusInvldParam;
495   }
496
497   return l_eStatus;
498 }