1 /*
2 * Copyright (c) 2020 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 "nativeapi_kv_impl.h"
17 #include <ctype.h>
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <limits.h>
21 #include <securec.h>
22 #include <stdbool.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include "nativeapi_config.h"
27 #if (defined _WIN32 || defined _WIN64)
28 #include "shlwapi.h"
29 #endif
30
31 static char g_kvFolder[FILE_NAME_MAX_LEN + 1] = {0};
32
IsValidValue(const char * value)33 static bool IsValidValue(const char* value)
34 {
35 if (value == NULL) {
36 return false;
37 }
38 size_t valueLen = strnlen(value, VALUE_MAX_LEN + 1);
39 if ((valueLen == 0) || (valueLen > VALUE_MAX_LEN)) {
40 return false;
41 }
42 return true;
43 }
44
GetKvFolder(const char * dataPath)45 static int GetKvFolder(const char* dataPath)
46 {
47 if (dataPath == NULL) {
48 return ERROR_CODE_PARAM;
49 }
50 if (memset_s(g_kvFolder, sizeof(g_kvFolder), 0x0, sizeof(g_kvFolder)) != EOK) {
51 return ERROR_CODE_GENERAL;
52 }
53 if (sprintf_s(g_kvFolder, sizeof(g_kvFolder), "%s/%s", dataPath, DEFAULT_FOLDER_PATH) < 0) {
54 return ERROR_CODE_GENERAL;
55 }
56 return NATIVE_SUCCESS;
57 }
58
GetRealPath(const char * originPath,char * trustPath,size_t tPathLen)59 static int GetRealPath(const char* originPath, char* trustPath, size_t tPathLen)
60 {
61 #if (defined _WIN32 || defined _WIN64)
62 if (PathCanonicalize(trustPath, originPath)) {
63 return NATIVE_SUCCESS;
64 }
65 #else
66 if (realpath(originPath, trustPath) != NULL) {
67 return NATIVE_SUCCESS;
68 }
69 #endif
70
71 if (errno == ENOENT) {
72 if (strncpy_s(trustPath, tPathLen, originPath, strlen(originPath)) == EOK) {
73 return NATIVE_SUCCESS;
74 }
75 }
76 return ERROR_CODE_GENERAL;
77 }
78
InitKv(const char * dataPath)79 int InitKv(const char* dataPath)
80 {
81 int ret = GetKvFolder(dataPath);
82 if (ret != NATIVE_SUCCESS) {
83 return ret;
84 }
85 if (access(g_kvFolder, F_OK) == F_OK) {
86 return NATIVE_SUCCESS;
87 }
88 #if (defined _WIN32 || defined _WIN64)
89 if (mkdir(g_kvFolder) != 0) {
90 return ERROR_CODE_GENERAL;
91 }
92 #else
93 if (mkdir(g_kvFolder, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
94 return ERROR_CODE_GENERAL;
95 }
96 #endif
97 return NATIVE_SUCCESS;
98 }
99
GetValue(const char * key,char * value)100 int GetValue(const char* key, char* value)
101 {
102 if ((key == NULL) || (value == NULL)) {
103 return ERROR_CODE_PARAM;
104 }
105 char* resolvePath = (char *)malloc(PATH_MAX);
106 if (resolvePath == NULL) {
107 return ERROR_CODE_GENERAL;
108 }
109 if (GetRealPath(key, resolvePath, PATH_MAX) != NATIVE_SUCCESS) {
110 free(resolvePath);
111 return ERROR_CODE_GENERAL;
112 }
113 int fileHandle = open(resolvePath, O_RDONLY, S_IRUSR);
114 free(resolvePath);
115 resolvePath = NULL;
116 if (fileHandle < 0) {
117 return (-errno);
118 }
119 int readLen = read(fileHandle, value, VALUE_MAX_LEN);
120 close(fileHandle);
121 fileHandle = -1;
122 if (readLen < 0) {
123 return ERROR_CODE_IO;
124 }
125 value[readLen] = '\0';
126 return NATIVE_SUCCESS;
127 }
128
SetValue(const char * key,const char * value)129 int SetValue(const char* key, const char* value)
130 {
131 if ((key == NULL) || (!IsValidValue(value))) {
132 return ERROR_CODE_PARAM;
133 }
134 char* resolvePath = (char *)malloc(PATH_MAX);
135 if (resolvePath == NULL) {
136 return ERROR_CODE_GENERAL;
137 }
138 if (GetRealPath(key, resolvePath, PATH_MAX) != NATIVE_SUCCESS) {
139 free(resolvePath);
140 return ERROR_CODE_GENERAL;
141 }
142 int fd = open(resolvePath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
143 free(resolvePath);
144 resolvePath = NULL;
145 if (fd < 0) {
146 return (-errno);
147 }
148 int ret = write(fd, value, strlen(value));
149 close(fd);
150 return (ret < 0) ? ERROR_CODE_IO : NATIVE_SUCCESS;
151 }
152
DeleteValue(const char * key)153 int DeleteValue(const char* key)
154 {
155 if (key == NULL) {
156 return ERROR_CODE_PARAM;
157 }
158 if (unlink(key) != NATIVE_SUCCESS) {
159 return (-errno);
160 }
161 return NATIVE_SUCCESS;
162 }
163
ClearKVStore(const char * dataPath)164 int ClearKVStore(const char* dataPath)
165 {
166 int ret = GetKvFolder(dataPath);
167 if (ret != NATIVE_SUCCESS) {
168 return ret;
169 }
170 ret = ERROR_CODE_GENERAL;
171 DIR* fileDir = opendir(g_kvFolder);
172 if (fileDir == NULL) {
173 return ret;
174 }
175 struct dirent* dir = readdir(fileDir);
176 char* fullPath = (char *)malloc(FILE_NAME_MAX_LEN + 1);
177 if (fullPath == NULL) {
178 goto EXIT;
179 }
180 while (dir != NULL) {
181 if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) {
182 dir = readdir(fileDir);
183 continue;
184 }
185 if (memset_s(fullPath, FILE_NAME_MAX_LEN + 1, 0x0, FILE_NAME_MAX_LEN + 1) != EOK) {
186 goto EXIT;
187 }
188 if (sprintf_s(fullPath, FILE_NAME_MAX_LEN + 1, "%s/%s", g_kvFolder, dir->d_name) < 0) {
189 goto EXIT;
190 }
191 if (unlink(fullPath) != 0) {
192 goto EXIT;
193 }
194 dir = readdir(fileDir);
195 }
196 ret = NATIVE_SUCCESS;
197 EXIT:
198 free(fullPath);
199 closedir(fileDir);
200 return ret;
201 }