• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 
16 #include "hisysevent_easy.h"
17 
18 #include <fcntl.h>
19 #include <securec.h>
20 #include <stddef.h>
21 #include <string.h>
22 #include <time.h>
23 #include <unistd.h>
24 
25 #include "easy_def.h"
26 #include "easy_event_builder.h"
27 #include "easy_socket_writer.h"
28 #include "easy_util.h"
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 static const char CUSTOMIZED_PARAM_KEY[] = "DATA";
35 static const int SEC_2_MILLIS = 1000;
36 static const int MILLS_2_NANOS = 1000000;
37 static const char PROC_SELF_STATUS_PATH[] = "/proc/self/status";
38 static const size_t LINE_BUF_SIZE = 1024;
39 static const char PID_STR_NAME[] = "Pid:";
40 static const int INVALID_PID = 0;
41 static const int ARGS_CNT_ONE = 1;
42 
GetTimestamp()43 static int64_t GetTimestamp()
44 {
45     struct timespec tp;
46     clock_gettime(CLOCK_REALTIME, &tp);
47     int64_t time = tp.tv_sec * SEC_2_MILLIS;
48     time += tp.tv_nsec / MILLS_2_NANOS;
49     return time;
50 }
51 
ParseTimeZone(long tz)52 static uint8_t ParseTimeZone(long tz)
53 {
54     static long allTimeZones[] = {
55         3600, 7200, 10800, 11880, 14400, 18000, 21600,
56         25200, 28800, 32400, 33480, 36000, 39600, 43200,
57         0, -3600, -7200, -10800, -11880, -14400, 15480,
58         -18000, -19080, -19620, -21600, -22680, -25200, -28800,
59         -30420, -32400, -33480, -36000, -37080, -39600, -43200,
60         -44820, -46800, -50400
61     };
62     uint8_t ret = 14; // 14 is the index of "+0000" in array
63     for (uint8_t index = 0; index < (sizeof(allTimeZones) / sizeof(long)); ++index) {
64         if (allTimeZones[index] == tz) {
65             ret = index;
66             break;
67         }
68     }
69     return ret;
70 }
71 
CheckEventType(uint8_t eventType)72 static int CheckEventType(uint8_t eventType)
73 {
74     if ((eventType < EASY_EVENT_TYPE_FAULT) || (eventType > EASY_EVENT_TYPE_BEHAVIOR)) {
75         return ERR_TYPE_INVALID;
76     }
77     return SUCCESS;
78 }
79 
ReadPidFromFormatStr(const char * buf,int * pid)80 static void ReadPidFromFormatStr(const char* buf, int* pid)
81 {
82     if (buf == NULL || sscanf_s(buf, "%*[^0-9]%d", pid) != ARGS_CNT_ONE) {
83         *pid = INVALID_PID;
84     }
85 }
86 
GetRealPid(void)87 static int GetRealPid(void)
88 {
89     int pid = INVALID_PID;
90     int fd = TEMP_FAILURE_RETRY(open(PROC_SELF_STATUS_PATH, O_RDONLY));
91     if (fd < 0) {
92         return pid;
93     }
94 
95     char buf[LINE_BUF_SIZE];
96     (void)memset_s(buf, sizeof(buf), '\0', sizeof(buf));
97     int pos = 0;
98     char curChar = 0;
99     while (1) {
100         ssize_t readCnt = TEMP_FAILURE_RETRY(read(fd, &curChar, sizeof(char)));
101         if (readCnt <= 0 || curChar == '\0') {
102             break;
103         }
104         if (curChar == '\n' || pos == LINE_BUF_SIZE) {
105             if (strncmp(buf, PID_STR_NAME, strlen(PID_STR_NAME)) == 0) {
106                 ReadPidFromFormatStr(buf, &pid);
107                 break;
108             }
109             pos = 0;
110             (void)memset_s(buf, sizeof(buf), '\0', sizeof(buf));
111             continue;
112         }
113         buf[pos] = curChar;
114         ++pos;
115     }
116     close(fd);
117     return pid;
118 }
119 
120 static int gPid = INVALID_PID;
121 
InitEventHeader(struct HiSysEventEasyHeader * header,const char * domain,const char * name,const uint8_t eventType)122 static int InitEventHeader(struct HiSysEventEasyHeader* header, const char* domain, const char* name,
123     const uint8_t eventType)
124 {
125     if ((MemoryCopy((uint8_t*)(header->domain), DOMAIN_ARRAY_LEN, (uint8_t*)domain, strlen(domain)) != SUCCESS) ||
126         (MemoryCopy((uint8_t*)(header->name), NAME_ARRAY_LEN, (uint8_t*)name, strlen(name)) != SUCCESS)) {
127         return ERR_MEM_OPT_FAILED;
128     }
129     header->type = eventType - 1; // only 2 bits to store event type
130     header->timestamp = (uint64_t)GetTimestamp();
131     header->timeZone = ParseTimeZone(timezone);
132     if (gPid == INVALID_PID) {
133         gPid = GetRealPid();
134         header->pid = (uint32_t)((gPid != INVALID_PID) ? gPid : getpid());
135     } else {
136         header->pid = gPid;
137     }
138     header->tid = (uint32_t)gettid();
139     header->uid = (uint32_t)getuid();
140     header->isTraceOpened = 0; // no need to allocate memory for trace info.
141     return SUCCESS;
142 }
143 
HiSysEventEasyWrite(const char * domain,const char * name,enum HiSysEventEasyType eventType,const char * data)144 int HiSysEventEasyWrite(const char* domain, const char* name, enum HiSysEventEasyType eventType, const char* data)
145 {
146     if ((domain == NULL) || (strlen(domain) > MAX_DOMAIN_LENGTH)) {
147         return ERR_DOMAIN_INVALID;
148     }
149     if ((name == NULL) || (strlen(name) > MAX_EVENT_NAME_LENGTH)) {
150         return ERR_NAME_INVALID;
151     }
152     int ret = CheckEventType(eventType);
153     if (ret != SUCCESS) {
154         return ret;
155     }
156     uint8_t eventBuffer[EVENT_BUFF_LEN] = { 0 };
157     size_t offset = 0;
158     // applend block size
159     *((int32_t*)eventBuffer) = EVENT_BUFF_LEN;
160     offset += sizeof(int32_t);
161     // append header, only two bits to store event type in memory
162     struct HiSysEventEasyHeader header;
163     ret = MemoryInit((uint8_t*)(&header), sizeof(struct HiSysEventEasyHeader));
164     if (ret != SUCCESS) {
165         return ret;
166     }
167     ret = InitEventHeader(&header, domain, name, eventType);
168     if (ret != SUCCESS) {
169         return ret;
170     }
171     ret = AppendHeader(eventBuffer, EVENT_BUFF_LEN, &offset, &header);
172     if (ret != SUCCESS) {
173         return ret;
174     }
175     // append param count, only one cutomized parameter
176     if (offset + sizeof(int32_t) > EVENT_BUFF_LEN) {
177         return ERR_EVENT_BUF_INVALID;
178     }
179     *((int32_t*)(eventBuffer + offset)) = 1;
180     offset += sizeof(int32_t);
181     ret = AppendStringParam(eventBuffer, EVENT_BUFF_LEN, &offset, CUSTOMIZED_PARAM_KEY, data);
182     if (ret != SUCCESS) {
183         return ret;
184     }
185     // write event to socket
186     ret = Write(eventBuffer, EVENT_BUFF_LEN);
187     if (ret != SUCCESS) {
188         return ret;
189     }
190     return SUCCESS;
191 }
192 
193 #ifdef __cplusplus
194 }
195 #endif
196