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 
16 #include "nstackx_util.h"
17 #include "nstackx_timer.h"
18 #include "nstackx_error.h"
19 #include "nstackx_log.h"
20 #include "securec.h"
21 
22 #define TAG "nStackXUtil"
23 #define DEFAULT_NEW_PATH_AUTHORITY 0750
24 
GetTargetFileSize(const char * dir,uint64_t * size)25 int32_t GetTargetFileSize(const char *dir, uint64_t *size)
26 {
27     struct stat statbuf;
28 
29     if (dir == NULL || size == NULL) {
30         LOGE(TAG, "Invalid dir or size");
31         return NSTACKX_EINVAL;
32     }
33 
34     if (stat(dir, &statbuf) != 0 || statbuf.st_size < 0) {
35         LOGE(TAG, "stat error: %d", GetErrno());
36         return NSTACKX_EFAILED;
37     }
38 
39     *size = (uint64_t)statbuf.st_size;
40     return NSTACKX_EOK;
41 }
42 
CheckPathSeprator(const char * path)43 int32_t CheckPathSeprator(const char *path)
44 {
45     if (strlen(path) > 0 && path[strlen(path) - 1] == PATH_SEPARATOR) {
46         return NSTACKX_TRUE;
47     }
48     return NSTACKX_FALSE;
49 }
50 
CheckFilenameSeprator(const char * fileName)51 int32_t CheckFilenameSeprator(const char *fileName)
52 {
53     if (strlen(fileName) > 0 && fileName[0] == PATH_SEPARATOR) {
54         return NSTACKX_TRUE;
55     }
56     return NSTACKX_FALSE;
57 }
58 
59 /*
60  * return value includes the length of terminator '\0'
61  * return value 0 means the input dir is null or it's last char is PATH_SEPARATOR
62  */
GetFileNameLen(const char * dir)63 uint32_t GetFileNameLen(const char *dir)
64 {
65     int32_t i;
66 
67     if (dir == NULL || strlen(dir) < 1 || dir[strlen(dir) - 1] == PATH_SEPARATOR) {
68         LOGE(TAG, "Invalid input param");
69         return 0;
70     }
71 
72     int32_t dirLen = (int32_t)strlen(dir);
73     for (i = dirLen - 1; i >= 0; i--) {
74         if (dir[i] == PATH_SEPARATOR) {
75             i++;
76             break;
77         }
78         if (i == 0) {
79             break;
80         }
81     }
82     return (uint32_t)(dirLen + 1 - i);
83 }
84 
GetFileName(const char * dir,char * name,uint32_t nameLen)85 int32_t GetFileName(const char *dir, char *name, uint32_t nameLen)
86 {
87     uint32_t fileNameLen, startIdx;
88 
89     if (dir == NULL || name == NULL) {
90         LOGE(TAG, "Invalid dir or name");
91         return NSTACKX_EINVAL;
92     }
93 
94     fileNameLen = GetFileNameLen(dir);
95     if (fileNameLen == 0 || fileNameLen > nameLen) {
96         LOGE(TAG, "Invalid fileNameLen dir: %s", dir);
97         return NSTACKX_EINVAL;
98     }
99     startIdx = (uint32_t)(strlen(dir) + 1 - fileNameLen);
100     if (strcpy_s(name, nameLen, dir + startIdx) != EOK) {
101         LOGE(TAG, "strcpy_s name error");
102         return NSTACKX_EFAILED;
103     }
104     return NSTACKX_EOK;
105 }
106 
IsAccessiblePath(const char * pathName,int32_t mode,uint32_t fileType)107 uint8_t IsAccessiblePath(const char *pathName, int32_t mode, uint32_t fileType)
108 {
109     struct stat statbuf;
110     if (pathName == NULL) {
111         LOGE(TAG, "invalid input");
112         return NSTACKX_FALSE;
113     }
114     if (stat(pathName, &statbuf) != 0) {
115         LOGE(TAG, "can't get file stat.error: %d", GetErrno());
116         return NSTACKX_FALSE;
117     }
118     if (((statbuf.st_mode) & S_IFMT) != fileType) {
119         LOGE(TAG, "this path name is not target file type");
120         return NSTACKX_FALSE;
121     }
122 
123     if (access(pathName, F_OK) != 0) {
124         return NSTACKX_FALSE;
125     }
126 
127     if (access(pathName, mode) != 0) {
128         return NSTACKX_FALSE;
129     }
130     return NSTACKX_TRUE;
131 }
132 
IsExistingFile(const char * fileName)133 uint8_t IsExistingFile(const char *fileName)
134 {
135     if (access(fileName, F_OK) != 0) {
136         return NSTACKX_FALSE;
137     }
138     return NSTACKX_TRUE;
139 }
140 
TestAndCreateDirectory(const char * path)141 int32_t TestAndCreateDirectory(const char *path)
142 {
143     uint32_t len, i;
144     char *tmp = NULL;
145     int32_t ret;
146 
147     if (path == NULL || strlen(path) == 0) {
148         return NSTACKX_EINVAL;
149     }
150 
151     len = (uint32_t)strlen(path);
152 
153     tmp = (char *)calloc(len + 1, sizeof(char));
154     if (tmp == NULL) {
155         LOGE(TAG, "tmp calloc error");
156         return NSTACKX_EFAILED;
157     }
158 
159     for (i = 0; i < len; i++) {
160         tmp[i] = path[i];
161         if (tmp[i] != PATH_SEPARATOR) {
162             continue;
163         }
164         if (access(tmp, 0) == -1) {
165             ret = mkdir(tmp, DEFAULT_NEW_PATH_AUTHORITY);
166             if (ret == -1 && errno != EEXIST) {
167                 LOGI(TAG, "mkdir failed(%d)", errno);
168                 free(tmp);
169                 return NSTACKX_EFAILED;
170             }
171         }
172     }
173     free(tmp);
174     return NSTACKX_EOK;
175 }
176 
177 #define UCHAR2_TO_UINT16(_buf) (((uint16_t)((_buf)[0]) << 8u) | (uint16_t)((_buf)[1]))
178 
IpAddrAnonymousFormat(char * buf,size_t len,const struct sockaddr * addr,size_t addrLen)179 int32_t IpAddrAnonymousFormat(char *buf, size_t len, const struct sockaddr *addr, size_t addrLen)
180 {
181     if (buf == NULL || len == 0 || addr == NULL) {
182         return NSTACKX_EFAILED;
183     }
184 
185     int32_t ret = NSTACKX_EFAILED;
186     if (addr->sa_family == AF_INET && addrLen >= sizeof(struct sockaddr_in)) {
187         uint32_t ip4 = ((const struct sockaddr_in *)addr)->sin_addr.s_addr;
188         ret = snprintf_s(buf, len, len - 1, "%hhu.%hhu.%hhu.*",
189             ((uint8_t *)&ip4)[0], ((uint8_t *)&ip4)[1], ((uint8_t *)&ip4)[2]); /* print the first 3 bytes */
190     } else if (addr->sa_family == AF_INET6 && addrLen >= sizeof(struct sockaddr_in6)) {
191         const uint8_t *ip6 = ((const struct sockaddr_in6 *)addr)->sin6_addr.s6_addr;
192         ret = snprintf_s(buf, len, len - 1, "%x:%x:%x*:*:*:*:*:*",
193             UCHAR2_TO_UINT16(ip6), UCHAR2_TO_UINT16(ip6 + 2), ip6[4]); /* print the first 5 bytes */
194     }
195 
196     return ret;
197 }
198