• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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