1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "init_utils.h"
16
17 #include <ctype.h>
18 #include <errno.h>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <grp.h>
22 #include <limits.h>
23 #include <pwd.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/ioctl.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #include "init_log.h"
31 #include "securec.h"
32 #include "service_control.h"
33
34 #define MAX_BUF_SIZE 1024
35 #define MAX_SMALL_BUFFER 3096
36
37 #define MAX_JSON_FILE_LEN 102400 // max init.cfg size 100KB
38 #define CONVERT_MICROSEC_TO_SEC(x) ((x) / 1000 / 1000.0)
39 #ifndef DT_DIR
40 #define DT_DIR 4
41 #endif
42
43 #define THOUSAND_UNIT_INT 1000
44 #define THOUSAND_UNIT_FLOAT 1000.0
45
ConvertMicrosecondToSecond(int x)46 float ConvertMicrosecondToSecond(int x)
47 {
48 return ((x / THOUSAND_UNIT_INT) / THOUSAND_UNIT_FLOAT);
49 }
50
51 #ifndef __LITEOS_M__
CheckDigit(const char * name)52 static bool CheckDigit(const char *name)
53 {
54 size_t nameLen = strlen(name);
55 for (size_t i = 0; i < nameLen; ++i) {
56 if (!isdigit(name[i])) {
57 return false;
58 }
59 }
60 return true;
61 }
62 #endif
63
StringToUint(const char * name,unsigned int * value)64 int StringToUint(const char *name, unsigned int *value)
65 {
66 errno = 0;
67 *value = (unsigned int)strtoul(name, 0, DECIMAL_BASE);
68 INIT_CHECK_RETURN_VALUE(errno == 0, -1);
69 return 0;
70 }
71
DecodeUid(const char * name)72 uid_t DecodeUid(const char *name)
73 {
74 #ifndef __LITEOS_M__
75 INIT_CHECK_RETURN_VALUE(name != NULL, -1);
76 uid_t uid = -1;
77 if (CheckDigit(name)) {
78 if (!StringToUint(name, &uid)) {
79 return uid;
80 } else {
81 INIT_LOGE("Failed to decode uid for %s", name);
82 return -1;
83 }
84 }
85 struct passwd *p = getpwnam(name);
86 if (p == NULL) {
87 INIT_LOGE("Failed to decode uid for %s", name);
88 return -1;
89 }
90 return p->pw_uid;
91 #else
92 (void)name;
93 return -1;
94 #endif
95 }
96
DecodeGid(const char * name)97 gid_t DecodeGid(const char *name)
98 {
99 #ifndef __LITEOS_M__
100 INIT_CHECK_RETURN_VALUE(name != NULL, -1);
101 gid_t gid = -1;
102 if (CheckDigit(name)) {
103 if (!StringToUint(name, &gid)) {
104 return gid;
105 } else {
106 INIT_LOGE("Failed to decode gid for %s", name);
107 return -1;
108 }
109 }
110 struct group *data = getgrnam(name);
111 if (data != NULL) {
112 return data->gr_gid;
113 }
114 while ((data = getgrent()) != NULL) {
115 if ((data->gr_name != NULL) && (strcmp(data->gr_name, name) == 0)) {
116 gid = data->gr_gid;
117 break;
118 }
119 }
120 endgrent();
121 return gid;
122 #else
123 (void)name;
124 return -1;
125 #endif
126 }
127
ReadFileToBuf(const char * configFile)128 char *ReadFileToBuf(const char *configFile)
129 {
130 char *buffer = NULL;
131 FILE *fd = NULL;
132 struct stat fileStat = {0};
133 INIT_CHECK_RETURN_VALUE(configFile != NULL && *configFile != '\0', NULL);
134 do {
135 if (stat(configFile, &fileStat) != 0 ||
136 fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) {
137 INIT_LOGE("Unexpected config file \" %s \", check if it exist. if exist, check file size", configFile);
138 break;
139 }
140 fd = fopen(configFile, "r");
141 if (fd == NULL) {
142 INIT_LOGE("Open %s failed. err = %d", configFile, errno);
143 break;
144 }
145 buffer = (char*)malloc((size_t)(fileStat.st_size + 1));
146 if (buffer == NULL) {
147 INIT_LOGE("Failed to allocate memory for config file, err = %d", errno);
148 break;
149 }
150
151 if (fread(buffer, fileStat.st_size, 1, fd) != 1) {
152 free(buffer);
153 buffer = NULL;
154 break;
155 }
156 buffer[fileStat.st_size] = '\0';
157 } while (0);
158
159 if (fd != NULL) {
160 (void)fclose(fd);
161 fd = NULL;
162 }
163 return buffer;
164 }
165
CloseStdio(void)166 void CloseStdio(void)
167 {
168 #ifndef __LITEOS_M__
169 int fd = open("/dev/null", O_RDWR | O_CLOEXEC);
170 if (fd < 0) {
171 return;
172 }
173 dup2(fd, 0);
174 dup2(fd, 1);
175 dup2(fd, STDERR_HANDLE);
176 close(fd);
177 #endif
178 }
179
ReadFileData(const char * fileName)180 char *ReadFileData(const char *fileName)
181 {
182 if (fileName == NULL) {
183 return NULL;
184 }
185 char *buffer = NULL;
186 int fd = -1;
187 fd = open(fileName, O_RDONLY);
188 INIT_ERROR_CHECK(fd >= 0, return NULL, "Failed to read file %s", fileName);
189 buffer = (char *)calloc(1, MAX_SMALL_BUFFER); // fsmanager not create, can not get fileStat st_size
190 INIT_ERROR_CHECK(buffer != NULL, close(fd);
191 return NULL, "Failed to allocate memory for %s", fileName);
192 ssize_t readLen = read(fd, buffer, MAX_SMALL_BUFFER - 1);
193 INIT_ERROR_CHECK((readLen > 0) && (readLen < (MAX_SMALL_BUFFER - 1)), close(fd);
194 free(buffer);
195 return NULL, "Failed to read data for %s", fileName);
196 buffer[readLen] = '\0';
197 if (fd != -1) {
198 close(fd);
199 }
200 return buffer;
201 }
202
GetProcCmdlineValue(const char * name,const char * buffer,char * value,int length)203 int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length)
204 {
205 INIT_ERROR_CHECK(name != NULL && buffer != NULL && value != NULL, return -1, "Failed get parameters");
206 char *endData = (char *)buffer + strlen(buffer);
207 char *tmp = strstr(buffer, name);
208 do {
209 if (tmp == NULL) {
210 return -1;
211 }
212 tmp = tmp + strlen(name);
213 while (tmp < endData && *tmp == ' ') {
214 tmp++;
215 }
216 if (*tmp == '=') {
217 break;
218 }
219 tmp = strstr(tmp + 1, name);
220 } while (tmp < endData);
221 tmp++;
222 size_t i = 0;
223 size_t endIndex = 0;
224 while (tmp < endData && *tmp == ' ') {
225 tmp++;
226 }
227 for (; i < (size_t)length; tmp++) {
228 if (tmp >= endData) {
229 endIndex = i;
230 break;
231 }
232 if (*tmp == ' ' || *tmp == '\n' || *tmp == '\r' || *tmp == '\t') {
233 endIndex = i;
234 break;
235 }
236 if (*tmp == '=') {
237 if (endIndex != 0) { // for root=uuid=xxxx
238 break;
239 }
240 i = 0;
241 endIndex = 0;
242 continue;
243 }
244 value[i++] = *tmp;
245 }
246 if (i >= (size_t)length) {
247 return -1;
248 }
249 value[endIndex] = '\0';
250 return 0;
251 }
252
SplitString(char * srcPtr,const char * del,char ** dstPtr,int maxNum)253 int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum)
254 {
255 INIT_CHECK_RETURN_VALUE(srcPtr != NULL && dstPtr != NULL && del != NULL, -1);
256 char *buf = NULL;
257 dstPtr[0] = strtok_r(srcPtr, del, &buf);
258 int counter = 0;
259 while ((counter < maxNum) && (dstPtr[counter] != NULL)) {
260 counter++;
261 if (counter >= maxNum) {
262 break;
263 }
264 dstPtr[counter] = strtok_r(NULL, del, &buf);
265 }
266 return counter;
267 }
268
FreeStringVector(char ** vector,int count)269 void FreeStringVector(char **vector, int count)
270 {
271 if (vector != NULL) {
272 for (int i = 0; i < count; i++) {
273 if (vector[i] != NULL) {
274 free(vector[i]);
275 }
276 }
277 free(vector);
278 }
279 }
280
SplitStringExt(char * buffer,const char * del,int * returnCount,int maxItemCount)281 char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount)
282 {
283 INIT_CHECK_RETURN_VALUE((maxItemCount >= 0) && (buffer != NULL) && (del != NULL) && (returnCount != NULL), NULL);
284 // Why is this number?
285 // Now we use this function to split a string with a given delimiter
286 // We do not know how many sub-strings out there after splitting.
287 // 50 is just a guess value.
288 const int defaultItemCounts = 50;
289 int itemCounts = maxItemCount;
290
291 if (maxItemCount > defaultItemCounts) {
292 itemCounts = defaultItemCounts;
293 }
294 char **items = (char **)malloc(sizeof(char*) * itemCounts);
295 INIT_ERROR_CHECK(items != NULL, return NULL, "No enough memory to store items");
296 char *rest = NULL;
297 char *p = strtok_r(buffer, del, &rest);
298 int count = 0;
299 while (p != NULL) {
300 if (count > itemCounts - 1) {
301 itemCounts += (itemCounts / 2) + 1; // 2 Request to increase the original memory by half.
302 INIT_LOGV("Too many items,expand size");
303 char **expand = (char **)(realloc(items, sizeof(char *) * itemCounts));
304 INIT_ERROR_CHECK(expand != NULL, FreeStringVector(items, count);
305 return NULL, "Failed to expand memory");
306 items = expand;
307 }
308 size_t len = strlen(p);
309 items[count] = (char *)malloc(len + 1);
310 INIT_CHECK(items[count] != NULL, FreeStringVector(items, count);
311 return NULL);
312 if (strncpy_s(items[count], len + 1, p, len) != EOK) {
313 INIT_LOGE("Copy string failed");
314 FreeStringVector(items, count);
315 return NULL;
316 }
317 items[count][len] = '\0';
318 count++;
319 p = strtok_r(NULL, del, &rest);
320 }
321 *returnCount = count;
322 return items;
323 }
324
WaitForFile(const char * source,unsigned int maxSecond)325 void WaitForFile(const char *source, unsigned int maxSecond)
326 {
327 INIT_ERROR_CHECK(maxSecond <= WAIT_MAX_SECOND, maxSecond = WAIT_MAX_SECOND, "WaitForFile max time is 5s");
328 struct stat sourceInfo = {0};
329 unsigned int waitTime = 500000;
330 /* 500ms interval, check maxSecond*2 times total */
331 unsigned int maxCount = maxSecond * 2;
332 #ifdef STARTUP_INIT_TEST
333 maxCount = 0;
334 #endif
335 unsigned int count = 0;
336 while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (count < maxCount)) {
337 usleep(waitTime);
338 count++;
339 }
340 INIT_CHECK_ONLY_ELOG(count != maxCount, "wait for file:%s failed after %d second.", source, maxSecond);
341 return;
342 }
343
WriteAll(int fd,const char * buffer,size_t size)344 size_t WriteAll(int fd, const char *buffer, size_t size)
345 {
346 INIT_CHECK_RETURN_VALUE(buffer != NULL && fd >= 0 && *buffer != '\0', 0);
347 const char *p = buffer;
348 size_t left = size;
349 ssize_t written;
350 while (left > 0) {
351 do {
352 written = write(fd, p, left);
353 } while (written < 0 && errno == EINTR);
354 if (written < 0) {
355 INIT_LOGE("Failed to write %lu bytes, err = %d", left, errno);
356 break;
357 }
358 p += written;
359 left -= written;
360 }
361 return size - left;
362 }
363
GetRealPath(const char * source)364 char *GetRealPath(const char *source)
365 {
366 INIT_CHECK_RETURN_VALUE(source != NULL, NULL);
367 char *path = realpath(source, NULL);
368 if (path == NULL) {
369 INIT_ERROR_CHECK(errno == ENOENT, return NULL, "Failed to resolve %s real path err=%d", source, errno);
370 }
371 return path;
372 }
373
MakeDir(const char * dir,mode_t mode)374 int MakeDir(const char *dir, mode_t mode)
375 {
376 int rc = -1;
377 if (dir == NULL || *dir == '\0') {
378 errno = EINVAL;
379 return rc;
380 }
381 rc = mkdir(dir, mode);
382 INIT_ERROR_CHECK(!(rc < 0 && errno != EEXIST), return rc,
383 "Create directory \" %s \" failed, err = %d", dir, errno);
384 // create dir success or it already exist.
385 return 0;
386 }
387
MakeDirRecursive(const char * dir,mode_t mode)388 int MakeDirRecursive(const char *dir, mode_t mode)
389 {
390 int rc = -1;
391 char buffer[PATH_MAX] = {0};
392 const char *p = NULL;
393 if (dir == NULL || *dir == '\0') {
394 errno = EINVAL;
395 return rc;
396 }
397 p = dir;
398 char *slash = strchr(dir, '/');
399 while (slash != NULL) {
400 int gap = slash - p;
401 p = slash + 1;
402 if (gap == 0) {
403 slash = strchr(p, '/');
404 continue;
405 }
406 if (gap < 0) { // end with '/'
407 break;
408 }
409 INIT_CHECK_RETURN_VALUE(memcpy_s(buffer, PATH_MAX, dir, p - dir - 1) == 0, -1);
410 rc = MakeDir(buffer, mode);
411 INIT_CHECK_RETURN_VALUE(rc >= 0, rc);
412 slash = strchr(p, '/');
413 }
414 return MakeDir(dir, mode);
415 }
416
CheckAndCreateDir(const char * fileName)417 void CheckAndCreateDir(const char *fileName)
418 {
419 #ifndef __LITEOS_M__
420 if (fileName == NULL || *fileName == '\0') {
421 return;
422 }
423 char *path = strndup(fileName, strrchr(fileName, '/') - fileName);
424 if (path == NULL) {
425 return;
426 }
427 if (access(path, F_OK) == 0) {
428 free(path);
429 return;
430 }
431 MakeDirRecursive(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
432 free(path);
433 #else
434 (void)fileName;
435 #endif
436 }
437
CheckAndCreatFile(const char * file,mode_t mode)438 int CheckAndCreatFile(const char *file, mode_t mode)
439 {
440 if (access(file, F_OK) == 0) {
441 BEGET_LOGW("File \' %s \' already exist", file);
442 return 0;
443 } else {
444 if (errno == ENOENT) {
445 CheckAndCreateDir(file);
446 int fd = open(file, O_CREAT, mode);
447 if (fd < 0) {
448 BEGET_LOGE("Failed create %s, err=%d", file, errno);
449 return -1;
450 } else {
451 BEGET_LOGI("Success create %s", file);
452 close(fd);
453 }
454 } else {
455 BEGET_LOGW("Failed to access \' %s \', err = %d", file, errno);
456 return -1;
457 }
458 }
459 return 0;
460 }
461
StringToInt(const char * str,int defaultValue)462 int StringToInt(const char *str, int defaultValue)
463 {
464 if (str == NULL || *str == '\0') {
465 return defaultValue;
466 }
467 errno = 0;
468 int value = (int)strtoul(str, NULL, DECIMAL_BASE);
469 return (errno != 0) ? defaultValue : value;
470 }
471
ReadFileInDir(const char * dirPath,const char * includeExt,int (* processFile)(const char * fileName,void * context),void * context)472 int ReadFileInDir(const char *dirPath, const char *includeExt,
473 int (*processFile)(const char *fileName, void *context), void *context)
474 {
475 INIT_CHECK_RETURN_VALUE(dirPath != NULL && processFile != NULL, -1);
476 DIR *pDir = opendir(dirPath);
477 INIT_ERROR_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno);
478 char *fileName = calloc(1, MAX_BUF_SIZE);
479 INIT_ERROR_CHECK(fileName != NULL, closedir(pDir);
480 return -1, "Failed to malloc for %s", dirPath);
481
482 struct dirent *dp;
483 uint32_t count = 0;
484 while ((dp = readdir(pDir)) != NULL) {
485 if (dp->d_type == DT_DIR) {
486 continue;
487 }
488 if (includeExt != NULL) {
489 char *tmp = strstr(dp->d_name, includeExt);
490 if (tmp == NULL) {
491 continue;
492 }
493 if (strcmp(tmp, includeExt) != 0) {
494 continue;
495 }
496 }
497 int ret = snprintf_s(fileName, MAX_BUF_SIZE, MAX_BUF_SIZE - 1, "%s/%s", dirPath, dp->d_name);
498 if (ret <= 0) {
499 INIT_LOGE("Failed to get file name for %s", dp->d_name);
500 continue;
501 }
502 struct stat st;
503 if (stat(fileName, &st) == 0) {
504 count++;
505 processFile(fileName, context);
506 }
507 }
508 INIT_LOGV("ReadFileInDir dirPath %s %d", dirPath, count);
509 free(fileName);
510 closedir(pDir);
511 return 0;
512 }
513
514 // Check if in updater mode.
InUpdaterMode(void)515 int InUpdaterMode(void)
516 {
517 #ifdef OHOS_LITE
518 return 0;
519 #else
520 const char * const updaterExecutableFile = "/bin/updater";
521 if (access(updaterExecutableFile, X_OK) == 0) {
522 return 1;
523 } else {
524 return 0;
525 }
526 #endif
527 }
528
StringReplaceChr(char * strl,char oldChr,char newChr)529 int StringReplaceChr(char *strl, char oldChr, char newChr)
530 {
531 INIT_ERROR_CHECK(strl != NULL, return -1, "Invalid parament");
532 char *p = strl;
533 while (*p != '\0') {
534 if (*p == oldChr) {
535 *p = newChr;
536 }
537 p++;
538 }
539 INIT_LOGV("strl is %s", strl);
540 return 0;
541 }
542
RedirectStdio(int fd)543 void RedirectStdio(int fd)
544 {
545 #ifndef __LITEOS_M__
546 const int stdError = 2;
547 dup2(fd, 0);
548 dup2(fd, 1);
549 dup2(fd, stdError); // Redirect fd to 0, 1, 2
550 #endif
551 }
552
OpenConsole(void)553 void OpenConsole(void)
554 {
555 #ifndef __LITEOS_M__
556 setsid();
557 WaitForFile("/dev/console", WAIT_MAX_SECOND);
558 int fd = open("/dev/console", O_RDWR);
559 if (fd >= 0) {
560 ioctl(fd, TIOCSCTTY, 0);
561 RedirectStdio(fd);
562 close(fd);
563 } else {
564 INIT_LOGE("Open /dev/console failed. err = %d", errno);
565 }
566 return;
567 #endif
568 }
569
StringToLL(const char * str,long long int * out)570 INIT_LOCAL_API int StringToLL(const char *str, long long int *out)
571 {
572 INIT_ERROR_CHECK(str != NULL && out != NULL, return -1, "Invalid parament");
573 const char *s = str;
574 while (isspace(*s)) {
575 s++;
576 }
577
578 size_t len = strlen(str);
579 int positiveHex = (len > 1 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
580 int negativeHex = (len > 2 && s[0] == '-' && s[1] == '0' && (s[2] == 'x' || s[2] == 'X')); // 2: shorttest
581 int base = (positiveHex || negativeHex) ? HEX_BASE : DECIMAL_BASE;
582 char *end = NULL;
583 errno = 0;
584 *out = strtoll(s, &end, base);
585 if (errno != 0) {
586 INIT_LOGE("StringToLL %s err = %d", str, errno);
587 return -1;
588 }
589 BEGET_CHECK(!(s == end || *end != '\0'), return -1);
590 return 0;
591 }
592
StringToULL(const char * str,unsigned long long int * out)593 INIT_LOCAL_API int StringToULL(const char *str, unsigned long long int *out)
594 {
595 INIT_ERROR_CHECK(str != NULL && out != NULL, return -1, "Invalid parament");
596 const char *s = str;
597 while (isspace(*s)) {
598 s++;
599 }
600 BEGET_CHECK(s[0] != '-', return -1);
601 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? HEX_BASE : DECIMAL_BASE;
602 char *end = NULL;
603 errno = 0;
604 *out = strtoull(s, &end, base);
605 if (errno != 0) {
606 INIT_LOGE("StringToULL %s err = %d", str, errno);
607 return -1;
608 }
609 BEGET_CHECK(end != s, return -1);
610 BEGET_CHECK(*end == '\0', return -1);
611 return 0;
612 }
613
TrimTail(char * str,char c)614 void TrimTail(char *str, char c)
615 {
616 char *end = str + strlen(str) - 1;
617 while (end >= str && *end == c) {
618 *end = '\0';
619 end--;
620 }
621 }
622
TrimHead(char * str,char c)623 char *TrimHead(char *str, char c)
624 {
625 char *head = str;
626 const char *end = str + strlen(str);
627 while (head < end && *head == c) {
628 *head = '\0';
629 head++;
630 }
631 return head;
632 }
633