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