add some tempfile goo to avoid race conditions in cache file creation

git-svn-id: http://google-breakpad.googlecode.com/svn/branches/processor-symbol-cache@406 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
ted.mielczarek 2009-10-01 22:40:28 +00:00
parent b8af9814ba
commit eeae662157
3 changed files with 42 additions and 3 deletions

View File

@ -30,9 +30,13 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <fstream>
#include <ios>
#include <vector>
#include "processor/disk_module_cache.h"
#include "processor/logging.h"
@ -43,10 +47,43 @@ using std::ofstream;
using std::istream;
using std::ifstream;
using std::ios;
using std::vector;
namespace google_breakpad {
// tempofstream writes data to a temporary file in the same
// directory as the file passed to the constructor.
// when closed, it renames the temporary file to the given filename.
class tempofstream : public ofstream
{
public:
tempofstream(const char * filename, ios_base::openmode mode = ios_base::out);
void close();
private:
string tempname_;
string filename_;
};
tempofstream::tempofstream(const char * filename,
ios_base::openmode mode) : tempname_(""),
filename_(filename)
{
string name_template_s = filename_ + "XXXXXX";
vector<char> name_template(name_template_s.length());
std::copy(name_template_s.begin(), name_template_s.end(),
name_template.begin());
tempname_ = mktemp(&name_template[0]);
open(tempname_.c_str(), mode);
}
void tempofstream::close()
{
ofstream::close();
rename(tempname_.c_str(), filename_.c_str());
}
DiskModuleCache::DiskModuleCache(string cache_directory) :
cache_directory_(cache_directory)
{
@ -88,8 +125,8 @@ bool DiskModuleCache::BeginSetModuleData(const string &symbol_file,
if (!EnsurePathExists(cache_file.substr(0, cache_file.rfind('/'))))
return false;
*data_stream = new ofstream(cache_file.c_str(),
ios::out | ios::binary | ios::trunc);
*data_stream = new tempofstream(cache_file.c_str(),
ios::out | ios::binary | ios::trunc);
if (!**data_stream) {
delete *data_stream;
*data_stream = NULL;
@ -101,7 +138,7 @@ bool DiskModuleCache::BeginSetModuleData(const string &symbol_file,
bool DiskModuleCache::EndSetModuleData(const string &symbol_file,
ostream **data_stream)
{
ofstream *file_stream = dynamic_cast<ofstream*>(*data_stream);
tempofstream *file_stream = dynamic_cast<tempofstream*>(*data_stream);
if (!file_stream)
return false;

View File

@ -36,6 +36,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef _WIN32

View File

@ -36,6 +36,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <algorithm>
#include <cassert>
#include "processor/simple_symbol_supplier.h"