13d8536b4Sopenharmony_ci/* 23d8536b4Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 33d8536b4Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 43d8536b4Sopenharmony_ci * 53d8536b4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 63d8536b4Sopenharmony_ci * are permitted provided that the following conditions are met: 73d8536b4Sopenharmony_ci * 83d8536b4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 93d8536b4Sopenharmony_ci * conditions and the following disclaimer. 103d8536b4Sopenharmony_ci * 113d8536b4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 123d8536b4Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 133d8536b4Sopenharmony_ci * provided with the distribution. 143d8536b4Sopenharmony_ci * 153d8536b4Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 163d8536b4Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 173d8536b4Sopenharmony_ci * permission. 183d8536b4Sopenharmony_ci * 193d8536b4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 203d8536b4Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 213d8536b4Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 223d8536b4Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 233d8536b4Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 243d8536b4Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 253d8536b4Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 263d8536b4Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 273d8536b4Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 283d8536b4Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 293d8536b4Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 303d8536b4Sopenharmony_ci */ 313d8536b4Sopenharmony_ci 323d8536b4Sopenharmony_ci#include <securec.h> 333d8536b4Sopenharmony_ci#include "stdio.h" 343d8536b4Sopenharmony_ci#include "stdlib.h" 353d8536b4Sopenharmony_ci#include "string.h" 363d8536b4Sopenharmony_ci#include "errno.h" 373d8536b4Sopenharmony_ci#include "limits.h" 383d8536b4Sopenharmony_ci#include "shell.h" 393d8536b4Sopenharmony_ci#include "show.h" 403d8536b4Sopenharmony_ci 413d8536b4Sopenharmony_ci#define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN) 423d8536b4Sopenharmony_ci 433d8536b4Sopenharmony_ciSTATIC UINT32 VfsStrnlen(const CHAR *str, size_t maxlen) 443d8536b4Sopenharmony_ci{ 453d8536b4Sopenharmony_ci const CHAR *p = NULL; 463d8536b4Sopenharmony_ci 473d8536b4Sopenharmony_ci for (p = str; ((maxlen-- != 0) && (*p != '\0')); ++p) {} 483d8536b4Sopenharmony_ci 493d8536b4Sopenharmony_ci return p - str; 503d8536b4Sopenharmony_ci} 513d8536b4Sopenharmony_ci 523d8536b4Sopenharmony_ci/* abandon the redundant '/' in the path, only keep one. */ 533d8536b4Sopenharmony_ciSTATIC CHAR *StrPath(CHAR *path) 543d8536b4Sopenharmony_ci{ 553d8536b4Sopenharmony_ci CHAR *dest = path; 563d8536b4Sopenharmony_ci CHAR *src = path; 573d8536b4Sopenharmony_ci 583d8536b4Sopenharmony_ci while (*src != '\0') { 593d8536b4Sopenharmony_ci if (*src == '/') { 603d8536b4Sopenharmony_ci *dest++ = *src++; 613d8536b4Sopenharmony_ci while (*src == '/') { 623d8536b4Sopenharmony_ci src++; 633d8536b4Sopenharmony_ci } 643d8536b4Sopenharmony_ci continue; 653d8536b4Sopenharmony_ci } 663d8536b4Sopenharmony_ci *dest++ = *src++; 673d8536b4Sopenharmony_ci } 683d8536b4Sopenharmony_ci *dest = '\0'; 693d8536b4Sopenharmony_ci return path; 703d8536b4Sopenharmony_ci} 713d8536b4Sopenharmony_ci 723d8536b4Sopenharmony_ciSTATIC VOID StrRemovePathEndSlash(CHAR *dest, const CHAR *fullpath) 733d8536b4Sopenharmony_ci{ 743d8536b4Sopenharmony_ci if ((*dest == '.') && (*(dest - 1) == '/')) { 753d8536b4Sopenharmony_ci *dest = '\0'; 763d8536b4Sopenharmony_ci dest--; 773d8536b4Sopenharmony_ci } 783d8536b4Sopenharmony_ci if ((dest != fullpath) && (*dest == '/')) { 793d8536b4Sopenharmony_ci *dest = '\0'; 803d8536b4Sopenharmony_ci } 813d8536b4Sopenharmony_ci} 823d8536b4Sopenharmony_ci 833d8536b4Sopenharmony_ciSTATIC CHAR *StrNormalizePath(CHAR *fullpath) 843d8536b4Sopenharmony_ci{ 853d8536b4Sopenharmony_ci CHAR *dest = fullpath; 863d8536b4Sopenharmony_ci CHAR *src = fullpath; 873d8536b4Sopenharmony_ci 883d8536b4Sopenharmony_ci /* 2: The position of the path character: / and the end character /0 */ 893d8536b4Sopenharmony_ci while (*src != '\0') { 903d8536b4Sopenharmony_ci if (*src == '.') { 913d8536b4Sopenharmony_ci if (*(src + 1) == '/') { 923d8536b4Sopenharmony_ci src += 2; /* 2, sizeof "./" */ 933d8536b4Sopenharmony_ci continue; 943d8536b4Sopenharmony_ci } else if (*(src + 1) == '.') { 953d8536b4Sopenharmony_ci if ((*(src + 2) == '/') || (*(src + 2) == '\0')) { /* 2, 2, offset to check */ 963d8536b4Sopenharmony_ci src += 2; /* 2, sizeof offset */ 973d8536b4Sopenharmony_ci } else { 983d8536b4Sopenharmony_ci while ((*src != '\0') && (*src != '/')) { 993d8536b4Sopenharmony_ci *dest++ = *src++; 1003d8536b4Sopenharmony_ci } 1013d8536b4Sopenharmony_ci continue; 1023d8536b4Sopenharmony_ci } 1033d8536b4Sopenharmony_ci } else { 1043d8536b4Sopenharmony_ci *dest++ = *src++; 1053d8536b4Sopenharmony_ci continue; 1063d8536b4Sopenharmony_ci } 1073d8536b4Sopenharmony_ci } else { 1083d8536b4Sopenharmony_ci *dest++ = *src++; 1093d8536b4Sopenharmony_ci continue; 1103d8536b4Sopenharmony_ci } 1113d8536b4Sopenharmony_ci 1123d8536b4Sopenharmony_ci if ((dest - 1) != fullpath) { 1133d8536b4Sopenharmony_ci dest--; 1143d8536b4Sopenharmony_ci } 1153d8536b4Sopenharmony_ci 1163d8536b4Sopenharmony_ci while ((dest > fullpath) && (*(dest - 1) != '/')) { 1173d8536b4Sopenharmony_ci dest--; 1183d8536b4Sopenharmony_ci } 1193d8536b4Sopenharmony_ci 1203d8536b4Sopenharmony_ci if (*src == '/') { 1213d8536b4Sopenharmony_ci src++; 1223d8536b4Sopenharmony_ci } 1233d8536b4Sopenharmony_ci } 1243d8536b4Sopenharmony_ci 1253d8536b4Sopenharmony_ci *dest = '\0'; 1263d8536b4Sopenharmony_ci 1273d8536b4Sopenharmony_ci /* remove '/' in the end of path if exist */ 1283d8536b4Sopenharmony_ci 1293d8536b4Sopenharmony_ci dest--; 1303d8536b4Sopenharmony_ci 1313d8536b4Sopenharmony_ci StrRemovePathEndSlash(dest, fullpath); 1323d8536b4Sopenharmony_ci return dest; 1333d8536b4Sopenharmony_ci} 1343d8536b4Sopenharmony_ci 1353d8536b4Sopenharmony_ciSTATIC INT32 VfsNormalizePathParameCheck(const CHAR *filename, CHAR **pathname) 1363d8536b4Sopenharmony_ci{ 1373d8536b4Sopenharmony_ci INT32 namelen; 1383d8536b4Sopenharmony_ci CHAR *name = NULL; 1393d8536b4Sopenharmony_ci 1403d8536b4Sopenharmony_ci if (pathname == NULL) { 1413d8536b4Sopenharmony_ci return -EINVAL; 1423d8536b4Sopenharmony_ci } 1433d8536b4Sopenharmony_ci 1443d8536b4Sopenharmony_ci /* check parameters */ 1453d8536b4Sopenharmony_ci 1463d8536b4Sopenharmony_ci if (filename == NULL) { 1473d8536b4Sopenharmony_ci *pathname = NULL; 1483d8536b4Sopenharmony_ci return -EINVAL; 1493d8536b4Sopenharmony_ci } 1503d8536b4Sopenharmony_ci 1513d8536b4Sopenharmony_ci namelen = VfsStrnlen(filename, PATH_MAX); 1523d8536b4Sopenharmony_ci if (!namelen) { 1533d8536b4Sopenharmony_ci *pathname = NULL; 1543d8536b4Sopenharmony_ci return -EINVAL; 1553d8536b4Sopenharmony_ci } else if (namelen >= PATH_MAX) { 1563d8536b4Sopenharmony_ci *pathname = NULL; 1573d8536b4Sopenharmony_ci return -ENAMETOOLONG; 1583d8536b4Sopenharmony_ci } 1593d8536b4Sopenharmony_ci 1603d8536b4Sopenharmony_ci for (name = (CHAR *)filename + namelen; ((name != filename) && (*name != '/')); name--) { 1613d8536b4Sopenharmony_ci if (strlen(name) > NAME_MAX) { 1623d8536b4Sopenharmony_ci *pathname = NULL; 1633d8536b4Sopenharmony_ci return -ENAMETOOLONG; 1643d8536b4Sopenharmony_ci } 1653d8536b4Sopenharmony_ci } 1663d8536b4Sopenharmony_ci 1673d8536b4Sopenharmony_ci return namelen; 1683d8536b4Sopenharmony_ci} 1693d8536b4Sopenharmony_ci 1703d8536b4Sopenharmony_ciSTATIC CHAR *VfsNotAbsolutePath(const CHAR *directory, const CHAR *filename, CHAR **pathname, INT32 namelen) 1713d8536b4Sopenharmony_ci{ 1723d8536b4Sopenharmony_ci INT32 ret; 1733d8536b4Sopenharmony_ci CHAR *fullpath = NULL; 1743d8536b4Sopenharmony_ci 1753d8536b4Sopenharmony_ci /* 2: The position of the path character: / and the end character /0 */ 1763d8536b4Sopenharmony_ci 1773d8536b4Sopenharmony_ci if ((namelen > 1) && (filename[0] == '.') && (filename[1] == '/')) { 1783d8536b4Sopenharmony_ci filename += 2; /* 2, size of "./" */ 1793d8536b4Sopenharmony_ci } 1803d8536b4Sopenharmony_ci 1813d8536b4Sopenharmony_ci fullpath = (CHAR *)malloc(strlen(directory) + namelen + 2); /* 2, size of "./" */ 1823d8536b4Sopenharmony_ci if (fullpath == NULL) { 1833d8536b4Sopenharmony_ci *pathname = NULL; 1843d8536b4Sopenharmony_ci SetErrno(ENOMEM); 1853d8536b4Sopenharmony_ci return (CHAR *)NULL; 1863d8536b4Sopenharmony_ci } 1873d8536b4Sopenharmony_ci 1883d8536b4Sopenharmony_ci /* 2, size of "./", join path and file name */ 1893d8536b4Sopenharmony_ci ret = snprintf_s(fullpath, strlen(directory) + namelen + 2, strlen(directory) + namelen + 1, 1903d8536b4Sopenharmony_ci "%s/%s", directory, filename); 1913d8536b4Sopenharmony_ci if (ret < 0) { 1923d8536b4Sopenharmony_ci *pathname = NULL; 1933d8536b4Sopenharmony_ci free(fullpath); 1943d8536b4Sopenharmony_ci SetErrno(ENAMETOOLONG); 1953d8536b4Sopenharmony_ci return (CHAR *)NULL; 1963d8536b4Sopenharmony_ci } 1973d8536b4Sopenharmony_ci 1983d8536b4Sopenharmony_ci return fullpath; 1993d8536b4Sopenharmony_ci} 2003d8536b4Sopenharmony_ci 2013d8536b4Sopenharmony_ciSTATIC CHAR *VfsNormalizeFullpath(const CHAR *directory, const CHAR *filename, CHAR **pathname, INT32 namelen) 2023d8536b4Sopenharmony_ci{ 2033d8536b4Sopenharmony_ci CHAR *fullpath = NULL; 2043d8536b4Sopenharmony_ci 2053d8536b4Sopenharmony_ci if (filename[0] != '/') { 2063d8536b4Sopenharmony_ci /* not an absolute path */ 2073d8536b4Sopenharmony_ci 2083d8536b4Sopenharmony_ci fullpath = VfsNotAbsolutePath(directory, filename, pathname, namelen); 2093d8536b4Sopenharmony_ci if (fullpath == NULL) { 2103d8536b4Sopenharmony_ci return (CHAR *)NULL; 2113d8536b4Sopenharmony_ci } 2123d8536b4Sopenharmony_ci } else { 2133d8536b4Sopenharmony_ci /* it's an absolute path, use it directly */ 2143d8536b4Sopenharmony_ci 2153d8536b4Sopenharmony_ci fullpath = strdup(filename); /* copy string */ 2163d8536b4Sopenharmony_ci if (fullpath == NULL) { 2173d8536b4Sopenharmony_ci *pathname = NULL; 2183d8536b4Sopenharmony_ci SetErrno(ENOMEM); 2193d8536b4Sopenharmony_ci return (CHAR *)NULL; 2203d8536b4Sopenharmony_ci } 2213d8536b4Sopenharmony_ci if (filename[1] == '/') { 2223d8536b4Sopenharmony_ci *pathname = NULL; 2233d8536b4Sopenharmony_ci free(fullpath); 2243d8536b4Sopenharmony_ci SetErrno(EINVAL); 2253d8536b4Sopenharmony_ci return (CHAR *)NULL; 2263d8536b4Sopenharmony_ci } 2273d8536b4Sopenharmony_ci } 2283d8536b4Sopenharmony_ci 2293d8536b4Sopenharmony_ci return fullpath; 2303d8536b4Sopenharmony_ci} 2313d8536b4Sopenharmony_ci 2323d8536b4Sopenharmony_ciINT32 VfsNormalizePath(const CHAR *directory, const CHAR *filename, CHAR **pathname) 2333d8536b4Sopenharmony_ci{ 2343d8536b4Sopenharmony_ci CHAR *fullpath = NULL; 2353d8536b4Sopenharmony_ci INT32 namelen; 2363d8536b4Sopenharmony_ci 2373d8536b4Sopenharmony_ci namelen = VfsNormalizePathParameCheck(filename, pathname); 2383d8536b4Sopenharmony_ci if (namelen < 0) { 2393d8536b4Sopenharmony_ci return namelen; 2403d8536b4Sopenharmony_ci } 2413d8536b4Sopenharmony_ci 2423d8536b4Sopenharmony_ci if ((directory == NULL) && (filename[0] != '/')) { 2433d8536b4Sopenharmony_ci PRINT_ERR("NO_WORKING_DIR\n"); 2443d8536b4Sopenharmony_ci *pathname = NULL; 2453d8536b4Sopenharmony_ci return -EINVAL; 2463d8536b4Sopenharmony_ci } 2473d8536b4Sopenharmony_ci 2483d8536b4Sopenharmony_ci /* 2, The position of the path character: / and the end character /0 */ 2493d8536b4Sopenharmony_ci if ((filename[0] != '/') && (strlen(directory) + namelen + 2 > TEMP_PATH_MAX)) { 2503d8536b4Sopenharmony_ci return -ENAMETOOLONG; 2513d8536b4Sopenharmony_ci } 2523d8536b4Sopenharmony_ci 2533d8536b4Sopenharmony_ci fullpath = VfsNormalizeFullpath(directory, filename, pathname, namelen); 2543d8536b4Sopenharmony_ci if (fullpath == NULL) { 2553d8536b4Sopenharmony_ci return -errno; 2563d8536b4Sopenharmony_ci } 2573d8536b4Sopenharmony_ci 2583d8536b4Sopenharmony_ci (VOID)StrPath(fullpath); 2593d8536b4Sopenharmony_ci (VOID)StrNormalizePath(fullpath); 2603d8536b4Sopenharmony_ci if (strlen(fullpath) >= PATH_MAX) { 2613d8536b4Sopenharmony_ci *pathname = NULL; 2623d8536b4Sopenharmony_ci free(fullpath); 2633d8536b4Sopenharmony_ci return -ENAMETOOLONG; 2643d8536b4Sopenharmony_ci } 2653d8536b4Sopenharmony_ci 2663d8536b4Sopenharmony_ci *pathname = fullpath; 2673d8536b4Sopenharmony_ci return 0; 2683d8536b4Sopenharmony_ci} 2693d8536b4Sopenharmony_ci 270