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
16 #include "read_core.h"
17
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <tuple>
21 #include <unistd.h>
22
23 #include "file_utils.h"
24 #include "filemgmt_libfs.h"
25 #include "filemgmt_libhilog.h"
26
27 namespace OHOS::FileManagement::ModuleFileIO {
28 using namespace std;
29
ValidReadArg(ArrayBuffer & arrayBuffer,const optional<ReadOptions> & options)30 static tuple<bool, void *, size_t, int64_t> ValidReadArg(ArrayBuffer &arrayBuffer, const optional<ReadOptions> &options)
31 {
32 size_t retLen = 0;
33 int64_t offset = -1;
34 bool succ = false;
35 void *buf = arrayBuffer.buf;
36 size_t bufLen = arrayBuffer.length;
37
38 if (bufLen > UINT_MAX) {
39 HILOGE("Invalid arraybuffer");
40 return { false, nullptr, retLen, offset };
41 }
42 optional<size_t> lengthOp = nullopt;
43 optional<int64_t> offsetOp = nullopt;
44 if (options.has_value()) {
45 ReadOptions op = options.value();
46 lengthOp = op.length;
47 offsetOp = op.offset;
48 }
49 tie(succ, retLen) = FsUtils::GetActualLen(bufLen, 0, lengthOp);
50 if (!succ) {
51 HILOGE("Failed to get actual length");
52 return { false, nullptr, retLen, offset };
53 }
54 if (offsetOp.has_value()) {
55 offset = offsetOp.value();
56 if (offset < 0) {
57 HILOGE("option.offset shall be positive number");
58 return { false, nullptr, retLen, offset };
59 }
60 }
61 return { true, buf, retLen, offset };
62 }
63
DoRead(const int32_t & fd,ArrayBuffer & arrayBuffer,const optional<ReadOptions> & options)64 FsResult<int64_t> ReadCore::DoRead(const int32_t &fd, ArrayBuffer &arrayBuffer, const optional<ReadOptions> &options)
65 {
66 if (fd < 0) {
67 HILOGE("Invalid fd");
68 return FsResult<int64_t>::Error(EINVAL);
69 }
70
71 auto [succ, buf, len, offset] = ValidReadArg(arrayBuffer, options);
72 if (!succ) {
73 return FsResult<int64_t>::Error(EINVAL);
74 }
75
76 uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<uint32_t>(len));
77 unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> readReq = { new uv_fs_t, FsUtils::FsReqCleanup };
78 if (!readReq) {
79 HILOGE("Failed to request heap memory.");
80 return FsResult<int64_t>::Error(ENOMEM);
81 }
82 int ret = uv_fs_read(nullptr, readReq.get(), fd, &buffer, 1, offset, nullptr);
83 if (ret < 0) {
84 HILOGE("Failed to read file for %{public}d", ret);
85 return FsResult<int64_t>::Error(ret);
86 }
87
88 return FsResult<int64_t>::Success(static_cast<int64_t>(ret));
89 }
90
91 } // namespace OHOS::FileManagement::ModuleFileIO