output.cc (8229:78bf55f23338) output.cc (8634:8390f2d80227)
1/*
2 * Copyright (c) 2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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;

--- 12 unchanged lines hidden (view full) ---

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.
27 *
28 * Authors: Nathan Binkert
1/*
2 * Copyright (c) 2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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;

--- 12 unchanged lines hidden (view full) ---

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.
27 *
28 * Authors: Nathan Binkert
29 * Chris Emmons
29 */
30
31#include <sys/stat.h>
32#include <sys/types.h>
30 */
31
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <dirent.h>
33
35
36#include <cassert>
34#include <cerrno>
35#include <climits>
36#include <cstdlib>
37#include <fstream>
38
39#include <gzstream.hh>
40
41#include "base/misc.hh"
42#include "base/output.hh"
43
44using namespace std;
45
46OutputDirectory simout;
47
48/**
37#include <cerrno>
38#include <climits>
39#include <cstdlib>
40#include <fstream>
41
42#include <gzstream.hh>
43
44#include "base/misc.hh"
45#include "base/output.hh"
46
47using namespace std;
48
49OutputDirectory simout;
50
51/**
49 *
52 * @file This file manages creating / deleting output files for the simulator.
50 */
51OutputDirectory::OutputDirectory()
52{}
53
54OutputDirectory::~OutputDirectory()
55{
56 for (map_t::iterator i = files.begin(); i != files.end(); i++) {
57 if (i->second)

--- 10 unchanged lines hidden (view full) ---

68 if (name == "cout" || name == "stdout")
69 return &cout;
70
71 return NULL;
72}
73
74ostream *
75OutputDirectory::openFile(const string &filename,
53 */
54OutputDirectory::OutputDirectory()
55{}
56
57OutputDirectory::~OutputDirectory()
58{
59 for (map_t::iterator i = files.begin(); i != files.end(); i++) {
60 if (i->second)

--- 10 unchanged lines hidden (view full) ---

71 if (name == "cout" || name == "stdout")
72 return &cout;
73
74 return NULL;
75}
76
77ostream *
78OutputDirectory::openFile(const string &filename,
76 ios_base::openmode mode) const
79 ios_base::openmode mode)
77{
78 if (filename.find(".gz", filename.length()-3) < filename.length()) {
79 ogzstream *file = new ogzstream(filename.c_str(), mode);
80{
81 if (filename.find(".gz", filename.length()-3) < filename.length()) {
82 ogzstream *file = new ogzstream(filename.c_str(), mode);
80
81 if (!file->is_open())
82 fatal("Cannot open file %s", filename);
83 if (!file->is_open())
84 fatal("Cannot open file %s", filename);
83
85 assert(files.find(filename) == files.end());
86 files[filename] = file;
84 return file;
85 } else {
86 ofstream *file = new ofstream(filename.c_str(), mode);
87 return file;
88 } else {
89 ofstream *file = new ofstream(filename.c_str(), mode);
87
88 if (!file->is_open())
89 fatal("Cannot open file %s", filename);
90 if (!file->is_open())
91 fatal("Cannot open file %s", filename);
90
92 assert(files.find(filename) == files.end());
93 files[filename] = file;
91 return file;
92 }
93}
94
95void
94 return file;
95 }
96}
97
98void
99OutputDirectory::close(ostream *openStream) {
100 map_t::iterator i;
101 for (i = files.begin(); i != files.end(); i++) {
102 if (i->second != openStream)
103 continue;
104
105 ofstream *fs = dynamic_cast<ofstream*>(i->second);
106 if (fs) {
107 fs->close();
108 delete i->second;
109 break;
110 } else {
111 ogzstream *gfs = dynamic_cast<ogzstream*>(i->second);
112 if (gfs) {
113 gfs->close();
114 delete i->second;
115 break;
116 }
117 }
118 }
119
120 if (i == files.end())
121 fatal("Attempted to close an unregistred file stream");
122
123 files.erase(i);
124}
125
126void
96OutputDirectory::setDirectory(const string &d)
97{
98 if (!dir.empty())
99 panic("Output directory already set!\n");
100
101 dir = d;
102
127OutputDirectory::setDirectory(const string &d)
128{
129 if (!dir.empty())
130 panic("Output directory already set!\n");
131
132 dir = d;
133
103 // guarantee that directory ends with a '/'
104 if (dir[dir.size() - 1] != '/')
105 dir += "/";
134 // guarantee that directory ends with a path separator
135 if (dir[dir.size() - 1] != PATH_SEPARATOR)
136 dir += PATH_SEPARATOR;
106}
107
108const string &
109OutputDirectory::directory() const
110{
111 if (dir.empty())
112 panic("Output directory not set!");
113
114 return dir;
115}
116
117inline string
118OutputDirectory::resolve(const string &name) const
119{
137}
138
139const string &
140OutputDirectory::directory() const
141{
142 if (dir.empty())
143 panic("Output directory not set!");
144
145 return dir;
146}
147
148inline string
149OutputDirectory::resolve(const string &name) const
150{
120 return (name[0] != '/') ? dir + name : name;
151 return (name[0] != PATH_SEPARATOR) ? dir + name : name;
121}
122
123ostream *
124OutputDirectory::create(const string &name, bool binary)
125{
126 ostream *file = checkForStdio(name);
127 if (file)
128 return file;
129
130 string filename = resolve(name);
131 ios_base::openmode mode =
132 ios::trunc | binary ? ios::binary : (ios::openmode)0;
133 file = openFile(filename, mode);
134
135 return file;
136}
137
138ostream *
152}
153
154ostream *
155OutputDirectory::create(const string &name, bool binary)
156{
157 ostream *file = checkForStdio(name);
158 if (file)
159 return file;
160
161 string filename = resolve(name);
162 ios_base::openmode mode =
163 ios::trunc | binary ? ios::binary : (ios::openmode)0;
164 file = openFile(filename, mode);
165
166 return file;
167}
168
169ostream *
139OutputDirectory::find(const string &name)
170OutputDirectory::find(const string &name) const
140{
141 ostream *file = checkForStdio(name);
142 if (file)
143 return file;
144
171{
172 ostream *file = checkForStdio(name);
173 if (file)
174 return file;
175
145 string filename = resolve(name);
146 map_t::iterator i = files.find(filename);
176 const string filename = resolve(name);
177 map_t::const_iterator i = files.find(filename);
147 if (i != files.end())
148 return (*i).second;
149
178 if (i != files.end())
179 return (*i).second;
180
150 file = openFile(filename);
151 files[filename] = file;
152 return file;
181 return NULL;
153}
154
155bool
156OutputDirectory::isFile(const std::ostream *os)
157{
158 return os && os != &cerr && os != &cout;
159}
182}
183
184bool
185OutputDirectory::isFile(const std::ostream *os)
186{
187 return os && os != &cerr && os != &cout;
188}
189
190bool
191OutputDirectory::isFile(const string &name) const
192{
193 // definitely a file if in our data structure
194 if (find(name) != NULL) return true;
195
196 struct stat st_buf;
197 int st = stat(name.c_str(), &st_buf);
198 return (st == 0) && S_ISREG(st_buf.st_mode);
199}
200
201string
202OutputDirectory::createSubdirectory(const string &name) const
203{
204 const string new_dir = resolve(name);
205 if (new_dir.find(directory()) == string::npos)
206 fatal("Attempting to create subdirectory not in m5 output dir\n");
207
208 // if it already exists, that's ok; otherwise, fail if we couldn't create
209 if ((mkdir(new_dir.c_str(), 0755) != 0) && (errno != EEXIST))
210 fatal("Failed to create new output subdirectory '%s'\n", new_dir);
211
212 return name + PATH_SEPARATOR;
213}
214
215void
216OutputDirectory::remove(const string &name, bool recursive)
217{
218 const string fname = resolve(name);
219
220 if (fname.find(directory()) == string::npos)
221 fatal("Attempting to remove file/dir not in output dir\n");
222
223 if (isFile(fname)) {
224 // close and release file if we have it open
225 map_t::iterator itr = files.find(fname);
226 if (itr != files.end()) {
227 delete itr->second;
228 files.erase(itr);
229 }
230
231 if (::remove(fname.c_str()) != 0)
232 fatal("Could not erase file '%s'\n", fname);
233 } else {
234 // assume 'name' is a directory
235 if (recursive) {
236 DIR *dir = opendir(fname.c_str());
237
238 // silently ignore removal request for non-existent directory
239 if ((!dir) && (errno == ENOENT))
240 return;
241
242 // fail on other errors
243 if (!dir) {
244 perror("opendir");
245 fatal("Error opening directory for recursive removal '%s'\n",
246 fname);
247 }
248
249 struct dirent *de = readdir(dir);
250 while (de != NULL) {
251 // ignore files starting with a '.'; user must delete those
252 // manually if they really want to
253 if (de->d_name[0] != '.')
254 remove(name + PATH_SEPARATOR + de->d_name, recursive);
255
256 de = readdir(dir);
257 }
258 }
259
260 // try to force recognition that we deleted the files in the directory
261 sync();
262
263 if (::remove(fname.c_str()) != 0) {
264 perror("Warning! 'remove' failed. Could not erase directory.");
265 }
266 }
267}