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

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: Review feedback. 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 2014 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 image_writer {
12
13 // Since block devices like large sequential access and IPC is expensive we're
14 // doing work in 1MB chunks.
15 const int kBurningBlockSize = 1 << 20;
Jorge Lucangeli Obes 2014/02/15 01:43:19 Why signed? Block size cannot be negative.
Drew Haven 2014/02/15 02:15:15 You're right. It should be a size_t, if I underst
16
17 ImageWriter::ImageWriter(ImageWriterHandler* handler)
18 : image_file_(base::kInvalidPlatformFileValue),
19 device_file_(base::kInvalidPlatformFileValue),
20 bytes_processed_(0),
21 handler_(handler) {}
22
23 ImageWriter::~ImageWriter() { CleanUp(); }
24
25 void ImageWriter::Write(const base::FilePath& image_path,
26 const base::FilePath& device_path) {
27 if (IsRunning()) {
28 handler_->SendFailed(error::kOperationAlreadyInProgress);
29 return;
30 }
31
32 image_path_ = image_path;
33 device_path_ = device_path;
34 bytes_processed_ = 0;
35
36 base::PlatformFileError error;
37
38 image_file_ = base::CreatePlatformFile(
39 image_path_,
40 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
41 NULL,
42 &error);
43
44 if (error != base::PLATFORM_FILE_OK) {
45 DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
46 Error(error::kOpenImage);
47 return;
48 }
49
50 #if defined(OS_WIN)
51 // Windows requires that device files be opened with FILE_FLAG_NO_BUFFERING
52 // and FILE_FLAG_WRITE_THROUGH. These two flags are not part of
53 // PlatformFile::CreatePlatformFile.
54 device_file_ = CreateFile(device_path.value().c_str(),
55 GENERIC_WRITE,
56 FILE_SHARE_WRITE,
57 NULL,
58 OPEN_EXISTING,
59 FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
60 INVALID_HANDLE_VALUE);
61
62 if (device_file_ == base::kInvalidPlatformFileValue) {
63 Error(error::kOpenDevice);
64 return;
65 }
66 #else
67 device_file_ = base::CreatePlatformFile(
68 device_path_,
69 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
70 NULL,
71 &error);
72
73 if (error != base::PLATFORM_FILE_OK) {
74 DLOG(ERROR) << "Unable to open file for write(" << error
75 << "): " << device_path_.value();
76 Error(error::kOpenDevice);
77 return;
78 }
79 #endif
80
81 PostProgress(0);
82
83 PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr()));
84 }
85
86 void ImageWriter::Verify(const base::FilePath& image_path,
87 const base::FilePath& device_path) {
88 if (IsRunning()) {
89 handler_->SendFailed(error::kOperationAlreadyInProgress);
90 return;
91 }
92
93 image_path_ = image_path;
94 device_path_ = device_path;
95 bytes_processed_ = 0;
96
97 base::PlatformFileError error;
98
99 image_file_ = base::CreatePlatformFile(
100 image_path_,
101 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
102 NULL,
103 &error);
104
105 if (error != base::PLATFORM_FILE_OK) {
106 DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
107 Error(error::kOpenImage);
108 return;
109 }
110
111 device_file_ = base::CreatePlatformFile(
112 device_path_,
113 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
114 NULL,
115 &error);
116
117 if (error != base::PLATFORM_FILE_OK) {
118 DLOG(ERROR) << "Unable to open file for read: " << device_path_.value();
119 Error(error::kOpenDevice);
120 return;
121 }
122
123 PostProgress(0);
124
125 PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr()));
126 }
127
128 void ImageWriter::Cancel() {
129 CleanUp();
130 handler_->SendCancelled();
131 }
132
133 bool ImageWriter::IsRunning() {
134 return image_file_ != base::kInvalidPlatformFileValue ||
135 device_file_ != base::kInvalidPlatformFileValue;
136 }
137
138 void ImageWriter::PostTask(const base::Closure& task) {
139 base::MessageLoop::current()->PostTask(FROM_HERE, task);
140 }
141
142 void ImageWriter::PostProgress(int64 progress) {
143 handler_->SendProgress(progress);
144 }
145
146 void ImageWriter::Error(const std::string& message) {
147 CleanUp();
148 handler_->SendFailed(message);
149 }
150
151 void ImageWriter::WriteChunk() {
152 if (!IsRunning()) {
153 return;
154 }
155
156 scoped_ptr<char[]> buffer(new char[kBurningBlockSize]);
157 base::PlatformFileInfo info;
158
159 int bytes_read = base::ReadPlatformFile(
160 image_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
161
162 if (bytes_read > 0) {
163 // Always attempt to write a whole block, as Windows requires 512-byte
164 // aligned writes to devices.
165 int bytes_written = base::WritePlatformFile(
166 device_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
167
168 if (bytes_written < bytes_read) {
169 Error(error::kWriteImage);
170 return;
171 }
172
173 bytes_processed_ += bytes_read;
174 PostProgress(bytes_processed_);
175
176 PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr()));
177 } else if (bytes_read == 0) {
178 // End of file.
179 base::FlushPlatformFile(device_file_);
180 CleanUp();
181 handler_->SendSucceeded();
182 } else {
183 // Unable to read entire file.
184 Error(error::kReadImage);
185 }
186 }
187
188 void ImageWriter::VerifyChunk() {
189 if (!IsRunning()) {
190 return;
191 }
192
193 scoped_ptr<char[]> image_buffer(new char[kBurningBlockSize]);
194 scoped_ptr<char[]> device_buffer(new char[kBurningBlockSize]);
195 base::PlatformFileInfo info;
196 int image_size;
197
198 if (base::GetPlatformFileInfo(image_file_, &info)) {
199 image_size = info.size;
200 } else {
201 Error(error::kReadImage);
202 }
203
204 int bytes_read = base::ReadPlatformFile(
205 image_file_, bytes_processed_, image_buffer.get(), kBurningBlockSize);
206
207 if (bytes_read > 0) {
208 if (base::ReadPlatformFile(device_file_,
209 bytes_processed_,
210 device_buffer.get(),
211 kBurningBlockSize) < 0) {
212 LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of "
213 << "device at offset " << bytes_processed_;
214 Error(error::kReadDevice);
215 return;
216 }
217
218 if (memcmp(image_buffer.get(), device_buffer.get(), bytes_read) != 0) {
219 LOG(ERROR) << "Write verification failed when comparing " << bytes_read
220 << " bytes at " << bytes_processed_;
221 Error(error::kVerificationFailed);
222 return;
223 }
224
225 bytes_processed_ += bytes_read;
226 PostProgress(bytes_processed_);
227
228 PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr()));
229 } else if (bytes_read == 0 && bytes_processed_ == image_size) {
230 // End of file.
231 CleanUp();
232 handler_->SendSucceeded();
233 } else {
234 // Unable to read entire file.
235 LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of image "
236 << "at offset " << bytes_processed_;
237 Error(error::kReadImage);
238 }
239 }
240
241 void ImageWriter::CleanUp() {
242 if (image_file_ != base::kInvalidPlatformFileValue) {
243 base::ClosePlatformFile(image_file_);
244 image_file_ = base::kInvalidPlatformFileValue;
245 }
246 if (device_file_ != base::kInvalidPlatformFileValue) {
247 base::ClosePlatformFile(device_file_);
248 device_file_ = base::kInvalidPlatformFileValue;
249 }
250 }
251
252 } // namespace image_writer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698