1 // Copyright 2013 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.
7 #include "base/file_util.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
10 #include "content/public/browser/browser_thread.h"
12 namespace extensions {
13 // TODO(haven): Udev code may be duplicated in the Chrome codebase.
14 // https://code.google.com/p/chromium/issues/detail?id=284898
16 // Returns the integer contained in |attr|. Returns 0 on error.
17 static uint64 get_int_attr(const char* attr){
19 // In error cases, StringToInt will set result to 0
20 base::StringToUint64(attr, &result);
24 static int get_device_blk_size(const std::string& path) {
25 base::FilePath file_path(path);
26 std::string device = file_path.BaseName().value();
28 base::FilePath info_file_path = base::FilePath("/sys/block")
30 .Append("queue/logical_block_size");
32 std::string file_contents;
35 if (!base::ReadFileToString(info_file_path, &file_contents)) {
38 // In error cases, StringToInt will set blk_size to 0
39 base::StringToInt(file_contents, &blk_size);
44 bool RemovableStorageProvider::PopulateDeviceList(
45 scoped_refptr<StorageDeviceList> device_list) {
47 struct udev_enumerate* enumerate;
48 struct udev_list_entry* devices, *dev_list_entry;
49 struct udev_device* dev, *parent;
53 DLOG(ERROR) << "Can't create udev";
57 /* Create a list of the devices in the 'block' subsystem. */
58 enumerate = udev_enumerate_new(udev);
60 udev_enumerate_add_match_subsystem(enumerate, "block");
61 udev_enumerate_scan_devices(enumerate);
62 devices = udev_enumerate_get_list_entry(enumerate);
64 udev_list_entry_foreach(dev_list_entry, devices) {
65 const char* path = udev_list_entry_get_name(dev_list_entry);
66 dev = udev_device_new_from_syspath(udev, path);
68 const char* partition = udev_device_get_sysattr_value(dev, "partition");
69 if (partition && get_int_attr(partition)){
70 // This is a partition of a device, not the device itself
74 const char* removable = udev_device_get_sysattr_value(dev, "removable");
75 if (!removable || !get_int_attr(removable)) {
76 // This is not a removable storage device.
80 /* Get the parent SCSI device that contains the model
81 and manufacturer. You can look at the hierarchy with
82 udevadm info -a -n /dev/<device> */
83 parent = udev_device_get_parent_with_subsystem_devtype(
88 // this is not a usb device
92 linked_ptr<api::image_writer_private::RemovableStorageDevice> device(
93 new api::image_writer_private::RemovableStorageDevice());
94 device->vendor = udev_device_get_sysattr_value(parent, "vendor");
95 device->model = udev_device_get_sysattr_value(parent, "model");
96 // TODO (smaskell): Don't expose raw device path
97 device->storage_unit_id = udev_device_get_devnode(dev);
98 device->capacity = get_int_attr(udev_device_get_sysattr_value(dev, "size"))
99 * get_device_blk_size(device->storage_unit_id);
100 device->removable = removable;
102 device_list->data.push_back(device);
104 udev_device_unref(dev);
106 /* Free the enumerator object */
107 udev_enumerate_unref(enumerate);
113 } // namespace extensions