• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "read_text_core.h"
16 
17 #include <cinttypes>
18 #include <fcntl.h>
19 #include <tuple>
20 #include <unistd.h>
21 #include <sys/stat.h>
22 
23 #include "file_utils.h"
24 #include "filemgmt_libhilog.h"
25 
26 namespace OHOS {
27 namespace FileManagement {
28 namespace ModuleFileIO {
29 using namespace std;
30 
ValidReadTextArg(const std::optional<ReadTextOptions> & options)31 static tuple<bool, int64_t, bool, int64_t, unique_ptr<char[]>> ValidReadTextArg(
32     const std::optional<ReadTextOptions> &options)
33 {
34     int64_t offset = -1;
35     int64_t len = 0;
36     bool hasLen = false;
37     unique_ptr<char[]> encoding { new char[]{ "utf-8" } };
38 
39     if (!options.has_value()) {
40         return { true, offset, hasLen, len, move(encoding) };
41     }
42 
43     ReadTextOptions op = options.value();
44     if (op.offset.has_value()) {
45         offset = op.offset.value();
46         if (offset < 0) {
47             HILOGE("Illegal option.offset parameter");
48             return { false, offset, hasLen, len, nullptr };
49         }
50     }
51 
52     if (op.length.has_value()) {
53         len = op.length.value();
54         if (len < 0 || len > UINT_MAX) {
55             HILOGE("Illegal option.length parameter");
56             return { false, offset, hasLen, len, nullptr };
57         }
58         hasLen = true;
59     }
60 
61     if (op.encoding.has_value()) {
62         auto encoding = op.encoding.value();
63         if (encoding != "utf-8") {
64             HILOGE("Illegal option.encoding parameter");
65             return { false, offset, hasLen, len, nullptr };
66         }
67     }
68 
69     return { true, offset, hasLen, len, move(encoding) };
70 }
71 
OpenFile(const std::string & path)72 static int OpenFile(const std::string& path)
73 {
74     std::unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup)*> openReq = {
75         new uv_fs_t, FsUtils::FsReqCleanup
76     };
77     if (openReq == nullptr) {
78         HILOGE("Failed to request heap memory.");
79         return -ENOMEM;
80     }
81 
82     return uv_fs_open(nullptr, openReq.get(), path.c_str(), O_RDONLY,
83         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, nullptr);
84 }
85 
ReadFromFile(int fd,int64_t offset,string & buffer)86 static int ReadFromFile(int fd, int64_t offset, string& buffer)
87 {
88     uv_buf_t readbuf = uv_buf_init(const_cast<char *>(buffer.c_str()), static_cast<unsigned int>(buffer.size()));
89     std::unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup)*> readReq = {
90         new uv_fs_t, FsUtils::FsReqCleanup };
91     if (readReq == nullptr) {
92         HILOGE("Failed to request heap memory.");
93         return -ENOMEM;
94     }
95     return uv_fs_read(nullptr, readReq.get(), fd, &readbuf, 1, offset, nullptr);
96 }
97 
DoReadText(const std::string & path,const std::optional<ReadTextOptions> & options)98 FsResult<tuple<string, int64_t>> ReadTextCore::DoReadText(const std::string &path,
99     const std::optional<ReadTextOptions> &options)
100 {
101     auto [resGetReadTextArg, offset, hasLen, len, encoding] = ValidReadTextArg(options);
102     if (!resGetReadTextArg) {
103         return FsResult<tuple<string, int64_t>>::Error(EINVAL);
104     }
105 
106     OHOS::DistributedFS::FDGuard sfd;
107     int fd = OpenFile(path);
108     if (fd < 0) {
109         HILOGD("Failed to open file by ret: %{public}d", fd);
110         return FsResult<tuple<string, int64_t>>::Error(fd);
111     }
112     sfd.SetFD(fd);
113 
114     struct stat statbf;
115     if ((!sfd) || (fstat(sfd.GetFD(), &statbf) < 0)) {
116         HILOGE("Failed to get stat of file by fd: %{public}d", sfd.GetFD());
117         return FsResult<tuple<string, int64_t>>::Error(errno);
118     }
119 
120     if (offset > statbf.st_size) {
121         HILOGE("Invalid offset: %{public}" PRIu64, offset);
122         return FsResult<tuple<string, int64_t>>::Error(EINVAL);
123     }
124 
125     len = (!hasLen || len > statbf.st_size) ? statbf.st_size : len;
126     string buffer(len, '\0');
127     int readRet = ReadFromFile(sfd.GetFD(), offset, buffer);
128     if (readRet < 0) {
129         HILOGE("Failed to read file by fd: %{public}d", fd);
130         return FsResult<tuple<string, int64_t>>::Error(readRet);
131     }
132 
133     return FsResult<tuple<string, int64_t>>::Success(make_tuple(move(buffer), readRet));
134 }
135 
136 } // namespace ModuleFileIO
137 } // namespace FileManagement
138 } // namespace OHOS