1 /*
2 * Copyright (c) 2021-2022 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 "ecmascript/dfx/hprof/file_stream.h"
17
18 #include <climits>
19 #include <unistd.h>
20
21 #include "ecmascript/log_wrapper.h"
22 #include "ecmascript/platform/file.h"
23
24 namespace panda::ecmascript {
FileStream(const std::string & fileName)25 FileStream::FileStream(const std::string &fileName)
26 {
27 Initialize(fileName);
28 }
29
~FileStream()30 FileStream::~FileStream()
31 {
32 EndOfStream();
33 }
34
EndOfStream()35 void FileStream::EndOfStream()
36 {
37 if (fileStream_.is_open()) {
38 fileStream_.close();
39 }
40 }
41
Good()42 bool FileStream::Good()
43 {
44 return fileStream_.good();
45 }
46
Initialize(const std::string & fileName)47 void FileStream::Initialize(const std::string &fileName)
48 {
49 // check file name
50 std::pair<bool, std::string> realPath = FilePathValid(fileName);
51 if (!realPath.first) {
52 LOG_ECMA(ERROR) << "FileStream: check file path failed";
53 return;
54 }
55
56 fileStream_.open(realPath.second.c_str(), std::ios::out);
57 if (fileStream_.fail()) {
58 LOG_ECMA(ERROR) << "FileStream: open file failed";
59 }
60 }
61
FilePathValid(const std::string & fileName)62 std::pair<bool, std::string> FileStream::FilePathValid(const std::string &fileName)
63 {
64 if (fileName.empty() || fileName.size() > PATH_MAX) {
65 return std::make_pair(false, "");
66 }
67 char resolvedPath[PATH_MAX] = {0};
68 auto result = realpath(fileName.c_str(), resolvedPath);
69 if (result == resolvedPath || errno == ENOENT) {
70 return std::make_pair(true, std::string(resolvedPath));
71 }
72 return std::make_pair(false, "");
73 }
74
75 // Writes the chunk of data into the stream
WriteChunk(char * data,int32_t size)76 bool FileStream::WriteChunk(char *data, int32_t size)
77 {
78 if (fileStream_.fail()) {
79 return false;
80 }
81
82 std::string str(data, size);
83
84 fileStream_ << str;
85
86 return true;
87 }
88
FileDescriptorStream(int32_t fd)89 FileDescriptorStream::FileDescriptorStream(int32_t fd) : fd_(fd)
90 {
91 FdsanExchangeOwnerTag(reinterpret_cast<fd_t>(fd));
92 }
93
~FileDescriptorStream()94 FileDescriptorStream::~FileDescriptorStream()
95 {
96 EndOfStream();
97 }
98
EndOfStream()99 void FileDescriptorStream::EndOfStream()
100 {
101 if (Good()) {
102 Close(reinterpret_cast<fd_t>(fd_));
103 fd_ = -1;
104 }
105 }
106
Good()107 bool FileDescriptorStream::Good()
108 {
109 return fd_ > 0;
110 }
111
112 // Writes the chunk of data into the stream
WriteChunk(char * data,int32_t size)113 bool FileDescriptorStream::WriteChunk(char *data, int32_t size)
114 {
115 if (fd_ < 0) {
116 return false;
117 }
118
119 std::string str(data, size);
120 int ret = dprintf(fd_, "%s", str.c_str());
121 if (ret < 0) {
122 LOG_ECMA(ERROR) << "Write FD print failed, ret" << ret;
123 return false;
124 }
125 ret = fsync(fd_);
126 if (ret < 0) {
127 LOG_ECMA(ERROR) << "Write FD file failed, ret" << ret;
128 return false;
129 }
130 return true;
131 }
132
WriteBinBlock(char * data,int32_t size)133 bool FileDescriptorStream::WriteBinBlock(char *data, int32_t size)
134 {
135 if (fd_ < 0) {
136 return false;
137 }
138 ssize_t written = write(fd_, data, size);
139 if (written == -1) {
140 perror("write");
141 return false;
142 }
143 return true;
144 }
145
BinaryWriter(Stream * stream)146 BinaryWriter::BinaryWriter(Stream *stream)
147 : stream_(stream), chunkSize_(stream->GetSize()), chunk_(chunkSize_), current_(0)
148 {
149 }
150
~BinaryWriter()151 BinaryWriter::~BinaryWriter()
152 {
153 }
154
WriteBinBlock(char * block,int size)155 void BinaryWriter::WriteBinBlock(char *block, int size)
156 {
157 char *cur = block;
158 while (size > 0) {
159 MaybeWriteBinBlock();
160 int dstSize = chunkSize_ - current_;
161 int writeSize = std::min(dstSize, size);
162 if (memcpy_s(chunk_.data() + current_, dstSize, cur, writeSize) != EOK) {
163 LOG_FULL(FATAL) << "memcpy_s failed!";
164 }
165 cur += writeSize;
166 size -= writeSize;
167 IncreaseFileIndex(writeSize);
168 }
169 }
170
WriteUInt64(uint64_t num)171 void BinaryWriter::WriteUInt64(uint64_t num)
172 {
173 if (UNLIKELY(chunkSize_ - current_ < sizeof(uint64_t))) {
174 WriteBinBlock();
175 }
176 *reinterpret_cast<uint64_t *>(chunk_.data() + current_) = num;
177 IncreaseFileIndex(sizeof(uint64_t));
178 }
179
WriteUInt32(uint32_t num)180 void BinaryWriter::WriteUInt32(uint32_t num)
181 {
182 if (UNLIKELY(chunkSize_ - current_ < sizeof(uint32_t))) {
183 WriteBinBlock();
184 }
185 *reinterpret_cast<uint32_t *>(chunk_.data() + current_) = num;
186 IncreaseFileIndex(sizeof(uint32_t));
187 }
188
WriteUInt16(uint16_t num)189 void BinaryWriter::WriteUInt16(uint16_t num)
190 {
191 if (UNLIKELY(chunkSize_ - current_ < sizeof(uint16_t))) {
192 WriteBinBlock();
193 }
194 *reinterpret_cast<uint16_t *>(chunk_.data() + current_) = num;
195 IncreaseFileIndex(sizeof(uint16_t));
196 }
197
WriteUInt8(uint8_t num)198 void BinaryWriter::WriteUInt8(uint8_t num)
199 {
200 if (UNLIKELY(chunkSize_ - current_ < sizeof(uint8_t))) {
201 WriteBinBlock();
202 }
203 *reinterpret_cast<uint8_t *>(chunk_.data() + current_) = num;
204 IncreaseFileIndex(sizeof(uint8_t));
205 }
206
EndOfWriteBinBlock()207 void BinaryWriter::EndOfWriteBinBlock()
208 {
209 if (current_ > 0) {
210 WriteBinBlock();
211 }
212 stream_->EndOfStream();
213 }
214
MaybeWriteBinBlock()215 void BinaryWriter::MaybeWriteBinBlock()
216 {
217 ASSERT(current_ <= chunkSize_);
218 if (UNLIKELY(current_ == chunkSize_)) {
219 WriteBinBlock();
220 }
221 }
222
WriteBinBlock()223 void BinaryWriter::WriteBinBlock()
224 {
225 stream_->WriteBinBlock(chunk_.data(), current_);
226 current_ = 0;
227 }
228 }
229