1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/utility/image_writer/disk_unmounter_mac.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/socket.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <IOKit/storage/IOStorageProtocolCharacteristics.h> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/message_loop/message_pump_mac.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/posix/eintr_wrapper.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/utility/image_writer/error_messages.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/utility/image_writer/image_writer.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace image_writer { 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DiskUnmounterMac::DiskUnmounterMac() : cf_thread_("ImageWriterDiskArb") { 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Thread::Options options; 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) options.message_pump_factory = base::Bind(&CreateMessagePump); 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cf_thread_.StartWithOptions(options); 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DiskUnmounterMac::~DiskUnmounterMac() { 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (disk_) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DADiskUnclaim(disk_); 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DiskUnmounterMac::Unmount(const std::string& device_path, 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Closure& success_continuation, 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::Closure& failure_continuation) { 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Should only be used once. 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!original_thread_.get()); 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) original_thread_ = base::MessageLoopProxy::current(); 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) success_continuation_ = success_continuation; 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) failure_continuation_ = failure_continuation; 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cf_thread_.message_loop()->PostTask( 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FROM_HERE, 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&DiskUnmounterMac::UnmountOnWorker, 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Unretained(this), 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) device_path)); 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DiskUnmounterMac::DiskClaimed(DADiskRef disk, 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DADissenterRef dissenter, 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* context) { 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DiskUnmounterMac* disk_unmounter = static_cast<DiskUnmounterMac*>(context); 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dissenter) { 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "Unable to claim disk."; 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) disk_unmounter->Error(); 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DADiskUnmount(disk, 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kDADiskUnmountOptionForce | kDADiskUnmountOptionWhole, 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DiskUnmounted, 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) disk_unmounter); 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DADissenterRef DiskUnmounterMac::DiskClaimRevoked(DADiskRef disk, 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* context) { 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CFStringRef reason = CFSTR( 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "Hi. Sorry to bother you, but I'm busy overwriting the entire disk " 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "here. There's nothing to claim but the smoldering ruins of bytes " 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "that were in flash memory. Trust me, it's nothing that you want. " 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "All the best. Toodles!"); 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return DADissenterCreate(kCFAllocatorDefault, kDAReturnBusy, reason); 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DiskUnmounterMac::DiskUnmounted(DADiskRef disk, 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DADissenterRef dissenter, 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* context) { 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DiskUnmounterMac* disk_unmounter = static_cast<DiskUnmounterMac*>(context); 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dissenter) { 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "Unable to unmount disk."; 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) disk_unmounter->Error(); 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) disk_unmounter->original_thread_->PostTask( 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FROM_HERE, disk_unmounter->success_continuation_); 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)scoped_ptr<base::MessagePump> DiskUnmounterMac::CreateMessagePump() { 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return scoped_ptr<base::MessagePump>(new base::MessagePumpCFRunLoop); 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DiskUnmounterMac::UnmountOnWorker(const std::string& device_path) { 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(cf_thread_.message_loop() == base::MessageLoop::current()); 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) session_.reset(DASessionCreate(NULL)); 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DASessionScheduleWithRunLoop( 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) session_, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) disk_.reset(DADiskCreateFromBSDName( 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kCFAllocatorDefault, session_, device_path.c_str())); 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!disk_) { 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "Unable to get disk reference."; 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error(); 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DADiskClaim(disk_, 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kDADiskClaimOptionDefault, 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DiskClaimRevoked, 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this, 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DiskClaimed, 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this); 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DiskUnmounterMac::Error() { 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) original_thread_->PostTask(FROM_HERE, failure_continuation_); 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace image_writer 126