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 }