• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <limits.h>
22 #include <pwd.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <time.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_DATA_BUFFER 2048
36 
37 #ifdef STARTUP_UT
38 #define LOG_FILE_NAME "/media/sf_ubuntu/test/log.txt"
39 #else
40 #define LOG_FILE_NAME "/data/startup_log.txt"
41 #endif
42 
43 #define MAX_JSON_FILE_LEN 102400    // max init.cfg size 100KB
44 #define CONVERT_MICROSEC_TO_SEC(x) ((x) / 1000 / 1000.0)
45 #ifndef DT_DIR
46 #define DT_DIR 4
47 #endif
48 
49 #define THOUSAND_UNIT_INT 1000
50 #define THOUSAND_UNIT_FLOAT 1000.0
51 
ConvertMicrosecondToSecond(int x)52 float ConvertMicrosecondToSecond(int x)
53 {
54     return ((x / THOUSAND_UNIT_INT) / THOUSAND_UNIT_FLOAT);
55 }
56 
DecodeUid(const char * name)57 uid_t DecodeUid(const char *name)
58 {
59     INIT_CHECK_RETURN_VALUE(name != NULL, -1);
60     int digitFlag = 1;
61     for (unsigned int i = 0; i < strlen(name); ++i) {
62         if (isalpha(name[i])) {
63             digitFlag = 0;
64             break;
65         }
66     }
67     if (digitFlag) {
68         errno = 0;
69         uid_t result = strtoul(name, 0, DECIMAL_BASE);
70         INIT_CHECK_RETURN_VALUE(errno == 0, -1);
71         return result;
72     } else {
73         struct passwd *userInf = getpwnam(name);
74         if (userInf == NULL) {
75             return -1;
76         }
77         return userInf->pw_uid;
78     }
79 }
80 
ReadFileToBuf(const char * configFile)81 char *ReadFileToBuf(const char *configFile)
82 {
83     char *buffer = NULL;
84     FILE *fd = NULL;
85     struct stat fileStat = {0};
86     INIT_CHECK_RETURN_VALUE(configFile != NULL && *configFile != '\0', NULL);
87     do {
88         if (stat(configFile, &fileStat) != 0 ||
89             fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) {
90             INIT_LOGE("Unexpected config file \" %s \", check if it exist. if exist, check file size", configFile);
91             break;
92         }
93         fd = fopen(configFile, "r");
94         if (fd == NULL) {
95             INIT_LOGE("Open %s failed. err = %d", configFile, errno);
96             break;
97         }
98         buffer = (char*)malloc((size_t)(fileStat.st_size + 1));
99         if (buffer == NULL) {
100             INIT_LOGE("Failed to allocate memory for config file, err = %d", errno);
101             break;
102         }
103 
104         if (fread(buffer, fileStat.st_size, 1, fd) != 1) {
105             free(buffer);
106             buffer = NULL;
107             break;
108         }
109         buffer[fileStat.st_size] = '\0';
110     } while (0);
111 
112     if (fd != NULL) {
113         (void)fclose(fd);
114         fd = NULL;
115     }
116     return buffer;
117 }
118 
ReadFileData(const char * fileName)119 char *ReadFileData(const char *fileName)
120 {
121     if (fileName == NULL) {
122         return NULL;
123     }
124     char *buffer = NULL;
125     int fd = -1;
126     do {
127         fd = open(fileName, O_RDONLY);
128         INIT_ERROR_CHECK(fd >= 0, break, "Failed to read file %s", fileName);
129 
130         buffer = (char *)malloc(MAX_DATA_BUFFER); // fsmanager not create, can not get fileStat st_size
131         INIT_ERROR_CHECK(buffer != NULL, break, "Failed to allocate memory for %s", fileName);
132         ssize_t readLen = read(fd, buffer, MAX_DATA_BUFFER - 1);
133         INIT_ERROR_CHECK(readLen > 0, break, "Failed to read data for %s", fileName);
134         buffer[readLen] = '\0';
135     } while (0);
136     if (fd != -1) {
137         close(fd);
138     }
139     return buffer;
140 }
141 
GetProcCmdlineValue(const char * name,const char * buffer,char * value,int length)142 int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length)
143 {
144     INIT_ERROR_CHECK(name != NULL && buffer != NULL && value != NULL, return -1, "Failed get parameters");
145     char *endData = (char *)buffer + strlen(buffer);
146     char *tmp = strstr(buffer, name);
147     do {
148         if (tmp == NULL) {
149             return -1;
150         }
151         tmp = tmp + strlen(name);
152         while (tmp < endData && *tmp == ' ') {
153             tmp++;
154         }
155         if (*tmp == '=') {
156             break;
157         }
158         tmp = strstr(tmp + 1, name);
159     } while (tmp < endData);
160     tmp++;
161     size_t i = 0;
162     size_t endIndex = 0;
163     while (tmp < endData && *tmp == ' ') {
164         tmp++;
165     }
166     for (; i < (size_t)length; tmp++) {
167         if (tmp >= endData) {
168             endIndex = i;
169             break;
170         }
171         if (*tmp == ' ' || *tmp == '\n' || *tmp == '\r' || *tmp == '\t') {
172             endIndex = i;
173             break;
174         }
175         if (*tmp == '=') {
176             if (endIndex != 0) { // for root=uuid=xxxx
177                 break;
178             }
179             i = 0;
180             endIndex = 0;
181             continue;
182         }
183         value[i++] = *tmp;
184     }
185     if (i >= (size_t)length) {
186         return -1;
187     }
188     value[endIndex] = '\0';
189     return 0;
190 }
191 
SplitString(char * srcPtr,const char * del,char ** dstPtr,int maxNum)192 int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum)
193 {
194     INIT_CHECK_RETURN_VALUE(srcPtr != NULL && dstPtr != NULL && del != NULL, -1);
195     char *buf = NULL;
196     dstPtr[0] = strtok_r(srcPtr, del, &buf);
197     int counter = 0;
198     while ((counter < maxNum) && (dstPtr[counter] != NULL)) {
199         counter++;
200         if (counter >= maxNum) {
201             break;
202         }
203         dstPtr[counter] = strtok_r(NULL, del, &buf);
204     }
205     return counter;
206 }
207 
FreeStringVector(char ** vector,int count)208 void FreeStringVector(char **vector, int count)
209 {
210     if (vector != NULL) {
211         for (int i = 0; i < count; i++) {
212             if (vector[i] != NULL) {
213                 free(vector[i]);
214             }
215         }
216         free(vector);
217     }
218 }
219 
SplitStringExt(char * buffer,const char * del,int * returnCount,int maxItemCount)220 char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount)
221 {
222     INIT_CHECK_RETURN_VALUE((maxItemCount >= 0) && (buffer != NULL) && (del != NULL) && (returnCount != NULL), NULL);
223     // Why is this number?
224     // Now we use this function to split a string with a given delimeter
225     // We do not know how many sub-strings out there after splitting.
226     // 50 is just a guess value.
227     const int defaultItemCounts = 50;
228     int itemCounts = maxItemCount;
229 
230     if (maxItemCount > defaultItemCounts) {
231         itemCounts = defaultItemCounts;
232     }
233     char **items = (char **)malloc(sizeof(char*) * itemCounts);
234     INIT_ERROR_CHECK(items != NULL, return NULL, "No enough memory to store items");
235     char *rest = NULL;
236     char *p = strtok_r(buffer, del, &rest);
237     int count = 0;
238     while (p != NULL) {
239         if (count > itemCounts - 1) {
240             itemCounts += (itemCounts / 2) + 1; // 2 Request to increase the original memory by half.
241             INIT_LOGV("Too many items,expand size");
242             char **expand = (char **)(realloc(items, sizeof(char *) * itemCounts));
243             INIT_ERROR_CHECK(expand != NULL, FreeStringVector(items, count);
244                 return NULL, "Failed to expand memory for uevent config parser");
245             items = expand;
246         }
247         size_t len = strlen(p);
248         items[count] = (char *)malloc(len + 1);
249         INIT_CHECK(items[count] != NULL, FreeStringVector(items, count);
250             return NULL);
251         if (strncpy_s(items[count], len + 1, p, len) != EOK) {
252             INIT_LOGE("Copy string failed");
253             FreeStringVector(items, count);
254             return NULL;
255         }
256         items[count][len] = '\0';
257         count++;
258         p = strtok_r(NULL, del, &rest);
259     }
260     *returnCount = count;
261     return items;
262 }
263 
WaitForFile(const char * source,unsigned int maxSecond)264 void WaitForFile(const char *source, unsigned int maxSecond)
265 {
266     INIT_ERROR_CHECK(maxSecond <= WAIT_MAX_SECOND, maxSecond = WAIT_MAX_SECOND, "WaitForFile max time is 5s");
267     struct stat sourceInfo = {};
268     unsigned int waitTime = 500000;
269     /* 500ms interval, check maxSecond*2 times total */
270     unsigned int maxCount = maxSecond * 2;
271     unsigned int count = 0;
272     do {
273         usleep(waitTime);
274         count++;
275     } while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (count < maxCount));
276     INIT_CHECK_ONLY_ELOG(count != maxCount, "wait for file:%s failed after %d second.", source, maxSecond);
277     return;
278 }
279 
WriteAll(int fd,const char * buffer,size_t size)280 size_t WriteAll(int fd, const char *buffer, size_t size)
281 {
282     INIT_CHECK_RETURN_VALUE(buffer != NULL && fd >= 0 && *buffer != '\0', 0);
283     const char *p = buffer;
284     size_t left = size;
285     ssize_t written;
286     while (left > 0) {
287         do {
288             written = write(fd, p, left);
289         } while (written < 0 && errno == EINTR);
290         if (written < 0) {
291             INIT_LOGE("Failed to write %lu bytes, err = %d", left, errno);
292             break;
293         }
294         p += written;
295         left -= written;
296     }
297     return size - left;
298 }
299 
GetRealPath(const char * source)300 char *GetRealPath(const char *source)
301 {
302     INIT_CHECK_RETURN_VALUE(source != NULL, NULL);
303     char *path = realpath(source, NULL);
304     if (path == NULL) {
305         INIT_ERROR_CHECK(errno == ENOENT, return NULL, "Failed to resolve %s real path err=%d", source, errno);
306     }
307     return path;
308 }
309 
MakeDir(const char * dir,mode_t mode)310 int MakeDir(const char *dir, mode_t mode)
311 {
312     int rc = -1;
313     if (dir == NULL || *dir == '\0') {
314         errno = EINVAL;
315         return rc;
316     }
317     rc = mkdir(dir, mode);
318     INIT_ERROR_CHECK(!(rc < 0 && errno != EEXIST), return rc,
319         "Create directory \" %s \" failed, err = %d", dir, errno);
320     // create dir success or it already exist.
321     return 0;
322 }
323 
MakeDirRecursive(const char * dir,mode_t mode)324 int MakeDirRecursive(const char *dir, mode_t mode)
325 {
326     int rc = -1;
327     char buffer[PATH_MAX] = {};
328     const char *p = NULL;
329     if (dir == NULL || *dir == '\0') {
330         errno = EINVAL;
331         return rc;
332     }
333     p = dir;
334     char *slash = strchr(dir, '/');
335     while (slash != NULL) {
336         int gap = slash - p;
337         p = slash + 1;
338         if (gap == 0) {
339             slash = strchr(p, '/');
340             continue;
341         }
342         if (gap < 0) { // end with '/'
343             break;
344         }
345         INIT_CHECK_RETURN_VALUE(memcpy_s(buffer, PATH_MAX, dir, p - dir - 1) == 0, -1);
346         rc = MakeDir(buffer, mode);
347         INIT_CHECK_RETURN_VALUE(rc >= 0, rc);
348         slash = strchr(p, '/');
349     }
350     return MakeDir(dir, mode);
351 }
352 
StringToInt(const char * str,int defaultValue)353 int StringToInt(const char *str, int defaultValue)
354 {
355     if (str == NULL || *str == '\0') {
356         return defaultValue;
357     }
358     errno = 0;
359     int value = (int)strtoul(str, NULL, DECIMAL_BASE);
360     return (errno != 0) ? defaultValue : value;
361 }
362 
ReadFileInDir(const char * dirPath,const char * includeExt,int (* processFile)(const char * fileName,void * context),void * context)363 int ReadFileInDir(const char *dirPath, const char *includeExt,
364     int (*processFile)(const char *fileName, void *context), void *context)
365 {
366     INIT_CHECK_RETURN_VALUE(dirPath != NULL && processFile != NULL, -1);
367     DIR *pDir = opendir(dirPath);
368     INIT_ERROR_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno);
369     char *fileName = malloc(MAX_BUF_SIZE);
370     INIT_ERROR_CHECK(fileName != NULL, closedir(pDir);
371         return -1, "Failed to malloc for %s", dirPath);
372 
373     struct dirent *dp;
374     while ((dp = readdir(pDir)) != NULL) {
375         if (dp->d_type == DT_DIR) {
376             continue;
377         }
378         INIT_LOGV("ReadFileInDir %s", dp->d_name);
379         if (includeExt != NULL) {
380             char *tmp = strstr(dp->d_name, includeExt);
381             if (tmp == NULL) {
382                 continue;
383             }
384             if (strcmp(tmp, includeExt) != 0) {
385                 continue;
386             }
387         }
388         int ret = snprintf_s(fileName, MAX_BUF_SIZE, MAX_BUF_SIZE - 1, "%s/%s", dirPath, dp->d_name);
389         if (ret <= 0) {
390             INIT_LOGE("Failed to get file name for %s", dp->d_name);
391             continue;
392         }
393         struct stat st;
394         if (stat(fileName, &st) == 0) {
395             processFile(fileName, context);
396         }
397     }
398     free(fileName);
399     closedir(pDir);
400     return 0;
401 }
402 
403 // Check if in updater mode.
InUpdaterMode(void)404 int InUpdaterMode(void)
405 {
406     const char * const updaterExecutabeFile = "/bin/updater";
407     if (access(updaterExecutabeFile, X_OK) == 0) {
408         return 1;
409     } else {
410         return 0;
411     }
412 }
413 
StringReplaceChr(char * strl,char oldChr,char newChr)414 int StringReplaceChr(char *strl, char oldChr, char newChr)
415 {
416     INIT_ERROR_CHECK(strl != NULL, return -1, "Invalid parament");
417     char *p = strl;
418     while (*p != '\0') {
419         if (*p == oldChr) {
420             *p = newChr;
421         }
422         p++;
423     }
424     INIT_LOGV("strl is %s", strl);
425     return 0;
426 }
427 
GetMapValue(const char * name,const InitArgInfo * infos,int argNum,int defValue)428 int GetMapValue(const char *name, const InitArgInfo *infos, int argNum, int defValue)
429 {
430     if ((argNum == 0) || (infos == NULL) || (name == NULL)) {
431         return defValue;
432     }
433     for (int i = 0; i < argNum; i++) {
434         if (strcmp(infos[i].name, name) == 0) {
435             return infos[i].value;
436         }
437     }
438     return defValue;
439 }
440 
441 const static InitArgInfo g_servieStatusMap[] = {
442     {"created", SERVICE_IDLE},
443     {"starting", SERVICE_STARTING},
444     {"running", SERVICE_STARTED},
445     {"ready", SERVICE_READY},
446     {"stopping", SERVICE_STOPPING},
447     {"stopped", SERVICE_STOPPED},
448     {"suspended", SERVICE_SUSPENDED},
449     {"freezed", SERVICE_FREEZED},
450     {"disabled", SERVICE_DISABLED},
451     {"critial", SERVICE_CRITIAL}
452 };
453 
GetServieStatusMap(int * size)454 const InitArgInfo *GetServieStatusMap(int *size)
455 {
456     if (size != 0) {
457         *size = ARRAY_LENGTH(g_servieStatusMap);
458     }
459     return g_servieStatusMap;
460 }
461