1// Copyright 2015 The Chromium Authors 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "components/metrics/drive_metrics_provider.h" 6 7#include <CoreFoundation/CoreFoundation.h> 8#include <DiskArbitration/DiskArbitration.h> 9#import <Foundation/Foundation.h> 10#include <IOKit/IOKitLib.h> 11#include <IOKit/storage/IOStorageDeviceCharacteristics.h> 12#include <stdlib.h> 13#include <sys/stat.h> 14 15#include "base/apple/bridging.h" 16#include "base/apple/foundation_util.h" 17#include "base/apple/scoped_cftyperef.h" 18#include "base/files/file_path.h" 19#include "base/mac/mac_util.h" 20#include "base/mac/scoped_ioobject.h" 21 22namespace metrics { 23 24// static 25bool DriveMetricsProvider::HasSeekPenalty(const base::FilePath& path, 26 bool* has_seek_penalty) { 27 struct stat path_stat; 28 if (stat(path.value().c_str(), &path_stat) < 0) 29 return false; 30 31 const char* dev_name = devname(path_stat.st_dev, S_IFBLK); 32 if (!dev_name) 33 return false; 34 35 std::string bsd_name("/dev/"); 36 bsd_name.append(dev_name); 37 38 base::apple::ScopedCFTypeRef<DASessionRef> session( 39 DASessionCreate(kCFAllocatorDefault)); 40 if (!session) 41 return false; 42 43 base::apple::ScopedCFTypeRef<DADiskRef> disk(DADiskCreateFromBSDName( 44 kCFAllocatorDefault, session.get(), bsd_name.c_str())); 45 if (!disk) 46 return false; 47 48 base::mac::ScopedIOObject<io_object_t> io_media( 49 DADiskCopyIOMedia(disk.get())); 50 base::apple::ScopedCFTypeRef<CFDictionaryRef> characteristics( 51 static_cast<CFDictionaryRef>(IORegistryEntrySearchCFProperty( 52 io_media.get(), kIOServicePlane, 53 CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, 54 kIORegistryIterateRecursively | kIORegistryIterateParents))); 55 if (!characteristics) 56 return false; 57 58 CFStringRef type_ref = base::apple::GetValueFromDictionary<CFStringRef>( 59 characteristics.get(), CFSTR(kIOPropertyMediumTypeKey)); 60 if (!type_ref) 61 return false; 62 63 NSString* type = base::apple::CFToNSPtrCast(type_ref); 64 if ([type isEqualToString:@kIOPropertyMediumTypeRotationalKey]) { 65 *has_seek_penalty = true; 66 return true; 67 } 68 if ([type isEqualToString:@kIOPropertyMediumTypeSolidStateKey]) { 69 *has_seek_penalty = false; 70 return true; 71 } 72 73 // TODO(dbeam): should I look for these Rotational/Solid State keys in 74 // |characteristics|? What if I find device characteristic but there's no 75 // type? Assume rotational? 76 return false; 77} 78 79} // namespace metrics 80