[collectd] Patch: collectd hddtemp support, second tentative

Vincent Stehlé collectd@verplant.org
Sat, 08 Oct 2005 03:27:41 +0200


This is a multi-part message in MIME format.
--------------000407000208000409080108
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit


Sorry for the previous partial patch. It seems I am not quite used to 
GNU/arch for now.

Hopefully, that patch will be ok.

Regards,

-- 
Vincent Stehlé

--------------000407000208000409080108
Content-Type: text/plain;
 name="patch-2.1.0-vs"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
 filename="patch-2.1.0-vs"

diff -urN collectd-2.1.0/AUTHORS collectd-2.1.0-vs/AUTHORS
--- collectd-2.1.0/AUTHORS	2005-10-08 03:22:10.996842720 +0200
+++ collectd-2.1.0-vs/AUTHORS	2005-10-08 03:22:21.930806617 +0200
@@ -1,6 +1,9 @@
 This package was written by:
   Florian octo Forster <octo@verplant.org>
 
+hddtemp support by:
+  Vincent Stehlé <vincent.stehle@free.fr>
+
 It is available at:
   http://verplant.org/collectd/
 
diff -urN collectd-2.1.0/ChangeLog collectd-2.1.0-vs/ChangeLog
--- collectd-2.1.0/ChangeLog	2005-10-08 03:22:11.008840486 +0200
+++ collectd-2.1.0-vs/ChangeLog	2005-10-08 03:22:21.950802893 +0200
@@ -1,3 +1,6 @@
+2005-09-29, Version 2.0.1-vs
+	* Module for hddtemp added by Vincent Stehlé <vincent.stehle@free.fr>.
+
 2005-09-16, Version 2.0.1 (Revision 170)
 	* A module for swap statistics has been added.
 
diff -urN collectd-2.1.0/README collectd-2.1.0-vs/README
--- collectd-2.1.0/README	2005-10-08 03:22:11.035835459 +0200
+++ collectd-2.1.0-vs/README	2005-10-08 03:22:21.970799169 +0200
@@ -90,4 +90,3 @@
 ------
 
   Florian octo Forster <octo at verplant.org>
-
diff -urN collectd-2.1.0/collectd.spec collectd-2.1.0-vs/collectd.spec
--- collectd-2.1.0/collectd.spec	2005-10-08 03:22:11.067829502 +0200
+++ collectd-2.1.0-vs/collectd.spec	2005-10-08 03:22:21.989795632 +0200
@@ -1,6 +1,6 @@
 Summary:	Statistics collection daemon for filling RRD files.
 Name:           collectd
-Version:	2.1.0
+Version:	2.1.0-vs
 Release:	1
 Source:		http://verplant.org/collectd/%{name}-%{version}.tar.gz
 License:	GPL
@@ -48,6 +48,9 @@
 %dir /var/lib/collectd
 
 %changelog
+* Thr Sep 29 2005 Vincent Stehlé <vincent.stehle@free.fr> 2.0.1-vs
+- hddtemp support
+
 * Mon Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
 - New upstream version
 
diff -urN collectd-2.1.0/configure collectd-2.1.0-vs/configure
--- collectd-2.1.0/configure	2005-10-08 03:22:11.162811814 +0200
+++ collectd-2.1.0-vs/configure	2005-10-08 03:22:22.828639421 +0200
@@ -1040,6 +1040,7 @@
   --disable-sensors       Disable lm_sensors statistics
   --disable-swap          Disable swap statistics
   --disable-traffic       Disable system traffic statistics
+  --disable-hddtemp       Disable hdd temperature statistics
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1814,7 +1815,7 @@
 
 # Define the identity of the package.
  PACKAGE=collectd
- VERSION=2.1.0
+ VERSION=2.1.0-vs
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3963,7 +3964,7 @@
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 3966 "configure"' > conftest.$ac_ext
+  echo '#line 3967 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -5293,7 +5294,7 @@
 
 
 # Provide some information about the compiler.
-echo "$as_me:5296:" \
+echo "$as_me:5297:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -6325,11 +6326,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6328: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6329: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6332: \$? = $ac_status" >&5
+   echo "$as_me:6333: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -6558,11 +6559,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6561: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6562: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6565: \$? = $ac_status" >&5
+   echo "$as_me:6566: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -6618,11 +6619,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6621: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6622: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:6625: \$? = $ac_status" >&5
+   echo "$as_me:6626: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -8806,7 +8807,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 8809 "configure"
+#line 8810 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -8904,7 +8905,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 8907 "configure"
+#line 8908 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11081,11 +11082,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11084: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11085: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:11088: \$? = $ac_status" >&5
+   echo "$as_me:11089: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -11141,11 +11142,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11144: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11145: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:11148: \$? = $ac_status" >&5
+   echo "$as_me:11149: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -12510,7 +12511,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 12513 "configure"
+#line 12514 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12608,7 +12609,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 12611 "configure"
+#line 12612 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13435,11 +13436,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13438: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13439: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13442: \$? = $ac_status" >&5
+   echo "$as_me:13443: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -13495,11 +13496,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13498: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13499: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13502: \$? = $ac_status" >&5
+   echo "$as_me:13503: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -15540,11 +15541,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15543: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15544: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15547: \$? = $ac_status" >&5
+   echo "$as_me:15548: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -15773,11 +15774,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15776: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15777: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15780: \$? = $ac_status" >&5
+   echo "$as_me:15781: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -15833,11 +15834,11 @@
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15836: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15837: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15840: \$? = $ac_status" >&5
+   echo "$as_me:15841: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -18021,7 +18022,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 18024 "configure"
+#line 18025 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -18119,7 +18120,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 18122 "configure"
+#line 18123 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -23789,6 +23790,22 @@
 
 fi
 
+# Check whether --enable-hddtemp or --disable-hddtemp was given.
+if test "${enable_hddtemp+set}" = set; then
+  enableval="$enable_hddtemp"
+
+else
+  enable_hddtemp="yes"
+fi;
+if test "x$enable_hddtemp" = "xno"
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define COLLECT_HDDTEMP 0
+_ACEOF
+
+fi
+
                               ac_config_files="$ac_config_files Makefile src/libping/Makefile src/Makefile"
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -25239,6 +25256,7 @@
     sensors . . . . . . $enable_sensors
     swap  . . . . . . . $enable_swap
     traffic . . . . . . $enable_traffic
+    hddtemp . . . . . . $enable_hddtemp
 
 (*) Enabled features are not neccessarily compiled in. Wether or not a feature
     is included depends on wether or not your system provides the required
diff -urN collectd-2.1.0/configure.in collectd-2.1.0-vs/configure.in
--- collectd-2.1.0/configure.in	2005-10-08 03:22:11.168810697 +0200
+++ collectd-2.1.0-vs/configure.in	2005-10-08 03:22:22.850635325 +0200
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(src/collectd.c)
-AM_INIT_AUTOMAKE(collectd, 2.1.0)
+AM_INIT_AUTOMAKE(collectd, 2.1.0-vs)
 AM_CONFIG_HEADER(src/config.h src/libping/config.h)
 AC_LANG(C)
 
@@ -194,6 +194,12 @@
 	AC_DEFINE(COLLECT_TRAFFIC, 0, [Wether or not to collect network traffic statistics])
 fi
 
+AC_ARG_ENABLE(hddtemp, AC_HELP_STRING([--disable-hddtemp], [Disable hdd temperature statistics]),, [enable_hddtemp="yes"])
+if test "x$enable_hddtemp" = "xno"
+then
+	AC_DEFINE(COLLECT_HDDTEMP, 0, [Wether or not to collect hdd temperature statistics])
+fi
+
 AC_OUTPUT(Makefile src/libping/Makefile src/Makefile)
 
 cat <<EOF;
@@ -214,6 +220,7 @@
     sensors . . . . . . $enable_sensors
     swap  . . . . . . . $enable_swap
     traffic . . . . . . $enable_traffic
+    hddtemp . . . . . . $enable_hddtemp
 
 (*) Enabled features are not neccessarily compiled in. Wether or not a feature
     is included depends on wether or not your system provides the required
diff -urN collectd-2.1.0/src/.arch-ids/hddtemp.c.id collectd-2.1.0-vs/src/.arch-ids/hddtemp.c.id
--- collectd-2.1.0/src/.arch-ids/hddtemp.c.id	1970-01-01 01:00:00.000000000 +0100
+++ collectd-2.1.0-vs/src/.arch-ids/hddtemp.c.id	2005-10-08 03:22:21.895813133 +0200
@@ -0,0 +1 @@
+Vincent Stehle <vincent.stehle@free.fr> Thu Sep 29 23:14:43 2005 11590.0
diff -urN collectd-2.1.0/src/.arch-ids/hddtemp.h.id collectd-2.1.0-vs/src/.arch-ids/hddtemp.h.id
--- collectd-2.1.0/src/.arch-ids/hddtemp.h.id	1970-01-01 01:00:00.000000000 +0100
+++ collectd-2.1.0-vs/src/.arch-ids/hddtemp.h.id	2005-10-08 03:22:21.900812202 +0200
@@ -0,0 +1 @@
+Vincent Stehle <vincent.stehle@free.fr> Thu Sep 29 23:14:43 2005 11590.1
diff -urN collectd-2.1.0/src/Makefile.am collectd-2.1.0-vs/src/Makefile.am
--- collectd-2.1.0/src/Makefile.am	2005-10-08 03:22:11.597730826 +0200
+++ collectd-2.1.0-vs/src/Makefile.am	2005-10-08 03:22:22.114772359 +0200
@@ -11,7 +11,8 @@
 		   ping.c ping.h \
 		   sensors.c sensors.h \
 		   swap.c swap.h \
-		   traffic.c traffic.h
+		   traffic.c traffic.h \
+		   hddtemp.c hddtemp.h
 
 collectd_LDADD = libping/libping.la
 
diff -urN collectd-2.1.0/src/Makefile.in collectd-2.1.0-vs/src/Makefile.in
--- collectd-2.1.0/src/Makefile.in	2005-10-08 03:22:11.605729336 +0200
+++ collectd-2.1.0-vs/src/Makefile.in	2005-10-08 03:22:25.077220687 +0200
@@ -54,7 +54,7 @@
 am_collectd_OBJECTS = collectd.$(OBJEXT) common.$(OBJEXT) \
 	cpu.$(OBJEXT) diskstats.$(OBJEXT) load.$(OBJEXT) \
 	meminfo.$(OBJEXT) ping.$(OBJEXT) sensors.$(OBJEXT) \
-	swap.$(OBJEXT) traffic.$(OBJEXT)
+	swap.$(OBJEXT) traffic.$(OBJEXT) hddtemp.$(OBJEXT)
 collectd_OBJECTS = $(am_collectd_OBJECTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I. -I$(top_builddir)/src/libping
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -193,7 +193,8 @@
 		   ping.c ping.h \
 		   sensors.c sensors.h \
 		   swap.c swap.h \
-		   traffic.c traffic.h
+		   traffic.c traffic.h \
+		   hddtemp.c hddtemp.h
 
 collectd_LDADD = libping/libping.la
 collectd_DEPENDENCIES = libping/libping.la
@@ -293,6 +294,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskstats.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meminfo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ping.Po@am__quote@
diff -urN collectd-2.1.0/src/collectd.c collectd-2.1.0-vs/src/collectd.c
--- collectd-2.1.0/src/collectd.c	2005-10-08 03:22:11.616727288 +0200
+++ collectd-2.1.0-vs/src/collectd.c	2005-10-08 03:22:22.156764539 +0200
@@ -8,6 +8,7 @@
 #include "sensors.h"
 #include "swap.h"
 #include "traffic.h"
+#include "hddtemp.h"
 
 static int loop = 0;
 static char basedir[PATH_MAX];
@@ -102,6 +103,9 @@
 #if COLLECT_TRAFFIC
 	traffic_init ();
 #endif
+#if COLLECT_HDDTEMP
+	hddtemp_init ();
+#endif
 } /* init_all */
 
 #ifdef HAVE_LIBKSTAT
@@ -151,8 +155,10 @@
 			"  Sensors:   %s\n"
 			"  Swap:      %s\n"
 			"  Traffic:   %s\n"
+			"  Hddtemp:   %s\n"
 			"\n%s %s, http://verplant.org/collectd/\n"
-			"by Florian octo Forster <octo@verplant.org>\n",
+			"by Florian octo Forster <octo@verplant.org>\n"
+			"hddtemp support by Vincent Stehlé <vincent.stehle@free.fr>\n",
 			PACKAGE,
 			(COLLECT_CPU     ? "yes" : "no"),
 			(COLLECT_DISK    ? "yes" : "no"),
@@ -162,6 +168,7 @@
 			(COLLECT_SENSORS ? "yes" : "no"),
 			(COLLECT_SWAP    ? "yes" : "no"),
 			(COLLECT_TRAFFIC ? "yes" : "no"),
+			(COLLECT_HDDTEMP ? "yes" : "no"),
 			PACKAGE, VERSION);
 	exit (0);
 }
@@ -288,6 +295,9 @@
 #if COLLECT_TRAFFIC
 		traffic_update ();
 #endif
+#if COLLECT_HDDTEMP
+		hddtemp_update ();
+#endif
 
 #if DEBUG
 		fputs ("Sleeping for 10 seconds\n", stdout);
diff -urN collectd-2.1.0/src/config.h.in collectd-2.1.0-vs/src/config.h.in
--- collectd-2.1.0/src/config.h.in	2005-10-08 03:22:11.636723565 +0200
+++ collectd-2.1.0-vs/src/config.h.in	2005-10-08 03:22:22.961614659 +0200
@@ -6,6 +6,9 @@
 /* Wether or not to collect diskstats */
 #undef COLLECT_DISK
 
+/* Wether or not to collect hdd temperature statistics */
+#undef COLLECT_HDDTEMP
+
 /* Wether or not to collect system load statistics */
 #undef COLLECT_LOAD
 
diff -urN collectd-2.1.0/src/hddtemp.c collectd-2.1.0-vs/src/hddtemp.c
--- collectd-2.1.0/src/hddtemp.c	1970-01-01 01:00:00.000000000 +0100
+++ collectd-2.1.0-vs/src/hddtemp.c	2005-10-08 03:22:25.098216777 +0200
@@ -0,0 +1,555 @@
+/* hddtemp "collector" for collectd 
+   Author: Vincent Stehlé <vincent.stehle@free.fr>
+
+
+   This program is free software; you can distribute it and/or modify it
+   under the terms of the GNU General Public License (Version 2) as
+   published by the Free Software Foundation.
+
+   This program is distributed in the hope it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+
+
+   The following data sources are stored in each disk's rrd file:
+     temperature: Hard disk temperature, in whatever unit the daemon
+                  reported. Currently, your best bet is that this is °C.
+     code:        The status reported from the hddtemp daemon, as coded in
+                  our manner, in [0 : 5] (see the enum for details).
+
+   Here is a sample command to graph the stored rrd:
+
+   rrdtool graph temperature.png \
+     DEF:t=$rrd:temperature:MAX \
+     LINE2:t#7777ff:temperature \
+     DEF:c=$rrd:code:MAX \
+     LINE2:c#ff0000:code
+
+   You will notice that while the drive sleeps, the temperature is unknown.
+
+*/
+
+#include "hddtemp.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if COLLECT_HDDTEMP
+
+/* LOCALHOST_ADDR
+   The ip address 127.0.0.1, as a 32 bit. */
+
+#define LOCALHOST_ADDR ((127 << 24) | 1)
+
+/* HDDTEMP_PORT
+   The tcp port the hddtemp daemon is listening on. */
+
+#define HDDTEMP_PORT 7634
+
+/* BUFFER_SIZE
+   Size of the buffer we use to receive from the hddtemp daemon. */
+
+#define BUFFER_SIZE 1024
+
+/* DEVICE_NAME_SIZE
+   Maximum size for a disk device name, including terminating \0. */
+
+#define DEVICE_NAME_SIZE 32
+
+/* MODEL_NAME_SIZE
+   Maximum size for a disk model name, including terminating \0. */
+
+#define MODEL_NAME_SIZE 32
+
+/* CODE_STRING_SIZE
+   Maximum size for a hddtemp code, including terminating \0. */
+
+#define CODE_STRING_SIZE 4
+
+/* UNIT_STRING_SIZE
+   Maximum size for temperature unit, including terminating \0. */
+
+#define UNIT_STRING_SIZE 2
+
+/* hddtemp_code
+   Enum, corresponding to hddtemp "return code". */
+
+enum hddtemp_code {
+	KNOWN			= 0,
+	NOT_APPLICABLE	= 1,
+	UNKNOWN 		= 2,
+	NOSENSOR		= 3,
+	DRIVE_SLEEP 	= 4,
+	ERROR			= 5
+};
+
+/* disk_infos
+   The structure we use to handle per-disk information.
+
+   Fields worth describing:
+     device_name: disk device. e.g. /dev/hda
+     model_name:  disk model. e.g. ST340014A
+     unit:        temperature unit. e.g. C 
+
+   Note: the temperature is only valid when the hddtemp code is "KNOWN".
+
+ */
+
+struct disk_infos {
+	int temperature;
+	enum hddtemp_code code;
+	char device_name[DEVICE_NAME_SIZE],
+		model_name[MODEL_NAME_SIZE],
+		code_as_string[CODE_STRING_SIZE],
+		unit[UNIT_STRING_SIZE];
+};
+
+/* buffer
+   The buffer we use to receive data from the hddtemp daemon. */
+
+static char buffer[BUFFER_SIZE];
+
+/* num_disks
+   Number of disks in the system, or < 0 if an error happened */
+
+static int num_disks;
+
+/* disks_infos
+   Buffer to hold all disks informations. */
+
+static struct disk_infos *disks_infos;
+
+/* debug
+   debug printing, when DEBUG is defined */
+
+static void debug(const char *message)
+{
+#	if DEBUG
+	syslog(LOG_ERR, message);
+#	endif
+}
+
+/* ask_hddtemp_daemon_for_data
+   Connect to the hddtemp daemon and receive data.
+
+   Parameters:
+     buffer:      the buffer where we put the received ascii string.
+     buffer_size: size of the buffer
+
+   Return value:
+     >= 0 if ok, < 0 otherwise.
+
+   Example of possible strings, as received from daemon:
+
+	   |/dev/hda|ST340014A|36|C|
+	   |/dev/hda|ST380011A|46|C||/dev/hdd|ST340016A|SLP|*|
+
+   Note: we need to create a new socket each time. Is there another way? */
+
+static int ask_hddtemp_daemon_for_data(char *buffer, unsigned buffer_size)
+{
+	int sock;
+	size_t size;
+	const struct sockaddr_in addr = {
+		AF_INET,					/* sin_family */
+		htons(HDDTEMP_PORT),		/* sin_port */
+		{							/* sin_addr */
+			htonl(LOCALHOST_ADDR),	/* s_addr */
+		}
+	};
+
+	/* create our socket descriptor */
+
+	sock = socket(PF_INET, SOCK_STREAM, 0);
+
+	if(sock == -1){
+		syslog (LOG_ERR, "hddtemp: could not create socket! %s",
+			strerror (errno));
+		return -1;
+	}
+
+	/* connect to the hddtemp daemon */
+
+	if(connect(sock, (const struct sockaddr *)&addr, sizeof(addr)) != 0){
+		syslog (LOG_ERR, "hddtemp: could not connect to the hddtemp daemon! %s",
+			strerror (errno));
+		goto error;
+	}
+
+	/* receive data from the hddtemp daemon
+	   TODO: handle case when there is more data than buffer size */
+
+#	if DEBUG
+	memset(buffer, 0xba, buffer_size);
+#	endif
+
+	size = recv(sock, buffer, (buffer_size - 1), 0);
+
+	if(size <= 0){
+		syslog (LOG_ERR,
+			"hddtemp: could not receive from the hddtemp daemon! %s",
+			strerror (errno));
+		goto error;
+	}
+
+	/* ensure null-terminated string */
+	buffer[size] = '\0';
+	debug("hddtemp: received:");
+	debug(buffer);
+
+	return 0;
+
+error:
+	/* close our socket and exit */
+
+	if(close(sock) != 0){
+		/* even close does'nt work. there are days like this one... */
+		syslog (LOG_ERR, "hddtemp: could not close socket! %s",
+			strerror (errno));
+	}
+
+	return -1;
+}
+
+/* count_bars
+   Count the number of '|' in a string. */
+
+static unsigned count_bars(const char *p)
+{
+	unsigned u = 0;
+
+	for(; *p; p++)
+		if(*p == '|')
+			u++;
+
+	return u;
+}
+
+/* find_number_of_disks
+   Parse the received string and determine the number of disks in the system.
+
+   Return value:
+     Number of disk(s) found if ok, < 0 otherwise. */
+
+static int find_number_of_disks(const char *string)
+{
+	unsigned num_disks, num_bars;
+
+	/* there are five bars per disk; deduce number of disks */
+	num_bars = count_bars(string);
+	num_disks = num_bars / 5;
+
+	/* check everything is ok */
+	if((num_disks * 5) != num_bars)
+		return -1;
+
+	return (int)num_disks;
+}
+
+/* extract_field
+   Extract a field between |.
+
+   Returned value:
+     NULL in case of error,
+     string, advanced to the next delimiter if ok.
+
+   Note: we terminate field with a \0. */
+
+static const char *extract_field(const char *string, char *buffer, unsigned buffer_size)
+{
+	const char *d;
+	unsigned s;
+
+	/* skip first | */
+	if(*string++ != '|')
+		return NULL;
+
+	/* extract field */
+	d = strchr(string, '|');
+
+	if(!d)
+		return NULL;
+
+	s = d - string;
+
+	if(!s)
+		return NULL;
+
+	/* prevent overflow */
+	s = (s > (buffer_size - 1)) ? (buffer_size - 1) : s;
+
+	/* copy, \0-terminated */
+	strncpy(buffer, string, s);
+	buffer[s] = '\0';
+
+	/* advance to next delimiter */
+	return d;
+}
+
+/* extract_single_disk_infos
+   Extract one disk information from the received string.
+
+   Returned value:
+     string, advanced just after what we parsed if ok,
+     NULL if error. */
+
+static const char *extract_single_disk_infos(const char *string, struct disk_infos *p)
+{
+	const char *d;
+	unsigned s;
+	char temp[5];
+
+	/* check first |, but do not skip */
+	if(*string != '|')
+		return NULL;
+
+	/* extract device */
+	string = extract_field(string, p->device_name, DEVICE_NAME_SIZE);
+
+	if(!string)
+		return NULL;
+
+	debug("hddtemp: device name:");
+	debug(p->device_name);
+
+	/* extract model */
+	string = extract_field(string, p->model_name, MODEL_NAME_SIZE);
+
+	if(!string)
+		return NULL;
+
+	debug("hddtemp: model name:");
+	debug(p->model_name);
+
+	/* extract code/temperature as string, to intermediate buffer */
+	string = extract_field(string, temp, 5);
+
+	if(!string)
+		return NULL;
+
+	debug("hddtemp: code/temperature:");
+	debug(temp);
+
+	/* parse code, and temperature */
+
+	if(!strcmp(temp, "NA")){
+		p->code = NOT_APPLICABLE;
+		strcpy(p->code_as_string, temp);
+		p->temperature = 0;
+
+	} else if(!strcmp(temp, "UNK")){
+		p->code = UNKNOWN;
+		strcpy(p->code_as_string, temp);
+		p->temperature = 0;
+
+	} else if(!strcmp(temp, "NOS")){
+		p->code = NOSENSOR;
+		strcpy(p->code_as_string, temp);
+		p->temperature = 0;
+
+	} else if(!strcmp(temp, "SLP")){
+		p->code = DRIVE_SLEEP;
+		strcpy(p->code_as_string, temp);
+		p->temperature = 0;
+
+	} else if(!strcmp(temp, "ERR")){
+		p->code = ERROR;
+		strcpy(p->code_as_string, temp);
+		p->temperature = 0;
+
+	} else {
+		/* assume valid temperature */
+		p->code = KNOWN;
+		p->temperature = atoi(temp);
+	}
+
+	/* extract unit */
+	string = extract_field(string, p->unit, UNIT_STRING_SIZE);
+
+	if(!string)
+		return NULL;
+
+	debug("hddtemp: unit:");
+	debug(p->unit);
+
+	/* check last | */
+	if(*string++ != '|')
+		return NULL;
+
+	return string;
+}
+
+/* extract_all_disks_infos
+   Extract all disks information from the received string.
+
+   Parameters worth describing:
+     n: awaited number of disks
+
+   Returned value:
+     >= 0 if ok, < 0 otherwise. */
+
+static int extract_all_disks_infos(const char *string, unsigned n,
+	struct disk_infos *p)
+{
+	unsigned u;
+
+	for(u = 0; u < n; u++){
+		string = extract_single_disk_infos(string, p);
+
+		if(!string)
+			return -1;
+
+		p++;
+	}
+
+	return 0;
+}
+
+/* substitute_slashes
+   Substitute all / by %, in place. */
+
+static void substitute_slashes(char *p)
+{
+	for(; *p; p++)
+		if(*p == '/')
+			*p = '%';
+}
+
+/* rrd_update_single_hddtemp
+   Update rrd file for one disk with hddtemp informations.
+
+   TODO: find a way to store drive name, model, as well as
+         temperature units in the rrd file in a convenient way. */
+
+static void rrd_update_single_hddtemp(const struct disk_infos *p)
+{
+	static const char *ds_def[] = {
+		"DS:temperature:GAUGE:25:U:U",
+		"DS:code:GAUGE:25:0:5", 		/* sync. with codes */
+		NULL
+	};
+	char device_name[DEVICE_NAME_SIZE],
+		filename[DEVICE_NAME_SIZE + 16],
+		rrd_data[256];
+
+	/* substitute all / in device name with % */
+	strcpy(device_name, p->device_name);
+	substitute_slashes(device_name);
+
+	/* construct filename */
+	sprintf(filename, "hddtemp-%s.rrd", device_name);
+
+	/* construct rrd data */
+
+	if(p->code == KNOWN)
+		snprintf (rrd_data, 256, "N:%i:%u", p->temperature,	p->code);
+
+	else
+		snprintf (rrd_data, 256, "N:U:%u", p->code);
+
+	buffer[255] = '\0';
+
+	rrd_update_file(filename, rrd_data, ds_def, 2);
+}
+
+/* rrd_update_all_hddtemp
+   Update rrd file for all disks with hddtemp informations.
+
+   Parameters worth describing:
+     n: number of disks */
+
+static void rrd_update_all_hddtemp(const struct disk_infos *p, unsigned n)
+{
+	unsigned u;
+
+	for(u = 0; u < n; u++)
+		rrd_update_single_hddtemp(p + u);
+}
+
+/* hddtemp_init
+   Initialize everything needed for hddtemp "collector".
+   Note: we do not touch the rrd file here. */
+
+void hddtemp_init (void)
+{
+	debug("hddtemp: hddtemp_init");
+
+	/* get data from daemon */
+
+	if(ask_hddtemp_daemon_for_data(buffer, BUFFER_SIZE) < 0){
+		syslog (LOG_ERR, "hddtemp: could not receive from daemon!");
+		num_disks = -1;
+		return;
+	}
+
+	/* find out number of disks in the system */
+
+	num_disks = find_number_of_disks(buffer);
+
+	if(num_disks < 0){
+		syslog (LOG_ERR, "hddtemp: could not determine number of disks!");
+		return;
+
+	} else if(num_disks == 0){
+		syslog (LOG_INFO, "hddtemp: zero disk found.");
+		return;
+
+	} else {
+		syslog (LOG_INFO, "hddtemp: found %u disk(s).", num_disks);
+	}
+
+	/* allocate memory accordingly */
+
+	disks_infos = malloc(num_disks * sizeof(struct disk_infos));
+
+	if(!disks_infos){
+		syslog (LOG_ERR, "hddtemp: could not allocate memory ! %s", strerror(errno));
+		num_disks = -1;
+	}
+}
+
+/* hddtemp_update
+   Periodic update for hddtemp stats. */
+
+void hddtemp_update (void)
+{
+	debug("hddtemp: hddtemp_update");
+
+	/* early exit, in case init failed, or no disk */
+
+	if(num_disks <= 0){
+		debug("early exit");
+		return;
+	}
+
+	/* get data from daemon */
+
+	if(ask_hddtemp_daemon_for_data(buffer, BUFFER_SIZE) < 0){
+		syslog (LOG_ERR, "hddtemp: could not receive from daemon!");
+		return;
+	}
+
+	/* parse data */
+
+	if(extract_all_disks_infos(buffer, num_disks, disks_infos) < 0){
+		syslog (LOG_ERR, "hddtemp: could not parse data from daemon!");
+		return;
+	}
+
+	/* update rrd files */
+
+	rrd_update_all_hddtemp(disks_infos, num_disks);
+}
+
+#endif /* COLLECT_HDDTEMP */
diff -urN collectd-2.1.0/src/hddtemp.h collectd-2.1.0-vs/src/hddtemp.h
--- collectd-2.1.0/src/hddtemp.h	1970-01-01 01:00:00.000000000 +0100
+++ collectd-2.1.0-vs/src/hddtemp.h	2005-10-08 03:22:21.910810341 +0200
@@ -0,0 +1,33 @@
+/* hddtemp "collector" for collectd 
+   Author: Vincent Stehlé <vincent.stehle@free.fr>
+
+   This program is free software; you can distribute it and/or modify it
+   under the terms of the GNU General Public License (Version 2) as
+   published by the Free Software Foundation.
+
+   This program is distributed in the hope it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston MA 02111-1307, USA. */
+
+#ifndef HDDTEMP_H
+#define HDDTEMP_H
+
+#include "collectd.h"
+#include "common.h"
+
+#ifndef COLLECT_HDDTEMP
+#define COLLECT_HDDTEMP 1
+#endif
+
+#if COLLECT_HDDTEMP
+
+void hddtemp_init (void);
+void hddtemp_update (void);
+
+#endif /* COLLECT_HDDTEMP */
+#endif /* HDDTEMP_H */

--------------000407000208000409080108--