1 /*
2  * Copyright (c) 2022-2023 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 <arpa/inet.h>
17 #include <fcntl.h>
18 #include <stdbool.h>
19 #include <string.h>
20 
21 #include "client_trans_proxy_file_common.h"
22 
23 #include "securec.h"
24 #include "softbus_adapter_file.h"
25 #include "softbus_adapter_mem.h"
26 #include "softbus_adapter_timer.h"
27 #include "softbus_def.h"
28 #include "softbus_errcode.h"
29 #include "trans_log.h"
30 
31 #pragma pack(push, 1)
32 struct FileListItem {
33     uint32_t index;
34     uint32_t fileNameLength;
35     char fileName[0];
36 };
37 #pragma pack(pop)
38 
IsPathValid(char * filePath)39 bool IsPathValid(char *filePath)
40 {
41     if (filePath == NULL) {
42         TRANS_LOGE(TRANS_FILE, "filePath is null");
43         return false;
44     }
45     if ((strlen(filePath) == 0) || (strlen(filePath) > (MAX_FILE_PATH_NAME_LEN - 1))) {
46         TRANS_LOGE(TRANS_FILE, "filePathSize is wrong. filePathSize=%{public}d", (int32_t)strlen(filePath));
47         return false;
48     }
49 
50     if (filePath[strlen(filePath) - 1] == PATH_SEPARATOR) {
51         TRANS_LOGE(TRANS_FILE, "filePath is end with '/' ");
52         return false;
53     }
54     return true;
55 }
56 
GetAndCheckRealPath(const char * filePath,char * absPath)57 int32_t GetAndCheckRealPath(const char *filePath, char *absPath)
58 {
59     if ((filePath == NULL) || (absPath == NULL)) {
60         TRANS_LOGE(TRANS_FILE, "invalid param");
61         return SOFTBUS_INVALID_PARAM;
62     }
63 
64     if (SoftBusRealPath(filePath, absPath) == NULL) {
65         TRANS_LOGE(TRANS_FILE, "softbus realpath failed");
66         return SOFTBUS_FILE_ERR;
67     }
68 
69     int32_t pathLength = (int32_t)(strlen(absPath));
70     if (pathLength > (MAX_FILE_PATH_NAME_LEN - 1)) {
71         TRANS_LOGE(TRANS_FILE, "pathLength is too large. pathLength=%{public}d", pathLength);
72         return SOFTBUS_INVALID_PARAM;
73     }
74     return SOFTBUS_OK;
75 }
76 
CheckDestFilePathValid(const char * destFile)77 bool CheckDestFilePathValid(const char *destFile)
78 {
79     if (destFile == NULL) {
80         TRANS_LOGE(TRANS_FILE, "destFile is null");
81         return false;
82     }
83     int32_t len = (int32_t)(strlen(destFile));
84     if ((len == 0) || (len > MAX_FILE_PATH_NAME_LEN)) {
85         TRANS_LOGE(TRANS_FILE, "destFile path len is invalid");
86         return false;
87     }
88 
89     if (strstr(destFile, "..") != NULL) {
90         TRANS_LOGE(TRANS_FILE, "dest path is not canonical form");
91         return false;
92     }
93     return true;
94 }
95 
FrameIndexToType(uint64_t index,uint64_t frameNumber)96 int32_t FrameIndexToType(uint64_t index, uint64_t frameNumber)
97 {
98     if (index == FRAME_NUM_0 || frameNumber == FRAME_NUM_0) {
99         return TRANS_SESSION_FILE_FIRST_FRAME;
100     }
101     if ((index == FRAME_NUM_1) && (frameNumber == FRAME_NUM_2)) {
102         return TRANS_SESSION_FILE_ONLYONE_FRAME;
103     }
104     if (index == (frameNumber - 1)) {
105         return TRANS_SESSION_FILE_LAST_FRAME;
106     }
107     return TRANS_SESSION_FILE_ONGOINE_FRAME;
108 }
109 
110 // crc校验表
111 static const unsigned char g_auchCRCHi[] = {
112 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
113 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
114 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
115 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80,
116 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
117 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
118 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
119 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
120 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
121 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
122 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
123 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
124 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
125 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
126 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
127 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
128 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
129 0x81, 0x40};
130 
131 static const unsigned char g_auchCRCLo[] = {
132 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5,
133 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B,
134 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
135 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
136 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2,
137 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F,
138 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB,
139 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25,
140 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
141 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C,
142 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8,
143 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D,
144 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73,
145 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57,
146 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A,
147 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E,
148 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
149 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
150 
151 // 校验函数
RTU_CRC(const unsigned char * puchMsg,uint16_t usDataLen)152 uint16_t RTU_CRC(const unsigned char *puchMsg, uint16_t usDataLen)
153 {
154     unsigned char uchCRCHi = 0xFF;
155     unsigned char uchCRCLo = 0xFF;
156     uint16_t dataLen = usDataLen;
157     const uint8_t *data = puchMsg;
158     while (dataLen--) {
159         unsigned char uIndex = uchCRCLo ^ (*data++);
160         uchCRCLo = uchCRCHi ^ g_auchCRCHi[uIndex];
161         uchCRCHi = g_auchCRCLo[uIndex];
162     }
163     return ((uchCRCHi << BIT_BYTE_NUM) | uchCRCLo);
164 }
165 
TransGetFileName(const char * path)166 const char *TransGetFileName(const char *path)
167 {
168     if (path == NULL) {
169         TRANS_LOGE(TRANS_FILE, "input is NULL!");
170         return NULL;
171     }
172     size_t pathLength = strlen(path);
173     if (pathLength == 0) {
174         TRANS_LOGE(TRANS_FILE, "input length is 0!");
175         return NULL;
176     }
177     if (path[pathLength - 1] == SOFTBUS_PATH_SEPRATOR) {
178         TRANS_LOGE(TRANS_FILE, "input is dir path!");
179         return NULL;
180     }
181 
182     int i;
183     for (i = (int)(pathLength - 1); i >= 0; i--) {
184         if (path[i] == SOFTBUS_PATH_SEPRATOR) {
185             i++;
186             break;
187         }
188         if (i == 0) {
189             break;
190         }
191     }
192     return path + i;
193 }
194 
FileListToBuffer(const char ** destFile,uint32_t fileCnt,FileListBuffer * outbufferInfo)195 int32_t FileListToBuffer(const char **destFile, uint32_t fileCnt, FileListBuffer *outbufferInfo)
196 {
197     if (destFile == NULL || outbufferInfo == NULL || fileCnt == 0) {
198         TRANS_LOGE(TRANS_FILE, "invalid param");
199         return SOFTBUS_INVALID_PARAM;
200     }
201     int32_t errCode = SOFTBUS_OK;
202     uint32_t totalLength = 0;
203     uint32_t offset = 0;
204     for (uint32_t i = 0; i < fileCnt; i++) {
205         size_t fileNameLength = strlen(destFile[i]);
206         if (fileNameLength == 0 || fileNameLength > MAX_FILE_PATH_NAME_LEN) {
207             TRANS_LOGE(TRANS_FILE, "bad file name at index=%{public}" PRIu32, i);
208             return SOFTBUS_INVALID_PARAM;
209         } else {
210             totalLength += fileNameLength;
211         }
212     }
213 
214     size_t bufferSize = totalLength + (sizeof(struct FileListItem) * fileCnt);
215     uint8_t *buffer = (uint8_t *)SoftBusCalloc(bufferSize);
216     if (buffer == NULL) {
217         TRANS_LOGE(TRANS_FILE, "calloc filelist failed");
218         return SOFTBUS_MALLOC_ERR;
219     }
220 
221     for (uint32_t index = 0; index < fileCnt; index++) {
222         uint32_t fileNameSize = strlen(destFile[index]);
223         struct FileListItem *fileItem = (struct FileListItem *)(buffer + offset);
224         fileItem->index = htonl(index);
225         fileItem->fileNameLength = htonl(fileNameSize);
226         offset += sizeof(struct FileListItem);
227 
228         // note: no \0 here
229         if (memcpy_s(fileItem->fileName, bufferSize - offset, destFile[index], fileNameSize) != EOK) {
230             TRANS_LOGE(TRANS_FILE, "copy file name failed!");
231             errCode = SOFTBUS_MEM_ERR;
232             break;
233         }
234 
235         offset += fileNameSize;
236     }
237 
238     if (errCode != SOFTBUS_OK) {
239         SoftBusFree(buffer);
240         return errCode;
241     }
242 
243     outbufferInfo->buffer = buffer;
244     outbufferInfo->bufferSize = offset;
245     return SOFTBUS_OK;
246 }
247 
BufferToFileList(uint8_t * buffer,uint32_t bufferSize,int32_t * fileCount)248 char *BufferToFileList(uint8_t *buffer, uint32_t bufferSize, int32_t *fileCount)
249 {
250     if ((buffer == NULL) || (fileCount == NULL) || bufferSize < sizeof(struct FileListItem)) {
251         TRANS_LOGE(TRANS_FILE, "input invalid");
252         return NULL;
253     }
254     char *firstFile = (char *)SoftBusCalloc(MAX_FILE_PATH_NAME_LEN + 1);
255     if (firstFile == NULL) {
256         TRANS_LOGE(TRANS_FILE, "calloc fail");
257         return NULL;
258     }
259     uint32_t offset = 0;
260     int32_t count = 0;
261     while (offset < bufferSize - sizeof(struct FileListItem)) {
262         const struct FileListItem *fileListItem = (const struct FileListItem *)(buffer + offset);
263         offset += sizeof(struct FileListItem);
264 
265         uint32_t fileNameLength = ntohl(fileListItem->fileNameLength);
266         if (fileNameLength > bufferSize - offset || fileNameLength > MAX_FILE_PATH_NAME_LEN) {
267             TRANS_LOGE(TRANS_FILE, "invalid fileLength");
268             SoftBusFree(firstFile);
269             return NULL;
270         }
271         /* only output first file path */
272         if (count == 0) {
273             // note: no \0 in buffer
274             if (memcpy_s(firstFile, MAX_FILE_PATH_NAME_LEN, fileListItem->fileName, fileNameLength) != EOK) {
275                 SoftBusFree(firstFile);
276                 return NULL;
277             }
278         }
279         offset += fileNameLength;
280         count++;
281     }
282 
283     *fileCount = count;
284     return firstFile;
285 }
286 
FileLock(int32_t fd,int32_t type,bool isBlock)287 int32_t FileLock(int32_t fd, int32_t type, bool isBlock)
288 {
289     if (fd < 0) {
290         TRANS_LOGE(TRANS_FILE, "[FileLock] invalid file handle");
291         return SOFTBUS_INVALID_PARAM;
292     }
293     struct flock fl = {0};
294     fl.l_type = (short)(type == SOFTBUS_F_RDLCK ? F_RDLCK : F_WRLCK);
295     fl.l_whence = SEEK_SET;
296     fl.l_start = 0;
297     fl.l_len = 0;
298     int32_t ret = fcntl(fd, isBlock ? F_SETLKW : F_SETLK, &fl);
299     if (ret != 0 && !isBlock) {
300         TRANS_LOGE(TRANS_FILE, "lock file is blocked, file busy errno=%{public}d", errno);
301         return SOFTBUS_FILE_BUSY;
302     }
303     TRANS_LOGE(TRANS_FILE, "file locked! ret=%{public}d, errno=%{public}d", ret, errno);
304     return SOFTBUS_OK;
305 }
306 
TryFileLock(int32_t fd,int32_t type,int32_t retryTimes)307 int32_t TryFileLock(int32_t fd, int32_t type, int32_t retryTimes)
308 {
309 #define TRY_LOCK_WAIT_TIME 100
310     int32_t errCode;
311     while (retryTimes > 0) {
312         errCode = FileLock(fd, type, false);
313         if (errCode == SOFTBUS_OK) {
314             return SOFTBUS_OK;
315         } else if (errCode == SOFTBUS_FILE_BUSY) {
316             --retryTimes;
317             SoftBusSleepMs(TRY_LOCK_WAIT_TIME);
318             continue;
319         } else {
320             return SOFTBUS_FILE_ERR;
321         }
322     }
323     return SOFTBUS_FILE_BUSY;
324 }
325 
FileUnLock(int32_t fd)326 int32_t FileUnLock(int32_t fd)
327 {
328     if (fd < 0) {
329         TRANS_LOGE(TRANS_FILE, "[FileUnLock] invalid file handle");
330         return SOFTBUS_OK;
331     }
332     struct flock fl = {0};
333     fl.l_type = F_UNLCK;
334     fl.l_whence = SEEK_SET;
335     fl.l_start = 0;
336     fl.l_len = 0;
337     if (fcntl(fd, F_SETLK, &fl) < 0) {
338         TRANS_LOGE(TRANS_FILE, "unLock file failed, errno=%{public}d", errno);
339         return SOFTBUS_FILE_ERR;
340     }
341     TRANS_LOGE(TRANS_FILE, "unLock file success");
342     return SOFTBUS_OK;
343 }