From 0ffaf86a5587257b67cbc8339c9543481e59ba3a Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 13 Jan 2009 15:23:13 +0100 Subject: added basic backup of modified config files --- worker/output_handler.c | 185 +++++++++++++++++++++++++++++++++++++++++++++--- worker/worker.c | 1 + 2 files changed, 175 insertions(+), 11 deletions(-) diff --git a/worker/output_handler.c b/worker/output_handler.c index f082a0f..c77e15c 100644 --- a/worker/output_handler.c +++ b/worker/output_handler.c @@ -4,6 +4,11 @@ #include #include #include +#include +#include +#include + + #include @@ -21,6 +26,151 @@ #include "xml_helper.h" #include "helpers.h" +#define BACKUP_PATH "/var/spool/poliproc" +#define ORIGINAL_BACKUP_EXTENSION "ipa_original_backup_DO_NOT_DELETE" + +static int copy_file(const char *src_name, const char *dest_name) { + int src_fd=-1; + int dest_fd=-1; + int ret=0; + struct stat stat_buffer; + void *src; + void *dest; + char *tmp_file_name=NULL; + + tmp_file_name=(char *) malloc(strlen(src_name)+7); + CHECK(tmp_file_name, NULL, ("malloc failed."), return -1); + strcpy(tmp_file_name, src_name); + strcat(tmp_file_name, ".XXXXXX"); + + ret=-1; + src_fd = open(src_name, O_RDONLY); + CHECK(src_fd, -1, ("Failed to open %s read-only.\n", src_name), goto cleanup); + + dest_fd=open_temporary_file(tmp_file_name, "0600", "root", "root", NULL); + CHECK(dest_fd, -1, ("Failed to open temporary file %s\n", tmp_file_name), goto cleanup); + + ret=fstat(src_fd, &stat_buffer); + CHECK(ret, -1, ("Failed to stat file %s: %s\n", src_name, strerror(errno)), goto cleanup); + + ret = lseek(dest_fd, stat_buffer.st_size - 1, SEEK_SET); + CHECK(ret, -1, ("Lseek failed for file %s: %s\n", dest_name, strerror(errno)), goto cleanup); + + ret = write(dest_fd, "", 1); + if ( ret != 1 ) { + DEBUG(0, ("Failed to write one byte to %s: %s.\n", dest_name, strerror(errno))); + goto cleanup; + } + + src = mmap(NULL, stat_buffer.st_size, PROT_READ, MAP_SHARED, src_fd, 0); + if ( src == MAP_FAILED ) { + DEBUG(0, ("Mmap failed for file %s: %s.\n", src_name, strerror(errno))); + goto cleanup; + } + + dest = mmap(NULL, stat_buffer.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, + dest_fd, 0); + if ( src == MAP_FAILED ) { + DEBUG(0, ("Mmap failed for file %s: %s.\n", src_name, strerror(errno))); + munmap(src, stat_buffer.st_size); + goto cleanup; + } + + memcpy(dest, src, stat_buffer.st_size); + + munmap(dest, stat_buffer.st_size); + munmap(src, stat_buffer.st_size); + + close(dest_fd); + close(src_fd); + ret=rename(tmp_file_name, dest_name); + CHECK(ret, -1, ("Cannot rename %s to %s: %s\n", tmp_file_name, dest_name, strerror(errno) ), goto cleanup); + +cleanup: + if (dest_fd != -1) close(dest_fd); + if (src_fd != -1) close(src_fd); + free(tmp_file_name); + + return ret; +} +static int check_dir_create(const char *name) { + int ret; + struct stat stat_buffer; + + if( (ret=stat(name, &stat_buffer)) == -1) { + DEBUG(0, ("Directory %s does not exist, creating it.\n", name, strerror(errno))); + ret=mkdir(name, 0600); + CHECK(ret, -1, ("mkdir %s failed: %s\n", name, strerror(errno)), return -1); + } else if (!S_ISDIR(stat_buffer.st_mode)) { + DEBUG(0,("%s is not a regular file!\n",name)); + return -1; + } + + return 0; +} + +static int safe_config_file(const char *name, const char *app_name) { + int ret; + struct stat stat_buffer; + char backup_dir[PATH_MAX]; + char backup_file[PATH_MAX]; + char original_backup[PATH_MAX]; + char *buffer=NULL; + char *base_name=NULL; + + if ( (ret=lstat(name, &stat_buffer)) == -1) { + DEBUG(0,("stat on %s failed: %s\n",name, strerror(errno))); + goto cleanup; + } + if (!S_ISREG(stat_buffer.st_mode)) { + DEBUG(0,("%s is not a regular file!\n",name)); + ret=-1; + goto cleanup; + } + + ret=check_dir_create(BACKUP_PATH); + CHECK(ret, -1, ("Failed to create main backup directory %s.\n", BACKUP_PATH), goto cleanup); + + ret=snprintf(backup_dir, PATH_MAX, "%s/%s", BACKUP_PATH, app_name); + ret=snprintf(original_backup, PATH_MAX, "%s/%s.%s",backup_dir,base_name,ORIGINAL_BACKUP_EXTENSION); + if (ret<0) { + DEBUG(0,("snprintf failed.\n")); + ret=-1; + goto cleanup; + } + ret=check_dir_create(backup_dir); + CHECK(ret, -1, ("Failed to create backup directory %s for application %s.\n", backup_dir, app_name), goto cleanup); + + buffer=strdup(name); + base_name=basename(buffer); + ret=snprintf(original_backup, PATH_MAX, "%s/%s.%s",backup_dir,base_name,ORIGINAL_BACKUP_EXTENSION); + if (ret<0) { + DEBUG(0,("snprintf failed.\n")); + ret=-1; + goto cleanup; + } + + if ( (ret=lstat(original_backup, &stat_buffer)) == -1) { + DEBUG(0, ("There is no original backup file, I will assume that %s is the original file.\n", name)); + ret=copy_file(name, original_backup); + } else { + DEBUG(3, ("Original backup file exists, I will create an ordinary backup file\n", name)); + ret=snprintf(backup_file, PATH_MAX, "%s/%s.%d",backup_dir,base_name,time(NULL)); + if (ret<0) { + DEBUG(0,("snprintf failed.\n")); + ret=-1; + goto cleanup; + } + ret=copy_file(name, backup_file); + } + + +cleanup: + free(buffer); + return ret; +} + + char *get_output_handler_parameter(xmlNode *node, const char *name, const char *default_value, const int required) { char *value; @@ -51,14 +201,15 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil char *permission=NULL; char *param_name=NULL; char *param_value=NULL; + char *app_name=NULL; struct stat stat_buffer; char *dir_name=NULL; char *tmp_file_name=NULL; char *buffer=NULL; - int ret; + int ret=0; int fd; xsltStylesheetPtr parsed_stylesheet = NULL; - xmlDocPtr res; + xmlDocPtr res=NULL; name=get_output_handler_parameter(node, "name", NULL, 1); @@ -67,20 +218,22 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil dir_name=dirname(buffer); if( (ret=stat(dir_name, &stat_buffer)) == -1) { DEBUG(0,("stat on %s failed: %s\n",dir_name, strerror(errno))); - goto failed; + goto cleanup; } if(!S_ISDIR(stat_buffer.st_mode)) { DEBUG(0,("%s is not a directory!\n",dir_name)); - goto failed; + ret=-1; + goto cleanup; } if( (ret=lstat(name, &stat_buffer)) == -1) { DEBUG(0,("stat on %s failed: %s\n",name, strerror(errno))); - goto failed; + goto cleanup; } if(!S_ISREG(stat_buffer.st_mode)) { DEBUG(0,("%s is not a regular file!\n",name)); - goto failed; + ret=-1; + goto cleanup; } owner=get_output_handler_parameter(node, "owner", "root", 0); @@ -91,6 +244,11 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil param_value=get_output_handler_parameter(node, "param_value", NULL, 0); /* TODO: create backup copy */ + app_name = find_by_xpath(doc, "//def:metadata/def:app", FIND_VALUE); + CHECK(app_name, NULL, ("Cannot find the name of the application in policy file.\n"), goto failed); + DEBUG(3, ("Found application name: %s\n", app_name)); + ret=safe_config_file(name, app_name); + CHECK(ret, -1, ("Failed to safe config file %s of application %s.\n", name, app_name), goto cleanup); tmp_file_name=(char *) malloc(strlen(name)+7); CHECK_NULL_RETURN(tmp_file_name,("malloc failed.")); @@ -107,14 +265,17 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil ret = xsltSaveResultToFd(fd, res, parsed_stylesheet); if (ret == -1) { DEBUG(0, ("Cannot save result!\n")); - exit(1); + close(fd); + goto cleanup; } - xmlFreeDoc(res); - xsltFreeStylesheet(parsed_stylesheet); close(fd); ret=rename(tmp_file_name, name); - CHECK_MINUS_ONE_RETURN(ret, ("Cannot rename %s to %s: %s\n", tmp_file_name, name, strerror(errno) )); + CHECK(ret, -1, ("Cannot rename %s to %s: %s\n", tmp_file_name, name, strerror(errno) ), goto cleanup); + +cleanup: + xmlFreeDoc(res); + xsltFreeStylesheet(parsed_stylesheet); free(buffer); free(tmp_file_name); @@ -125,7 +286,8 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil free(permission); free(param_name); free(param_value); - return 0; + free(app_name); + return ret; failed: free(buffer); @@ -137,6 +299,7 @@ failed: free(permission); free(param_name); free(param_value); + free(app_name); return -1; } diff --git a/worker/worker.c b/worker/worker.c index 33b3afb..327f948 100644 --- a/worker/worker.c +++ b/worker/worker.c @@ -113,6 +113,7 @@ int main(int argc, const char *argv[]) cleanup: free_xml_search_path(); + free(policy_file_name); return ret; } -- cgit