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