516a1d05ab05ed5663085c5b3c19f6ceff4bdba6
2 * Copyright (c) 2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Nathan Binkert
33 #include <sys/types.h>
43 #include <gzstream.hh>
45 #include "base/misc.hh"
46 #include "base/output.hh"
50 OutputDirectory simout
;
53 * @file This file manages creating / deleting output files for the simulator.
55 OutputDirectory::OutputDirectory()
58 OutputDirectory::~OutputDirectory()
60 for (map_t::iterator i
= files
.begin(); i
!= files
.end(); i
++) {
67 OutputDirectory::checkForStdio(const string
&name
) const
69 if (name
== "cerr" || name
== "stderr")
72 if (name
== "cout" || name
== "stdout")
79 OutputDirectory::openFile(const string
&filename
,
80 ios_base::openmode mode
, bool no_gz
)
83 gz
= gz
&& filename
.find(".gz", filename
.length()-3) < filename
.length();
85 ogzstream
*file
= new ogzstream(filename
.c_str(), mode
);
87 fatal("Cannot open file %s", filename
);
88 assert(files
.find(filename
) == files
.end());
89 files
[filename
] = file
;
92 ofstream
*file
= new ofstream(filename
.c_str(), mode
);
94 fatal("Cannot open file %s", filename
);
95 assert(files
.find(filename
) == files
.end());
96 files
[filename
] = file
;
102 OutputDirectory::close(ostream
*openStream
) {
104 for (i
= files
.begin(); i
!= files
.end(); i
++) {
105 if (i
->second
!= openStream
)
108 ofstream
*fs
= dynamic_cast<ofstream
*>(i
->second
);
114 ogzstream
*gfs
= dynamic_cast<ogzstream
*>(i
->second
);
123 if (i
== files
.end())
124 fatal("Attempted to close an unregistred file stream");
130 OutputDirectory::setDirectory(const string
&d
)
133 panic("Output directory already set!\n");
137 // guarantee that directory ends with a path separator
138 if (dir
[dir
.size() - 1] != PATH_SEPARATOR
)
139 dir
+= PATH_SEPARATOR
;
143 OutputDirectory::directory() const
146 panic("Output directory not set!");
152 OutputDirectory::resolve(const string
&name
) const
154 return (name
[0] != PATH_SEPARATOR
) ? dir
+ name
: name
;
158 OutputDirectory::create(const string
&name
, bool binary
, bool no_gz
)
160 ostream
*file
= checkForStdio(name
);
164 string filename
= resolve(name
);
165 ios_base::openmode mode
=
166 ios::trunc
| (binary
? ios::binary
: (ios::openmode
)0);
167 file
= openFile(filename
, mode
, no_gz
);
173 OutputDirectory::find(const string
&name
) const
175 ostream
*file
= checkForStdio(name
);
179 const string filename
= resolve(name
);
180 map_t::const_iterator i
= files
.find(filename
);
181 if (i
!= files
.end())
188 OutputDirectory::isFile(const std::ostream
*os
)
190 return os
&& os
!= &cerr
&& os
!= &cout
;
194 OutputDirectory::isFile(const string
&name
) const
196 // definitely a file if in our data structure
197 if (find(name
) != NULL
) return true;
200 int st
= stat(name
.c_str(), &st_buf
);
201 return (st
== 0) && S_ISREG(st_buf
.st_mode
);
205 OutputDirectory::createSubdirectory(const string
&name
) const
207 const string new_dir
= resolve(name
);
208 if (new_dir
.find(directory()) == string::npos
)
209 fatal("Attempting to create subdirectory not in m5 output dir\n");
211 // if it already exists, that's ok; otherwise, fail if we couldn't create
212 if ((mkdir(new_dir
.c_str(), 0755) != 0) && (errno
!= EEXIST
))
213 fatal("Failed to create new output subdirectory '%s'\n", new_dir
);
215 return name
+ PATH_SEPARATOR
;
219 OutputDirectory::remove(const string
&name
, bool recursive
)
221 const string fname
= resolve(name
);
223 if (fname
.find(directory()) == string::npos
)
224 fatal("Attempting to remove file/dir not in output dir\n");
227 // close and release file if we have it open
228 map_t::iterator itr
= files
.find(fname
);
229 if (itr
!= files
.end()) {
234 if (::remove(fname
.c_str()) != 0)
235 fatal("Could not erase file '%s'\n", fname
);
237 // assume 'name' is a directory
239 DIR *subdir
= opendir(fname
.c_str());
241 // silently ignore removal request for non-existent directory
242 if ((!subdir
) && (errno
== ENOENT
))
245 // fail on other errors
248 fatal("Error opening directory for recursive removal '%s'\n",
252 struct dirent
*de
= readdir(subdir
);
254 // ignore files starting with a '.'; user must delete those
255 // manually if they really want to
256 if (de
->d_name
[0] != '.')
257 remove(name
+ PATH_SEPARATOR
+ de
->d_name
, recursive
);
259 de
= readdir(subdir
);
265 // try to force recognition that we deleted the files in the directory
268 if (::remove(fname
.c_str()) != 0) {
269 perror("Warning! 'remove' failed. Could not erase directory.");