1 /*
2  * Copyright (c) 2023 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 "adapter/ohos/entrance/file_asset_provider_impl.h"
17 
18 #include <dirent.h>
19 
20 #include "base/log/ace_trace.h"
21 #include "base/utils/utils.h"
22 
23 namespace OHOS::Ace {
24 constexpr int64_t FOO_MAX_LEN = 20 * 1024 * 1024;
Initialize(const std::string& packagePath, const std::vector<std::string>& assetBasePaths)25 bool FileAssetProviderImpl::Initialize(const std::string& packagePath, const std::vector<std::string>& assetBasePaths)
26 {
27     ACE_SCOPED_TRACE("Initialize");
28     if (assetBasePaths.empty()) {
29         LOGE("the assetBasePath is empty");
30         return false;
31     }
32 
33     if (!packagePath.empty() && packagePath.back() != '/') {
34         packagePath_ = packagePath + "/";
35     } else {
36         packagePath_ = packagePath;
37     }
38 
39     assetBasePaths_ = assetBasePaths;
40     return true;
41 }
42 
IsValid() const43 bool FileAssetProviderImpl::IsValid() const
44 {
45     return true;
46 }
47 
GetAsMapping(const std::string& assetName) const48 std::unique_ptr<AssetMapping> FileAssetProviderImpl::GetAsMapping(const std::string& assetName) const
49 {
50     ACE_SCOPED_TRACE("GetAsMapping");
51     std::lock_guard<std::mutex> lock(mutex_);
52 
53     for (const auto& basePath : assetBasePaths_) {
54         std::string fileName = packagePath_ + basePath + assetName;
55         char realPath[PATH_MAX] = { 0x00 };
56         if (!RealPath(fileName, realPath)) {
57             continue;
58         }
59         std::FILE* fp = std::fopen(realPath, "r");
60         if (fp == nullptr) {
61             continue;
62         }
63 
64         if (std::fseek(fp, 0, SEEK_END) != 0) {
65             LOGE("seek file tail error");
66             std::fclose(fp);
67             continue;
68         }
69 
70         int64_t size = std::ftell(fp);
71         if (size == -1L || size == 0L || size > FOO_MAX_LEN) {
72             LOGE("ftell file error");
73             std::fclose(fp);
74             continue;
75         }
76 
77         uint8_t* dataArray = new (std::nothrow) uint8_t[size];
78         if (dataArray == nullptr) {
79             LOGE("new uint8_t array failed");
80             std::fclose(fp);
81             continue;
82         }
83 
84         rewind(fp);
85         std::unique_ptr<uint8_t[]> data(dataArray);
86         size_t result = std::fread(data.get(), 1, size, fp);
87         if (result != (size_t)size) {
88             LOGE("read file failed");
89             std::fclose(fp);
90             continue;
91         }
92 
93         std::fclose(fp);
94         return std::make_unique<FileAssetImplMapping>(std::move(data), size);
95     }
96     return nullptr;
97 }
98 
GetAssetPath(const std::string& assetName, bool )99 std::string FileAssetProviderImpl::GetAssetPath(const std::string& assetName, bool /* isAddHapPath */)
100 {
101     std::lock_guard<std::mutex> lock(mutex_);
102     for (const auto& basePath : assetBasePaths_) {
103         std::string assetBasePath = packagePath_ + basePath;
104         std::string fileName = assetBasePath + assetName;
105         char realPath[PATH_MAX] = { 0x00 };
106         if (!RealPath(fileName, realPath)) {
107             continue;
108         }
109         std::FILE* fp = std::fopen(realPath, "r");
110         if (fp == nullptr) {
111             continue;
112         }
113         std::fclose(fp);
114         return assetBasePath;
115     }
116     LOGE("Cannot find base path of %{public}s", assetName.c_str());
117     return "";
118 }
119 
GetAssetList(const std::string& path, std::vector<std::string>& assetList)120 void FileAssetProviderImpl::GetAssetList(const std::string& path, std::vector<std::string>& assetList)
121 {
122     std::lock_guard<std::mutex> lock(mutex_);
123     for (const auto& basePath : assetBasePaths_) {
124         std::string assetPath = packagePath_ + basePath + path;
125         std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(assetPath.c_str()), closedir);
126         if (dir == nullptr) {
127             continue;
128         }
129         struct dirent* dptr = nullptr;
130         while ((dptr = readdir(dir.get())) != nullptr) {
131             if (strcmp(dptr->d_name, ".") != 0 && strcmp(dptr->d_name, "..") != 0) {
132                 assetList.push_back(dptr->d_name);
133             }
134         }
135     }
136 }
137 } // namespace OHOS::Ace
138