LCOV - code coverage report
Current view: top level - adump/common - path.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.4 % 145 134
Test Date: 2026-08-12 11:04:53 Functions: 96.0 % 25 24

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "path.h"
      12              : #include <algorithm>
      13              : #include "str_utils.h"
      14              : #include "log/hdc_log.h"
      15              : 
      16              : namespace Adx {
      17              : namespace {
      18              : constexpr char DIRECTORY_SEPARATOR = '/';
      19              : constexpr char FILE_EXTENSION_CHAR = '.';
      20              : constexpr const char *PARENT_DIR = "..";
      21              : 
      22              : constexpr mmMode_t DEFAULT_DIR_MODE = M_IRUSR | M_IWUSR | M_IXUSR;
      23              : } // namespace
      24              : 
      25          126 : bool Path::HasParentDirSegment(const std::string &path)
      26              : {
      27          126 :     size_t begin = 0;
      28          162 :     while (begin <= path.size()) {
      29          162 :         const size_t end = path.find(DIRECTORY_SEPARATOR, begin);
      30          162 :         const size_t len = (end == std::string::npos ? path.size() : end) - begin;
      31          162 :         if (path.compare(begin, len, PARENT_DIR) == 0) {
      32           21 :             return true;
      33              :         }
      34          141 :         if (end == std::string::npos) {
      35          105 :             break;
      36              :         }
      37           36 :         begin = end + 1;
      38              :     }
      39          105 :     return false;
      40              : }
      41              : 
      42           29 : Path &Path::operator = (const std::string &path)
      43              : {
      44           29 :     path_ = path;
      45           29 :     return *this;
      46              : }
      47              : 
      48            0 : bool Path::operator == (const Path &other) const
      49              : {
      50            0 :     return this->path_ == other.GetString();
      51              : }
      52              : 
      53            3 : Path &Path::operator += (const std::string &path)
      54              : {
      55            3 :     return Append(path);
      56              : }
      57              : 
      58            3 : Path &Path::Assign(const std::string &path)
      59              : {
      60            3 :     path_ = path;
      61            3 :     return *this;
      62              : }
      63              : 
      64          636 : Path &Path::Append(const std::string &path)
      65              : {
      66          636 :     AddSeperator();
      67          636 :     AppendPath(path);
      68          636 :     AddSeperator();
      69          636 :     return *this;
      70              : }
      71              : 
      72          373 : Path &Path::Concat(const std::string &path)
      73              : {
      74          373 :     AddSeperator();
      75          373 :     AppendPath(path);
      76          373 :     return *this;
      77              : }
      78              : 
      79           13 : Path &Path::AddExtension(const std::string &extension)
      80              : {
      81           13 :     std::string ext = StrUtils::Trim(extension);
      82           13 :     if (path_.empty() || ext.empty() || GetExtension() == ext) {
      83            3 :         return *this;
      84              :     }
      85              : 
      86           10 :     if (ext.front() != FILE_EXTENSION_CHAR) {
      87            3 :         path_ += FILE_EXTENSION_CHAR;
      88              :     }
      89           10 :     path_.append(ext);
      90           10 :     return *this;
      91           13 : }
      92              : 
      93           25 : std::string Path::GetExtension() const
      94              : {
      95           25 :     std::string file = GetFileName();
      96           25 :     const auto pos = file.rfind(FILE_EXTENSION_CHAR);
      97           63 :     return pos != std::string::npos ? file.substr(pos) : "";
      98           25 : }
      99              : 
     100          281 : std::string Path::GetFileName() const
     101              : {
     102          281 :     const auto pos = path_.find_last_of(DIRECTORY_SEPARATOR);
     103          281 :     return pos != std::string::npos ? path_.substr(pos + 1) : path_;
     104              : }
     105              : 
     106          471 : bool Path::Empty() const
     107              : {
     108          471 :     return path_.empty();
     109              : }
     110              : 
     111           67 : bool Path::Exist() const
     112              : {
     113           67 :     return Asccess(F_OK);
     114              : }
     115              : 
     116          573 : bool Path::Asccess(mmMode_t mode) const
     117              : {
     118          573 :     return !path_.empty() && mmAccess2(path_.c_str(), mode) == EN_OK;
     119              : }
     120              : 
     121          979 : bool Path::IsDirectory() const
     122              : {
     123          979 :     return mmIsDir(path_.c_str()) == EN_OK;
     124              : }
     125              : 
     126       139807 : bool Path::RealPath()
     127              : {
     128       139807 :     if (path_.empty()) {
     129            3 :         return false;
     130              :     }
     131              : 
     132       139854 :     char realPath[MMPA_MAX_PATH] = {0};
     133       139854 :     const int32_t ret = mmRealPath(path_.c_str(), realPath, MMPA_MAX_PATH);
     134       139679 :     if (ret != EN_OK) {
     135           68 :         return false;
     136              :     }
     137       139611 :     path_ = realPath;
     138       139650 :     return true;
     139              : }
     140              : 
     141              : /*
     142              :  * @brief: Get parent path
     143              :  *         /path/to/file -> /path/to
     144              :  *         / -> /
     145              :  *         /file -> /
     146              :  *         file -> ""
     147              :  */
     148          473 : Path Path::ParentPath() const
     149              : {
     150          473 :     if (path_.length() == 1 && path_[0] == DIRECTORY_SEPARATOR) {
     151            3 :         return Path(path_);
     152              :     }
     153              : 
     154          470 :     const size_t pos = path_.find_last_of(DIRECTORY_SEPARATOR);
     155          470 :     std::string parentPath = pos != std::string::npos ?
     156          476 :         (pos == 0 ? std::string(&DIRECTORY_SEPARATOR, 1) : path_.substr(0, pos)) : "";
     157          470 :     return Path(parentPath);
     158          470 : }
     159              : 
     160          425 : bool Path::CreateDirectory(bool recursion) const
     161              : {
     162          425 :     if (path_.empty() || path_.length() > MMPA_MAX_PATH) {
     163            3 :         IDE_LOGW("Directory path is empty or overlength, path: %s", path_.c_str());
     164            3 :         return false;
     165              :     }
     166              : 
     167          422 :     if (IsDirectory()) {
     168          202 :         return true;
     169              :     }
     170              : 
     171          220 :     if (recursion) {
     172          214 :         Path parentPath = ParentPath();
     173          214 :         if (!parentPath.Empty() && !parentPath.CreateDirectory(recursion)) {
     174            0 :             return false;
     175              :         }
     176          214 :     }
     177              : 
     178          220 :     const int32_t ret = mmMkdir(path_.c_str(), DEFAULT_DIR_MODE);
     179          220 :     if (ret != 0 && errno != EEXIST) {
     180            3 :         IDE_LOGW("Can not mkdir %s, mode: %d, errno: %s", path_.c_str(), DEFAULT_DIR_MODE, strerror(errno));
     181            3 :         return false;
     182              :     }
     183          217 :     return true;
     184              : }
     185              : 
     186       139779 : std::string Path::GetString() const
     187              : {
     188       139779 :     return path_;
     189              : }
     190              : 
     191          344 : const char *Path::GetCString() const
     192              : {
     193          344 :     return path_.c_str();
     194              : }
     195              : 
     196           60 : bool Path::BuildFullPathUnderRoot(const std::string &rootPath, const std::string &relativeFile,
     197              :     std::string &canonicalFile)
     198              : {
     199           60 :     if (rootPath.empty() || relativeFile.empty()) {
     200           18 :         IDE_LOGE("rootPath or relativeFile is empty.");
     201           18 :         return false;
     202              :     }
     203              : 
     204           42 :     if (HasParentDirSegment(relativeFile)) {
     205            3 :         IDE_LOGE("relativeFile[%s] contains '..' segment.", relativeFile.c_str());
     206            3 :         return false;
     207              :     }
     208              : 
     209           39 :     const std::string filePath = Path(rootPath).Concat(relativeFile).GetString();
     210           39 :     const std::string baseName = Path(filePath).GetFileName();
     211              : 
     212           39 :     Path dirPath = Path(filePath).ParentPath();
     213           39 :     if (!dirPath.CreateDirectory(true)) {
     214            0 :         IDE_LOGE("create directory failed, dirPath=%s.", dirPath.GetCString());
     215            0 :         return false;
     216              :     }
     217              : 
     218           39 :     if (!dirPath.RealPath()) {
     219            0 :         IDE_LOGE("get real path failed, dirPath=%s.", dirPath.GetCString());
     220            0 :         return false;
     221              :     }
     222              : 
     223           39 :     if (!dirPath.IsDirectory()) {
     224            0 :         IDE_LOGE("path is not a directory, dirPath=%s", dirPath.GetCString());
     225            0 :         return false;
     226              :     }
     227              : 
     228           39 :     Path realRootPath(rootPath);
     229           39 :     if (!realRootPath.RealPath()) {
     230            0 :         IDE_LOGE("get real path failed, rootPath=%s.", realRootPath.GetCString());
     231            0 :         return false;
     232              :     }
     233              : 
     234           39 :     if (!IsUnderDirectory(realRootPath.GetString(), dirPath.GetString())) {
     235            3 :         IDE_LOGE("resolved dirPath=%s escapes rootPath=%s.", dirPath.GetCString(), realRootPath.GetCString());
     236            3 :         return false;
     237              :     }
     238              : 
     239           36 :     canonicalFile = dirPath.GetString() + DIRECTORY_SEPARATOR + baseName;
     240           36 :     return true;
     241           39 : }
     242              : 
     243           75 : bool Path::IsUnderDirectory(const std::string &realDirPath, const std::string &realSubPath)
     244              : {
     245           75 :     if (realDirPath.empty() || realSubPath.empty()) {
     246            6 :         return false;
     247              :     }
     248              : 
     249              :     // Both paths are already canonical, so a segment-aware prefix match is sufficient.
     250           69 :     std::string prefix = realDirPath;
     251           69 :     if (prefix.back() != DIRECTORY_SEPARATOR) {
     252           54 :         prefix += DIRECTORY_SEPARATOR;
     253              :     }
     254              : 
     255           69 :     std::string target = realSubPath;
     256           69 :     if (target.back() != DIRECTORY_SEPARATOR) {
     257           66 :         target += DIRECTORY_SEPARATOR;
     258              :     }
     259              : 
     260           69 :     return target.compare(0, prefix.size(), prefix) == 0;
     261           69 : }
     262              : 
     263         1009 : void Path::AppendPath(const std::string &path)
     264              : {
     265         1009 :     std::string newPath = StrUtils::Trim(path);
     266         1009 :     (void)newPath.erase(newPath.begin(),
     267         1182 :         std::find_if(newPath.begin(), newPath.end(), [](uint8_t ch) { return ch != DIRECTORY_SEPARATOR; }));
     268         1009 :     (void)newPath.erase(std::find_if(newPath.rbegin(), newPath.rend(),
     269         1123 :         [](uint8_t ch) {
     270         1123 :             return ch != DIRECTORY_SEPARATOR;
     271              :         }).base(),
     272              :         newPath.end());
     273         1009 :     path_ += newPath;
     274         1009 : }
     275              : 
     276         1645 : void Path::AddSeperator()
     277              : {
     278         1645 :     if (!path_.empty() && path_.back() != DIRECTORY_SEPARATOR) {
     279         1337 :         path_ += DIRECTORY_SEPARATOR;
     280              :     }
     281         1645 : }
     282              : } // namespace Adx
        

Generated by: LCOV version 2.0-1