Apache Mesos
read.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_OS_READ_HPP__
14 #define __STOUT_OS_READ_HPP__
15 
16 #include <assert.h>
17 #include <stdio.h>
18 #ifndef __WINDOWS__
19 #include <unistd.h>
20 #endif // __WINDOWS__
21 
22 #include <string>
23 
24 #if defined(__sun) || defined(__WINDOWS__)
25 #include <fstream>
26 #endif // __sun || __WINDOWS__
27 
28 #include <stout/error.hpp>
29 #include <stout/result.hpp>
30 #include <stout/try.hpp>
31 #ifdef __WINDOWS__
32 #include <stout/windows.hpp>
33 #endif // __WINDOWS__
34 
35 #include <stout/os/int_fd.hpp>
36 #include <stout/os/socket.hpp>
37 
38 #ifdef __WINDOWS__
40 #else
41 #include <stout/os/posix/read.hpp>
42 #endif // __WINDOWS__
43 
44 
45 namespace os {
46 
47 // Reads 'size' bytes from a file from its current offset.
48 // If EOF is encountered before reading 'size' bytes then the result
49 // will contain the bytes read and a subsequent read will return None.
50 inline Result<std::string> read(int_fd fd, size_t size)
51 {
52  char* buffer = new char[size];
53  size_t offset = 0;
54 
55  while (offset < size) {
56  ssize_t length = os::read(fd, buffer + offset, size - offset);
57 
58 #ifdef __WINDOWS__
59  int error = WSAGetLastError();
60 #else
61  int error = errno;
62 #endif // __WINDOWS__
63 
64  if (length < 0) {
65  // TODO(bmahler): Handle a non-blocking fd? (EAGAIN, EWOULDBLOCK)
66  if (net::is_restartable_error(error)) {
67  continue;
68  }
69  ErrnoError error; // Constructed before 'delete' to capture errno.
70  delete[] buffer;
71  return error;
72  } else if (length == 0) {
73  // Reached EOF before expected! Only return as much data as
74  // available or None if we haven't read anything yet.
75  if (offset > 0) {
76  std::string result(buffer, offset);
77  delete[] buffer;
78  return result;
79  }
80  delete[] buffer;
81  return None();
82  }
83 
84  offset += length;
85  }
86 
87  std::string result(buffer, size);
88  delete[] buffer;
89  return result;
90 }
91 
92 
93 // Returns the contents of the file. NOTE: getline is not available on Solaris
94 // or Windows, so we use STL.
95 #if defined(__sun) || defined(__WINDOWS__)
96 inline Try<std::string> read(const std::string& path)
97 {
98  std::ifstream file(path.c_str());
99  if (!file.is_open()) {
100  // Does ifstream actually set errno?
101  return ErrnoError("Failed to open file");
102  }
103  return std::string((std::istreambuf_iterator<char>(file)),
104  (std::istreambuf_iterator<char>()));
105 }
106 #else
107 inline Try<std::string> read(const std::string& path)
108 {
109  FILE* file = ::fopen(path.c_str(), "r");
110  if (file == nullptr) {
111  return ErrnoError();
112  }
113 
114  // Use a buffer to read the file in BUFSIZ
115  // chunks and append it to the string we return.
116  //
117  // NOTE: We aren't able to use fseek() / ftell() here
118  // to find the file size because these functions don't
119  // work properly for in-memory files like /proc/*/stat.
120  char* buffer = new char[BUFSIZ];
121  std::string result;
122 
123  while (true) {
124  size_t read = ::fread(buffer, 1, BUFSIZ, file);
125 
126  if (::ferror(file)) {
127  // NOTE: ferror() will not modify errno if the stream
128  // is valid, which is the case here since it is open.
130  delete[] buffer;
131  ::fclose(file);
132  return error;
133  }
134 
135  result.append(buffer, read);
136 
137  if (read != BUFSIZ) {
138  assert(feof(file));
139  break;
140  }
141  };
142 
143  ::fclose(file);
144  delete[] buffer;
145  return result;
146 }
147 #endif // __sun || __WINDOWS__
148 
149 } // namespace os {
150 
151 #endif // __STOUT_OS_READ_HPP__
SSIZE_T ssize_t
Definition: windows.hpp:192
Try< Bytes > size(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:100
Definition: try.hpp:34
Definition: errorbase.hpp:49
Definition: result.hpp:40
bool is_restartable_error(int error)
Definition: socket.hpp:33
URI file(const std::string &path)
Creates a file URI with the given path on the local host.
Definition: file.hpp:33
Result< std::string > read(int_fd fd, size_t size)
Definition: read.hpp:50
Definition: none.hpp:27
std::string error(const std::string &msg, uint32_t code)
int int_fd
Definition: int_fd.hpp:35