OK, I recently received a sysfs-fix.diff, which looks correct to me.
I've fixed the problem in a different way though, on git.sf.net. My
patches are larger, but they should waste less CPU time. The second one
fixes a potential bug in the parser. I'll also make this the 0.8.1
release. Hope that works for debian^^


-------- Original Message --------
Subject:        A thinkfan 0.8 bug and a patch
Date:   Sat, 14 Jul 2012 21:15:54 -0400
From:   M. Vefa Bicakci <m....@runbox.com>
To:     mat...@lih.rwth-aachen.de



Dear Victor Matare,

I have found a bug in thinkfan 0.8 regarding the handling of sysfs files. I am
using a 32-bit Debian Sid installation, up-to-date as of today, on a Thinkpad 
T420.

In summary, instead of writing only the string form of an integer to a sysfs
"pwm" fan control file, thinkfan 0.8 writes the string "level <integer>". As you
will predict, this causes the kernel to report an error, which causes thinkfan
to terminate.

I am attaching a patch which fixes this issue. Even though the way I convert the
level integer to a string is a bit crude, the patch fixes the bug.

Thank you,

M. Vefa Bicakci




Index: thinkfan-0.8.0/globaldefs.h
===================================================================
--- thinkfan-0.8.0.orig/globaldefs.h	2012-05-10 14:37:34.000000000 -0400
+++ thinkfan-0.8.0/globaldefs.h	2012-07-14 20:54:27.188026323 -0400
@@ -95,7 +95,7 @@
 
 struct tf_config *config;
 unsigned long int errcnt;
-int *temps, tmax, last_tmax, lvl_idx, *b_tmax, line_count;
+int *temps, tmax, last_tmax, cur_nlvl, lvl_idx, *b_tmax, line_count;
 unsigned int chk_sanity, watchdog_timeout, num_temps;
 char *config_file, *prefix, *rbuf,
 	*cur_lvl,
Index: thinkfan-0.8.0/system.c
===================================================================
--- thinkfan-0.8.0.orig/system.c	2012-05-10 14:37:34.000000000 -0400
+++ thinkfan-0.8.0/system.c	2012-07-14 20:56:06.332031818 -0400
@@ -249,14 +249,20 @@
  * Set fan speed (sysfs interface).
  ***********************************************************/
 void setfan_sysfs() {
-	int fan, l = strlen(cur_lvl);
+	#define INT_STR_SIZE 128
+	int fan, l;
+	char buf[INT_STR_SIZE];
 
-	if (unlikely((fan = open(config->fan, O_WRONLY)) < 0)) {
+	if (unlikely((l = snprintf(buf, INT_STR_SIZE, "%d", cur_nlvl)) >= INT_STR_SIZE)) {
+		report(LOG_ERR, LOG_ERR, "%d is too large!\n", cur_nlvl);
+		errcnt++;
+	}
+	else if (unlikely((fan = open(config->fan, O_WRONLY)) < 0)) {
 		report(LOG_ERR, LOG_ERR, "%s: %s\n", config->fan, strerror(errno));
 		errcnt++;
 	}
 	else {
-		if (unlikely(write(fan, cur_lvl, l) < l)) {
+		if (unlikely(write(fan, buf, l) < l)) {
 			report(LOG_ERR, LOG_ERR, MSG_ERR_FANCTRL);
 			errcnt++;
 		}
Index: thinkfan-0.8.0/thinkfan.c
===================================================================
--- thinkfan-0.8.0.orig/thinkfan.c	2012-05-10 14:37:34.000000000 -0400
+++ thinkfan-0.8.0/thinkfan.c	2012-07-14 20:54:27.191026323 -0400
@@ -37,6 +37,7 @@
 unsigned int sleeptime, tmp_sleeptime;
 
 #define set_fan cur_lvl = config->limits[lvl_idx].level; \
+	cur_nlvl = config->limits[lvl_idx].nlevel; \
 	if (!quiet && nodaemon) \
 	report(LOG_DEBUG, LOG_DEBUG, MSG_DBG_T_STAT); \
 	config->setfan();

From 6de7d99e8cb95d15117454ffc5eea037bef54656 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Victor=20Matar=C3=A9?= <mat...@lih.rwth-aachen.de>
Date: Fri, 10 Aug 2012 21:42:15 +0200
Subject: [PATCH 1/2] fix sysfs fan level string

---
 config.c     |    9 ++++++---
 globaldefs.h |    4 ++--
 system.c     |    3 ++-
 thinkfan.c   |    3 +--
 4 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/config.c b/config.c
index 9ccf794..2b34532 100644
--- a/config.c
+++ b/config.c
@@ -183,7 +183,7 @@ struct tf_config *readconfig(char* fname) {
                cfg_local->uninit_fan = uninit_fan_ibm;
        }
 
-       cur_lvl = cfg_local->limits[cfg_local->num_limits - 1].level;
+       lvl_idx = cfg_local->num_limits - 1;
 
        // configure sensor interface
        if (cfg_local->num_sensors > 0 &&
@@ -310,6 +310,8 @@ static int add_limit(struct tf_config *cfg, struct limit 
*limit) {
        long int tmp;
        char *end, *conv_lvl;
 
+       limit->sysfslevel = NULL;
+
        // Check formatting of level string...
        tmp = strtol(limit->level, &end, 0);
        if (tmp < INT_MIN || tmp > INT_MAX) {
@@ -324,13 +326,13 @@ static int add_limit(struct tf_config *cfg, struct limit 
*limit) {
        }
        else if (*end == 0) {
                // just a number
+               limit->sysfslevel = limit->level;
                conv_lvl = calloc(7 + strlen(limit->level), sizeof(char));
                snprintf(conv_lvl, 7 + strlen(limit->level), "level %d", 
(int)tmp);
-               free(limit->level);
                limit->level = conv_lvl;
                limit->nlevel = (int)tmp;
        }
-       else if (sscanf(limit->level, "level %d", (int * )&tmp)) {
+       else if (sscanf(limit->level, "level %d", (int *)&tmp)) {
                limit->nlevel = (int)tmp;
        }
        else if (!strcmp(limit->level, "level disengaged")
@@ -403,6 +405,7 @@ void free_config(struct tf_config *cfg) {
        }
        for (j=0; j < cfg->num_limits; j++) {
                free(cfg->limits[j].level);
+               free(cfg->limits[j].sysfslevel);
                free(cfg->limits[j].low);
                free(cfg->limits[j].high);
        }
diff --git a/globaldefs.h b/globaldefs.h
index c3b9fc2..99099bc 100644
--- a/globaldefs.h
+++ b/globaldefs.h
@@ -65,7 +65,8 @@
 #define unlikely(x)     __builtin_expect((x),0)
 
 struct limit {
-       char *level; // this is written to the fan control file.
+       char *level; // "level x" representation for /proc/acpi/ibm/fan.
+       char *sysfslevel; // numeric representation for /sys/class/hwmon
        int nlevel;   // A numeric interpretation of the level
        int *low;   // int array specifying the LOWER limit, terminated by 
INT_MIN
        int *high;  // dito for UPPER limit.
@@ -98,7 +99,6 @@ unsigned long int errcnt;
 int *temps, tmax, last_tmax, lvl_idx, *b_tmax, line_count;
 unsigned int chk_sanity, watchdog_timeout, num_temps;
 char *config_file, *prefix, *rbuf,
-       *cur_lvl,
        errmsg[1024],
        quiet, nodaemon, resume_is_safe,
        *oldpwm; // old contents of pwm*_enable, used for uninit_fan()
diff --git a/system.c b/system.c
index 7dfb3de..df4999d 100644
--- a/system.c
+++ b/system.c
@@ -109,6 +109,7 @@ int get_temps_ibm() {
  * Set fan speed (IBM interface).
  ***********************************************************/
 void setfan_ibm() {
+       char *cur_lvl = config->limits[lvl_idx].level;
        int ibm_fan, l = strlen(cur_lvl);
 
        if (unlikely((ibm_fan = open(IBM_FAN, O_RDWR, O_TRUNC)) < 0)) {
@@ -249,6 +250,7 @@ int get_temps_sysfs() {
  * Set fan speed (sysfs interface).
  ***********************************************************/
 void setfan_sysfs() {
+       char *cur_lvl = config->limits[lvl_idx].sysfslevel;
        int fan, l = strlen(cur_lvl);
 
        if (unlikely((fan = open(config->fan, O_WRONLY)) < 0)) {
@@ -322,7 +324,6 @@ void init_fan_sysfs() {
 
        if ((fd = open(fan_enable, O_WRONLY)) < 0) {
                report(LOG_ERR, LOG_ERR, "%s: %s\n", fan_enable, 
strerror(errno));
-               free(fan_enable);
                errcnt |= ERR_FAN_INIT;
                goto fail;
        }
diff --git a/thinkfan.c b/thinkfan.c
index 4f627f1..31291f0 100644
--- a/thinkfan.c
+++ b/thinkfan.c
@@ -36,7 +36,7 @@
 volatile int interrupted;
 unsigned int sleeptime, tmp_sleeptime;
 
-#define set_fan cur_lvl = config->limits[lvl_idx].level; \
+#define set_fan \
        if (!quiet && nodaemon) \
        report(LOG_DEBUG, LOG_DEBUG, MSG_DBG_T_STAT); \
        config->setfan();
@@ -184,7 +184,6 @@ int main(int argc, char **argv) {
        last_tmax = 0;
        tmax = 0;
        temps = NULL;
-       cur_lvl = NULL;
 
        openlog("thinkfan", LOG_CONS, LOG_USER);
        syslog(LOG_INFO, "thinkfan " VERSION " starting...");
-- 
1.7.8.6

From 4a997a99bda24ba9815792513ffcaae39f4099bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Victor=20Matar=C3=A9?= <mat...@lih.rwth-aachen.de>
Date: Sat, 11 Aug 2012 00:19:41 +0200
Subject: [PATCH 2/2] parser.c: fix quotation parsing

---
 parser.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/parser.c b/parser.c
index ab0c0c1..fff923b 100644
--- a/parser.c
+++ b/parser.c
@@ -311,7 +311,10 @@ char *parse_quotation(char **input, const char *mark) {
        int oldlc = line_count;
 
        start = *input;
-       if (!char_alt(input, mark, 0)) return NULL;
+       if (!char_alt(input, mark, 0)) {
+               *input = start;
+               return NULL;
+       }
        ret = char_cat(input, mark, 1);
        if (!ret) {
                ret = malloc(sizeof(char));
@@ -321,6 +324,7 @@ char *parse_quotation(char **input, const char *mark) {
                free(ret);
                ret = NULL;
                line_count = oldlc;
+               *input = start;
        }
        return ret;
 }
-- 
1.7.8.6

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to