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#include <time.h> 30 31#include "init_log.h" 32#include "securec.h" 33#include "service_control.h" 34 35#define MAX_BUF_SIZE 1024 36#define MAX_SMALL_BUFFER 4096 37 38#define MAX_JSON_FILE_LEN 102400 // max init.cfg size 100KB 39#define CONVERT_MICROSEC_TO_SEC(x) ((x) / 1000 / 1000.0) 40#ifndef DT_DIR 41#define DT_DIR 4 42#endif 43 44#define THOUSAND_UNIT_INT 1000 45#define THOUSAND_UNIT_FLOAT 1000.0 46 47float ConvertMicrosecondToSecond(int x) 48{ 49 return ((x / THOUSAND_UNIT_INT) / THOUSAND_UNIT_FLOAT); 50} 51 52#ifndef __LITEOS_M__ 53static bool CheckDigit(const char *name) 54{ 55 size_t nameLen = strlen(name); 56 for (size_t i = 0; i < nameLen; ++i) { 57 if (!isdigit(name[i])) { 58 return false; 59 } 60 } 61 return true; 62} 63#endif 64 65int StringToUint(const char *name, unsigned int *value) 66{ 67 errno = 0; 68 *value = (unsigned int)strtoul(name, 0, DECIMAL_BASE); 69 INIT_CHECK_RETURN_VALUE(errno == 0, -1); 70 return 0; 71} 72 73uid_t DecodeUid(const char *name) 74{ 75#ifndef __LITEOS_M__ 76 INIT_CHECK_RETURN_VALUE(name != NULL, -1); 77 uid_t uid = -1; 78 if (CheckDigit(name)) { 79 if (!StringToUint(name, &uid)) { 80 return uid; 81 } else { 82 return -1; 83 } 84 } 85 struct passwd *p = getpwnam(name); 86 if (p == NULL) { 87 return -1; 88 } 89 return p->pw_uid; 90#else 91 (void)name; 92 return -1; 93#endif 94} 95 96gid_t DecodeGid(const char *name) 97{ 98#ifndef __LITEOS_M__ 99 INIT_CHECK_RETURN_VALUE(name != NULL, -1); 100 gid_t gid = -1; 101 if (CheckDigit(name)) { 102 if (!StringToUint(name, &gid)) { 103 return gid; 104 } else { 105 return -1; 106 } 107 } 108 struct group *data = getgrnam(name); 109 if (data != NULL) { 110 return data->gr_gid; 111 } 112 while ((data = getgrent()) != NULL) { 113 if ((data->gr_name != NULL) && (strcmp(data->gr_name, name) == 0)) { 114 gid = data->gr_gid; 115 break; 116 } 117 } 118 endgrent(); 119 return gid; 120#else 121 (void)name; 122 return -1; 123#endif 124} 125 126char *ReadFileToBuf(const char *configFile) 127{ 128 char *buffer = NULL; 129 FILE *fd = NULL; 130 struct stat fileStat = {0}; 131 INIT_CHECK_RETURN_VALUE(configFile != NULL && *configFile != '\0', NULL); 132 do { 133 if (stat(configFile, &fileStat) != 0 || 134 fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) { 135 break; 136 } 137 fd = fopen(configFile, "r"); 138 if (fd == NULL) { 139 INIT_LOGE("Open %s failed. err = %d", configFile, errno); 140 break; 141 } 142 buffer = (char*)calloc((size_t)(fileStat.st_size + 1), sizeof(char)); 143 if (buffer == NULL) { 144 INIT_LOGE("Failed to allocate memory for config file, err = %d", errno); 145 break; 146 } 147 148 if (fread(buffer, fileStat.st_size, 1, fd) != 1) { 149 free(buffer); 150 buffer = NULL; 151 break; 152 } 153 buffer[fileStat.st_size] = '\0'; 154 } while (0); 155 156 if (fd != NULL) { 157 (void)fclose(fd); 158 fd = NULL; 159 } 160 return buffer; 161} 162 163void CloseStdio(void) 164{ 165#ifndef STARTUP_INIT_TEST 166#ifndef __LITEOS_M__ 167 int fd = open("/dev/null", O_RDWR); 168 if (fd < 0) { 169 return; 170 } 171 dup2(fd, 0); 172 dup2(fd, 1); 173 dup2(fd, STDERR_HANDLE); 174 if (fd > STDERR_HANDLE) { 175 close(fd); 176 } 177#endif 178#endif 179} 180 181char *ReadFileData(const char *fileName) 182{ 183 if (fileName == NULL) { 184 return NULL; 185 } 186 char *buffer = NULL; 187 int fd = -1; 188 fd = open(fileName, O_RDONLY); 189 INIT_ERROR_CHECK(fd >= 0, return NULL, "Failed to read file %s errno:%d", fileName, errno); 190 buffer = (char *)calloc(1, MAX_SMALL_BUFFER); // fsmanager not create, can not get fileStat st_size 191 INIT_ERROR_CHECK(buffer != NULL, close(fd); 192 return NULL, "Failed to allocate memory for %s", fileName); 193 ssize_t readLen = read(fd, buffer, MAX_SMALL_BUFFER - 1); 194 INIT_ERROR_CHECK((readLen > 0) && (readLen <= (MAX_SMALL_BUFFER - 1)), close(fd); 195 free(buffer); 196 return NULL, "Failed to read data for %s", fileName); 197 buffer[readLen] = '\0'; 198 if (fd != -1) { 199 close(fd); 200 } 201 return buffer; 202} 203 204int IterateNameValuePairs(const char *src, void (*iterator)(const NAME_VALUE_PAIR *nv, void *context), void *context) 205{ 206 int cnt = 0; 207 const char *seperator; 208 const char *tmp = src; 209 NAME_VALUE_PAIR nv; 210 if ((src == NULL) || (iterator == NULL)) { 211 return -1; 212 } 213 214 do { 215 // Find space seperator 216 nv.name = tmp; 217 seperator = strchr(tmp, ' '); 218 if (seperator == NULL) { 219 // Last nv 220 nv.valueEnd = tmp + strlen(tmp); 221 tmp = NULL; 222 } else { 223 nv.valueEnd = seperator; 224 tmp = seperator + 1; 225 } 226 227 // Find equal seperator 228 seperator = strchr(nv.name, '='); 229 if (seperator == NULL) { 230 // Invalid name value pair 231 continue; 232 } 233 if (seperator > nv.valueEnd) { 234 // name without value, just ignore 235 continue; 236 } 237 nv.nameEnd = seperator; 238 nv.value = seperator + 1; 239 240 iterator(&nv, context); 241 cnt += 1; 242 } while (tmp != NULL); 243 244 return cnt; 245} 246 247int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length) 248{ 249 INIT_ERROR_CHECK(name != NULL && buffer != NULL && value != NULL, return -1, "Failed get parameters"); 250 char *endData = (char *)buffer + strlen(buffer); 251 char *tmp = strstr(buffer, name); 252 do { 253 if (tmp == NULL) { 254 return -1; 255 } 256 tmp = tmp + strlen(name); 257 while (tmp < endData && *tmp == ' ') { 258 tmp++; 259 } 260 if (tmp >= endData) { 261 return -1; 262 } 263 if (*tmp == '=') { 264 break; 265 } 266 tmp = strstr(tmp + 1, name); 267 } while (tmp < endData); 268 tmp++; 269 size_t i = 0; 270 size_t endIndex = 0; 271 while (tmp < endData && *tmp == ' ') { 272 tmp++; 273 } 274 for (; i < (size_t)length; tmp++) { 275 if (tmp >= endData || *tmp == ' ' || *tmp == '\n' || *tmp == '\r' || *tmp == '\t') { 276 endIndex = i; 277 break; 278 } 279 if (*tmp == '=') { 280 if (endIndex != 0) { // for root=uuid=xxxx 281 break; 282 } 283 i = 0; 284 endIndex = 0; 285 continue; 286 } 287 value[i++] = *tmp; 288 } 289 if (i >= (size_t)length) { 290 return -1; 291 } 292 value[endIndex] = '\0'; 293 return 0; 294} 295 296int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum) 297{ 298 INIT_CHECK_RETURN_VALUE(srcPtr != NULL && dstPtr != NULL && del != NULL, -1); 299 char *buf = NULL; 300 dstPtr[0] = strtok_r(srcPtr, del, &buf); 301 int counter = 0; 302 while ((counter < maxNum) && (dstPtr[counter] != NULL)) { 303 counter++; 304 if (counter >= maxNum) { 305 break; 306 } 307 dstPtr[counter] = strtok_r(NULL, del, &buf); 308 } 309 return counter; 310} 311 312void FreeStringVector(char **vector, int count) 313{ 314 if (vector != NULL) { 315 for (int i = 0; i < count; i++) { 316 if (vector[i] != NULL) { 317 free(vector[i]); 318 } 319 } 320 free(vector); 321 } 322} 323 324char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount) 325{ 326 INIT_CHECK_RETURN_VALUE((maxItemCount >= 0) && (buffer != NULL) && (del != NULL) && (returnCount != NULL), NULL); 327 // Why is this number? 328 // Now we use this function to split a string with a given delimiter 329 // We do not know how many sub-strings out there after splitting. 330 // 50 is just a guess value. 331 const int defaultItemCounts = 50; 332 int itemCounts = maxItemCount; 333 334 if (maxItemCount > defaultItemCounts) { 335 itemCounts = defaultItemCounts; 336 } 337 char **items = (char **)malloc(sizeof(char*) * itemCounts); 338 INIT_ERROR_CHECK(items != NULL, return NULL, "No enough memory to store items"); 339 char *rest = NULL; 340 char *p = strtok_r(buffer, del, &rest); 341 int count = 0; 342 while (p != NULL) { 343 if (count > itemCounts - 1) { 344 itemCounts += (itemCounts / 2) + 1; // 2 Request to increase the original memory by half. 345 INIT_LOGV("Too many items,expand size"); 346 char **expand = (char **)(realloc(items, sizeof(char *) * itemCounts)); 347 INIT_ERROR_CHECK(expand != NULL, FreeStringVector(items, count); 348 return NULL, "Failed to expand memory"); 349 items = expand; 350 } 351 size_t len = strlen(p); 352 items[count] = (char *)calloc(len + 1, sizeof(char)); 353 INIT_CHECK(items[count] != NULL, FreeStringVector(items, count); 354 return NULL); 355 if (strncpy_s(items[count], len + 1, p, len) != EOK) { 356 INIT_LOGE("Copy string failed"); 357 FreeStringVector(items, count); 358 return NULL; 359 } 360 count++; 361 p = strtok_r(NULL, del, &rest); 362 } 363 *returnCount = count; 364 return items; 365} 366 367long long InitDiffTime(INIT_TIMING_STAT *stat) 368{ 369 long long diff = (long long)(stat->endTime.tv_sec - stat->startTime.tv_sec) * 1000000; // 1000000 1000ms 370 if (stat->endTime.tv_nsec > stat->startTime.tv_nsec) { 371 diff += (stat->endTime.tv_nsec - stat->startTime.tv_nsec) / BASE_MS_UNIT; 372 } else { 373 diff -= (stat->startTime.tv_nsec - stat->endTime.tv_nsec) / BASE_MS_UNIT; 374 } 375 return diff; 376} 377 378void WaitForFile(const char *source, unsigned int maxSecond) 379{ 380 INIT_ERROR_CHECK(maxSecond <= WAIT_MAX_SECOND, maxSecond = WAIT_MAX_SECOND, 381 "WaitForFile max time is %us", WAIT_MAX_SECOND); 382 struct stat sourceInfo = {0}; 383 unsigned int waitTime = 10 * BASE_MS_UNIT; // 10ms 384 long long maxDuration = maxSecond * BASE_MS_UNIT * BASE_MS_UNIT; // 5s 385#ifdef STARTUP_INIT_TEST 386 maxDuration = 0; 387#endif 388 long long duration = 0; 389 INIT_TIMING_STAT cmdTimer; 390 (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.startTime); 391 while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (duration < maxDuration)) { 392 usleep(waitTime); 393 (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.endTime); 394 duration = InitDiffTime(&cmdTimer); 395 } 396 INIT_CHECK_ONLY_ELOG(duration < maxDuration, "wait for file:%s failed after %d second.", source, maxSecond); 397 return; 398} 399 400size_t WriteAll(int fd, const char *buffer, size_t size) 401{ 402 INIT_CHECK_RETURN_VALUE(buffer != NULL && fd >= 0 && *buffer != '\0', 0); 403 const char *p = buffer; 404 size_t left = size; 405 ssize_t written; 406 while (left > 0) { 407 do { 408 written = write(fd, p, left); 409 } while (written < 0 && errno == EINTR); 410 if (written < 0) { 411 INIT_LOGE("Failed to write %lu bytes, err = %d", left, errno); 412 break; 413 } 414 p += written; 415 left -= written; 416 } 417 return size - left; 418} 419 420char *GetRealPath(const char *source) 421{ 422 INIT_CHECK_RETURN_VALUE(source != NULL, NULL); 423 char *path = realpath(source, NULL); 424 if (path == NULL) { 425 INIT_ERROR_CHECK(errno == ENOENT, return NULL, "Failed to resolve %s real path err=%d", source, errno); 426 } 427 return path; 428} 429 430int MakeDir(const char *dir, mode_t mode) 431{ 432 int rc = -1; 433 if (dir == NULL || *dir == '\0') { 434 errno = EINVAL; 435 return rc; 436 } 437 rc = mkdir(dir, mode); 438 INIT_ERROR_CHECK(!(rc < 0 && errno != EEXIST), return rc, 439 "Create directory \" %s \" failed, err = %d", dir, errno); 440 // create dir success or it already exist. 441 return 0; 442} 443 444int MakeDirRecursive(const char *dir, mode_t mode) 445{ 446 int rc = -1; 447 char buffer[PATH_MAX] = {0}; 448 const char *p = NULL; 449 if (dir == NULL || *dir == '\0') { 450 errno = EINVAL; 451 return rc; 452 } 453 p = dir; 454 char *slash = strchr(dir, '/'); 455 while (slash != NULL) { 456 int gap = slash - p; 457 p = slash + 1; 458 if (gap == 0) { 459 slash = strchr(p, '/'); 460 continue; 461 } 462 if (gap < 0) { // end with '/' 463 break; 464 } 465 INIT_CHECK_RETURN_VALUE(memcpy_s(buffer, PATH_MAX, dir, p - dir - 1) == 0, -1); 466 rc = MakeDir(buffer, mode); 467 INIT_CHECK_RETURN_VALUE(rc >= 0, rc); 468 slash = strchr(p, '/'); 469 } 470 return MakeDir(dir, mode); 471} 472 473void CheckAndCreateDir(const char *fileName) 474{ 475#ifndef __LITEOS_M__ 476 if (fileName == NULL || *fileName == '\0') { 477 return; 478 } 479 char *path = strndup(fileName, strrchr(fileName, '/') - fileName); 480 if (path == NULL) { 481 return; 482 } 483 if (access(path, F_OK) == 0) { 484 free(path); 485 return; 486 } 487 MakeDirRecursive(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 488 free(path); 489#else 490 (void)fileName; 491#endif 492} 493 494int CheckAndCreatFile(const char *file, mode_t mode) 495{ 496 if (access(file, F_OK) == 0) { 497 BEGET_LOGW("File \' %s \' already exist", file); 498 return 0; 499 } else { 500 if (errno == ENOENT) { 501 CheckAndCreateDir(file); 502 int fd = open(file, O_CREAT, mode); 503 if (fd < 0) { 504 BEGET_LOGE("Failed create %s, err=%d", file, errno); 505 return -1; 506 } else { 507 close(fd); 508 } 509 } else { 510 BEGET_LOGW("Failed to access \' %s \', err = %d", file, errno); 511 return -1; 512 } 513 } 514 return 0; 515} 516 517int StringToInt(const char *str, int defaultValue) 518{ 519 if (str == NULL || *str == '\0') { 520 return defaultValue; 521 } 522 errno = 0; 523 int value = (int)strtoul(str, NULL, DECIMAL_BASE); 524 return (errno != 0) ? defaultValue : value; 525} 526 527int ReadFileInDir(const char *dirPath, const char *includeExt, 528 int (*processFile)(const char *fileName, void *context), void *context) 529{ 530 INIT_CHECK_RETURN_VALUE(dirPath != NULL && processFile != NULL, -1); 531 DIR *pDir = opendir(dirPath); 532 INIT_ERROR_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno); 533 char *fileName = calloc(1, MAX_BUF_SIZE); 534 INIT_ERROR_CHECK(fileName != NULL, closedir(pDir); 535 return -1, "Failed to malloc for %s", dirPath); 536 537 struct dirent *dp; 538 uint32_t count = 0; 539 while ((dp = readdir(pDir)) != NULL) { 540 if (dp->d_type == DT_DIR) { 541 continue; 542 } 543 if (includeExt != NULL) { 544 char *tmp = strstr(dp->d_name, includeExt); 545 if (tmp == NULL) { 546 continue; 547 } 548 if (strcmp(tmp, includeExt) != 0) { 549 continue; 550 } 551 } 552 int ret = snprintf_s(fileName, MAX_BUF_SIZE, MAX_BUF_SIZE - 1, "%s/%s", dirPath, dp->d_name); 553 if (ret <= 0) { 554 INIT_LOGE("Failed to get file name for %s", dp->d_name); 555 continue; 556 } 557 struct stat st; 558 if (stat(fileName, &st) == 0) { 559 count++; 560 processFile(fileName, context); 561 } 562 } 563 INIT_LOGV("ReadFileInDir dirPath %s %d", dirPath, count); 564 free(fileName); 565 closedir(pDir); 566 return 0; 567} 568 569// Check if in updater mode. 570int InUpdaterMode(void) 571{ 572#ifdef OHOS_LITE 573 return 0; 574#else 575 const char * const updaterExecutableFile = "/bin/updater"; 576 if (access(updaterExecutableFile, X_OK) == 0) { 577 return 1; 578 } else { 579 return 0; 580 } 581#endif 582} 583 584// Check if in rescue mode. 585int InRescueMode(void) 586{ 587#ifdef OHOS_LITE 588 return 1; 589#else 590 char value[MAX_BUFFER_LEN] = {0}; 591 int ret = GetParameterFromCmdLine("rescue_mode", value, MAX_BUFFER_LEN); 592 if (ret == 0 && strcmp(value, "true") == 0) { 593 return 0; 594 } 595 return 1; 596#endif 597} 598 599int StringReplaceChr(char *strl, char oldChr, char newChr) 600{ 601 INIT_ERROR_CHECK(strl != NULL, return -1, "Invalid parament"); 602 char *p = strl; 603 while (*p != '\0') { 604 if (*p == oldChr) { 605 *p = newChr; 606 } 607 p++; 608 } 609 INIT_LOGV("strl is %s", strl); 610 return 0; 611} 612 613#ifndef __LITEOS_M__ 614static void RedirectStdio(int fd) 615{ 616 const int stdError = 2; 617 dup2(fd, 0); 618 dup2(fd, 1); 619 dup2(fd, stdError); // Redirect fd to 0, 1, 2 620} 621#endif 622 623#ifndef __LITEOS_M__ 624static int OpenStdioDevice(const char *dev, int flag) 625{ 626 setsid(); 627 WaitForFile(dev, WAIT_MAX_SECOND); 628 int fd = open(dev, O_RDWR); 629 if (fd >= 0) { 630 ioctl(fd, TIOCSCTTY, flag); 631 RedirectStdio(fd); 632 if (fd > 2) { 633 close(fd); 634 } 635 } else { 636 return errno; 637 } 638 return 0; 639} 640#endif 641 642int OpenConsole(void) 643{ 644#ifndef __LITEOS_M__ 645 return OpenStdioDevice("/dev/console", 1); 646#else 647 return 0; 648#endif 649} 650 651int OpenKmsg(void) 652{ 653#ifndef __LITEOS_M__ 654 return OpenStdioDevice("/dev/kmsg", 0); 655#else 656 return 0; 657#endif 658} 659 660INIT_LOCAL_API int StringToLL(const char *str, long long int *out) 661{ 662 INIT_ERROR_CHECK(str != NULL && out != NULL, return -1, "Invalid parament"); 663 const char *s = str; 664 while (isspace(*s)) { 665 s++; 666 } 667 668 size_t len = strlen(s); 669 int positiveHex = (len > 1 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')); 670 int negativeHex = (len > 2 && s[0] == '-' && s[1] == '0' && (s[2] == 'x' || s[2] == 'X')); // 2: shorttest 671 int base = (positiveHex || negativeHex) ? HEX_BASE : DECIMAL_BASE; 672 char *end = NULL; 673 errno = 0; 674 *out = strtoll(s, &end, base); 675 if (errno != 0) { 676 INIT_LOGE("StringToLL %s err = %d", str, errno); 677 return -1; 678 } 679 BEGET_CHECK(!(s == end || *end != '\0'), return -1); 680 return 0; 681} 682 683INIT_LOCAL_API int StringToULL(const char *str, unsigned long long int *out) 684{ 685 INIT_ERROR_CHECK(str != NULL && out != NULL, return -1, "Invalid parament"); 686 const char *s = str; 687 while (isspace(*s)) { 688 s++; 689 } 690 BEGET_CHECK(s[0] != '-', return -1); 691 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? HEX_BASE : DECIMAL_BASE; 692 char *end = NULL; 693 errno = 0; 694 *out = strtoull(s, &end, base); 695 if (errno != 0) { 696 INIT_LOGE("StringToULL %s err = %d", str, errno); 697 return -1; 698 } 699 BEGET_CHECK(end != s, return -1); 700 BEGET_CHECK(*end == '\0', return -1); 701 return 0; 702} 703 704void TrimTail(char *str, char c) 705{ 706 char *end = str + strlen(str) - 1; 707 while (end >= str && *end == c) { 708 *end = '\0'; 709 end--; 710 } 711} 712 713char *TrimHead(char *str, char c) 714{ 715 char *head = str; 716 const char *end = str + strlen(str); 717 while (head < end && *head == c) { 718 *head = '\0'; 719 head++; 720 } 721 return head; 722} 723 724int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen) 725{ 726 char *buffer = ReadFileData(BOOT_CMD_LINE); 727 BEGET_ERROR_CHECK(buffer != NULL, return -1, "Failed to read /proc/cmdline"); 728 int ret = GetProcCmdlineValue(paramName, buffer, value, valueLen); 729 free(buffer); 730 return ret; 731} 732 733uint32_t IntervalTime(struct timespec *startTime, struct timespec *endTime) 734{ 735 uint32_t diff = 0; 736 if (endTime->tv_sec > startTime->tv_sec) { 737 diff = (uint32_t)(endTime->tv_sec - startTime->tv_sec); 738 } else { 739 diff = (uint32_t)(startTime->tv_sec - endTime->tv_sec); 740 } 741 return diff; 742} 743 744typedef int (*str_compare)(const char *s1, const char *s2); 745int OH_ExtendableStrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase, const char *extend[]) 746{ 747 int i; 748 int idx; 749 str_compare cmp = strcmp; 750 751 if ((strArray == NULL) || (target == NULL) || (target[0] == '\0')) { 752 return -1; 753 } 754 755 if (ignoreCase) { 756 cmp = strcasecmp; 757 } 758 759 for (i = 0; strArray[i] != NULL; i++) { 760 if (cmp(strArray[i], target) == 0) { 761 return i; 762 } 763 } 764 if (extend == NULL) { 765 return -1; 766 } 767 idx = 0; 768 while (extend[idx] != NULL) { 769 if (cmp(extend[idx], target) == 0) { 770 return i + idx; 771 } 772 idx++; 773 } 774 return -1; 775} 776 777int OH_StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase) 778{ 779 return OH_ExtendableStrArrayGetIndex(strArray, target, ignoreCase, NULL); 780} 781 782void *OH_ExtendableStrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase, void **extendStrDict) 783{ 784 int i; 785 const char *pos; 786 str_compare cmp = strcmp; 787 788 if ((strDict == NULL) || dictSize < 0 || ((size_t)dictSize < sizeof(const char *)) || 789 (target == NULL) || (target[0] == '\0')) { 790 return NULL; 791 } 792 793 if (ignoreCase) { 794 cmp = strcasecmp; 795 } 796 797 i = 0; 798 pos = (const char *)strDict; 799 while (*(const char **)pos != NULL) { 800 if (cmp(*(const char **)pos, target) == 0) { 801 return (void *)pos; 802 } 803 i++; 804 pos = pos + dictSize; 805 } 806 if (extendStrDict == NULL) { 807 return NULL; 808 } 809 pos = (const char *)extendStrDict; 810 while (*(const char **)pos != NULL) { 811 if (cmp(*(const char **)pos, target) == 0) { 812 return (void *)pos; 813 } 814 i++; 815 pos = pos + dictSize; 816 } 817 return NULL; 818} 819 820void *OH_StrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase) 821{ 822 return OH_ExtendableStrDictGet(strDict, dictSize, target, ignoreCase, NULL); 823} 824 825long long GetUptimeInMicroSeconds(const struct timespec *uptime) 826{ 827 struct timespec now; 828 829 if (uptime == NULL) { 830 clock_gettime(CLOCK_MONOTONIC, &now); 831 uptime = &now; 832 } 833 834 #define SECOND_TO_MICRO_SECOND (1000000) 835 #define MICRO_SECOND_TO_NANOSECOND (1000) 836 837 return ((long long)uptime->tv_sec * SECOND_TO_MICRO_SECOND) + 838 (uptime->tv_nsec / MICRO_SECOND_TO_NANOSECOND); 839} 840