1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/utility/image_writer/disk_unmounter_mac.h"
7 #include <sys/socket.h>
8 #include <IOKit/storage/IOStorageProtocolCharacteristics.h>
10 #include "base/message_loop/message_pump_mac.h"
11 #include "base/posix/eintr_wrapper.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chrome/utility/image_writer/error_messages.h"
14 #include "chrome/utility/image_writer/image_writer.h"
16 namespace image_writer
{
18 DiskUnmounterMac::DiskUnmounterMac() : cf_thread_("ImageWriterDiskArb") {
19 base::Thread::Options options
;
20 options
.message_pump_factory
= base::Bind(&CreateMessagePump
);
22 cf_thread_
.StartWithOptions(options
);
25 DiskUnmounterMac::~DiskUnmounterMac() {
30 void DiskUnmounterMac::Unmount(const std::string
& device_path
,
31 const base::Closure
& success_continuation
,
32 const base::Closure
& failure_continuation
) {
33 // Should only be used once.
34 DCHECK(!original_thread_
.get());
35 original_thread_
= base::ThreadTaskRunnerHandle::Get();
36 success_continuation_
= success_continuation
;
37 failure_continuation_
= failure_continuation
;
39 cf_thread_
.message_loop()->PostTask(
41 base::Bind(&DiskUnmounterMac::UnmountOnWorker
,
42 base::Unretained(this),
47 void DiskUnmounterMac::DiskClaimed(DADiskRef disk
,
48 DADissenterRef dissenter
,
50 DiskUnmounterMac
* disk_unmounter
= static_cast<DiskUnmounterMac
*>(context
);
53 LOG(ERROR
) << "Unable to claim disk.";
54 disk_unmounter
->Error();
59 kDADiskUnmountOptionForce
| kDADiskUnmountOptionWhole
,
65 DADissenterRef
DiskUnmounterMac::DiskClaimRevoked(DADiskRef disk
,
67 CFStringRef reason
= CFSTR(
68 "Hi. Sorry to bother you, but I'm busy overwriting the entire disk "
69 "here. There's nothing to claim but the smoldering ruins of bytes "
70 "that were in flash memory. Trust me, it's nothing that you want. "
71 "All the best. Toodles!");
72 return DADissenterCreate(kCFAllocatorDefault
, kDAReturnBusy
, reason
);
76 void DiskUnmounterMac::DiskUnmounted(DADiskRef disk
,
77 DADissenterRef dissenter
,
79 DiskUnmounterMac
* disk_unmounter
= static_cast<DiskUnmounterMac
*>(context
);
82 LOG(ERROR
) << "Unable to unmount disk.";
83 disk_unmounter
->Error();
87 disk_unmounter
->original_thread_
->PostTask(
88 FROM_HERE
, disk_unmounter
->success_continuation_
);
92 scoped_ptr
<base::MessagePump
> DiskUnmounterMac::CreateMessagePump() {
93 return scoped_ptr
<base::MessagePump
>(new base::MessagePumpCFRunLoop
);
96 void DiskUnmounterMac::UnmountOnWorker(const std::string
& device_path
) {
97 DCHECK(cf_thread_
.message_loop() == base::MessageLoop::current());
99 session_
.reset(DASessionCreate(NULL
));
101 DASessionScheduleWithRunLoop(
102 session_
, CFRunLoopGetCurrent(), kCFRunLoopCommonModes
);
104 disk_
.reset(DADiskCreateFromBSDName(
105 kCFAllocatorDefault
, session_
, device_path
.c_str()));
108 LOG(ERROR
) << "Unable to get disk reference.";
114 kDADiskClaimOptionDefault
,
121 void DiskUnmounterMac::Error() {
122 original_thread_
->PostTask(FROM_HERE
, failure_continuation_
);
125 } // namespace image_writer