Fix hwmon location for kernel >= 2.6.31 (closes sf: #2865628)
authorCesare Tirabassi <norsetto@ubuntu.com>
Sun, 1 Nov 2009 17:37:48 +0000 (18:37 +0100)
committerCesare Tirabassi <norsetto@ubuntu.com>
Sun, 1 Nov 2009 17:37:48 +0000 (18:37 +0100)
In the linux kernel 2.6.31 and above, device data can either be in
/sys/class/hwmon/hwmonDEV or /sys/class/hwmon/hwmonDEV/device.
Just stat'ing for the latter doesn't work since it can exist but not contain
the required data (see https://bugs.launchpad.net/bugs/435571 for details).
The patch could be improved to keep in memory the right location of the data
on the user's system instead of trying each time, but, is it worth doing it?

src/linux.c

index ec7c75d..4d98bfd 100644 (file)
@@ -844,7 +844,6 @@ static int open_sysfs_sensor(const char *dir, const char *dev, const char *type,
        char buf[256];
        int fd;
        int divfd;
-       struct stat st;
 
        memset(buf, 0, sizeof(buf));
 
@@ -871,13 +870,6 @@ static int open_sysfs_sensor(const char *dir, const char *dev, const char *type,
                }
        }
 
-       /* At least the acpitz hwmon doesn't have a 'device' subdir,
-        * so check it's existence and strip it from buf otherwise. */
-       snprintf(path, 255, "%s%s", dir, dev);
-       if (stat(path, &st)) {
-               buf[strlen(buf) - 7] = 0;
-       }
-
        /* change vol to in, tempf to temp */
        if (strcmp(type, "vol") == 0) {
                type = "in";
@@ -885,16 +877,25 @@ static int open_sysfs_sensor(const char *dir, const char *dev, const char *type,
                type = "temp";
        }
 
+       /* construct path */
        snprintf(path, 255, "%s%s/%s%d_input", dir, dev, type, n);
-       strncpy(devtype, path, 255);
 
-       /* open file */
+       /* first, attempt to open file in /device */
        fd = open(path, O_RDONLY);
        if (fd < 0) {
-               CRIT_ERR(NULL, NULL, "can't open '%s': %s\nplease check your device or remove this "
-                       "var from "PACKAGE_NAME, path, strerror(errno));
+
+         /* if it fails, strip the /device from dev and attempt again */
+         buf[strlen(buf) - 7] = 0;
+         snprintf(path, 255, "%s%s/%s%d_input", dir, dev, type, n);
+         fd = open(path, O_RDONLY);
+         if (fd < 0) {
+                 CRIT_ERR(NULL, NULL, "can't open '%s': %s\nplease check your device or remove this "
+                                  "var from "PACKAGE_NAME, path, strerror(errno));
+         }
        }
 
+       strncpy(devtype, path, 255);
+
        if (strcmp(type, "in") == 0 || strcmp(type, "temp") == 0
                        || strcmp(type, "tempf") == 0) {
                *divisor = 1;