X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fchrome%2Futility%2Fimage_writer%2Fimage_writer.cc;h=13175d7624f043327460e672e36221b2b9576ba3;hb=004985e17e624662a4c85c76a7654039dc83f028;hp=de2caebe2a97a038f5a62c60ed63a323f9e8764b;hpb=2f108dbacb161091e42a3479f4e171339b7e7623;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/chrome/utility/image_writer/image_writer.cc b/src/chrome/utility/image_writer/image_writer.cc index de2caeb..13175d7 100644 --- a/src/chrome/utility/image_writer/image_writer.cc +++ b/src/chrome/utility/image_writer/image_writer.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/utility/image_writer/image_writer.h" - +#include "base/memory/aligned_memory.h" #include "chrome/utility/image_writer/error_messages.h" +#include "chrome/utility/image_writer/image_writer.h" #include "chrome/utility/image_writer/image_writer_handler.h" #include "content/public/utility/utility_thread.h" @@ -12,112 +12,56 @@ namespace image_writer { // Since block devices like large sequential access and IPC is expensive we're // doing work in 1MB chunks. -const int kBurningBlockSize = 1 << 20; - -ImageWriter::ImageWriter(ImageWriterHandler* handler) - : bytes_processed_(0), +const int kBurningBlockSize = 1 << 20; // 1 MB +const int kMemoryAlignment = 4096; + +ImageWriter::ImageWriter(ImageWriterHandler* handler, + const base::FilePath& image_path, + const base::FilePath& device_path) + : image_path_(image_path), + device_path_(device_path), + bytes_processed_(0), + running_(false), handler_(handler) {} ImageWriter::~ImageWriter() { - CleanUp(); -} - -void ImageWriter::Write(const base::FilePath& image_path, - const base::FilePath& device_path) { - if (IsRunning()) { - handler_->SendFailed(error::kOperationAlreadyInProgress); - return; - } - - image_path_ = image_path; - device_path_ = device_path; - bytes_processed_ = 0; - - image_file_.Initialize(image_path_, - base::File::FLAG_OPEN | base::File::FLAG_READ); - - if (!image_file_.IsValid()) { - DLOG(ERROR) << "Unable to open file for read: " << image_path_.value(); - Error(error::kOpenImage); - return; - } - #if defined(OS_WIN) - // Windows requires that device files be opened with FILE_FLAG_NO_BUFFERING - // and FILE_FLAG_WRITE_THROUGH. These two flags are not part of base::File. - device_file_ = - base::File(CreateFile(device_path.value().c_str(), - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, - NULL)); - - if (!device_file_.IsValid()) { - Error(error::kOpenDevice); - return; + for (std::vector::const_iterator it = volume_handles_.begin(); + it != volume_handles_.end(); + ++it) { + CloseHandle(*it); } -#else - device_file_.Initialize(device_path_, - base::File::FLAG_OPEN | base::File::FLAG_WRITE); +#endif +} - if (!device_file_.IsValid()) { - DLOG(ERROR) << "Unable to open file for write(" << - device_file_.error_details() << "): " << - device_path_.value(); - Error(error::kOpenDevice); +void ImageWriter::Write() { + if (!InitializeFiles()) { return; } -#endif PostProgress(0); - PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr())); } -void ImageWriter::Verify(const base::FilePath& image_path, - const base::FilePath& device_path) { - if (IsRunning()) { - handler_->SendFailed(error::kOperationAlreadyInProgress); - return; - } - - image_path_ = image_path; - device_path_ = device_path; - bytes_processed_ = 0; - - image_file_.Initialize(image_path_, - base::File::FLAG_OPEN | base::File::FLAG_READ); - - if (!image_file_.IsValid()) { - DLOG(ERROR) << "Unable to open file for read: " << image_path_.value(); - Error(error::kOpenImage); - return; - } - - device_file_.Initialize(device_path_, - base::File::FLAG_OPEN | base::File::FLAG_READ); - - if (!device_file_.IsValid()) { - DLOG(ERROR) << "Unable to open file for read: " << device_path_.value(); - Error(error::kOpenDevice); +void ImageWriter::Verify() { + if (!InitializeFiles()) { return; } PostProgress(0); - PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr())); } void ImageWriter::Cancel() { - CleanUp(); + running_ = false; handler_->SendCancelled(); } -bool ImageWriter::IsRunning() const { - return image_file_.IsValid() || device_file_.IsValid(); -} +bool ImageWriter::IsRunning() const { return running_; } + +const base::FilePath& ImageWriter::GetImagePath() { return image_path_; } + +const base::FilePath& ImageWriter::GetDevicePath() { return device_path_; } void ImageWriter::PostTask(const base::Closure& task) { base::MessageLoop::current()->PostTask(FROM_HERE, task); @@ -128,26 +72,73 @@ void ImageWriter::PostProgress(int64 progress) { } void ImageWriter::Error(const std::string& message) { - CleanUp(); + running_ = false; handler_->SendFailed(message); } +bool ImageWriter::InitializeFiles() { + if (!image_file_.IsValid()) { + image_file_.Initialize(image_path_, + base::File::FLAG_OPEN | base::File::FLAG_READ | + base::File::FLAG_EXCLUSIVE_READ); + + if (!image_file_.IsValid()) { + DLOG(ERROR) << "Unable to open file for read: " << image_path_.value(); + Error(error::kOpenImage); + return false; + } + } + + if (!device_file_.IsValid()) { +#if defined(OS_WIN) + // Windows requires that device files be opened with FILE_FLAG_NO_BUFFERING + // and FILE_FLAG_WRITE_THROUGH. These two flags are not part of base::File. + device_file_ = + base::File(CreateFile(device_path_.value().c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, + NULL)); +#else + device_file_.Initialize( + device_path_, + base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE | + base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE); +#endif + if (!device_file_.IsValid()) { + Error(error::kOpenDevice); + return false; + } + } + + bytes_processed_ = 0; + running_ = true; + + return true; +} + void ImageWriter::WriteChunk() { if (!IsRunning()) { return; } - scoped_ptr buffer(new char[kBurningBlockSize]); + // DASD buffers require memory alignment on some systems. + scoped_ptr buffer(static_cast( + base::AlignedAlloc(kBurningBlockSize, kMemoryAlignment))); memset(buffer.get(), 0, kBurningBlockSize); int bytes_read = image_file_.Read(bytes_processed_, buffer.get(), kBurningBlockSize); if (bytes_read > 0) { - // Always attempt to write a whole block, as Windows requires 512-byte + // Always attempt to write a whole block, as writing DASD requires sector- // aligned writes to devices. - int bytes_written = device_file_.Write(bytes_processed_, buffer.get(), - kBurningBlockSize); + int bytes_to_write = bytes_read + (kMemoryAlignment - 1) - + (bytes_read - 1) % kMemoryAlignment; + int bytes_written = + device_file_.Write(bytes_processed_, buffer.get(), bytes_to_write); if (bytes_written < bytes_read) { Error(error::kWriteImage); @@ -161,7 +152,7 @@ void ImageWriter::WriteChunk() { } else if (bytes_read == 0) { // End of file. device_file_.Flush(); - CleanUp(); + running_ = false; handler_->SendSucceeded(); } else { // Unable to read entire file. @@ -175,7 +166,9 @@ void ImageWriter::VerifyChunk() { } scoped_ptr image_buffer(new char[kBurningBlockSize]); - scoped_ptr device_buffer(new char[kBurningBlockSize]); + // DASD buffers require memory alignment on some systems. + scoped_ptr device_buffer(static_cast( + base::AlignedAlloc(kBurningBlockSize, kMemoryAlignment))); int bytes_read = image_file_.Read(bytes_processed_, image_buffer.get(), kBurningBlockSize); @@ -184,7 +177,7 @@ void ImageWriter::VerifyChunk() { if (device_file_.Read(bytes_processed_, device_buffer.get(), kBurningBlockSize) < bytes_read) { - LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of " + LOG(ERROR) << "Failed to read " << bytes_read << " bytes of " << "device at offset " << bytes_processed_; Error(error::kReadDevice); return; @@ -203,8 +196,8 @@ void ImageWriter::VerifyChunk() { PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr())); } else if (bytes_read == 0) { // End of file. - CleanUp(); handler_->SendSucceeded(); + running_ = false; } else { // Unable to read entire file. LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of image " @@ -213,9 +206,4 @@ void ImageWriter::VerifyChunk() { } } -void ImageWriter::CleanUp() { - image_file_.Close(); - device_file_.Close(); -} - } // namespace image_writer