• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <securec.h>
33 #include "stdio.h"
34 #include "stdlib.h"
35 #include "string.h"
36 #include "errno.h"
37 #include "limits.h"
38 #include "shell.h"
39 #include "show.h"
40 
41 #define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN)
42 
VfsStrnlen(const CHAR * str,size_t maxlen)43 STATIC UINT32 VfsStrnlen(const CHAR *str, size_t maxlen)
44 {
45     const CHAR *p = NULL;
46 
47     for (p = str; ((maxlen-- != 0) && (*p != '\0')); ++p) {}
48 
49     return p - str;
50 }
51 
52 /* abandon the redundant '/' in the path, only keep one. */
StrPath(CHAR * path)53 STATIC CHAR *StrPath(CHAR *path)
54 {
55     CHAR *dest = path;
56     CHAR *src = path;
57 
58     while (*src != '\0') {
59         if (*src == '/') {
60             *dest++ = *src++;
61             while (*src == '/') {
62                 src++;
63             }
64             continue;
65         }
66         *dest++ = *src++;
67     }
68     *dest = '\0';
69     return path;
70 }
71 
StrRemovePathEndSlash(CHAR * dest,const CHAR * fullpath)72 STATIC VOID StrRemovePathEndSlash(CHAR *dest, const CHAR *fullpath)
73 {
74     if ((*dest == '.') && (*(dest - 1) == '/')) {
75         *dest = '\0';
76         dest--;
77     }
78     if ((dest != fullpath) && (*dest == '/')) {
79         *dest = '\0';
80     }
81 }
82 
StrNormalizePath(CHAR * fullpath)83 STATIC CHAR *StrNormalizePath(CHAR *fullpath)
84 {
85     CHAR *dest = fullpath;
86     CHAR *src = fullpath;
87 
88     /* 2: The position of the path character: / and the end character /0 */
89     while (*src != '\0') {
90         if (*src == '.') {
91             if (*(src + 1) == '/') {
92                 src += 2; /* 2, sizeof "./" */
93                 continue;
94             } else if (*(src + 1) == '.') {
95                 if ((*(src + 2) == '/') || (*(src + 2) == '\0')) { /* 2, 2, offset to check */
96                     src += 2; /* 2, sizeof offset */
97                 } else {
98                     while ((*src != '\0') && (*src != '/')) {
99                         *dest++ = *src++;
100                     }
101                     continue;
102                 }
103             } else {
104                 *dest++ = *src++;
105                 continue;
106             }
107         } else {
108             *dest++ = *src++;
109             continue;
110         }
111 
112         if ((dest - 1) != fullpath) {
113             dest--;
114         }
115 
116         while ((dest > fullpath) && (*(dest - 1) != '/')) {
117             dest--;
118         }
119 
120         if (*src == '/') {
121             src++;
122         }
123     }
124 
125     *dest = '\0';
126 
127     /* remove '/' in the end of path if exist */
128 
129     dest--;
130 
131     StrRemovePathEndSlash(dest, fullpath);
132     return dest;
133 }
134 
VfsNormalizePathParameCheck(const CHAR * filename,CHAR ** pathname)135 STATIC INT32 VfsNormalizePathParameCheck(const CHAR *filename, CHAR **pathname)
136 {
137     INT32 namelen;
138     CHAR *name = NULL;
139 
140     if (pathname == NULL) {
141         return -EINVAL;
142     }
143 
144     /* check parameters */
145 
146     if (filename == NULL) {
147         *pathname = NULL;
148         return -EINVAL;
149     }
150 
151     namelen = VfsStrnlen(filename, PATH_MAX);
152     if (!namelen) {
153         *pathname = NULL;
154         return -EINVAL;
155     } else if (namelen >= PATH_MAX) {
156         *pathname = NULL;
157         return -ENAMETOOLONG;
158     }
159 
160     for (name = (CHAR *)filename + namelen; ((name != filename) && (*name != '/')); name--) {
161         if (strlen(name) > NAME_MAX) {
162             *pathname = NULL;
163             return -ENAMETOOLONG;
164         }
165     }
166 
167     return namelen;
168 }
169 
VfsNotAbsolutePath(const CHAR * directory,const CHAR * filename,CHAR ** pathname,INT32 namelen)170 STATIC CHAR *VfsNotAbsolutePath(const CHAR *directory, const CHAR *filename, CHAR **pathname, INT32 namelen)
171 {
172     INT32 ret;
173     CHAR *fullpath = NULL;
174 
175     /* 2: The position of the path character: / and the end character /0 */
176 
177     if ((namelen > 1) && (filename[0] == '.') && (filename[1] == '/')) {
178         filename += 2; /* 2, size of "./" */
179     }
180 
181     fullpath = (CHAR *)malloc(strlen(directory) + namelen + 2); /* 2, size of "./" */
182     if (fullpath == NULL) {
183         *pathname = NULL;
184         SetErrno(ENOMEM);
185         return (CHAR *)NULL;
186     }
187 
188     /* 2, size of "./", join path and file name */
189     ret = snprintf_s(fullpath, strlen(directory) + namelen + 2, strlen(directory) + namelen + 1,
190                      "%s/%s", directory, filename);
191     if (ret < 0) {
192         *pathname = NULL;
193         free(fullpath);
194         SetErrno(ENAMETOOLONG);
195         return (CHAR *)NULL;
196     }
197 
198     return fullpath;
199 }
200 
VfsNormalizeFullpath(const CHAR * directory,const CHAR * filename,CHAR ** pathname,INT32 namelen)201 STATIC CHAR *VfsNormalizeFullpath(const CHAR *directory, const CHAR *filename, CHAR **pathname, INT32 namelen)
202 {
203     CHAR *fullpath = NULL;
204 
205     if (filename[0] != '/') {
206         /* not an absolute path */
207 
208         fullpath = VfsNotAbsolutePath(directory, filename, pathname, namelen);
209         if (fullpath == NULL) {
210             return (CHAR *)NULL;
211         }
212     } else {
213         /* it's an absolute path, use it directly */
214 
215         fullpath = strdup(filename); /* copy string */
216         if (fullpath == NULL) {
217             *pathname = NULL;
218             SetErrno(ENOMEM);
219             return (CHAR *)NULL;
220         }
221         if (filename[1] == '/') {
222             *pathname = NULL;
223             free(fullpath);
224             SetErrno(EINVAL);
225             return (CHAR *)NULL;
226         }
227     }
228 
229     return fullpath;
230 }
231 
VfsNormalizePath(const CHAR * directory,const CHAR * filename,CHAR ** pathname)232 INT32 VfsNormalizePath(const CHAR *directory, const CHAR *filename, CHAR **pathname)
233 {
234     CHAR *fullpath = NULL;
235     INT32 namelen;
236 
237     namelen = VfsNormalizePathParameCheck(filename, pathname);
238     if (namelen < 0) {
239         return namelen;
240     }
241 
242     if ((directory == NULL) && (filename[0] != '/')) {
243         PRINT_ERR("NO_WORKING_DIR\n");
244         *pathname = NULL;
245         return -EINVAL;
246     }
247 
248     /* 2, The position of the path character: / and the end character /0 */
249     if ((filename[0] != '/') && (strlen(directory) + namelen + 2 > TEMP_PATH_MAX)) {
250         return -ENAMETOOLONG;
251     }
252 
253     fullpath = VfsNormalizeFullpath(directory, filename, pathname, namelen);
254     if (fullpath == NULL) {
255         return -errno;
256     }
257 
258     (VOID)StrPath(fullpath);
259     (VOID)StrNormalizePath(fullpath);
260     if (strlen(fullpath) >= PATH_MAX) {
261         *pathname = NULL;
262         free(fullpath);
263         return -ENAMETOOLONG;
264     }
265 
266     *pathname = fullpath;
267     return 0;
268 }
269 
270