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
23 namespace panda::ecmascript {
FileStream(const std::string & fileName)24 FileStream::FileStream(const std::string &fileName)
25 {
26 Initialize(fileName);
27 }
28
~FileStream()29 FileStream::~FileStream()
30 {
31 EndOfStream();
32 }
33
EndOfStream()34 void FileStream::EndOfStream()
35 {
36 if (fileStream_.is_open()) {
37 fileStream_.close();
38 }
39 }
40
Good()41 bool FileStream::Good()
42 {
43 return fileStream_.good();
44 }
45
Initialize(const std::string & fileName)46 void FileStream::Initialize(const std::string &fileName)
47 {
48 // check file name
49 std::pair<bool, std::string> realPath = FilePathValid(fileName);
50 if (!realPath.first) {
51 LOG_ECMA(ERROR) << "FileStream: check file path failed";
52 return;
53 }
54
55 fileStream_.open(realPath.second.c_str(), std::ios::out);
56 if (fileStream_.fail()) {
57 LOG_ECMA(ERROR) << "FileStream: open file failed";
58 }
59 }
60
FilePathValid(const std::string & fileName)61 std::pair<bool, std::string> FileStream::FilePathValid(const std::string &fileName)
62 {
63 if (fileName.empty() || fileName.size() > PATH_MAX) {
64 return std::make_pair(false, "");
65 }
66 char resolvedPath[PATH_MAX] = {0};
67 auto result = realpath(fileName.c_str(), resolvedPath);
68 if (result == resolvedPath || errno == ENOENT) {
69 return std::make_pair(true, std::string(resolvedPath));
70 }
71 return std::make_pair(false, "");
72 }
73
74 // Writes the chunk of data into the stream
WriteChunk(char * data,int32_t size)75 bool FileStream::WriteChunk(char *data, int32_t size)
76 {
77 if (fileStream_.fail()) {
78 return false;
79 }
80
81 std::string str(data, size);
82
83 fileStream_ << str;
84
85 return true;
86 }
87
EndOfStream()88 void FileDescriptorStream::EndOfStream()
89 {
90 if (Good()) {
91 close(fd_);
92 }
93 }
94
Good()95 bool FileDescriptorStream::Good()
96 {
97 return fd_ > 0;
98 }
99
100 // Writes the chunk of data into the stream
WriteChunk(char * data,int32_t size)101 bool FileDescriptorStream::WriteChunk(char *data, int32_t size)
102 {
103 if (fd_ < 0) {
104 return false;
105 }
106
107 std::string str(data, size);
108 int ret = dprintf(fd_, "%s", str.c_str());
109 if (ret < 0) {
110 LOG_ECMA(ERROR) << "Write FD print failed, ret" << ret;
111 return false;
112 }
113 ret = fsync(fd_);
114 if (ret < 0) {
115 LOG_ECMA(ERROR) << "Write FD file failed, ret" << ret;
116 return false;
117 }
118 return true;
119 }
120
WriteBinBlock(char * data,int32_t size)121 bool FileDescriptorStream::WriteBinBlock(char *data, int32_t size)
122 {
123 if (fd_ < 0) {
124 return false;
125 }
126 ssize_t written = write(fd_, data, size);
127 if (written == -1) {
128 perror("write");
129 return false;
130 }
131 return true;
132 }
133 }
134