fd_array.cc (11856:103e2f92c965) fd_array.cc (11886:43b882cada33)
1/*
2 * Copyright (c) 2016 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * For use for simulation and test purposes only
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Author: Brandon Potter
34 */
35
36#include "sim/fd_array.hh"
37
38#include <fcntl.h>
39#include <unistd.h>
40
41#include <array>
42#include <memory>
43#include <string>
44
45#include "base/misc.hh"
46#include "params/Process.hh"
47#include "sim/fd_entry.hh"
48
49FDArray::FDArray(std::string const& input, std::string const& output,
50 std::string const& errout)
51 : _input(input), _output(output), _errout(errout), _fdArray(),
52 imap {{"", -1},
53 {"cin", STDIN_FILENO},
54 {"stdin", STDIN_FILENO}},
55 oemap{{"", -1},
56 {"cout", STDOUT_FILENO},
57 {"stdout", STDOUT_FILENO},
58 {"cerr", STDERR_FILENO},
59 {"stderr", STDERR_FILENO}}
60{
61 int sim_fd;
62 std::map<std::string, int>::iterator it;
63
64 /**
65 * Search through the input options and setup the default fd if match is
66 * found; otherwise, open an input file and seek to location.
67 */
68 if ((it = imap.find(input)) != imap.end())
69 sim_fd = it->second;
70 else
71 sim_fd = openInputFile(input);
72
73 auto ffd = std::make_shared<FileFDEntry>(sim_fd, O_RDONLY, input, false);
74 _fdArray[STDIN_FILENO] = ffd;
75
76 /**
77 * Search through the output/error options and setup the default fd if
78 * match is found; otherwise, open an output file and seek to location.
79 */
80 if ((it = oemap.find(output)) != oemap.end())
81 sim_fd = it->second;
82 else
83 sim_fd = openOutputFile(output);
84
85 ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
86 output, false);
87 _fdArray[STDOUT_FILENO] = ffd;
88
89 if (output == errout)
90 ; /* Reuse the same file descriptor if these match. */
91 else if ((it = oemap.find(errout)) != oemap.end())
92 sim_fd = it->second;
93 else
94 sim_fd = openOutputFile(errout);
95
96 ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
97 errout, false);
98 _fdArray[STDERR_FILENO] = ffd;
99}
100
101void
102FDArray::updateFileOffsets()
103{
104 for (auto& fdp : _fdArray) {
105 /**
106 * It only makes sense to check the offsets if the file descriptor
107 * type is 'File' (which indicates that this file is backed by a
108 * file on the host). If the type is File, then record the offset.
109 */
110 auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp);
111
112 if (!ffd)
113 continue;
114
115 /**
116 * Use lseek with SEEK_CUR with offset 0 to figure out where the
117 * offset currently resides and pass that back to our setter.
118 */
119 int sim_fd = ffd->getSimFD();
120 ffd->setFileOffset(lseek(sim_fd, 0, SEEK_CUR));
121 }
122}
123
124void
125FDArray::restoreFileOffsets()
126{
127 /**
128 * Use this lambda to highlight what we mean to do with the seek.
129 * Notice that this either seeks correctly (sets the file location on the
130 * host) or it fails with a fatal. The error is fatal because it's not
131 * possible to guarantee that the simulation will proceed as it should
132 * have in the same way that it would have proceeded sans checkpoints.
133 */
134 void (*seek)(std::shared_ptr<FileFDEntry>)
135 = [] (std::shared_ptr<FileFDEntry> ffd)
136 {
137 if (lseek(ffd->getSimFD(), ffd->getFileOffset(), SEEK_SET) < 0)
138 fatal("Unable to seek to location in %s", ffd->getFileName());
139 };
140
141 std::map<std::string, int>::iterator it;
142
143 /**
144 * Search through the input options and set fd if match is found;
145 * otherwise, open an input file and seek to location.
146 * Check if user has specified a different input file, and if so, use it
147 * instead of the file specified in the checkpoint. This also resets the
148 * file offset from the checkpointed value
149 */
150 std::shared_ptr<FDEntry> stdin_fde = _fdArray[STDIN_FILENO];
151 auto stdin_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdin_fde);
152
153 if (_input != stdin_ffd->getFileName()) {
154 warn("Using new input file (%s) rather than checkpointed (%s)\n",
155 _input, stdin_ffd->getFileName());
156 stdin_ffd->setFileName(_input);
157 stdin_ffd->setFileOffset(0);
158 }
159
160 if ((it = imap.find(stdin_ffd->getFileName())) != imap.end()) {
161 stdin_ffd->setSimFD(it->second);
162 } else {
163 stdin_ffd->setSimFD(openInputFile(stdin_ffd->getFileName()));
164 seek(stdin_ffd);
165 }
166
167 /**
168 * Search through the output options and set fd if match is found;
169 * otherwise, open an output file and seek to location.
170 * Check if user has specified a different output file, and if so, use it
171 * instead of the file specified in the checkpoint. This also resets the
172 * file offset from the checkpointed value
173 */
174 std::shared_ptr<FDEntry> stdout_fde = _fdArray[STDOUT_FILENO];
175 auto stdout_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdout_fde);
176
177 if (_output != stdout_ffd->getFileName()) {
178 warn("Using new output file (%s) rather than checkpointed (%s)\n",
179 _output, stdout_ffd->getFileName());
180 stdout_ffd->setFileName(_output);
181 stdout_ffd->setFileOffset(0);
182 }
183
184 if ((it = oemap.find(stdout_ffd->getFileName())) != oemap.end()) {
185 stdout_ffd->setSimFD(it->second);
186 } else {
187 stdout_ffd->setSimFD(openOutputFile(stdout_ffd->getFileName()));
188 seek(stdout_ffd);
189 }
190
191 /**
192 * Search through the error options and set fd if match is found;
193 * otherwise, open an error file and seek to location.
194 * Check if user has specified a different error file, and if so, use it
195 * instead of the file specified in the checkpoint. This also resets the
196 * file offset from the checkpointed value
197 */
198 std::shared_ptr<FDEntry> stderr_fde = _fdArray[STDERR_FILENO];
199 auto stderr_ffd = std::dynamic_pointer_cast<FileFDEntry>(stderr_fde);
200
201 if (_errout != stderr_ffd->getFileName()) {
202 warn("Using new error file (%s) rather than checkpointed (%s)\n",
203 _errout, stderr_ffd->getFileName());
204 stderr_ffd->setFileName(_errout);
205 stderr_ffd->setFileOffset(0);
206 }
207
208 if (stdout_ffd->getFileName() == stderr_ffd->getFileName()) {
209 /* Reuse the same sim_fd file descriptor if these match. */
210 stderr_ffd->setSimFD(stdout_ffd->getSimFD());
211 } else if ((it = oemap.find(stderr_ffd->getFileName())) != oemap.end()) {
212 stderr_ffd->setSimFD(it->second);
213 } else {
214 stderr_ffd->setSimFD(openOutputFile(stderr_ffd->getFileName()));
215 seek(stderr_ffd);
216 }
217
218 for (int tgt_fd = 3; tgt_fd < _fdArray.size(); tgt_fd++) {
219 std::shared_ptr<FDEntry> fdp = _fdArray[tgt_fd];
220 if (!fdp)
221 continue;
222
223 /* Need to reconnect pipe ends. */
224 if (auto pfd = std::dynamic_pointer_cast<PipeFDEntry>(fdp)) {
225 /**
226 * Check which end of the pipe we are looking at; we only want
227 * to setup the pipe once so we arbitrarily choose the read
228 * end to be the end that sets up the pipe.
229 */
230 if (pfd->getEndType() == PipeFDEntry::EndType::write)
231 continue;
232
233 /* Setup the pipe or fatal out of the simulation. */
234 int fd_pair[2];
235 if (pipe(fd_pair) < 0)
236 fatal("Unable to create new pipe");
237
238 /**
239 * Reconstruct the ends of the pipe by reassigning the pipe
240 * that we created on the host. This one is the read end.
241 */
242 pfd->setSimFD(fd_pair[0]);
243
244 /**
245 * Grab the write end by referencing the read ends source and
246 * using that tgt_fd to index the array.
247 */
248 int prs = pfd->getPipeReadSource();
249 std::shared_ptr<FDEntry> write_fdp = _fdArray[prs];
250
251 /* Now cast it and make sure that we are still sane. */
252 auto write_pfd = std::dynamic_pointer_cast<PipeFDEntry>(write_fdp);
253
254 /* Hook up the write end back to the right side of the pipe. */
255 write_pfd->setSimFD(fd_pair[1]);
256 }
257
258 /* Need to reassign 'driver'. */
259 if (auto dfd = std::dynamic_pointer_cast<DeviceFDEntry>(fdp)) {
260 /**
261 * Yeah, how does one retain the entire driver state from this
262 * particular set of code? If you figure it out, add some code
263 * here to rectify the issue.
264 */
265 fatal("Unable to restore checkpoints with emulated drivers");
266 }
267
268 /* Need to open files and seek. */
269 if (auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp)) {
270 /**
271 * Assume that this has the mode of an output file so there's no
272 * need to worry about properly recording the mode. If you're
273 * reading this and this happens to be your issue, at least be
274 * happy that you've discovered the issue (and not mad at me).
275 * Onward ho!
276 */
277 int sim_fd = openFile(ffd->getFileName(), ffd->getFlags(), 0664);
278 ffd->setSimFD(sim_fd);
279 seek(ffd);
280 }
281 }
282}
283
284int
285FDArray::allocFD(std::shared_ptr<FDEntry> in)
286{
287 for (int i = 0; i < _fdArray.size(); i++) {
288 std::shared_ptr<FDEntry> fdp = _fdArray[i];
289 if (!fdp) {
290 _fdArray[i] = in;
291 return i;
292 }
293 }
294 fatal("Out of target file descriptors");
295}
296
297int
298FDArray::openFile(std::string const& filename, int flags, mode_t mode) const
299{
300 int sim_fd = open(filename.c_str(), flags, mode);
301 if (sim_fd != -1)
302 return sim_fd;
303 fatal("Unable to open %s with mode %O", filename, mode);
304}
305
306int
307FDArray::openInputFile(std::string const& filename) const
308{
309 return openFile(filename, O_RDONLY, 00);
310}
311
312int
313FDArray::openOutputFile(std::string const& filename) const
314{
315 return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
316}
317
318std::shared_ptr<FDEntry>
319FDArray::getFDEntry(int tgt_fd)
320{
321 assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
322 return _fdArray[tgt_fd];
323}
324
1/*
2 * Copyright (c) 2016 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * For use for simulation and test purposes only
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Author: Brandon Potter
34 */
35
36#include "sim/fd_array.hh"
37
38#include <fcntl.h>
39#include <unistd.h>
40
41#include <array>
42#include <memory>
43#include <string>
44
45#include "base/misc.hh"
46#include "params/Process.hh"
47#include "sim/fd_entry.hh"
48
49FDArray::FDArray(std::string const& input, std::string const& output,
50 std::string const& errout)
51 : _input(input), _output(output), _errout(errout), _fdArray(),
52 imap {{"", -1},
53 {"cin", STDIN_FILENO},
54 {"stdin", STDIN_FILENO}},
55 oemap{{"", -1},
56 {"cout", STDOUT_FILENO},
57 {"stdout", STDOUT_FILENO},
58 {"cerr", STDERR_FILENO},
59 {"stderr", STDERR_FILENO}}
60{
61 int sim_fd;
62 std::map<std::string, int>::iterator it;
63
64 /**
65 * Search through the input options and setup the default fd if match is
66 * found; otherwise, open an input file and seek to location.
67 */
68 if ((it = imap.find(input)) != imap.end())
69 sim_fd = it->second;
70 else
71 sim_fd = openInputFile(input);
72
73 auto ffd = std::make_shared<FileFDEntry>(sim_fd, O_RDONLY, input, false);
74 _fdArray[STDIN_FILENO] = ffd;
75
76 /**
77 * Search through the output/error options and setup the default fd if
78 * match is found; otherwise, open an output file and seek to location.
79 */
80 if ((it = oemap.find(output)) != oemap.end())
81 sim_fd = it->second;
82 else
83 sim_fd = openOutputFile(output);
84
85 ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
86 output, false);
87 _fdArray[STDOUT_FILENO] = ffd;
88
89 if (output == errout)
90 ; /* Reuse the same file descriptor if these match. */
91 else if ((it = oemap.find(errout)) != oemap.end())
92 sim_fd = it->second;
93 else
94 sim_fd = openOutputFile(errout);
95
96 ffd = std::make_shared<FileFDEntry>(sim_fd, O_WRONLY | O_CREAT | O_TRUNC,
97 errout, false);
98 _fdArray[STDERR_FILENO] = ffd;
99}
100
101void
102FDArray::updateFileOffsets()
103{
104 for (auto& fdp : _fdArray) {
105 /**
106 * It only makes sense to check the offsets if the file descriptor
107 * type is 'File' (which indicates that this file is backed by a
108 * file on the host). If the type is File, then record the offset.
109 */
110 auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp);
111
112 if (!ffd)
113 continue;
114
115 /**
116 * Use lseek with SEEK_CUR with offset 0 to figure out where the
117 * offset currently resides and pass that back to our setter.
118 */
119 int sim_fd = ffd->getSimFD();
120 ffd->setFileOffset(lseek(sim_fd, 0, SEEK_CUR));
121 }
122}
123
124void
125FDArray::restoreFileOffsets()
126{
127 /**
128 * Use this lambda to highlight what we mean to do with the seek.
129 * Notice that this either seeks correctly (sets the file location on the
130 * host) or it fails with a fatal. The error is fatal because it's not
131 * possible to guarantee that the simulation will proceed as it should
132 * have in the same way that it would have proceeded sans checkpoints.
133 */
134 void (*seek)(std::shared_ptr<FileFDEntry>)
135 = [] (std::shared_ptr<FileFDEntry> ffd)
136 {
137 if (lseek(ffd->getSimFD(), ffd->getFileOffset(), SEEK_SET) < 0)
138 fatal("Unable to seek to location in %s", ffd->getFileName());
139 };
140
141 std::map<std::string, int>::iterator it;
142
143 /**
144 * Search through the input options and set fd if match is found;
145 * otherwise, open an input file and seek to location.
146 * Check if user has specified a different input file, and if so, use it
147 * instead of the file specified in the checkpoint. This also resets the
148 * file offset from the checkpointed value
149 */
150 std::shared_ptr<FDEntry> stdin_fde = _fdArray[STDIN_FILENO];
151 auto stdin_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdin_fde);
152
153 if (_input != stdin_ffd->getFileName()) {
154 warn("Using new input file (%s) rather than checkpointed (%s)\n",
155 _input, stdin_ffd->getFileName());
156 stdin_ffd->setFileName(_input);
157 stdin_ffd->setFileOffset(0);
158 }
159
160 if ((it = imap.find(stdin_ffd->getFileName())) != imap.end()) {
161 stdin_ffd->setSimFD(it->second);
162 } else {
163 stdin_ffd->setSimFD(openInputFile(stdin_ffd->getFileName()));
164 seek(stdin_ffd);
165 }
166
167 /**
168 * Search through the output options and set fd if match is found;
169 * otherwise, open an output file and seek to location.
170 * Check if user has specified a different output file, and if so, use it
171 * instead of the file specified in the checkpoint. This also resets the
172 * file offset from the checkpointed value
173 */
174 std::shared_ptr<FDEntry> stdout_fde = _fdArray[STDOUT_FILENO];
175 auto stdout_ffd = std::dynamic_pointer_cast<FileFDEntry>(stdout_fde);
176
177 if (_output != stdout_ffd->getFileName()) {
178 warn("Using new output file (%s) rather than checkpointed (%s)\n",
179 _output, stdout_ffd->getFileName());
180 stdout_ffd->setFileName(_output);
181 stdout_ffd->setFileOffset(0);
182 }
183
184 if ((it = oemap.find(stdout_ffd->getFileName())) != oemap.end()) {
185 stdout_ffd->setSimFD(it->second);
186 } else {
187 stdout_ffd->setSimFD(openOutputFile(stdout_ffd->getFileName()));
188 seek(stdout_ffd);
189 }
190
191 /**
192 * Search through the error options and set fd if match is found;
193 * otherwise, open an error file and seek to location.
194 * Check if user has specified a different error file, and if so, use it
195 * instead of the file specified in the checkpoint. This also resets the
196 * file offset from the checkpointed value
197 */
198 std::shared_ptr<FDEntry> stderr_fde = _fdArray[STDERR_FILENO];
199 auto stderr_ffd = std::dynamic_pointer_cast<FileFDEntry>(stderr_fde);
200
201 if (_errout != stderr_ffd->getFileName()) {
202 warn("Using new error file (%s) rather than checkpointed (%s)\n",
203 _errout, stderr_ffd->getFileName());
204 stderr_ffd->setFileName(_errout);
205 stderr_ffd->setFileOffset(0);
206 }
207
208 if (stdout_ffd->getFileName() == stderr_ffd->getFileName()) {
209 /* Reuse the same sim_fd file descriptor if these match. */
210 stderr_ffd->setSimFD(stdout_ffd->getSimFD());
211 } else if ((it = oemap.find(stderr_ffd->getFileName())) != oemap.end()) {
212 stderr_ffd->setSimFD(it->second);
213 } else {
214 stderr_ffd->setSimFD(openOutputFile(stderr_ffd->getFileName()));
215 seek(stderr_ffd);
216 }
217
218 for (int tgt_fd = 3; tgt_fd < _fdArray.size(); tgt_fd++) {
219 std::shared_ptr<FDEntry> fdp = _fdArray[tgt_fd];
220 if (!fdp)
221 continue;
222
223 /* Need to reconnect pipe ends. */
224 if (auto pfd = std::dynamic_pointer_cast<PipeFDEntry>(fdp)) {
225 /**
226 * Check which end of the pipe we are looking at; we only want
227 * to setup the pipe once so we arbitrarily choose the read
228 * end to be the end that sets up the pipe.
229 */
230 if (pfd->getEndType() == PipeFDEntry::EndType::write)
231 continue;
232
233 /* Setup the pipe or fatal out of the simulation. */
234 int fd_pair[2];
235 if (pipe(fd_pair) < 0)
236 fatal("Unable to create new pipe");
237
238 /**
239 * Reconstruct the ends of the pipe by reassigning the pipe
240 * that we created on the host. This one is the read end.
241 */
242 pfd->setSimFD(fd_pair[0]);
243
244 /**
245 * Grab the write end by referencing the read ends source and
246 * using that tgt_fd to index the array.
247 */
248 int prs = pfd->getPipeReadSource();
249 std::shared_ptr<FDEntry> write_fdp = _fdArray[prs];
250
251 /* Now cast it and make sure that we are still sane. */
252 auto write_pfd = std::dynamic_pointer_cast<PipeFDEntry>(write_fdp);
253
254 /* Hook up the write end back to the right side of the pipe. */
255 write_pfd->setSimFD(fd_pair[1]);
256 }
257
258 /* Need to reassign 'driver'. */
259 if (auto dfd = std::dynamic_pointer_cast<DeviceFDEntry>(fdp)) {
260 /**
261 * Yeah, how does one retain the entire driver state from this
262 * particular set of code? If you figure it out, add some code
263 * here to rectify the issue.
264 */
265 fatal("Unable to restore checkpoints with emulated drivers");
266 }
267
268 /* Need to open files and seek. */
269 if (auto ffd = std::dynamic_pointer_cast<FileFDEntry>(fdp)) {
270 /**
271 * Assume that this has the mode of an output file so there's no
272 * need to worry about properly recording the mode. If you're
273 * reading this and this happens to be your issue, at least be
274 * happy that you've discovered the issue (and not mad at me).
275 * Onward ho!
276 */
277 int sim_fd = openFile(ffd->getFileName(), ffd->getFlags(), 0664);
278 ffd->setSimFD(sim_fd);
279 seek(ffd);
280 }
281 }
282}
283
284int
285FDArray::allocFD(std::shared_ptr<FDEntry> in)
286{
287 for (int i = 0; i < _fdArray.size(); i++) {
288 std::shared_ptr<FDEntry> fdp = _fdArray[i];
289 if (!fdp) {
290 _fdArray[i] = in;
291 return i;
292 }
293 }
294 fatal("Out of target file descriptors");
295}
296
297int
298FDArray::openFile(std::string const& filename, int flags, mode_t mode) const
299{
300 int sim_fd = open(filename.c_str(), flags, mode);
301 if (sim_fd != -1)
302 return sim_fd;
303 fatal("Unable to open %s with mode %O", filename, mode);
304}
305
306int
307FDArray::openInputFile(std::string const& filename) const
308{
309 return openFile(filename, O_RDONLY, 00);
310}
311
312int
313FDArray::openOutputFile(std::string const& filename) const
314{
315 return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
316}
317
318std::shared_ptr<FDEntry>
319FDArray::getFDEntry(int tgt_fd)
320{
321 assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
322 return _fdArray[tgt_fd];
323}
324
325void
326FDArray::setFDEntry(int tgt_fd, std::shared_ptr<FDEntry> fdep)
327{
328 assert(0 <= tgt_fd && tgt_fd < _fdArray.size());
329 _fdArray[tgt_fd] = fdep;
330}
331
325int
326FDArray::closeFDEntry(int tgt_fd)
327{
328 if (tgt_fd >= _fdArray.size() || tgt_fd < 0)
329 return -EBADF;
330
331 int sim_fd = -1;
332 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>(_fdArray[tgt_fd]);
333 if (hbfdp)
334 sim_fd = hbfdp->getSimFD();
335
336 int status = 0;
337 if (sim_fd > 2)
338 status = close(sim_fd);
339
340 if (status == 0)
341 _fdArray[tgt_fd] = nullptr;
342
343 return status;
344}
332int
333FDArray::closeFDEntry(int tgt_fd)
334{
335 if (tgt_fd >= _fdArray.size() || tgt_fd < 0)
336 return -EBADF;
337
338 int sim_fd = -1;
339 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>(_fdArray[tgt_fd]);
340 if (hbfdp)
341 sim_fd = hbfdp->getSimFD();
342
343 int status = 0;
344 if (sim_fd > 2)
345 status = close(sim_fd);
346
347 if (status == 0)
348 _fdArray[tgt_fd] = nullptr;
349
350 return status;
351}