Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / image_writer_private / removable_storage_provider_linux.cc
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.
4
5 #include <libudev.h>
6
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"
11
12 namespace extensions {
13
14 // TODO(haven): Udev code may be duplicated in the Chrome codebase.
15 // https://code.google.com/p/chromium/issues/detail?id=284898
16
17 // Returns the integer contained in |attr|.  Returns 0 on error.
18 static uint64 get_int_attr(const char* attr){
19   uint64 result = 0;
20   // In error cases, StringToInt will set result to 0
21   base::StringToUint64(attr, &result);
22   return result;
23 }
24
25 static int get_device_blk_size(const std::string& path) {
26   base::FilePath file_path(path);
27   std::string device = file_path.BaseName().value();
28
29   base::FilePath info_file_path = base::FilePath("/sys/block")
30                                   .Append(device)
31                                   .Append("queue/logical_block_size");
32
33   std::string file_contents;
34   int blk_size;
35
36   if (!base::ReadFileToString(info_file_path, &file_contents)) {
37     return 0;
38   }
39   // In error cases, StringToInt will set blk_size to 0
40   base::StringToInt(file_contents, &blk_size);
41
42   return blk_size;
43 }
44
45 void RemovableStorageProvider::GetAllDevices(
46     DeviceListReadyCallback callback) {
47   scoped_refptr<StorageDeviceList> device_list(new StorageDeviceList);
48
49   // We need to do some file i/o to get the device block size
50   content::BrowserThread::PostTaskAndReplyWithResult(
51     content::BrowserThread::FILE,
52     FROM_HERE,
53     base::Bind(GetDevicesOnFileThread, device_list),
54     base::Bind(callback, device_list));
55 }
56
57 bool RemovableStorageProvider::GetDevicesOnFileThread(
58     scoped_refptr<StorageDeviceList> device_list) {
59   struct udev* udev;
60   struct udev_enumerate* enumerate;
61   struct udev_list_entry* devices, *dev_list_entry;
62   struct udev_device* dev, *parent;
63
64   udev = udev_new();
65   if (!udev) {
66     DLOG(ERROR) << "Can't create udev";
67     return false;
68   }
69
70   /* Create a list of the devices in the 'block' subsystem. */
71   enumerate = udev_enumerate_new(udev);
72
73   udev_enumerate_add_match_subsystem(enumerate, "block");
74   udev_enumerate_scan_devices(enumerate);
75   devices = udev_enumerate_get_list_entry(enumerate);
76
77   udev_list_entry_foreach(dev_list_entry, devices) {
78     const char* path = udev_list_entry_get_name(dev_list_entry);
79     dev = udev_device_new_from_syspath(udev, path);
80
81     const char* partition = udev_device_get_sysattr_value(dev, "partition");
82     if (partition && get_int_attr(partition)){
83       // This is a partition of a device, not the device itself
84       continue;
85     }
86
87     const char* removable = udev_device_get_sysattr_value(dev, "removable");
88     if (!removable || !get_int_attr(removable)) {
89       // This is not a removable storage device.
90       continue;
91     }
92
93     /* Get the parent SCSI device that contains the model
94        and manufacturer.  You can look at the hierarchy with
95        udevadm info -a -n /dev/<device> */
96     parent = udev_device_get_parent_with_subsystem_devtype(
97            dev,
98            "scsi",
99            NULL);
100     if (!parent) {
101       // this is not a usb device
102       continue;
103     }
104
105     linked_ptr<api::image_writer_private::RemovableStorageDevice> device(
106       new api::image_writer_private::RemovableStorageDevice());
107     device->vendor = udev_device_get_sysattr_value(parent, "vendor");
108     device->model = udev_device_get_sysattr_value(parent, "model");
109     // TODO (smaskell): Don't expose raw device path
110     device->storage_unit_id = udev_device_get_devnode(dev);
111     device->capacity = get_int_attr(udev_device_get_sysattr_value(dev, "size"))
112       * get_device_blk_size(device->storage_unit_id);
113
114     device_list->data.push_back(device);
115
116     udev_device_unref(dev);
117   }
118   /* Free the enumerator object */
119   udev_enumerate_unref(enumerate);
120   udev_unref(udev);
121
122   return true;
123 }
124
125 } // namespace extensions