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