1 /*
2 * Copyright 2015 WebAssembly Community Group participants
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "support/file.h"
18 #include "support/debug.h"
19
20 #include <cstdint>
21 #include <cstdlib>
22 #include <iostream>
23 #include <limits>
24
25 #define DEBUG_TYPE "file"
26
read_stdin()27 std::vector<char> wasm::read_stdin() {
28 BYN_TRACE("Loading stdin...\n");
29 std::vector<char> input;
30 char c;
31 while (std::cin.get(c) && !std::cin.eof()) {
32 input.push_back(c);
33 }
34 return input;
35 }
36
37 template<typename T>
read_file(const std::string & filename,Flags::BinaryOption binary)38 T wasm::read_file(const std::string& filename, Flags::BinaryOption binary) {
39 BYN_TRACE("Loading '" << filename << "'...\n");
40 std::ifstream infile;
41 std::ios_base::openmode flags = std::ifstream::in;
42 if (binary == Flags::Binary) {
43 flags |= std::ifstream::binary;
44 }
45 infile.open(filename, flags);
46 if (!infile.is_open()) {
47 std::cerr << "Failed opening '" << filename << "'" << std::endl;
48 exit(EXIT_FAILURE);
49 }
50 infile.seekg(0, std::ios::end);
51 std::streampos insize = infile.tellg();
52 if (uint64_t(insize) >= std::numeric_limits<size_t>::max()) {
53 // Building a 32-bit executable where size_t == 32 bits, we are not able to
54 // create strings larger than 2^32 bytes in length, so must abort here.
55 std::cerr << "Failed opening '" << filename
56 << "': Input file too large: " << insize
57 << " bytes. Try rebuilding in 64-bit mode." << std::endl;
58 exit(EXIT_FAILURE);
59 }
60 T input(size_t(insize) + (binary == Flags::Binary ? 0 : 1), '\0');
61 if (size_t(insize) == 0) {
62 return input;
63 }
64 infile.seekg(0);
65 infile.read(&input[0], insize);
66 if (binary == Flags::Text) {
67 size_t chars = size_t(infile.gcount());
68 // Truncate size to the number of ASCII characters actually read in text
69 // mode (which is generally less than the number of bytes on Windows, if
70 // \r\n line endings are present)
71 input.resize(chars + 1);
72 input[chars] = '\0';
73 }
74 return input;
75 }
76
read_possible_response_file(const std::string & input)77 std::string wasm::read_possible_response_file(const std::string& input) {
78 if (input.size() == 0 || input[0] != '@') {
79 return input;
80 }
81 return wasm::read_file<std::string>(input.substr(1), Flags::Text);
82 }
83
84 // Explicit instantiations for the explicit specializations.
85 template std::string wasm::read_file<>(const std::string&, Flags::BinaryOption);
86 template std::vector<char> wasm::read_file<>(const std::string&,
87 Flags::BinaryOption);
88
Output(const std::string & filename,Flags::BinaryOption binary)89 wasm::Output::Output(const std::string& filename, Flags::BinaryOption binary)
90 : outfile(), out([this, filename, binary]() {
91 if (filename == "-") {
92 return std::cout.rdbuf();
93 }
94 std::streambuf* buffer;
95 if (filename.size()) {
96 BYN_TRACE("Opening '" << filename << "'\n");
97 auto flags = std::ofstream::out | std::ofstream::trunc;
98 if (binary == Flags::Binary) {
99 flags |= std::ofstream::binary;
100 }
101 outfile.open(filename, flags);
102 if (!outfile.is_open()) {
103 std::cerr << "Failed opening '" << filename << "'" << std::endl;
104 exit(EXIT_FAILURE);
105 }
106 buffer = outfile.rdbuf();
107 } else {
108 buffer = std::cout.rdbuf();
109 }
110 return buffer;
111 }()) {}
112
copy_file(std::string input,std::string output)113 void wasm::copy_file(std::string input, std::string output) {
114 std::ifstream src(input, std::ios::binary);
115 std::ofstream dst(output, std::ios::binary);
116 dst << src.rdbuf();
117 }
118
file_size(std::string filename)119 size_t wasm::file_size(std::string filename) {
120 std::ifstream infile(filename, std::ifstream::ate | std::ifstream::binary);
121 return infile.tellg();
122 }
123