Fix the path to the host specific system configurations
[staging/basesystem.git] / service / system / task_manager / server / src / tskm_port_pf.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 #include "tskm_port_pf.h"
18 #include <pthread.h>
19 #include <sys/mman.h>
20 #include <sys/stat.h>
21 #include <sys/file.h>
22 #include <pwd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <signal.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include <native_service/cl_process.h>
30 #include <native_service/cl_monitor.h>
31 #include <system_service/ss_services.h>
32 #include <system_service/ss_sm_client_if.h>
33
34 #include "system_service/tskm_svc.h"
35 #include "tskm_debug.h"
36
37 #define TSKM_PORTPF_IN() TSKM_PRINTF(TSKM_LOG_PORTPF, "%s:IN", __FUNCTION__)
38 #define TSKM_PORTPF_IN_ARG(format, ...) TSKM_PRINTF(TSKM_LOG_PORTPF, "%s:IN:" format, __FUNCTION__, __VA_ARGS__)
39 #define TSKM_PORTPF_OUT() TSKM_PRINTF(TSKM_LOG_PORTPF, "%s:OUT", __FUNCTION__)
40
41 #define TSKM_PRIO_MIN            1
42 #define TSKM_PRIO_MAX           99
43 #define TSKM_PRIO_MIN_TSS      -20
44 #define TSKM_PRIO_MAX_TSS       19
45
46 #define TSKM_TMP_DIRECTORY         "/tmp"
47 #define TSKM_TMP_TSKM_DIRECTORY    TSKM_TMP_DIRECTORY "/tskm"
48 #define TSKM_TMP_NV_INFO_FILEPATH  TSKM_TMP_TSKM_DIRECTORY "/nvInfo"
49
50 #define TSKM_NPP_NV_FILE_TAG       SS_TASK_MANAGER "/nvInfo"
51
52 /*********************************************************
53  *        user->uid/gid conversion
54  *********************************************************/
55 TSKM_STATIC int cnvUserName2UidGid(const char *user, uid_t *uid, gid_t *gid) {
56   int ret = -1;
57
58   if (0 == strcmp(user, "")) {
59     *uid = geteuid();
60     *gid = getegid();
61   } else {
62     static __thread size_t bufSize = 0;
63     static __thread char *buf = NULL;
64     struct passwd pwd;
65     struct passwd *result;
66
67     if (0 == bufSize) {
68       struct stat statInfo;
69
70       bufSize = -1;
71
72       if (0 != stat("/etc/passwd", &statInfo) || 0 >= statInfo.st_size) {  // LCOV_EXCL_START 8: Because buf is a static variable and cannot be passed test
73         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
74         TSKM_ASSERT_ERRNO(0);
75         goto ERROR;
76       }
77       // LCOV_EXCL_STOP
78
79       bufSize = statInfo.st_size * 2;
80
81       // Since TaskManager is a resident service, the area allocated here is expected to be released at process termination and is not explicitly released by free()
82       buf = (char *) malloc(sizeof(char) * bufSize);  // NOLINT (runtime/printf)
83       if (NULL == buf) {  // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function malloc
84         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
85         TSKM_ASSERT_ERRNO(0);  // LCOV_EXCL_LINE 5: Error branching of the standard-function malloc
86         goto ERROR;  // LCOV_EXCL_LINE 5: Error branching of the standard-function malloc
87       }
88     }
89
90     if (NULL == buf) {  // LCOV_EXCL_BR_LINE 8: Because buf is a static variable and cannot be passed test
91       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
92       TSKM_ASSERT(0);  // LCOV_EXCL_LINE 8: Because buf is a static variable and cannot be passed test
93       goto ERROR;  // LCOV_EXCL_LINE 8: Because buf is a static variable and cannot be passed test
94     }
95
96     ret = getpwnam_r(user, &pwd, buf, bufSize, &result);
97     if (ret != 0 || result == NULL) {
98       TSKM_ASSERT_PRINT(0, "ret = %d[%s]", ret, user);
99       goto ERROR;
100     }
101
102     *uid = pwd.pw_uid;
103     *gid = pwd.pw_gid;
104   }
105
106   ret = 0;
107
108   ERROR:
109
110   return ret;
111 }
112
113 /*********************************************************
114  *        Convert Scheduling Policy Definitions Values (TSKM -> CL)
115  *********************************************************/
116 TSKM_STATIC CL_ProcessSchedPolicy_t cnvTskmPolicy2ClPolicy(
117     TSKM_SVC_POLICY_t policy) {
118   switch (policy) {
119     case TSKM_SVC_POLICY_FIFO:
120       return CL_PROCESS_SCHED_POLICY_FIFO;
121     case TSKM_SVC_POLICY_TSS:
122       return CL_PROCESS_SCHED_POLICY_OTHER;
123     case TSKM_SVC_POLICY_RR:
124       return CL_PROCESS_SCHED_POLICY_RR;
125     default:
126       TSKM_ASSERT(0);
127       break;
128   }
129   return CL_PROCESS_SCHED_POLICY_OTHER;
130 }
131
132 /*********************************************************
133  *        Process priority valid value determination
134  *********************************************************/
135 TSKM_STATIC int chkPrioValue(TSKM_SVC_POLICY_t policy, int prio) {
136   switch (policy) {
137     case TSKM_SVC_POLICY_FIFO:
138     case TSKM_SVC_POLICY_RR:
139       if ((TSKM_PRIO_MIN > prio) || (prio > TSKM_PRIO_MAX)) {
140         TSKM_ASSERT(0);
141       }
142       break;
143     case TSKM_SVC_POLICY_TSS:
144     default:
145       if ((TSKM_PRIO_MIN_TSS > prio) || (prio > TSKM_PRIO_MAX_TSS)) {
146         TSKM_ASSERT(0);
147       }
148       break;
149   }
150
151   return prio;
152 }
153
154 /*********************************************************
155  *        COMMONLIB initialization (at system startup)
156  *********************************************************/
157 int tskm_pf_sysInit() {
158   int fd = 0;
159   int ret = 0;
160
161   TSKM_PORTPF_IN();
162
163   fd = CL_ProcessInit();
164   if (fd == -1) {  // LCOV_EXCL_BR_LINE 6: Error branching during process initialization
165     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
166     TSKM_ASSERT_ERRNO(0);  // LCOV_EXCL_LINE 6: Error branching during process initialization
167     goto ERROR;  // LCOV_EXCL_LINE 6: Error branching during process initialization
168   }
169
170   ret = CL_MonitorInit(CL_MONITOR_INIT_USER);
171   if (ret != 0) {   // LCOV_EXCL_BR_LINE 4: NSFW error case.
172     TSKM_ASSERT_ERRNO(0);
173   }
174
175   TSKM_PORTPF_OUT();
176   return fd;
177   // LCOV_EXCL_START 6: Error branching during process initialization
178   ERROR:
179   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
180   return -1;
181   // LCOV_EXCL_STOP
182 }
183
184 /*********************************************************
185  *        COMMONLIB initialization (at process startup)
186  *********************************************************/
187 int tskm_pf_procInit() {
188   TSKM_PORTPF_IN();
189   // Originally called the _sys_Setup_CWORD64_API (NULL), but changed to empty function along to derete "_sys"
190
191   TSKM_PORTPF_OUT();
192   return 0;
193 }
194
195 /*********************************************************
196  *        Process startup
197  *********************************************************/
198 pid_t tskm_pf_createProc(TSKM_SVC_ATTR_t* p_svcAttr) {
199   TSKM_PORTPF_IN();
200   pid_t retPid = -1;
201   pid_t pid = -1;
202
203   CL_ProcessAttr_t attr;
204   char procPath[255];
205   char* procName;
206   uid_t setUid = 0;
207   gid_t setGid = 0;
208
209   if (0 != CL_ProcessCreateAttrInit(&attr)) {  // LCOV_EXCL_BR_LINE 6: Error branching during process initialization
210     // LCOV_EXCL_START 6: Error branching during process initialization
211     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
212     TSKM_ASSERT(0);
213     goto ERROR;
214     // LCOV_EXCL_STOP
215   }
216
217   // Process name setting(from basename)
218   if (strlen(p_svcAttr->path) < sizeof(procPath)) {
219     strcpy(procPath, p_svcAttr->path);  // NOLINT (runtime/printf)
220   } else {
221     TSKM_ASSERT(0);
222     goto ERROR;
223   }
224
225   procName = basename(procPath);
226   if (strlen(procName) >= 16) {
227     TSKM_ASSERT(0);
228     procName[16] = '\0';
229   }
230
231   if (0 != CL_ProcessCreateAttrSetName(&attr, procName)) {  // LCOV_EXCL_BR_LINE 4: NSFW error case.
232     // LCOV_EXCL_START 4: NSFW error case.
233     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
234     TSKM_ASSERT_ERRNO(0);
235     goto ERROR;
236     // LCOV_EXCL_STOP
237   }
238
239   if (0 != cnvUserName2UidGid(p_svcAttr->user, &setUid, &setGid)) {  // LCOV_EXCL_BR_LINE 4: NSFW error case.
240     // LCOV_EXCL_START 4: NSFW error case.
241     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
242     TSKM_ASSERT(0);
243     setUid = geteuid();
244     setGid = getegid();
245     // LCOV_EXCL_STOP
246   }
247
248   if (0 != CL_ProcessCreateAttrSetUid(&attr, setUid)) {  // LCOV_EXCL_BR_LINE 4: NSFW error case.
249     // LCOV_EXCL_START 4: NSFW error case.
250     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
251     TSKM_ASSERT_ERRNO(0);
252     goto ERROR;
253     // LCOV_EXCL_STOP
254   }
255
256   if (0 != CL_ProcessCreateAttrSetGid(&attr, setGid)) {  // LCOV_EXCL_BR_LINE 4: NSFW error case.
257     // LCOV_EXCL_START 4: NSFW error case.
258     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
259     TSKM_ASSERT_ERRNO(0);
260     goto ERROR;
261     // LCOV_EXCL_STOP
262   }
263
264   // All are group leaders in order to recover to the child processes of the service
265   if (0 != CL_ProcessCreateAttrSetGroup(&attr, 1)) {  // LCOV_EXCL_BR_LINE 4: NSFW error case.
266     // LCOV_EXCL_START 4: NSFW error case.
267     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
268     TSKM_ASSERT_ERRNO(0);
269     goto ERROR;
270     // LCOV_EXCL_STOP
271   }
272   if (0 != CL_ProcessCreateAttrSetCpuAssign(&attr, p_svcAttr->cpuAssign)) {
273     TSKM_ASSERT_ERRNO(0);
274     goto ERROR;
275   }
276
277   if (0
278       != CL_ProcessCreateAttrSetSchedule(
279           &attr, cnvTskmPolicy2ClPolicy(p_svcAttr->policy),
280           chkPrioValue(p_svcAttr->policy, p_svcAttr->prio))) {
281     TSKM_ASSERT_ERRNO(0);
282     goto ERROR;
283   }
284
285   pid = CL_ProcessCreate(p_svcAttr->path, p_svcAttr->args, NULL, &attr);
286   if (pid == -1) {
287     TSKM_ASSERT_ERRNO(0);
288     goto ERROR;
289   }
290
291   retPid = pid;
292   ERROR:
293
294   TSKM_PORTPF_OUT();
295   return retPid;
296 }
297
298 /*********************************************************
299  *        Recover termination processes
300  *********************************************************/
301 int tskm_pf_cleanupProc(int sigFd, pid_t* p_pid, TSKM_ERR_t* p_err) {
302   int ret;
303   CL_ProcessCleanupInfo_t info;
304
305   ret = CL_ProcessCleanup(sigFd, &info);
306   if (ret != 0 && ret != 1) {
307     TSKM_ASSERT_PRINT(0, "ret = %d", ret);
308     TSKM_ASSERT_ERRNO(0);
309     goto ERROR;
310   }
311
312   TSKM_PRINTF(TSKM_LOG_STATE, "SVC TERM:pid:%d code:%d status:%d", info.pid,
313               info.code, info.status);
314
315   switch (info.code) {
316     case CLD_STOPPED:
317       // Not comes here usually
318       TSKM_PRINTF(TSKM_LOG_STATE, "svc stoped\n");
319       goto ERROR;
320     case CLD_TRAPPED:
321       // Comes here only during debugging
322       TSKM_PRINTF(TSKM_LOG_STATE, "svc traped\n");
323       goto ERROR;
324     case CLD_CONTINUED:
325       // Not comes here usually
326       TSKM_PRINTF(TSKM_LOG_STATE, "svc continue\n");
327       goto ERROR;
328     default:
329       break;
330   }
331
332   *p_pid = info.pid;
333   *p_err =
334       (info.code != CLD_EXITED) ? TSKM_E_NG :
335       (info.code == CLD_EXITED && info.status != EXIT_SUCCESS) ?
336           TSKM_E_NG : TSKM_E_OK;
337
338   if (TSKM_E_OK != *p_err) {
339     TSKM_PRINTF(TSKM_LOG_SYSTEMDATA, "SVC ERR TERM:pid:%d code:%d status:%d",
340                 info.pid, info.code, info.status);
341   }
342
343   return ret;
344   ERROR: return -1;
345 }
346
347 /*********************************************************
348  *        Force Terminating a Process Group
349  *********************************************************/
350 int tskm_pf_terminateProcGroup(uint16_t pid) {
351   int ret;
352   pid_t pgid;
353
354   pgid = getpgid(pid);
355   if (pgid < 0) {
356     TSKM_ASSERT(0);
357     goto ERROR;
358   }
359
360   TSKM_PRINTF(TSKM_LOG_STATE, "TERM SVC GROUP:pid:%dpgid:%d", pid, pgid);
361
362   ret = CL_ProcessEuthanizeGroup(pgid);
363   if (ret != 0) {
364     TSKM_ASSERT_ERRNO(0);
365     goto ERROR;
366   }
367
368   return 0;
369   ERROR: return -1;
370 }
371
372 /*********************************************************
373  *        Opening shared memory and trancating
374  *********************************************************/
375 int tskm_pf_shmCreate_Open_Ftrn(const char* name, int32_t size, void** p_addr) {
376   int ret = 0;
377   int fd = 0;
378
379   fd = shm_open(name, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
380   if (fd == -1) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
381     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
382     TSKM_ASSERT_ERRNO(0);  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
383     ret = -1;  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
384     if (fd > 0) {  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
385       TSKM_ASSERT_ERRNO(close(fd) == 0);  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
386     }  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
387     return ret;  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
388   }
389
390   ret = ftruncate(fd, size);
391   if (ret != 0) {  // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
392     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
393     TSKM_ASSERT_ERRNO(0);  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
394     if (fd > 0) {  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
395       TSKM_ASSERT_ERRNO(close(fd) == 0);  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
396     }  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
397     return ret;  // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded.
398   }
399
400   if (p_addr) {  // LCOV_EXCL_BR_LINE 8: Because p_addr is set to NULL only
401     // LCOV_EXCL_START 8: Because p_addr is set to NULL only
402     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
403     // Not supported
404     TSKM_ASSERT_ERRNO(0);
405     ret = -1;
406     if (fd > 0) {
407       TSKM_ASSERT_ERRNO(close(fd) == 0);
408     }
409     return ret;
410     // LCOV_EXCL_STOP
411   }
412
413   ret = 0;
414   if (fd > 0) {
415     TSKM_ASSERT_ERRNO(close(fd) == 0);
416   }
417   return ret;
418 }
419
420 /*********************************************************
421  *        Creating shared memory
422  *********************************************************/
423 int tskm_pf_shmCreate(const char* name, int32_t size, void** p_addr) {
424   TSKM_PORTPF_IN_ARG("%s,%d", name, size);
425   struct stat statInfo;
426   int ret = -1;
427
428   if (stat(name, &statInfo) == 0) {
429     TSKM_ASSERT_PRINT(0, "Already Exist %s", name);
430     ret = 0;  // To be Succeeded
431     TSKM_PORTPF_OUT();
432     return ret;
433   }
434
435   ret = tskm_pf_shmCreate_Open_Ftrn(name, size, p_addr);
436
437   TSKM_PORTPF_OUT();
438   return ret;
439 }
440
441 /*********************************************************
442  *        Deleting shared memory
443  *********************************************************/
444 int tskm_pf_shmDelete(const char* name) {
445   TSKM_PORTPF_IN_ARG("%s", name);
446   int ret = 0;
447
448   if (0 != shm_unlink(name)) {
449     TSKM_ASSERT_ERRNO(0);
450   }
451
452   TSKM_PORTPF_OUT();
453   return ret;
454 }
455
456 /*********************************************************
457  *        Starting thread
458  *********************************************************/
459 int tskm_pf_createThread(void* (*threadFunc)(void*), void* prm,
460                          uint32_t priority, const char* threadName,
461                          pthread_t* p_thId) {
462   TSKM_PORTPF_IN();
463
464   int ret;
465   CL_ThreadAttr_t cl_attr;
466
467   ret = CL_ThreadCreateAttrInit(&cl_attr);
468   if (ret != 0) {  // LCOV_EXCL_BR_LINE 6: For processing initializing process
469     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
470     TSKM_ASSERT_ERRNO(0);  // LCOV_EXCL_LINE 6: For processing initializing process
471     goto ERROR;  // LCOV_EXCL_LINE 6:  For processing initializing process
472   }
473
474   if (threadName) {
475     ret = CL_ThreadCreateAttrSetName(&cl_attr, threadName);
476     TSKM_ASSERT_ERRNO(ret == 0);
477   }
478
479   ret = CL_ThreadCreate(p_thId, NULL, &cl_attr, threadFunc, prm);
480   if (ret != 0) {  // LCOV_EXCL_BR_LINE 6: For processing initializing process
481     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
482     TSKM_ASSERT_ERRNO(0);  // LCOV_EXCL_LINE 6:  For processing initializing process
483     goto ERROR;  // LCOV_EXCL_LINE 6:  For processing initializing process
484   }
485   int sched_policy;
486   struct sched_param sparam;
487
488   pthread_getschedparam(*p_thId, &sched_policy, &sparam);
489
490   sparam.sched_priority = priority;
491   if ((priority != 0) && (sched_policy == SCHED_OTHER)) {
492     sched_policy = SCHED_FIFO;
493   } else if ((priority == 0) && (sched_policy != SCHED_OTHER)) {
494     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
495     sched_policy = SCHED_OTHER;  // LCOV_EXCL_LINE 6:  For processing initializing process
496   }
497
498   ret = pthread_setschedparam(*p_thId, sched_policy, &sparam);
499   TSKM_ASSERT(ret == 0);
500   TSKM_PORTPF_OUT();
501   return 0;
502   ERROR: return -1;
503 }
504 /*********************************************************
505  *        Send Stop Complete Response
506  *********************************************************/
507 int tskm_pf_sendStopCompResp() {
508   EFrameworkunifiedStatus l_eStatus;
509   TSKM_PORTPF_IN();
510
511   l_eStatus = SendInterfaceunifiedOnStopResponseToSystemManager(eFrameworkunifiedStatusOK);
512   if (l_eStatus != eFrameworkunifiedStatusOK) {
513     TSKM_ASSERT(0);
514   }
515
516   TSKM_PORTPF_OUT();
517   return 0;
518 }
519
520 /*********************************************************
521  *        ABORT
522  *********************************************************/
523 int tskm_pf_abort() {
524   TSKM_PORTPF_IN();
525
526   TSKM_ASSERT(0);
527   sleep(1);   // Sleep a little so that the logging at the time of abnormality may be interrupted
528
529   // Issure SIGSEG
530   printf("%d\n", *(int *) 0);  // NOLINT (readability/casting)
531
532   TSKM_PORTPF_OUT();
533   return 0;
534 }
535
536 /*********************************************************
537  *        EXIT
538  *********************************************************/
539 int tskm_pf_exit(int status) {  //LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded
540   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
541   TSKM_PORTPF_IN();
542
543   exit(status);
544
545   TSKM_PORTPF_OUT();
546   return 0;
547 }
548 // LCOV_EXCL_STOP
549
550 /*********************************************************
551  *        TOUCH
552  *********************************************************/
553 int tskm_pf_touch(char* path) {
554   TSKM_PORTPF_IN();
555   int fd;
556   fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
557   if (fd < 0) {
558     TSKM_ASSERT_ERRNO(0);
559     goto ERROR;
560   }
561
562   TSKM_ASSERT_ERRNO(close(fd) == 0);
563   TSKM_PORTPF_OUT();
564   return 0;
565   ERROR:
566   return -1;
567 }
568
569 /*********************************************************
570  *        Touch
571  *********************************************************/
572 int tskm_pf_mkTouchFileName(pid_t pid, char name[32]) {
573   TSKM_PORTPF_IN();
574
575   sprintf(name, "/tmp/tskm_touch%d", pid);  // NOLINT (runtime/printf)
576
577   TSKM_PORTPF_OUT();
578   return 0;
579 }
580
581 /*********************************************************
582  *     Read file
583  *********************************************************/
584 static ssize_t readFile(const char* filePath, void* l_buf, ssize_t bufSize) {
585   int fd = -1;
586   ssize_t readSize, totalReadSize = 0;
587   char *p_buf = (char*) l_buf;  // NOLINT (readability/casting)
588   fd = open(filePath, O_RDONLY);
589   if (fd == -1) {
590     TSKM_ASSERT_ERRNO(0);
591     goto ERROR;
592   }
593
594   do {
595     readSize = read(fd, p_buf, bufSize);
596     if (readSize == -1) {
597       if (errno == EINTR) {
598         continue;
599       } else {
600         TSKM_ASSERT_ERRNO(0);
601         goto ERROR;
602       }
603     } else if (readSize == 0) {
604       break;
605     }
606
607     p_buf += readSize;
608     bufSize -= readSize;
609     totalReadSize += readSize;
610   } while (bufSize > 0);
611
612   ERROR: if (fd != -1) {
613     close(fd);
614   }
615
616   return totalReadSize;
617 }
618
619 /*********************************************************
620  *     Write to file
621  *********************************************************/
622 static ssize_t writeFile(const char *filePath, const void* l_buf,
623                          ssize_t bufSize) {
624   int ret = -1;
625   int fd = -1;
626
627   const char *p_buf = (const char*) l_buf;
628
629   ssize_t writeSize, totalWriteSize = 0;
630
631   fd = open(filePath, O_RDWR | O_TRUNC | O_CREAT, S_IRWXU);
632   if (fd == -1) {  // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function open()
633     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
634     TSKM_ASSERT_ERRNO(0);  // LCOV_EXCL_LINE 5: Error branching of the standard-function open()
635     goto ERROR;  // LCOV_EXCL_LINE 5: Error branching of the standard-function open()
636   }
637
638   do {
639     writeSize = write(fd, p_buf, bufSize);
640     if (writeSize == -1) {  // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function write()
641       // LCOV_EXCL_START 5: Error branching of the standard-function write()
642       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
643       if (errno == EINTR) {
644         continue;
645       } else {
646         TSKM_ASSERT_ERRNO(0);
647         goto ERROR;
648       }
649       // LCOV_EXCL_STOP
650     } else if (writeSize == 0) {  // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function write()
651       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
652       break;  // LCOV_EXCL_LINE 5: Error branching of the standard-function write()
653     }
654     p_buf += writeSize;
655     bufSize -= writeSize;
656     totalWriteSize += writeSize;
657   } while (bufSize > 0);  // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function write()
658
659   ret = fsync(fd);
660   if (ret == -1) {  // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function fsync()
661     // LCOV_EXCL_START 5: Error branching of the standard-function fsync()
662     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
663     TSKM_ASSERT_ERRNO(0);
664     goto ERROR;
665     // LCOV_EXCL_STOP
666   }
667
668   ERROR: if (fd != -1) {  // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function open()
669     close(fd);
670   }
671
672   return totalWriteSize;
673 }
674
675 /*********************************************************
676  *     Checksum calculation
677  *********************************************************/
678 static uint32_t calcCheckSum(const void* p_buf, size_t bufSize) {
679   int ii;
680   int blockNum;
681   uint32_t sum = 0;
682   uint32_t *p_calcBuf = (uint32_t*) p_buf;  // NOLINT (readability/casting)
683
684   blockNum = static_cast<int>(bufSize) / static_cast<int>(sizeof(uint32_t));
685
686   for (ii = 0; ii < blockNum; ii++) {
687     sum += p_calcBuf[ii];
688   }
689
690   return sum;
691 }
692
693 /*********************************************************
694  *     Checking files
695  *********************************************************/
696 static TSKM_BOOL_t checkFile(const char *filePath) {  // LCOV_EXCL_START 6: Because the condition cannot be set
697   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
698   uint32_t checkSum;
699   struct stat st;
700   ssize_t readSize;
701   TSKM_NV_INFO_t nvInfo;
702   TSKM_BOOL_t isFileOk = TSKM_FALSE;
703
704   if (stat(filePath, &st) != 0) {
705     goto ERROR;
706   }
707
708   readSize = readFile(filePath, &nvInfo, sizeof(TSKM_NV_INFO_t));
709   if (readSize != sizeof(TSKM_NV_INFO_t)) {
710     TSKM_ASSERT(0);
711     goto ERROR;
712   }
713
714   checkSum = calcCheckSum(&nvInfo, offsetof(TSKM_NV_INFO_t, footer.checkSum));
715
716   if (checkSum != nvInfo.footer.checkSum) {
717     TSKM_ASSERT(0);
718     goto ERROR;
719   }
720
721   if (strncmp(nvInfo.header.version, TSKM_NV_STRUCT_VERSION,
722               sizeof(TSKM_NV_STRUCT_VERSION)) != 0) {
723     TSKM_ASSERT(0);
724     goto ERROR;
725   }
726
727   isFileOk = TSKM_TRUE;
728   ERROR: return isFileOk;
729 }
730 // LCOV_EXCL_STOP
731 /*********************************************************
732  *     Non-volatile file initialization (Including checksum write)
733  *********************************************************/
734 static int initNvFile() {
735   int ii;
736   ssize_t writeSize;
737   TSKM_NV_INFO_t nvInfo;
738
739   TSKM_STATIC_ASSERT(sizeof(TSKM_NV_INFO_t) == TSKM_NV_SIZE_ALL);
740   TSKM_STATIC_ASSERT(
741       offsetof(TSKM_NV_INFO_t, footer.checkSum) % sizeof(uint32_t) == 0);
742
743   memset(&nvInfo, 0, sizeof(TSKM_NV_INFO_t));
744   sprintf(nvInfo.header.version, TSKM_NV_STRUCT_VERSION);  // NOLINT (readability/casting)
745   nvInfo.body.rsvSvcNum = 0;
746   for (ii = 0; ii < TSKM_SVC_RESERVE_MAX; ii++) {
747     nvInfo.body.rsvSvcs[ii] = TSKM_SVCID_NONE;
748   }
749   nvInfo.footer.checkSum = calcCheckSum(
750       &nvInfo, offsetof(TSKM_NV_INFO_t, footer.checkSum));
751
752   writeSize = writeFile(TSKM_TMP_NV_INFO_FILEPATH, &nvInfo,
753                         sizeof(TSKM_NV_INFO_t));
754   if (writeSize != sizeof(TSKM_NV_INFO_t)) {  // LCOV_EXCL_BR_LINE 6: writeSize must be the size of TSKM_NV_INFO_t
755     // LCOV_EXCL_START 6: writeSize must be the size of TSKM_NV_INFO_t
756     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
757     TSKM_ASSERT(0);
758     goto ERROR;
759     // LCOV_EXCL_STOP
760   }
761
762   return 0;
763   ERROR: return -1;
764 }
765
766 /*********************************************************
767  *     Non-volatile file initialization
768  *********************************************************/
769 int tskm_pf_nvFileInit(HANDLE hApp) {
770   int ret = -1;
771   struct stat st;
772   EFrameworkunifiedStatus l_eStatus;
773
774   if (stat(TSKM_TMP_TSKM_DIRECTORY, &st) != 0) {  // LCOV_EXCL_BR_LINE 5:Standard C function return value
775     // LCOV_EXCL_START 5:Standard C function return value
776     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
777     ret = mkdir(TSKM_TMP_TSKM_DIRECTORY, S_IRWXU);
778     if (ret == -1) {
779       TSKM_ASSERT_ERRNO(0);
780       goto ERROR;
781     }
782     // LCOV_EXCL_STOP
783   }
784
785   l_eStatus = FrameworkunifiedNPRegisterPersistentFile(hApp, TSKM_NPP_NV_FILE_TAG);
786   if (eFrameworkunifiedStatusOK != l_eStatus) {  // LCOV_EXCL_BR_LINE 6: For processing initializing process
787     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
788     TSKM_ASSERT(0);  // LCOV_EXCL_LINE 6: For processing initializing process
789     goto ERROR;  // LCOV_EXCL_LINE 6: For processing initializing process
790   }
791
792   l_eStatus = FrameworkunifiedNPLoadPersistentFile(hApp, TSKM_TMP_NV_INFO_FILEPATH, TSKM_NPP_NV_FILE_TAG);
793   if (eFrameworkunifiedStatusOK != l_eStatus) {  // LCOV_EXCL_BR_LINE 6: For processing initializing process
794     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
795     TSKM_ASSERT(0);  // LCOV_EXCL_LINE 6: For processing initializing process
796     goto ERROR;  // LCOV_EXCL_LINE 6: For processing initializing process
797   }
798
799   return 0;
800   ERROR: return -1;
801 }
802
803 /*********************************************************
804  *     Non-volatile file read
805  *********************************************************/
806 int tskm_pf_nvFileRead(HANDLE hApp, TSKM_NV_INFO_t* p_nvInfo) {
807   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
808   NC_LoadPersistedAck l_tMsgAck;
809   ssize_t readSize;
810   TSKM_BOOL_t isTmpFileOk = TSKM_FALSE;
811
812   if (sizeof(l_tMsgAck) != FrameworkunifiedGetMsgLength(hApp)) {
813     TSKM_ASSERT(0);
814     goto ERROR;
815   } else if (eFrameworkunifiedStatusOK != (l_eStatus = FrameworkunifiedGetMsgDataOfSize(hApp, &l_tMsgAck, sizeof(l_tMsgAck)))) {  // LCOV_EXCL_BR_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
816     // LCOV_EXCL_START 4: NSFW error case
817     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
818     TSKM_ASSERT(0);
819     goto ERROR;
820     // LCOV_EXCL_STOP
821   }
822
823   if ((strncmp(l_tMsgAck.cTag, TSKM_NPP_NV_FILE_TAG, sizeof(TSKM_NPP_NV_FILE_TAG)) == 0)
824       && (eFrameworkunifiedStatusOK == l_tMsgAck.eStatus)) {
825     if (checkFile(TSKM_TMP_NV_INFO_FILEPATH) == TSKM_TRUE) {
826       isTmpFileOk = TSKM_TRUE;
827     }
828   }
829
830   if (isTmpFileOk == TSKM_FALSE) {
831     int ret;
832
833     ret = initNvFile();
834     if (ret == -1) {  // LCOV_EXCL_BR_LINE 6: must return ok
835       // LCOV_EXCL_START 6: must return ok
836       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
837       TSKM_ASSERT(0);
838       goto ERROR;
839       // LCOV_EXCL_STOP
840     }
841   }
842
843   readSize = readFile(TSKM_TMP_NV_INFO_FILEPATH, p_nvInfo,
844                       sizeof(TSKM_NV_INFO_t));
845   if (readSize != sizeof(TSKM_NV_INFO_t)) {  // LCOV_EXCL_BR_LINE 6: readSize must be the size of TSKM_NV_INFO_t
846     // LCOV_EXCL_START 6: readSize must be the size of TSKM_NV_INFO_t
847     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
848     TSKM_ASSERT(0);
849     goto ERROR;
850     // LCOV_EXCL_STOP
851   }
852
853   l_eStatus = FrameworkunifiedNPReleasePersistentFile(hApp, eFrameworkunifiedPersistOnShutdown, TSKM_NPP_NV_FILE_TAG, TSKM_TMP_NV_INFO_FILEPATH);
854   if (eFrameworkunifiedStatusOK != l_eStatus) {
855     TSKM_ASSERT(0);
856   }
857
858   return 0;
859   ERROR: return -1;
860 }
861
862 /*********************************************************
863  *     Write non-volatile file (Including checksum)
864  *********************************************************/
865 int tskm_pf_nvFileWrite(const TSKM_NV_INFO_t* p_nvInfo) {
866   ssize_t writeSize;
867   TSKM_NV_INFO_t nvInfo;
868
869   memcpy(&nvInfo, p_nvInfo, sizeof(TSKM_NV_INFO_t));
870
871   nvInfo.footer.checkSum = calcCheckSum(
872       &nvInfo, offsetof(TSKM_NV_INFO_t, footer.checkSum));
873
874   writeSize = writeFile(TSKM_TMP_NV_INFO_FILEPATH, &nvInfo,
875                         sizeof(TSKM_NV_INFO_t));
876   if (writeSize != sizeof(TSKM_NV_INFO_t)) {  // LCOV_EXCL_BR_LINE 6: writeSize must be the size of TSKM_NV_INFO_t
877     // LCOV_EXCL_START 6: writeSize must be the size of TSKM_NV_INFO_t
878     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
879     TSKM_ASSERT(0);
880     return -1;
881     // LCOV_EXCL_STOP
882   }
883   return 0;
884 }  // LCOV_EXCL_BR_LINE 10: Final line