[nagiosplug] Implemented writes to state file

"Ton Voon" <[email protected]>
Newsgroups gmane.network.nagios.plugins.cvs
Message-ID <[email protected]>
 Module: nagiosplug
 Branch: ton/state
 Commit: f58aa8e66bbb4ecf23cf6add7efc574abb733d3a
 Author: Ton Voon <[email protected]>
   Date: Fri Jun 18 17:34:24 2010 +0100
    URL: http://nagiosplug.git.sf.net/git/gitweb.cgi?p=nagiosplug/nagiosplug;a=commit;h=f58aa8e

Implemented writes to state file

---

 lib/tests/test_utils.c |   64 ++++++++++++++++++++++++++++++++---
 lib/utils_base.c       |   87 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 137 insertions(+), 14 deletions(-)

diff --git a/lib/tests/test_utils.c b/lib/tests/test_utils.c
index d7cdc33..6e04bfc 100644
--- a/lib/tests/test_utils.c
+++ b/lib/tests/test_utils.c
@@ -21,6 +21,9 @@
 
 #include "tap.h"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
 int
 main (int argc, char **argv)
 {
@@ -36,7 +39,7 @@ main (int argc, char **argv)
 	nagios_plugin *temp_nagios_plugin;
 	FILE    *temp_fp;
 
-	plan_tests(81+23);
+	plan_tests(134);
 
 	_get_nagios_plugin( &temp_nagios_plugin );
 	ok( temp_nagios_plugin==NULL, "nagios_plugin not initialised");
@@ -295,13 +298,11 @@ main (int argc, char **argv)
 	ok( !strcmp(temp_state_key->name, "Ahash"), "Got key name" );
 
 
-	printf("Filename=%s\n", temp_state_key->_filename);
 	np_enable_state("funnykeyname", 54);
 	temp_state_key = temp_nagios_plugin->state;
 	ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" );
 	ok( !strcmp(temp_state_key->name, "funnykeyname"), "Got key name" );
 
-	printf("Filename=%s\n", temp_state_key->_filename);
 
 
 	ok( !strcmp(temp_state_key->_filename, "/usr/local/nagios/var/check_test/funnykeyname"), "Got internal filename" );
@@ -325,20 +326,71 @@ main (int argc, char **argv)
 	ok( temp_nagios_plugin->state->state_data!=NULL, "Got state data now" );
 	ok( temp_nagios_plugin->state->state_data->time==1234567890, "Got time" );
 	ok( !strcmp((char *)temp_nagios_plugin->state->state_data->data, "String to read"), "Data as expected" );
-	printf("state_data=%s|\n", temp_nagios_plugin->state->state_data->data);
 
+	temp_state_key->data_version=53;
+	temp_state_data = np_state_read(temp_state_key);
+	ok( temp_state_data==NULL, "Older data version gives NULL" );
+	temp_state_key->data_version=54;
 
 	temp_state_key->_filename="var/nonexistant";
 	temp_state_data = np_state_read(temp_state_key);
 	ok( temp_state_data==NULL, "Missing file gives NULL" );
 	ok( temp_nagios_plugin->state->state_data==NULL, "No state information" );
 
-	time(&current_time);
-	np_state_write_string(NULL, "New data");
+	temp_state_key->_filename="var/oldformat";
+	temp_state_data = np_state_read(temp_state_key);
+	ok( temp_state_data==NULL, "Old file format gives NULL" );
+
+	temp_state_key->_filename="var/baddate";
+	temp_state_data = np_state_read(temp_state_key);
+	ok( temp_state_data==NULL, "Bad date gives NULL" );
 
+	temp_state_key->_filename="var/missingdataline";
+	temp_state_data = np_state_read(temp_state_key);
+	ok( temp_state_data==NULL, "Missing data line gives NULL" );
+
+
+
+
+	unlink("var/generated");
+	temp_state_key->_filename="var/generated";
+	current_time=1234567890;
+	np_state_write_string(&current_time, "String to read");
+	ok(system("cmp var/generated var/statefile")==0, "Generated file same as expected");
+
+
+
+
+	unlink("var/generated_directory/statefile");
+	unlink("var/generated_directory");
+	temp_state_key->_filename="var/generated_directory/statefile";
+	current_time=1234567890;
+	np_state_write_string(&current_time, "String to read");
+	ok(system("cmp var/generated_directory/statefile var/statefile")==0, "Have created directory");
+
+	/* This test to check cannot write to dir - can't automate yet */
+	/*
+	unlink("var/generated_bad_dir");
+	mkdir("var/generated_bad_dir", S_IRUSR);
+	np_state_write_string(&current_time, "String to read");
+	*/
+
+
+	temp_state_key->_filename="var/generated";
+	time(&current_time);
+	np_state_write_string(NULL, "String to read");
 	temp_state_data = np_state_read(temp_state_key);
 	/* Check time is set to current_time */
+	ok(system("cmp var/generated var/statefile > /dev/null")!=0, "Generated file should be different this time");
+	ok(temp_nagios_plugin->state->state_data->time-current_time<=1, "Has time generated from current time");
+	
 
+	/* Don't know how to automatically test this. Need to be able to redefine die and catch the error */
+	/*
+	temp_state_key->_filename="/dev/do/not/expect/to/be/able/to/write";
+	np_state_write_string(NULL, "Bad file");
+	*/
+	
 
 	np_cleanup();
 	ok(temp_state_key==NULL, "temp_state_key cleared");
diff --git a/lib/utils_base.c b/lib/utils_base.c
index 8550577..5eaf57b 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -357,7 +357,6 @@ char *_np_state_generate_key() {
 void _cleanup_state_data() {
 	if (this_nagios_plugin->state->state_data!=NULL) {
 		np_free(this_nagios_plugin->state->state_data->data);
-		printf("***Setting\n");
 		np_free(this_nagios_plugin->state->state_data);
 	}
 }
@@ -399,6 +398,7 @@ void np_enable_state(char *keyname, int expected_data_version) {
 	this_state->name=keyname;
 	this_state->plugin_name=this_nagios_plugin->plugin_name;
 	this_state->data_version=expected_data_version;
+	this_state->state_data=NULL;
 
 	/* Calculate filename */
 	asprintf(&temp_filename, "%s/%s/%s", _np_state_calculate_location_prefix(), this_nagios_plugin->plugin_name, keyname);
@@ -433,6 +433,7 @@ state_data *np_state_read() {
 		if(this_state_data==NULL)
 			die(STATE_UNKNOWN, _("Cannot allocate memory for state data"));
 
+		this_state_data->data=NULL;
 		this_nagios_plugin->state->state_data = this_state_data;
 
 		rc = _np_state_read_file(statefile);
@@ -441,7 +442,6 @@ state_data *np_state_read() {
 	}
 
 	if(rc==FALSE) {
-		printf("Called\n");
 		_cleanup_state_data();
 	}
 
@@ -465,21 +465,17 @@ int _np_state_read_file(FILE *f) {
 	/* Note: This introduces a limit of 1024 bytes in the string data */
 	line = (char *) malloc(1024);
 
-	printf("Here\n");
 	while(!failure && (fgets(line,1024,f))!=NULL){
 		pos=strlen(line);
 		if(line[pos-1]=='\n') {
 			line[pos-1]='\0';
 		}
-		printf("Reading line |%s|\n", line);
 
 		if(line[0] == '#') continue;
 
 		switch(expected) {
 			case STATE_FILE_VERSION:
 				i=atoi(line);
-				//printf("line=|%d|, exp=|%d|\n", i, NP_STATE_FORMAT_VERSION);
-				//if(!strcmp(NP_STATE_FORMAT_VERSION, line)) {
 				if(i!=NP_STATE_FORMAT_VERSION)
 					failure++;
 				else
@@ -487,7 +483,6 @@ int _np_state_read_file(FILE *f) {
 				break;
 			case STATE_DATA_VERSION:
 				i=atoi(line);
-				printf("i=%d, exp=%d\n", i, this_nagios_plugin->state->data_version);
 				if(i != this_nagios_plugin->state->data_version)
 					failure++;
 				else
@@ -514,7 +509,6 @@ int _np_state_read_file(FILE *f) {
 	}
 
 	np_free(line);
-	printf("Returning status=%d\n", status);
 	return status;
 }
 
@@ -526,5 +520,82 @@ int _np_state_read_file(FILE *f) {
  * Will die with UNKNOWN if errors
  */
 void np_state_write_string(time_t *data_time, char *data_string) {
+	FILE *fp;
+	char *temp_file=NULL;
+	int fd=0, result=0;
+	time_t current_time;
+	size_t len;
+	char *directories=NULL;
+	char *p=NULL;
+
+	if(data_time==NULL)
+		time(&current_time);
+	else
+		current_time=*data_time;
+	
+	/* If file doesn't currently exist, create directories */
+	if(access(this_nagios_plugin->state->_filename,F_OK)!=0) {
+		asprintf(&directories, "%s", this_nagios_plugin->state->_filename);
+		if(directories==NULL)
+			die(STATE_UNKNOWN, _("Cannot malloc"));
+
+		for(p=directories+1; *p; p++) {
+			if(*p=='/') {
+				*p='\0';
+				if((access(directories,F_OK)!=0) && (mkdir(directories, S_IRWXU)!=0)) {
+					/* Can't free this! Otherwise error message is wrong! */
+					/* np_free(directories); */ 
+					die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories);
+				}
+				*p='/';
+			}
+		}
+		np_free(directories);
+	}
+
+	asprintf(&temp_file,"%s.XXXXXX",this_nagios_plugin->state->_filename);
+	if(temp_file==NULL)
+		die(STATE_UNKNOWN, _("Cannot malloc temporary state file"));
+
+	if((fd=mkstemp(temp_file))==-1) {
+		np_free(temp_file);
+		die(STATE_UNKNOWN, _("Cannot create temporary filename"));
+	}
+
+	fp=(FILE *)fdopen(fd,"w");
+	if(fp==NULL) {
+		close(fd);
+		unlink(temp_file);
+		np_free(temp_file);
+		die(STATE_UNKNOWN, _("Unable to open temporary state file"));
+	}
+	
+	fprintf(fp,"# NP State file\n");
+	fprintf(fp,"%d\n",NP_STATE_FORMAT_VERSION);
+	fprintf(fp,"%d\n",this_nagios_plugin->state->data_version);
+	fprintf(fp,"%lu\n",current_time);
+	fprintf(fp,"%s\n",data_string);
+	
+	fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP);
+	
+	fflush(fp);
+
+	result=fclose(fp);
+
+	fsync(fd);
+
+	if(result!=0) {
+		unlink(temp_file);
+		np_free(temp_file);
+		die(STATE_UNKNOWN, _("Error writing temp file"));
+	}
+
+	if(rename(temp_file, this_nagios_plugin->state->_filename)!=0) {
+		unlink(temp_file);
+		np_free(temp_file);
+		die(STATE_UNKNOWN, _("Cannot rename state temp file"));
+	}
+
+	np_free(temp_file);
 }
 


------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate 
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the 
lucky parental unit.  See the prize list and enter to win: 
http://p.sf.net/sfu/thinkgeek-promo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.