• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "stream_impl.h"
17 #include <memory>
18 #include <tuple>
19 #include "securec.h"
20 #include "utils.h"
21 
22 using namespace std;
23 
24 namespace OHOS {
25 namespace CJSystemapi {
26 namespace FileFs {
27 
GetActualLen(size_t bufLen,size_t bufOff,int64_t offset,int64_t length)28 std::tuple<int, size_t> GetActualLen(size_t bufLen, size_t bufOff, int64_t offset, int64_t length)
29 {
30     size_t retLen = bufLen - bufOff;
31 
32     if (length == 0) {
33         return { SUCCESS_CODE, retLen };
34     }
35 
36     if (length < 0 || static_cast<size_t>(length) > retLen) {
37         LOGE("Invalid option length, length: %{public}" PRId64 ", retLen: %{public}zu", length, retLen);
38         return { EINVAL, 0 };
39     }
40     retLen = static_cast<size_t>(length);
41     return { SUCCESS_CODE, retLen };
42 }
43 
GetReadArg(size_t bufLen,int64_t length,int64_t offset)44 tuple<int, std::unique_ptr<char[]>, size_t, int64_t> GetReadArg(size_t bufLen, int64_t length, int64_t offset)
45 {
46     std::unique_ptr<char[]> buf = std::make_unique<char[]>(bufLen);
47 
48     auto [state, retLen] = GetActualLen(bufLen, 0, offset, length);
49     if (state != SUCCESS_CODE) {
50         LOGE("Failed to get actual length");
51         return { EINVAL, nullptr, 0, 0 };
52     }
53 
54     if (offset < 0) {
55         LOGE("option.offset shall be positive number");
56         return { EINVAL, nullptr, 0, 0 };
57     }
58 
59     return { SUCCESS_CODE, move(buf), retLen, offset };
60 }
61 
Close()62 int StreamImpl::Close()
63 {
64     if (!fp_) {
65         LOGE("close false, fp is null");
66         return GetErrorCode(EIO);
67     }
68     fp_.reset();
69     return SUCCESS_CODE;
70 }
71 
Flush()72 int StreamImpl::Flush()
73 {
74     if (!fp_) {
75         LOGE("flush false, fp is null");
76         return GetErrorCode(EIO);
77     }
78     int ret = fflush(fp_.get());
79     if (ret < 0) {
80         LOGE("Failed to fflush file in the stream, ret: %{public}d", ret);
81         return GetErrorCode(errno);
82     }
83     return SUCCESS_CODE;
84 }
85 
ReadImpl(std::unique_ptr<char[]> & buf,size_t len,FILE * filp,uint8_t * buffer)86 tuple<int, int64_t> ReadImpl(std::unique_ptr<char[]> &buf, size_t len, FILE* filp, uint8_t* buffer)
87 {
88     size_t actLen = fread(buf.get(), sizeof(char), len, filp);
89     if ((actLen != static_cast<size_t>(len) && !feof(filp)) || ferror(filp)) {
90         LOGE("Invalid buffer size and pointer, actlen: %{public}zu", actLen);
91         return {GetErrorCode(EIO), 0};
92     }
93     if (actLen != 0) {
94         int ret = memcpy_s(buffer, actLen, buf.get(), actLen);
95         if (ret != 0) {
96             return {GetErrorCode(EIO), 0};
97         }
98     }
99     return {SUCCESS_CODE, static_cast<int64_t>(actLen)};
100 }
101 
ReadCur(uint8_t * buffer,size_t buLen,int64_t length)102 tuple<int, int64_t> StreamImpl::ReadCur(uint8_t* buffer, size_t buLen, int64_t length)
103 {
104     if (!fp_) {
105         LOGE("Stream may have been closed");
106         return {GetErrorCode(EIO), 0};
107     }
108 
109     FILE *filp = nullptr;
110     filp = fp_.get();
111 
112     auto [state, buf, len, offsetResult] = GetReadArg(static_cast<size_t>(buLen), length, 0.0);
113     if (state != SUCCESS_CODE) {
114         LOGE("Failed to resolve buf and options");
115         return {GetErrorCode(state), 0};
116     }
117 
118     return ReadImpl(buf, len, filp, buffer);
119 }
120 
Read(uint8_t * buffer,size_t buLen,int64_t length,int64_t offset)121 tuple<int, int64_t> StreamImpl::Read(uint8_t* buffer, size_t buLen, int64_t length, int64_t offset)
122 {
123     if (!fp_) {
124         LOGE("Stream may have been closed");
125         return {GetErrorCode(EIO), 0};
126     }
127 
128     FILE *filp = nullptr;
129     filp = fp_.get();
130 
131     auto [state, buf, len, offsetResult] = GetReadArg(static_cast<size_t>(buLen), length, offset);
132     if (state != SUCCESS_CODE) {
133         LOGE("Failed to resolve buf and options");
134         return {GetErrorCode(state), 0};
135     }
136 
137     if (offsetResult >= 0) {
138         int result = fseek(filp, static_cast<long>(offsetResult), SEEK_SET);
139         if (result < 0) {
140             LOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", result);
141             return {GetErrorCode(errno), 0};
142         }
143     }
144     return ReadImpl(buf, len, filp, buffer);
145 }
146 
WriteCur(void * buffer,int64_t length,const std::string & encode)147 tuple<int, int64_t> StreamImpl::WriteCur(void* buffer, int64_t length, const std::string& encode)
148 {
149     FILE *filp = nullptr;
150     filp = fp_.get();
151 
152     auto [state, buf, len, offsetResult] =
153         CommonFunc::GetWriteArg(buffer, length, 0, encode);
154     if (state != SUCCESS_CODE) {
155         LOGE("Failed to resolve buf and options");
156         return {GetErrorCode(state), 0};
157     }
158 
159     size_t writeLen = fwrite(buf, 1, len, filp);
160     if ((writeLen == 0) && (writeLen != len)) {
161         LOGE("Failed to fwrite stream");
162         return {GetErrorCode(EIO), 0};
163     }
164     return {SUCCESS_CODE, static_cast<int64_t>(writeLen)};
165 }
166 
Write(void * buffer,int64_t length,int64_t offset,const std::string & encode)167 tuple<int, int64_t> StreamImpl::Write(void* buffer, int64_t length, int64_t offset, const std::string& encode)
168 {
169     FILE *filp = nullptr;
170     filp = fp_.get();
171 
172     auto [state, buf, len, offsetResult] =
173         CommonFunc::GetWriteArg(buffer, length, offset, encode);
174     if (state != SUCCESS_CODE) {
175         LOGE("Failed to resolve buf and options");
176         return {GetErrorCode(state), 0};
177     }
178 
179     if (offsetResult >= 0) {
180         int ret = fseek(filp, static_cast<long>(offsetResult), SEEK_SET);
181         if (ret < 0) {
182             LOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret);
183             return {GetErrorCode(errno), 0};
184         }
185     }
186 
187     size_t writeLen = fwrite(buf, 1, len, filp);
188     if ((writeLen == 0) && (writeLen != len)) {
189         LOGE("Failed to fwrite stream");
190         return {GetErrorCode(EIO), 0};
191     }
192     return {SUCCESS_CODE, static_cast<int64_t>(writeLen)};
193 }
194 
195 }
196 }
197 }