Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: chrome/utility/image_writer/image_writer.cc

Issue 61643015: Adds imageWriterPrivate support for Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes comment. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this image code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/platform_file.h"
6 #include "chrome/utility/image_writer/error_messages.h"
7 #include "chrome/utility/image_writer/image_writer.h"
8 #include "chrome/utility/image_writer/image_writer_handler.h"
9 #include "content/public/utility/utility_thread.h"
10
11 namespace chrome {
12 namespace image_writer {
13
14 // Since block devices like large sequential access and IPC is expensive we're
15 // doing work in 1MB chunks.
16 const int kBurningBlockSize = 1 << 20;
17
18 ImageWriter::ImageWriter(ImageWriterHandler* handler)
19 : image_file_(base::kInvalidPlatformFileValue),
20 device_file_(base::kInvalidPlatformFileValue),
21 bytes_processed_(0),
22 handler_(handler) {}
23
24 ImageWriter::~ImageWriter() { CleanUp(); }
25
26 void ImageWriter::Write(const base::FilePath& image_path,
27 const base::FilePath& device_path) {
28 if (IsRunning()) {
29 handler_->SendFailed(error::kOperationAlreadyInProgress);
30 return;
31 }
32
33 image_path_ = image_path;
34 device_path_ = device_path;
35 bytes_processed_ = 0;
36
37 base::PlatformFileError error;
38
39 image_file_ = base::CreatePlatformFile(
40 image_path_,
41 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
42 NULL,
43 &error);
44
45 if (error != base::PLATFORM_FILE_OK) {
46 DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
47 Error(error::kOpenImage);
48 return;
49 }
50
51 #if defined(OS_WIN)
52 // Windows requires that device files be opened with FILE_FLAG_NO_BUFFERING
53 // and FILE_FLAG_WRITE_THROUGH. These two flags are not part of
54 // PlatformFile::CreatePlatformFile.
55 device_file_ = CreateFile(device_path.value().c_str(),
56 GENERIC_WRITE,
57 FILE_SHARE_WRITE,
58 NULL,
59 OPEN_EXISTING,
60 FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
61 INVALID_HANDLE_VALUE);
62
63 if (device_file_ == base::kInvalidPlatformFileValue) {
64 Error(error::kOpenDevice);
65 return;
66 }
67 #else
68 device_file_ = base::CreatePlatformFile(
69 device_path_,
70 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
71 NULL,
72 &error);
73
74 if (error != base::PLATFORM_FILE_OK) {
75 DLOG(ERROR) << "Unable to open file for write(" << error
76 << "): " << device_path_.value();
77 Error(error::kOpenDevice);
78 return;
79 }
80 #endif
81
82 PostProgress(0);
83
84 PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr()));
85 }
86
87 void ImageWriter::Verify(const base::FilePath& image_path,
88 const base::FilePath& device_path) {
89 if (IsRunning()) {
90 handler_->SendFailed(error::kOperationAlreadyInProgress);
91 return;
92 }
93
94 image_path_ = image_path;
95 device_path_ = device_path;
96 bytes_processed_ = 0;
97
98 base::PlatformFileError error;
99
100 image_file_ = base::CreatePlatformFile(
101 image_path_,
102 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
103 NULL,
104 &error);
105
106 if (error != base::PLATFORM_FILE_OK) {
107 DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
108 Error(error::kOpenImage);
109 return;
110 }
111
112 device_file_ = base::CreatePlatformFile(
113 device_path_,
114 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
115 NULL,
116 &error);
117
118 if (error != base::PLATFORM_FILE_OK) {
119 DLOG(ERROR) << "Unable to open file for read: " << device_path_.value();
120 Error(error::kOpenDevice);
121 return;
122 }
123
124 PostProgress(0);
125
126 PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr()));
127 }
128
129 void ImageWriter::Cancel() {
130 CleanUp();
131 handler_->SendCancelled();
132 }
133
134 bool ImageWriter::IsRunning() {
Lei Zhang 2014/02/15 00:49:16 nit: const method
Drew Haven 2014/02/15 01:23:58 Done.
135 return image_file_ != base::kInvalidPlatformFileValue ||
136 device_file_ != base::kInvalidPlatformFileValue;
137 }
138
139 void ImageWriter::PostTask(const base::Closure& task) {
140 base::MessageLoop::current()->PostTask(FROM_HERE, task);
141 }
142
143 void ImageWriter::PostProgress(int64 progress) {
144 handler_->SendProgress(progress);
145 }
146
147 void ImageWriter::Error(const std::string& message) {
148 CleanUp();
149 handler_->SendFailed(message);
150 }
151
152 void ImageWriter::WriteChunk() {
153 if (!IsRunning()) {
154 return;
155 }
156
157 scoped_ptr<char[]> buffer(new char[kBurningBlockSize]);
158 base::PlatformFileInfo info;
159
160 int bytes_read = base::ReadPlatformFile(
161 image_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
162
163 if (bytes_read > 0) {
164 // Always attempt to write a whole block, as Windows requires 512-byte
165 // aligned writes to devices.
166 int bytes_written = base::WritePlatformFile(
167 device_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
168
169 if (bytes_written < bytes_read) {
170 Error(error::kWriteImage);
171 return;
172 }
173
174 bytes_processed_ += bytes_read;
Lei Zhang 2014/02/15 00:49:16 Presumably it's ok to share |bytes_processed_| bet
Drew Haven 2014/02/15 01:23:58 Correct. Since the PlatformFiles are ultimately th
175 PostProgress(bytes_processed_);
176
177 PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr()));
178 } else if (bytes_read == 0) {
179 // End of file.
180 base::FlushPlatformFile(device_file_);
181 CleanUp();
182 handler_->SendSucceeded();
183 } else {
184 // Unable to read entire file.
185 Error(error::kReadImage);
186 }
187 }
188
189 void ImageWriter::VerifyChunk() {
190 if (!IsRunning()) {
191 return;
192 }
193
194 scoped_ptr<char[]> image_buffer(new char[kBurningBlockSize]);
195 scoped_ptr<char[]> device_buffer(new char[kBurningBlockSize]);
196 base::PlatformFileInfo info;
197 int image_size;
198
199 if (base::GetPlatformFileInfo(image_file_, &info)) {
200 image_size = info.size;
201 } else {
202 Error(error::kReadImage);
Lei Zhang 2014/02/15 00:49:16 do you want to return in this case?
Drew Haven 2014/02/15 01:23:58 Actually, I'm going to remove this because I shoul
203 }
204
205 int bytes_read = base::ReadPlatformFile(
206 image_file_, bytes_processed_, image_buffer.get(), kBurningBlockSize);
207
208 if (bytes_read > 0) {
209 if (base::ReadPlatformFile(device_file_,
210 bytes_processed_,
211 device_buffer.get(),
212 kBurningBlockSize) < 0) {
213 LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of "
214 << "device at offset " << bytes_processed_;
215 Error(error::kReadDevice);
216 return;
217 }
218
219 if (memcmp(image_buffer.get(), device_buffer.get(), bytes_read) != 0) {
220 LOG(ERROR) << "Write verification failed when comparing " << bytes_read
221 << " bytes at " << bytes_processed_;
222 Error(error::kVerificationFailed);
223 return;
224 }
225
226 bytes_processed_ += bytes_read;
227 PostProgress(bytes_processed_);
228
229 PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr()));
230 } else if (bytes_read == 0 && bytes_processed_ == image_size) {
231 // End of file.
232 CleanUp();
233 handler_->SendSucceeded();
234 } else {
235 // Unable to read entire file.
236 LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of image "
237 << "at offset " << bytes_processed_;
238 Error(error::kReadImage);
239 }
240 }
241
242 void ImageWriter::CleanUp() {
243 if (image_file_ != base::kInvalidPlatformFileValue) {
244 base::ClosePlatformFile(image_file_);
245 image_file_ = base::kInvalidPlatformFileValue;
246 }
247 if (device_file_ != base::kInvalidPlatformFileValue) {
248 base::ClosePlatformFile(device_file_);
249 device_file_ = base::kInvalidPlatformFileValue;
250 }
251 }
252
253 } // namespace image_writer
254 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698