• 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 
16 #include "write_core.h"
17 
18 #include <cstring>
19 #include <ctime>
20 #include <iostream>
21 #include <memory>
22 #include <sstream>
23 #include <unistd.h>
24 
25 #ifdef FILE_API_TRACE
26 #include "hitrace_meter.h"
27 #endif
28 
29 namespace OHOS {
30 namespace FileManagement {
31 namespace ModuleFileIO {
32 using namespace std;
33 
ValidWriteArg(void * buffer,const size_t bufLen,const optional<WriteOptions> & options)34 static tuple<bool, void *, size_t, int64_t> ValidWriteArg(
35     void *buffer, const size_t bufLen, const optional<WriteOptions> &options)
36 {
37     size_t retLen = 0;
38     int64_t offset = -1;
39     bool succ = false;
40 
41     if (bufLen > UINT_MAX) {
42         HILOGE("The Size of buffer is too large");
43         return { false, nullptr, 0, offset };
44     }
45 
46     optional<size_t> lengthOp = nullopt;
47     optional<int64_t> offsetOp = nullopt;
48     if (options.has_value()) {
49         WriteOptions op = options.value();
50         lengthOp = op.length;
51         offsetOp = op.offset;
52     }
53 
54     tie(succ, retLen) = FsUtils::GetActualLen(bufLen, 0, lengthOp);
55     if (!succ) {
56         HILOGE("Failed to get actual length");
57         return { false, nullptr, 0, offset };
58     }
59 
60     if (offsetOp.has_value()) {
61         offset = offsetOp.value();
62         if (offset < 0) {
63             HILOGE("option.offset shall be positive number");
64             return { false, nullptr, 0, offset };
65         }
66     }
67     return { true, buffer, retLen, offset };
68 }
69 
DoWrite(const int32_t fd,const string & buffer,const optional<WriteOptions> & options)70 FsResult<int64_t> WriteCore::DoWrite(const int32_t fd, const string &buffer, const optional<WriteOptions> &options)
71 {
72     if (fd < 0) {
73         HILOGE("Invalid fd from JS first argument");
74         return FsResult<int64_t>::Error(EINVAL);
75     }
76 
77     bool succ = false;
78     size_t len = 0;
79     int64_t offset = -1;
80     void *buf = const_cast<void *>(static_cast<const void *>(buffer.c_str()));
81     size_t bufLen = static_cast<size_t>(buffer.length());
82 
83     tie(succ, buf, len, offset) = ValidWriteArg(buf, bufLen, options);
84     if (!succ) {
85         HILOGE("Failed to resolve buf and options");
86         return FsResult<int64_t>::Error(EINVAL);
87     }
88 
89     return DoWrite(fd, buf, len, offset);
90 }
91 
DoWrite(const int32_t fd,const ArrayBuffer & buffer,const optional<WriteOptions> & options)92 FsResult<int64_t> WriteCore::DoWrite(const int32_t fd, const ArrayBuffer &buffer, const optional<WriteOptions> &options)
93 {
94     if (fd < 0) {
95         HILOGE("Invalid fd from JS first argument");
96         return FsResult<int64_t>::Error(EINVAL);
97     }
98 
99     bool succ = false;
100     size_t len = 0;
101     int64_t offset = -1;
102     void *buf = nullptr;
103 
104     tie(succ, buf, len, offset) = ValidWriteArg(buffer.buf, buffer.length, options);
105     if (!succ) {
106         HILOGE("Failed to resolve buf and options");
107         return FsResult<int64_t>::Error(EINVAL);
108     }
109 
110     return DoWrite(fd, buf, len, offset);
111 }
112 
DoWrite(const int32_t fd,void * buf,const size_t len,const int64_t offset)113 FsResult<int64_t> WriteCore::DoWrite(const int32_t fd, void *buf, const size_t len, const int64_t offset)
114 {
115     uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<unsigned int>(len));
116     unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> writeReq = { new uv_fs_t, FsUtils::FsReqCleanup };
117     if (!writeReq) {
118         return FsResult<int64_t>::Error(ENOMEM);
119     }
120     int ret = uv_fs_write(nullptr, writeReq.get(), fd, &buffer, 1, offset, nullptr);
121     if (ret < 0) {
122         HILOGE("Failed to write file for %{public}d", ret);
123         return FsResult<int64_t>::Error(ret);
124     }
125     return FsResult<int64_t>::Success(static_cast<int64_t>(ret));
126 }
127 
128 } // namespace ModuleFileIO
129 } // namespace FileManagement
130 } // namespace OHOS