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} |
|