[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--