shill: Clean up GetDeviceTechnology
Make GetDeviceTechnology more libbasey. This has the bonus
of losing the fd leak that the previous code had.
BUG=chromium-os:23849
TEST=Rerun unit tests (for regression), run on a real system:
- Ensure lo is treated as "Unknown", usb0 (gobi) treated as cellular
and wlan0 treated as wifi. Ensure correct VLOC messages displayed in
each case.
- Ensure (via monitoring of /proc/###/fd) that fd list for shill
process remains constant over multiple plug/unplug events.
Change-Id: I3c4fea5a74efa7d3a45b6a23c55806c1486cde8a
Reviewed-on: https://gerrit.chromium.org/gerrit/12525
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
diff --git a/device_info.cc b/device_info.cc
index c886eb1..90487c6 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -45,6 +45,8 @@
// static
const char DeviceInfo::kInterfaceUevent[] = "/sys/class/net/%s/uevent";
// static
+const char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n";
+// static
const char DeviceInfo::kInterfaceDriver[] = "/sys/class/net/%s/device/driver";
// static
const char *DeviceInfo::kModemDrivers[] = {
@@ -105,47 +107,46 @@
Technology::Identifier DeviceInfo::GetDeviceTechnology(
const string &iface_name) {
- char contents[1024];
- int length;
- int fd;
- string uevent_file = StringPrintf(kInterfaceUevent, iface_name.c_str());
- string driver_file = StringPrintf(kInterfaceDriver, iface_name.c_str());
- const char *wifi_type;
- const char *driver_name;
- int modem_idx;
-
- fd = open(uevent_file.c_str(), O_RDONLY);
- if (fd < 0)
+ FilePath uevent_file(StringPrintf(kInterfaceUevent, iface_name.c_str()));
+ string contents;
+ if (!file_util::ReadFileToString(uevent_file, &contents)) {
+ VLOG(2) << StringPrintf("%s: device %s has no uevent file",
+ __func__, iface_name.c_str());
return Technology::kUnknown;
-
- length = read(fd, contents, sizeof(contents) - 1);
- if (length < 0)
- return Technology::kUnknown;
+ }
/*
* If the "uevent" file contains the string "DEVTYPE=wlan\n" at the
* start of the file or after a newline, we can safely assume this
* is a wifi device.
*/
- contents[length] = '\0';
- wifi_type = strstr(contents, "DEVTYPE=wlan\n");
- if (wifi_type != NULL && (wifi_type == contents || wifi_type[-1] == '\n'))
+ if (contents.find(kInterfaceUeventWifiSignature) != string::npos) {
+ VLOG(2) << StringPrintf("%s: device %s has wifi signature in uevent file",
+ __func__, iface_name.c_str());
return Technology::kWifi;
-
- length = readlink(driver_file.c_str(), contents, sizeof(contents)-1);
- if (length < 0)
- return Technology::kUnknown;
-
- contents[length] = '\0';
- driver_name = strrchr(contents, '/');
- if (driver_name != NULL) {
- driver_name++;
- // See if driver for this interface is in a list of known modem driver names
- for (modem_idx = 0; kModemDrivers[modem_idx] != NULL; modem_idx++)
- if (strcmp(driver_name, kModemDrivers[modem_idx]) == 0)
- return Technology::kCellular;
}
+ FilePath driver_file(StringPrintf(kInterfaceDriver, iface_name.c_str()));
+ FilePath driver_path;
+ if (!file_util::ReadSymbolicLink(driver_file, &driver_path)) {
+ VLOG(2) << StringPrintf("%s: device %s has no device symlink",
+ __func__, iface_name.c_str());
+ return Technology::kUnknown;
+ }
+
+ string driver_name(driver_path.BaseName().value());
+ // See if driver for this interface is in a list of known modem driver names
+ for (int modem_idx = 0; kModemDrivers[modem_idx] != NULL; ++modem_idx) {
+ if (driver_name == kModemDrivers[modem_idx]) {
+ VLOG(2) << StringPrintf("%s: device %s is matched with modem driver %s",
+ __func__, iface_name.c_str(),
+ driver_name.c_str());
+ return Technology::kCellular;
+ }
+ }
+
+ VLOG(2) << StringPrintf("%s: device %s is is defaulted to type ethernet",
+ __func__, iface_name.c_str());
return Technology::kEthernet;
}