更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
fullpath.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "stdio.h"
33#include "stdlib.h"
34#include "string.h"
35#include "errno.h"
36#include "limits.h"
37#include "los_process_pri.h"
38#include "fs/fd_table.h"
39#include "fs/file.h"
40
41#ifdef LOSCFG_SHELL
42#include "shell.h"
43#endif
44
45
46#ifdef LOSCFG_SHELL
47#define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN)
48#else
49#define TEMP_PATH_MAX PATH_MAX
50#endif
51
52static unsigned int vfs_strnlen(const char *str, size_t maxlen)
53{
54 const char *p = NULL;
55
56 for (p = str; ((maxlen-- != 0) && (*p != '\0')); ++p) {}
57
58 return p - str;
59}
60
61/* abandon the redundant '/' in the path, only keep one. */
62
63static char *str_path(char *path)
64{
65 char *dest = path;
66 char *src = path;
67
68 while (*src != '\0') {
69 if (*src == '/') {
70 *dest++ = *src++;
71 while (*src == '/') {
72 src++;
73 }
74 continue;
75 }
76 *dest++ = *src++;
77 }
78 *dest = '\0';
79 return path;
80}
81
82static void str_remove_path_end_slash(char *dest, const char *fullpath)
83{
84 if ((*dest == '.') && (*(dest - 1) == '/')) {
85 *dest = '\0';
86 dest--;
87 }
88 if ((dest != fullpath) && (*dest == '/')) {
89 *dest = '\0';
90 }
91}
92
93static char *str_normalize_path(char *fullpath)
94{
95 char *dest = fullpath;
96 char *src = fullpath;
97
98 /* 2: The position of the path character: / and the end character /0 */
99
100 while (*src != '\0') {
101 if (*src == '.') {
102 if (*(src + 1) == '/') {
103 src += 2;
104 continue;
105 } else if (*(src + 1) == '.') {
106 if ((*(src + 2) == '/') || (*(src + 2) == '\0')) {
107 src += 2;
108 } else {
109 while ((*src != '\0') && (*src != '/')) {
110 *dest++ = *src++;
111 }
112 continue;
113 }
114 } else {
115 *dest++ = *src++;
116 continue;
117 }
118 } else {
119 *dest++ = *src++;
120 continue;
121 }
122
123 if ((dest - 1) != fullpath) {
124 dest--;
125 }
126
127 while ((dest > fullpath) && (*(dest - 1) != '/')) {
128 dest--;
129 }
130
131 if (*src == '/') {
132 src++;
133 }
134 }
135
136 *dest = '\0';
137
138 /* remove '/' in the end of path if exist */
139
140 dest--;
141
142 str_remove_path_end_slash(dest, fullpath);
143 return dest;
144}
145
146static int vfs_normalize_path_parame_check(const char *filename, char **pathname)
147{
148 int namelen;
149 char *name = NULL;
150
151 if (pathname == NULL) {
152 return -EINVAL;
153 }
154
155 /* check parameters */
156
157 if (filename == NULL) {
158 *pathname = NULL;
159 return -EINVAL;
160 }
161
162 namelen = vfs_strnlen(filename, PATH_MAX);
163 if (!namelen) {
164 *pathname = NULL;
165 return -EINVAL;
166 } else if (namelen >= PATH_MAX) {
167 *pathname = NULL;
168 return -ENAMETOOLONG;
169 }
170
171 for (name = (char *)filename + namelen; ((name != filename) && (*name != '/')); name--) {
172 if (strlen(name) > NAME_MAX) {
173 *pathname = NULL;
174 return -ENAMETOOLONG;
175 }
176 }
177
178 return namelen;
179}
180
181static char *vfs_not_absolute_path(const char *directory, const char *filename, char **pathname, int namelen)
182{
183 int ret;
184 char *fullpath = NULL;
185
186 /* 2: The position of the path character: / and the end character /0 */
187
188 if ((namelen > 1) && (filename[0] == '.') && (filename[1] == '/')) {
189 filename += 2;
190 }
191
192 fullpath = (char *)malloc(strlen(directory) + namelen + 2);
193 if (fullpath == NULL) {
194 *pathname = NULL;
195 set_errno(ENOMEM);
196 return (char *)NULL;
197 }
198
199 /* join path and file name */
200
201 ret = snprintf_s(fullpath, strlen(directory) + namelen + 2, strlen(directory) + namelen + 1,
202 "%s/%s", directory, filename);
203 if (ret < 0) {
204 *pathname = NULL;
205 free(fullpath);
206 set_errno(ENAMETOOLONG);
207 return (char *)NULL;
208 }
209
210 return fullpath;
211}
212
213static char *vfs_normalize_fullpath(const char *directory, const char *filename, char **pathname, int namelen)
214{
215 char *fullpath = NULL;
216
217 if (filename[0] != '/') {
218 /* not a absolute path */
219
220 fullpath = vfs_not_absolute_path(directory, filename, pathname, namelen);
221 if (fullpath == NULL) {
222 return (char *)NULL;
223 }
224 } else {
225 /* it's a absolute path, use it directly */
226
227 fullpath = strdup(filename); /* copy string */
228
229 if (fullpath == NULL) {
230 *pathname = NULL;
231 set_errno(ENOMEM);
232 return (char *)NULL;
233 }
234 if (filename[1] == '/') {
235 *pathname = NULL;
236 free(fullpath);
237 set_errno(EINVAL);
238 return (char *)NULL;
239 }
240 }
241
242 return fullpath;
243}
244
245int vfs_normalize_path(const char *directory, const char *filename, char **pathname)
246{
247 char *fullpath = NULL;
248 int namelen;
249#ifdef VFS_USING_WORKDIR
250 UINTPTR lock_flags;
252 BOOL dir_flags = (directory == NULL) ? TRUE : FALSE;
253#endif
254
255 namelen = vfs_normalize_path_parame_check(filename, pathname);
256 if (namelen < 0) {
257 return namelen;
258 }
259
260#ifdef VFS_USING_WORKDIR
261 if (directory == NULL)
262 {
263 spin_lock_irqsave(&curr->files->workdir_lock, lock_flags);
264 directory = curr->files->workdir;
265 }
266#else
267 if ((directory == NULL) && (filename[0] != '/')) {
268 PRINT_ERR("NO_WORKING_DIR\n");
269 *pathname = NULL;
270 return -EINVAL;
271 }
272#endif
273
274 /* 2: The position of the path character: / and the end character /0 */
275
276 if ((filename[0] != '/') && (strlen(directory) + namelen + 2 > TEMP_PATH_MAX)) {
277#ifdef VFS_USING_WORKDIR
278 if (dir_flags == TRUE)
279 {
280 spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
281 }
282#endif
283 return -ENAMETOOLONG;
284 }
285
286 fullpath = vfs_normalize_fullpath(directory, filename, pathname, namelen);
287#ifdef VFS_USING_WORKDIR
288 if (dir_flags == TRUE)
289 {
290 spin_unlock_irqrestore(&curr->files->workdir_lock, lock_flags);
291 }
292#endif
293 if (fullpath == NULL) {
294 return -get_errno();
295 }
296
297 (void)str_path(fullpath);
298 (void)str_normalize_path(fullpath);
299 if (strlen(fullpath) >= PATH_MAX) {
300 *pathname = NULL;
301 free(fullpath);
302 return -ENAMETOOLONG;
303 }
304
305 *pathname = fullpath;
306 return ENOERR;
307}
308
309int vfs_normalize_pathat(int dirfd, const char *filename, char **pathname)
310{
311 /* Get path by dirfd*/
312 char *relativeoldpath = NULL;
313 char *fullpath = NULL;
314 int ret = 0;
315
316 ret = get_path_from_fd(dirfd, &relativeoldpath);
317 if (ret < 0) {
318 return ret;
319 }
320
321 ret = vfs_normalize_path((const char *)relativeoldpath, filename, &fullpath);
322 if (relativeoldpath) {
323 free(relativeoldpath);
324 }
325
326 if (ret < 0) {
327 return ret;
328 }
329
330 *pathname = fullpath;
331 return ret;
332}
333
static char * vfs_not_absolute_path(const char *directory, const char *filename, char **pathname, int namelen)
Definition: fullpath.c:181
static void str_remove_path_end_slash(char *dest, const char *fullpath)
Definition: fullpath.c:82
static char * vfs_normalize_fullpath(const char *directory, const char *filename, char **pathname, int namelen)
Definition: fullpath.c:213
static char * str_path(char *path)
Definition: fullpath.c:63
static unsigned int vfs_strnlen(const char *str, size_t maxlen)
Definition: fullpath.c:52
static char * str_normalize_path(char *fullpath)
Definition: fullpath.c:93
int vfs_normalize_path(const char *directory, const char *filename, char **pathname)
Definition: fullpath.c:245
int vfs_normalize_pathat(int dirfd, const char *filename, char **pathname)
Definition: fullpath.c:309
static int vfs_normalize_path_parame_check(const char *filename, char **pathname)
Definition: fullpath.c:146
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
unsigned long UINTPTR
Definition: los_typedef.h:68
size_t BOOL
Definition: los_typedef.h:88
void * malloc(size_t size)
动态分配内存块大小
Definition: malloc.c:81
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
struct files_struct * files
spinlock_t workdir_lock
工作区目录自旋锁
Definition: fd_table.h:99
char workdir[PATH_MAX]
工作区路径,最大 256个字符
Definition: fd_table.h:100
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void