blob: 4259e7f22e3e8bc48966ad8767fc2d3ac9a825ac [file] [log] [blame]
Ben Chance7ee542011-04-12 17:02:49 -07001// Copyright (c) 2011 The Chromium OS 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
Ben Chan5ccd9fe2013-11-13 18:28:27 -08005#include "cros-disks/udev_device.h"
Ben Chanbeefd0d2011-07-25 09:31:34 -07006
Ben Chance7ee542011-04-12 17:02:49 -07007#include <fcntl.h>
8#include <libudev.h>
Ben Chanda410a02011-08-24 23:37:53 -07009#include <stdlib.h>
Ben Chance7ee542011-04-12 17:02:49 -070010#include <sys/statvfs.h>
Ben Chanbdc39742011-05-11 17:51:26 -070011
Chris Masoneec4761f2011-05-12 14:04:13 -070012#include <base/logging.h>
Ben Chan0e1b5502013-07-24 23:39:29 -070013#include <base/sha1.h>
Ben Chan97e20d42014-02-05 18:38:07 -080014#include <base/strings/string_number_conversions.h>
15#include <base/strings/string_split.h>
16#include <base/strings/string_util.h>
Ben Chanbdc39742011-05-11 17:51:26 -070017#include <rootdev/rootdev.h>
18
Ben Chan5ccd9fe2013-11-13 18:28:27 -080019#include "cros-disks/mount_info.h"
20#include "cros-disks/usb_device_info.h"
Ben Chance7ee542011-04-12 17:02:49 -070021
Ben Chan190d3cf2011-07-07 09:38:48 -070022using std::string;
23using std::vector;
24
Ben Chan54342622011-08-18 00:57:11 -070025namespace {
Ben Chance7ee542011-04-12 17:02:49 -070026
Ben Chan460439f2011-09-13 09:16:28 -070027const char kNullDeviceFile[] = "/dev/null";
Ben Chan0a389a62011-10-03 15:02:34 -070028const char kAttributeIdProduct[] = "idProduct";
29const char kAttributeIdVendor[] = "idVendor";
Ben Chan460439f2011-09-13 09:16:28 -070030const char kAttributePartition[] = "partition";
31const char kAttributeRange[] = "range";
32const char kAttributeReadOnly[] = "ro";
33const char kAttributeRemovable[] = "removable";
34const char kAttributeSize[] = "size";
Ben Chan58aad1d2013-02-26 16:09:34 -080035const char kDriverMMCBlock[] = "mmcblk";
Ben Chan460439f2011-09-13 09:16:28 -070036const char kPropertyBlkIdFilesystemType[] = "TYPE";
37const char kPropertyBlkIdFilesystemLabel[] = "LABEL";
38const char kPropertyBlkIdFilesystemUUID[] = "UUID";
39const char kPropertyCDROM[] = "ID_CDROM";
Ben Chan7d8f9f72012-05-02 10:02:20 -070040const char kPropertyCDROMDVD[] = "ID_CDROM_DVD";
Ben Chan460439f2011-09-13 09:16:28 -070041const char kPropertyCDROMMedia[] = "ID_CDROM_MEDIA";
Ben Chana0fe0ef2012-09-06 23:39:56 -070042const char kPropertyCDROMMediaTrackCountData[] =
43 "ID_CDROM_MEDIA_TRACK_COUNT_DATA";
Ben Chan0a389a62011-10-03 15:02:34 -070044const char kPropertyDeviceType[] = "DEVTYPE";
45const char kPropertyDeviceTypeUSBDevice[] = "usb_device";
Ben Chan460439f2011-09-13 09:16:28 -070046const char kPropertyFilesystemUsage[] = "ID_FS_USAGE";
Ben Chan1f418382013-06-17 23:33:28 -070047const char kPropertyMistSupportedDevice[] = "MIST_SUPPORTED_DEVICE";
Ben Chan460439f2011-09-13 09:16:28 -070048const char kPropertyModel[] = "ID_MODEL";
Ben Chancac20332014-02-13 23:21:17 -080049const char kPropertyPartitionEntryType[] = "ID_PART_ENTRY_TYPE";
Ben Chan460439f2011-09-13 09:16:28 -070050const char kPropertyPartitionSize[] = "UDISKS_PARTITION_SIZE";
51const char kPropertyPresentationHide[] = "UDISKS_PRESENTATION_HIDE";
52const char kPropertyRotationRate[] = "ID_ATA_ROTATION_RATE_RPM";
Ben Chan0e1b5502013-07-24 23:39:29 -070053const char kPropertySerial[] = "ID_SERIAL";
Ben Chan1f418382013-06-17 23:33:28 -070054const char kSubsystemUsb[] = "usb";
Ben Chan460439f2011-09-13 09:16:28 -070055const char kVirtualDevicePathPrefix[] = "/sys/devices/virtual/";
Ben Chan2923ed72013-07-29 15:52:29 -070056const char kLoopDevicePathPrefix[] = "/sys/devices/virtual/block/loop";
Ben Chan0a389a62011-10-03 15:02:34 -070057const char kUSBDeviceInfoFile[] = "/opt/google/cros-disks/usb-device-info";
Ben Chan120c11c2012-09-10 23:10:18 -070058const char kUSBIdentifierDatabase[] = "/usr/share/misc/usb.ids";
Ben Chancac20332014-02-13 23:21:17 -080059const char* kPartitionTypesToHide[] = {
60 "c12a7328-f81f-11d2-ba4b-00a0c93ec93b", // EFI system partition
61 "fe3a2a5d-4f32-41a7-b725-accc3285a309", // Chrome OS kernel
62 "3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec", // Chrome OS root filesystem
63 "cab6e88e-abf3-4102-a07a-d4bb9be3c1d3", // Chrome OS firmware
64 "2e0a753d-9e48-43b0-8337-b15192cb1b5e", // Chrome OS reserved
Ben Chan1c2d4252011-06-03 13:33:49 -070065};
66
Ben Chan54342622011-08-18 00:57:11 -070067} // namespace
68
69namespace cros_disks {
70
Ben Chance7ee542011-04-12 17:02:49 -070071UdevDevice::UdevDevice(struct udev_device *dev)
Ben Chanda410a02011-08-24 23:37:53 -070072 : dev_(dev),
Ben Chan44e7ea62014-08-29 18:13:37 -070073 blkid_cache_(nullptr) {
Ben Chance7ee542011-04-12 17:02:49 -070074 CHECK(dev_) << "Invalid udev device";
75 udev_device_ref(dev_);
76}
77
78UdevDevice::~UdevDevice() {
Ben Chanda410a02011-08-24 23:37:53 -070079 if (blkid_cache_) {
80 // It needs to call blkid_put_cache to deallocate the blkid cache.
81 blkid_put_cache(blkid_cache_);
82 }
Ben Chance7ee542011-04-12 17:02:49 -070083 udev_device_unref(dev_);
84}
85
Ben Chan1f418382013-06-17 23:33:28 -070086// static
Ben Chan22c0e602012-02-13 12:37:34 -080087string UdevDevice::EnsureUTF8String(const string& str) {
Ben Chanaf25ddb2014-05-21 18:32:47 -070088 return base::IsStringUTF8(str) ? str : "";
Ben Chan22c0e602012-02-13 12:37:34 -080089}
90
Ben Chan1f418382013-06-17 23:33:28 -070091// static
92bool UdevDevice::IsValueBooleanTrue(const char *value) {
Ben Chance7ee542011-04-12 17:02:49 -070093 return value && strcmp(value, "1") == 0;
94}
95
Ben Chan190d3cf2011-07-07 09:38:48 -070096string UdevDevice::GetAttribute(const char *key) const {
Ben Chance7ee542011-04-12 17:02:49 -070097 const char *value = udev_device_get_sysattr_value(dev_, key);
98 return (value) ? value : "";
99}
100
101bool UdevDevice::IsAttributeTrue(const char *key) const {
102 const char *value = udev_device_get_sysattr_value(dev_, key);
103 return IsValueBooleanTrue(value);
104}
105
106bool UdevDevice::HasAttribute(const char *key) const {
107 const char *value = udev_device_get_sysattr_value(dev_, key);
Ben Chan44e7ea62014-08-29 18:13:37 -0700108 return value != nullptr;
Ben Chance7ee542011-04-12 17:02:49 -0700109}
110
Ben Chan190d3cf2011-07-07 09:38:48 -0700111string UdevDevice::GetProperty(const char *key) const {
Ben Chance7ee542011-04-12 17:02:49 -0700112 const char *value = udev_device_get_property_value(dev_, key);
113 return (value) ? value : "";
114}
115
116bool UdevDevice::IsPropertyTrue(const char *key) const {
117 const char *value = udev_device_get_property_value(dev_, key);
118 return IsValueBooleanTrue(value);
119}
120
121bool UdevDevice::HasProperty(const char *key) const {
122 const char *value = udev_device_get_property_value(dev_, key);
Ben Chan44e7ea62014-08-29 18:13:37 -0700123 return value != nullptr;
Ben Chance7ee542011-04-12 17:02:49 -0700124}
125
Ben Chanda410a02011-08-24 23:37:53 -0700126string UdevDevice::GetPropertyFromBlkId(const char *key) {
127 string value;
128 const char *dev_file = udev_device_get_devnode(dev_);
129 if (dev_file) {
130 // No cache file is used as it should always query information from
131 // the device, i.e. setting cache file to /dev/null.
132 if (blkid_cache_ || blkid_get_cache(&blkid_cache_, kNullDeviceFile) == 0) {
133 blkid_dev dev = blkid_get_dev(blkid_cache_, dev_file, BLKID_DEV_NORMAL);
134 if (dev) {
135 char *tag_value = blkid_get_tag_value(blkid_cache_, key, dev_file);
136 if (tag_value) {
137 value = tag_value;
138 free(tag_value);
139 }
140 }
141 }
142 }
143 return value;
144}
145
Ben Chana169b0a2014-08-06 17:22:40 -0700146void UdevDevice::GetSizeInfo(uint64_t *total_size,
147 uint64_t *remaining_size) const {
Ben Chanf51ff002011-04-25 12:41:57 -0700148 static const int kSectorSize = 512;
Ben Chana169b0a2014-08-06 17:22:40 -0700149 uint64_t total = 0, remaining = 0;
Ben Chance7ee542011-04-12 17:02:49 -0700150
Ben Chanf51ff002011-04-25 12:41:57 -0700151 // If the device is mounted, obtain the total and remaining size in bytes
152 // using statvfs.
Ben Chan190d3cf2011-07-07 09:38:48 -0700153 vector<string> mount_paths = GetMountPaths();
Ben Chanf51ff002011-04-25 12:41:57 -0700154 if (!mount_paths.empty()) {
155 struct statvfs stat;
156 if (statvfs(mount_paths[0].c_str(), &stat) == 0) {
157 total = stat.f_blocks * stat.f_frsize;
158 remaining = stat.f_bfree * stat.f_frsize;
Ben Chance7ee542011-04-12 17:02:49 -0700159 }
160 }
161
Ben Chanf51ff002011-04-25 12:41:57 -0700162 // If the UDISKS_PARTITION_SIZE property is set, use it as the total size
163 // instead. If the UDISKS_PARTITION_SIZE property is not set but sysfs
164 // provides a size value, which is the actual size in bytes divided by 512,
165 // use that as the total size instead.
Ben Chan54342622011-08-18 00:57:11 -0700166 const char *partition_size =
167 udev_device_get_property_value(dev_, kPropertyPartitionSize);
Ben Chana169b0a2014-08-06 17:22:40 -0700168 int64_t size = 0;
Ben Chanf51ff002011-04-25 12:41:57 -0700169 if (partition_size) {
170 base::StringToInt64(partition_size, &size);
171 total = size;
172 } else {
Ben Chan54342622011-08-18 00:57:11 -0700173 const char *size_attr = udev_device_get_sysattr_value(dev_, kAttributeSize);
Ben Chanf51ff002011-04-25 12:41:57 -0700174 if (size_attr) {
175 base::StringToInt64(size_attr, &size);
176 total = size * kSectorSize;
177 }
178 }
179
180 if (total_size)
181 *total_size = total;
Ben Chance7ee542011-04-12 17:02:49 -0700182 if (remaining_size)
Ben Chanf51ff002011-04-25 12:41:57 -0700183 *remaining_size = remaining;
Ben Chance7ee542011-04-12 17:02:49 -0700184}
185
Ben Chan53e12a22014-02-13 23:34:09 -0800186size_t UdevDevice::GetPartitionCount() const {
Ben Chanca369942011-09-10 17:03:05 -0700187 size_t partition_count = 0;
188 const char *dev_file = udev_device_get_devnode(dev_);
189 if (dev_file) {
Ben Chan53e12a22014-02-13 23:34:09 -0800190 blkid_probe probe = blkid_new_probe_from_filename(dev_file);
191 if (probe) {
192 blkid_partlist partitions = blkid_probe_get_partitions(probe);
193 if (partitions) {
194 partition_count = blkid_partlist_numof_partitions(partitions);
Ben Chanca369942011-09-10 17:03:05 -0700195 }
Ben Chan53e12a22014-02-13 23:34:09 -0800196 blkid_free_probe(probe);
Ben Chanca369942011-09-10 17:03:05 -0700197 }
198 }
199 return partition_count;
200}
201
Ben Chan0a389a62011-10-03 15:02:34 -0700202DeviceMediaType UdevDevice::GetDeviceMediaType() const {
Ben Chan7d8f9f72012-05-02 10:02:20 -0700203 if (IsPropertyTrue(kPropertyCDROMDVD))
204 return DEVICE_MEDIA_DVD;
205
Ben Chan0a389a62011-10-03 15:02:34 -0700206 if (IsPropertyTrue(kPropertyCDROM))
Ben Chan6d0b2722011-11-18 08:24:14 -0800207 return DEVICE_MEDIA_OPTICAL_DISC;
Ben Chan0a389a62011-10-03 15:02:34 -0700208
Ben Chan58aad1d2013-02-26 16:09:34 -0800209 if (IsOnMMCDevice())
210 return DEVICE_MEDIA_SD;
211
Ben Chan120c11c2012-09-10 23:10:18 -0700212 string vendor_id, product_id;
213 if (GetVendorAndProductId(&vendor_id, &product_id)) {
214 USBDeviceInfo info;
215 info.RetrieveFromFile(kUSBDeviceInfoFile);
216 return info.GetDeviceMediaType(vendor_id, product_id);
217 }
218 return DEVICE_MEDIA_UNKNOWN;
219}
220
221bool UdevDevice::GetVendorAndProductId(
222 string* vendor_id, string* product_id) const {
Ben Chan0a389a62011-10-03 15:02:34 -0700223 // Search up the parent device tree to obtain the vendor and product ID
224 // of the first device with a device type "usb_device". Then look up the
225 // media type based on the vendor and product ID from a USB device info file.
226 for (struct udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
227 const char *device_type =
228 udev_device_get_property_value(dev, kPropertyDeviceType);
229 if (device_type && strcmp(device_type, kPropertyDeviceTypeUSBDevice) == 0) {
Ben Chan120c11c2012-09-10 23:10:18 -0700230 const char *vendor_id_attr =
Ben Chan0a389a62011-10-03 15:02:34 -0700231 udev_device_get_sysattr_value(dev, kAttributeIdVendor);
Ben Chan120c11c2012-09-10 23:10:18 -0700232 const char *product_id_attr =
Ben Chan0a389a62011-10-03 15:02:34 -0700233 udev_device_get_sysattr_value(dev, kAttributeIdProduct);
Ben Chan120c11c2012-09-10 23:10:18 -0700234 if (vendor_id_attr && product_id_attr) {
235 *vendor_id = vendor_id_attr;
236 *product_id = product_id_attr;
237 return true;
Ben Chan0a389a62011-10-03 15:02:34 -0700238 }
239 }
240 }
Ben Chan120c11c2012-09-10 23:10:18 -0700241 return false;
Ben Chan0a389a62011-10-03 15:02:34 -0700242}
243
Ben Chance7ee542011-04-12 17:02:49 -0700244bool UdevDevice::IsMediaAvailable() const {
245 bool is_media_available = true;
Ben Chan54342622011-08-18 00:57:11 -0700246 if (IsAttributeTrue(kAttributeRemovable)) {
247 if (IsPropertyTrue(kPropertyCDROM)) {
248 is_media_available = IsPropertyTrue(kPropertyCDROMMedia);
Ben Chance7ee542011-04-12 17:02:49 -0700249 } else {
250 const char *dev_file = udev_device_get_devnode(dev_);
Ben Chanf51ff002011-04-25 12:41:57 -0700251 if (dev_file) {
252 int fd = open(dev_file, O_RDONLY);
253 if (fd < 0) {
254 is_media_available = false;
255 } else {
256 close(fd);
257 }
Ben Chance7ee542011-04-12 17:02:49 -0700258 }
259 }
260 }
261 return is_media_available;
262}
263
Ben Chan1f418382013-06-17 23:33:28 -0700264bool UdevDevice::IsMobileBroadbandDevice() const {
265 // Check if a parent device, which belongs to the "usb" subsystem and has a
266 // device type "usb_device", has a property "MIST_SUPPORTED_DEVICE=1". If so,
267 // it is a mobile broadband device supported by mist.
268 struct udev_device* parent = udev_device_get_parent_with_subsystem_devtype(
269 dev_, kSubsystemUsb, kPropertyDeviceTypeUSBDevice);
270 if (!parent)
271 return false;
272
273 const char* value =
274 udev_device_get_property_value(parent, kPropertyMistSupportedDevice);
275 return IsValueBooleanTrue(value);
276}
277
Ben Chan0255db62011-09-19 12:14:28 -0700278bool UdevDevice::IsAutoMountable() const {
Ben Chan9b425702011-09-07 10:57:09 -0700279 // TODO(benchan): Find a reliable way to detect if a device is a removable
280 // storage as the removable attribute in sysfs does not always tell the truth.
Ben Chana4b96512012-04-10 17:37:42 -0700281 return !IsOnBootDevice() && !IsVirtual();
Ben Chan0255db62011-09-19 12:14:28 -0700282}
Ben Chanf8692882011-08-21 10:15:30 -0700283
Ben Chan0255db62011-09-19 12:14:28 -0700284bool UdevDevice::IsHidden() {
285 if (IsPropertyTrue(kPropertyPresentationHide))
286 return true;
287
Ben Chana0fe0ef2012-09-06 23:39:56 -0700288 // Hide an optical disc without any data track.
289 // udev/cdrom_id only sets ID_CDROM_MEDIA_TRACK_COUNT_DATA when there is at
290 // least one data track.
291 if (IsPropertyTrue(kPropertyCDROM) &&
292 !HasProperty(kPropertyCDROMMediaTrackCountData)) {
293 return true;
294 }
295
Ben Chan1f418382013-06-17 23:33:28 -0700296 // Hide a mobile broadband device, which may initially expose itself as a USB
297 // mass storage device and later be switched to a modem by mist.
298 if (IsMobileBroadbandDevice())
299 return true;
300
Ben Chan0255db62011-09-19 12:14:28 -0700301 // Hide a device that is neither marked as a partition nor a filesystem,
Ben Chanca369942011-09-10 17:03:05 -0700302 // unless it has no valid partitions (e.g. the device is unformatted or
Ben Chan0255db62011-09-19 12:14:28 -0700303 // corrupted). An unformatted or corrupted device is visible in the file
304 // the file browser so that we can provide a way to format it.
Ben Chanf8692882011-08-21 10:15:30 -0700305 if (!HasAttribute(kAttributePartition) &&
Ben Chanca369942011-09-10 17:03:05 -0700306 !HasProperty(kPropertyFilesystemUsage) &&
Ben Chan53e12a22014-02-13 23:34:09 -0800307 (GetPartitionCount() > 0))
Ben Chan0255db62011-09-19 12:14:28 -0700308 return true;
Ben Chan1c2d4252011-06-03 13:33:49 -0700309
Ben Chancac20332014-02-13 23:21:17 -0800310 // Hide special partitions based on partition type.
311 string partition_type = GetProperty(kPropertyPartitionEntryType);
312 if (!partition_type.empty()) {
313 for (size_t i = 0; i < arraysize(kPartitionTypesToHide); ++i) {
314 if (partition_type == kPartitionTypesToHide[i])
Ben Chan0255db62011-09-19 12:14:28 -0700315 return true;
Ben Chan1c2d4252011-06-03 13:33:49 -0700316 }
317 }
Ben Chan0255db62011-09-19 12:14:28 -0700318 return false;
Ben Chan1c2d4252011-06-03 13:33:49 -0700319}
320
Ben Chan2923ed72013-07-29 15:52:29 -0700321bool UdevDevice::IsIgnored() const {
322 return IsVirtual() && !IsLoopDevice();
323}
324
Ben Chan490319f2011-05-06 14:00:42 -0700325bool UdevDevice::IsOnBootDevice() const {
326 // Obtain the boot device path, e.g. /dev/sda
327 char boot_device_path[PATH_MAX];
328 if (rootdev(boot_device_path, sizeof(boot_device_path), true, true)) {
329 LOG(ERROR) << "Could not determine root device";
330 // Assume it is on the boot device when there is any uncertainty.
331 // This is to prevent a device, which is potentially on the boot device,
332 // from being auto mounted and exposed to users.
333 // TODO(benchan): Find a way to eliminate the uncertainty.
334 return true;
335 }
336
337 // Compare the device file path of the current device and all its parents
338 // with the boot device path. Any match indicates that the current device
339 // is on the boot device.
Ben Chan54342622011-08-18 00:57:11 -0700340 for (struct udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
Ben Chan490319f2011-05-06 14:00:42 -0700341 const char *dev_file = udev_device_get_devnode(dev);
342 if (dev_file) {
343 if (strncmp(boot_device_path, dev_file, PATH_MAX) == 0) {
344 return true;
345 }
346 }
347 }
348 return false;
349}
350
Ben Chan58aad1d2013-02-26 16:09:34 -0800351bool UdevDevice::IsOnMMCDevice() const {
352 for (struct udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
353 const char *driver = udev_device_get_driver(dev);
354 if (driver && strcmp(driver, kDriverMMCBlock) == 0) {
355 return true;
356 }
357 }
358 return false;
359}
360
Ben Chan54342622011-08-18 00:57:11 -0700361bool UdevDevice::IsOnRemovableDevice() const {
362 for (struct udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
363 const char *value = udev_device_get_sysattr_value(dev, kAttributeRemovable);
364 if (IsValueBooleanTrue(value))
365 return true;
366 }
367 return false;
368}
369
Ben Chan9cda93a2011-05-24 13:31:04 -0700370bool UdevDevice::IsVirtual() const {
371 const char *sys_path = udev_device_get_syspath(dev_);
372 if (sys_path) {
Ben Chan54342622011-08-18 00:57:11 -0700373 return StartsWithASCII(sys_path, kVirtualDevicePathPrefix, true);
Ben Chan9cda93a2011-05-24 13:31:04 -0700374 }
375 // To be safe, mark it as virtual device if sys path cannot be determined.
376 return true;
377}
378
Ben Chan2923ed72013-07-29 15:52:29 -0700379bool UdevDevice::IsLoopDevice() const {
380 const char *sys_path = udev_device_get_syspath(dev_);
381 if (sys_path) {
382 return StartsWithASCII(sys_path, kLoopDevicePathPrefix, true);
383 }
384 return false;
385}
386
Ben Chan190d3cf2011-07-07 09:38:48 -0700387string UdevDevice::NativePath() const {
Ben Chan42888362011-06-09 18:16:24 -0700388 const char *sys_path = udev_device_get_syspath(dev_);
389 return sys_path ? sys_path : "";
390}
391
Ben Chan190d3cf2011-07-07 09:38:48 -0700392vector<string> UdevDevice::GetMountPaths() const {
Ben Chanf51ff002011-04-25 12:41:57 -0700393 const char *device_path = udev_device_get_devnode(dev_);
394 if (device_path) {
395 return GetMountPaths(device_path);
Ben Chance7ee542011-04-12 17:02:49 -0700396 }
Ben Chan190d3cf2011-07-07 09:38:48 -0700397 return vector<string>();
Ben Chance7ee542011-04-12 17:02:49 -0700398}
399
Ben Chan190d3cf2011-07-07 09:38:48 -0700400vector<string> UdevDevice::GetMountPaths(const string& device_path) {
Ben Chanbeefd0d2011-07-25 09:31:34 -0700401 MountInfo mount_info;
402 if (mount_info.RetrieveFromCurrentProcess()) {
403 return mount_info.GetMountPaths(device_path);
Ben Chanf51ff002011-04-25 12:41:57 -0700404 }
Ben Chan190d3cf2011-07-07 09:38:48 -0700405 return vector<string>();
Ben Chanf51ff002011-04-25 12:41:57 -0700406}
407
Ben Chanda410a02011-08-24 23:37:53 -0700408Disk UdevDevice::ToDisk() {
Ben Chance7ee542011-04-12 17:02:49 -0700409 Disk disk;
410
Ben Chan1c2d4252011-06-03 13:33:49 -0700411 disk.set_is_auto_mountable(IsAutoMountable());
Ben Chan54342622011-08-18 00:57:11 -0700412 disk.set_is_read_only(IsAttributeTrue(kAttributeReadOnly));
413 disk.set_is_drive(HasAttribute(kAttributeRange));
414 disk.set_is_rotational(HasProperty(kPropertyRotationRate));
Ben Chan0255db62011-09-19 12:14:28 -0700415 disk.set_is_hidden(IsHidden());
Ben Chance7ee542011-04-12 17:02:49 -0700416 disk.set_is_media_available(IsMediaAvailable());
Ben Chan490319f2011-05-06 14:00:42 -0700417 disk.set_is_on_boot_device(IsOnBootDevice());
Ben Chane80629f2014-07-11 14:31:20 -0700418 disk.set_is_on_removable_device(IsOnRemovableDevice());
Ben Chan9cda93a2011-05-24 13:31:04 -0700419 disk.set_is_virtual(IsVirtual());
Ben Chan0a389a62011-10-03 15:02:34 -0700420 disk.set_media_type(GetDeviceMediaType());
Ben Chanda410a02011-08-24 23:37:53 -0700421 disk.set_filesystem_type(GetPropertyFromBlkId(kPropertyBlkIdFilesystemType));
Ben Chan42888362011-06-09 18:16:24 -0700422 disk.set_native_path(NativePath());
Ben Chance7ee542011-04-12 17:02:49 -0700423
Ben Chan22c0e602012-02-13 12:37:34 -0800424 // Drive model and filesystem label may not be UTF-8 encoded, so we
425 // need to ensure that they are either set to a valid UTF-8 string or
426 // an empty string before later passed to a DBus message iterator.
427 disk.set_drive_model(EnsureUTF8String(GetProperty(kPropertyModel)));
428 disk.set_label(
429 EnsureUTF8String(GetPropertyFromBlkId(kPropertyBlkIdFilesystemLabel)));
430
Ben Chan120c11c2012-09-10 23:10:18 -0700431 string vendor_id, product_id;
432 if (GetVendorAndProductId(&vendor_id, &product_id)) {
433 disk.set_vendor_id(vendor_id);
434 disk.set_product_id(product_id);
435
436 string vendor_name, product_name;
437 USBDeviceInfo info;
438 if (info.GetVendorAndProductName(kUSBIdentifierDatabase,
439 vendor_id, product_id,
440 &vendor_name, &product_name)) {
441 disk.set_vendor_name(EnsureUTF8String(vendor_name));
442 disk.set_product_name(EnsureUTF8String(product_name));
443 }
444 }
445
Ben Chan0e1b5502013-07-24 23:39:29 -0700446 // TODO(benchan): Add a proper unit test when fixing crbug.com/221380.
447 string uuid_hash = base::SHA1HashString(
448 vendor_id + product_id + GetProperty(kPropertySerial) +
449 GetPropertyFromBlkId(kPropertyBlkIdFilesystemUUID));
450 disk.set_uuid(base::HexEncode(uuid_hash.data(), uuid_hash.size()));
451
Ben Chance7ee542011-04-12 17:02:49 -0700452 const char *dev_file = udev_device_get_devnode(dev_);
Ben Chanf51ff002011-04-25 12:41:57 -0700453 if (dev_file)
454 disk.set_device_file(dev_file);
Ben Chance7ee542011-04-12 17:02:49 -0700455
Ben Chan190d3cf2011-07-07 09:38:48 -0700456 vector<string> mount_paths = GetMountPaths();
Ben Chanf51ff002011-04-25 12:41:57 -0700457 disk.set_is_mounted(!mount_paths.empty());
458 disk.set_mount_paths(mount_paths);
Ben Chance7ee542011-04-12 17:02:49 -0700459
Ben Chana169b0a2014-08-06 17:22:40 -0700460 uint64_t total_size, remaining_size;
Ben Chance7ee542011-04-12 17:02:49 -0700461 GetSizeInfo(&total_size, &remaining_size);
462 disk.set_device_capacity(total_size);
463 disk.set_bytes_remaining(remaining_size);
464
465 return disk;
466}
467
468} // namespace cros_disks