OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/important_file_writer.h" | 5 #include "chrome/common/important_file_writer.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 18 matching lines...) Expand all Loading... | |
29 : path_(path), | 29 : path_(path), |
30 data_(data) { | 30 data_(data) { |
31 } | 31 } |
32 | 32 |
33 virtual void Run() { | 33 virtual void Run() { |
34 // Write the data to a temp file then rename to avoid data loss if we crash | 34 // Write the data to a temp file then rename to avoid data loss if we crash |
35 // while writing the file. Ensure that the temp file is on the same volume | 35 // while writing the file. Ensure that the temp file is on the same volume |
36 // as target file, so it can be moved in one step, and that the temp file | 36 // as target file, so it can be moved in one step, and that the temp file |
37 // is securely created. | 37 // is securely created. |
38 FilePath tmp_file_path; | 38 FilePath tmp_file_path; |
39 FILE* tmp_file = file_util::CreateAndOpenTemporaryFileInDir( | 39 if (!file_util::CreateTemporaryFileInDir(path_.DirName(), &tmp_file_path)) { |
40 path_.DirName(), &tmp_file_path); | |
41 if (!tmp_file) { | |
42 LogFailure("could not create temporary file"); | 40 LogFailure("could not create temporary file"); |
43 return; | 41 return; |
44 } | 42 } |
45 | 43 |
46 size_t bytes_written = fwrite(data_.data(), 1, data_.length(), tmp_file); | 44 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE; |
47 if (!file_util::CloseFile(tmp_file)) { | 45 base::PlatformFile tmp_file = |
46 base::CreatePlatformFile(tmp_file_path, flags, NULL, NULL); | |
Scott Hess - ex-Googler
2011/08/23 00:54:38
I would prefer if you could not introduce a race c
rvargas (doing something else)
2011/08/23 01:41:52
I was writing the code with some posix specific ve
Scott Hess - ex-Googler
2011/08/23 19:23:57
The rename case is a very good point! I won't dig
| |
47 if (tmp_file == base::kInvalidPlatformFileValue) { | |
48 LogFailure("could not open temporary file"); | |
49 return; | |
50 } | |
51 | |
52 CHECK_LE(data_.length(), static_cast<size_t>(kint32max)); | |
53 int bytes_written = base::WritePlatformFile( | |
54 tmp_file, 0, data_.data(), static_cast<int>(data_.length())); | |
Scott Hess - ex-Googler
2011/08/23 19:27:17
BTW ... AFAICT the POSIX version of this function
rvargas (doing something else)
2011/08/23 23:36:58
In that case, line 63 should detect the error and
| |
55 base::FlushPlatformFile(tmp_file); // Ignore return value. | |
Scott Hess - ex-Googler
2011/08/23 00:54:38
Would it be reasonable to wire up something like f
rvargas (doing something else)
2011/08/23 01:41:52
Not sure. I can make fflush do the right thing on
Scott Hess - ex-Googler
2011/08/23 19:23:57
OK, that's all I wanted to hear - I hate having mu
| |
56 | |
57 if (!base::ClosePlatformFile(tmp_file)) { | |
48 LogFailure("failed to close temporary file"); | 58 LogFailure("failed to close temporary file"); |
49 file_util::Delete(tmp_file_path, false); | 59 file_util::Delete(tmp_file_path, false); |
50 return; | 60 return; |
51 } | 61 } |
52 if (bytes_written < data_.length()) { | 62 |
63 if (bytes_written < static_cast<int>(data_.length())) { | |
53 LogFailure("error writing, bytes_written=" + | 64 LogFailure("error writing, bytes_written=" + |
54 base::Uint64ToString(bytes_written)); | 65 base::IntToString(bytes_written)); |
55 file_util::Delete(tmp_file_path, false); | 66 file_util::Delete(tmp_file_path, false); |
56 return; | 67 return; |
57 } | 68 } |
58 | 69 |
59 if (!file_util::ReplaceFile(tmp_file_path, path_)) { | 70 if (!file_util::ReplaceFile(tmp_file_path, path_)) { |
60 LogFailure("could not rename temporary file"); | 71 LogFailure("could not rename temporary file"); |
61 file_util::Delete(tmp_file_path, false); | 72 file_util::Delete(tmp_file_path, false); |
62 return; | 73 return; |
63 } | 74 } |
64 } | 75 } |
(...skipping 30 matching lines...) Expand all Loading... | |
95 DCHECK(!HasPendingWrite()); | 106 DCHECK(!HasPendingWrite()); |
96 } | 107 } |
97 | 108 |
98 bool ImportantFileWriter::HasPendingWrite() const { | 109 bool ImportantFileWriter::HasPendingWrite() const { |
99 DCHECK(CalledOnValidThread()); | 110 DCHECK(CalledOnValidThread()); |
100 return timer_.IsRunning(); | 111 return timer_.IsRunning(); |
101 } | 112 } |
102 | 113 |
103 void ImportantFileWriter::WriteNow(const std::string& data) { | 114 void ImportantFileWriter::WriteNow(const std::string& data) { |
104 DCHECK(CalledOnValidThread()); | 115 DCHECK(CalledOnValidThread()); |
116 if (data.length() > static_cast<size_t>(kint32max)) { | |
117 NOTREACHED(); | |
118 return; | |
119 } | |
105 | 120 |
106 if (HasPendingWrite()) | 121 if (HasPendingWrite()) |
107 timer_.Stop(); | 122 timer_.Stop(); |
108 | 123 |
109 if (!file_message_loop_proxy_->PostTask( | 124 if (!file_message_loop_proxy_->PostTask( |
110 FROM_HERE, new WriteToDiskTask(path_, data))) { | 125 FROM_HERE, new WriteToDiskTask(path_, data))) { |
111 // Posting the task to background message loop is not expected | 126 // Posting the task to background message loop is not expected |
112 // to fail, but if it does, avoid losing data and just hit the disk | 127 // to fail, but if it does, avoid losing data and just hit the disk |
113 // on the current thread. | 128 // on the current thread. |
114 NOTREACHED(); | 129 NOTREACHED(); |
(...skipping 25 matching lines...) Expand all Loading... | |
140 DCHECK(serializer_); | 155 DCHECK(serializer_); |
141 std::string data; | 156 std::string data; |
142 if (serializer_->SerializeData(&data)) { | 157 if (serializer_->SerializeData(&data)) { |
143 WriteNow(data); | 158 WriteNow(data); |
144 } else { | 159 } else { |
145 LOG(WARNING) << "failed to serialize data to be saved in " | 160 LOG(WARNING) << "failed to serialize data to be saved in " |
146 << path_.value(); | 161 << path_.value(); |
147 } | 162 } |
148 serializer_ = NULL; | 163 serializer_ = NULL; |
149 } | 164 } |
OLD | NEW |