From 4f703837e8c7a7d23ca1c1ac55df40887557d493 Mon Sep 17 00:00:00 2001 From: thib Date: Fri, 1 Nov 2002 18:13:49 +0000 Subject: [PATCH] save file to a temp name, then rename it --- conf.c | 70 ++++++++++++++++++++++++++++------------------ convert-fcrontab.c | 63 ++++++++++++++++++++++++++--------------- save.c | 44 +++++++++++++++++++++++++++-- save.h | 4 ++- 4 files changed, 129 insertions(+), 52 deletions(-) diff --git a/conf.c b/conf.c index ebf1cb5..58120d8 100644 --- a/conf.c +++ b/conf.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: conf.c,v 1.61 2002-10-28 17:54:19 thib Exp $ */ + /* $Id: conf.c,v 1.62 2002-11-01 18:13:49 thib Exp $ */ #include "fcron.h" @@ -35,6 +35,7 @@ int add_line_to_file(cl_t *cl, cf_t *cf, uid_t runas, char *runas_str, int read_strn(int fd, char **str, short int size); int read_type(int fd, short int *type, short int *size); void synchronize_file(char *file_name); +int save_one_file(cf_t *file, char *filename); /* this is used to create a list of files to remove, to add */ @@ -971,13 +972,49 @@ delete_file(const char *user_name) } +/* this function is called in save.c */ +int +save_one_file(cf_t *file, char *filename) +/* save a given file to disk */ +{ + int fd; + + /* open file */ + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR|S_IWUSR); + if ( fd == -1 ) { + error_e("Could not open %s", file->cf_user); + return ERR; + } + else { + + /* chown the file to root:root : this file should only be read and + * modified by fcron (not fcrontab) */ + if (fchown(fd, ROOTUID, ROOTGID) != 0) { + error_e("Could not fchown \"%s\"", file->cf_user); + close(fd); + return ERR; + } + else { + /* save file : */ + if ( write_file_to_disk(fd, file, now) == ERR ) { + close(fd); + remove(file->cf_user); + return ERR; + } + else + close(fd); + } + } + + return OK; +} + void save_file(cf_t *arg_file) - /* Store the informations relatives to the executions - * of tasks at a defined frequency of system's running time */ +/* Store the informations relatives to the executions + * of tasks at a defined frequency of system's running time */ { cf_t *file = NULL; - int fd; cf_t *start_file = NULL; if (arg_file != NULL) @@ -990,29 +1027,8 @@ save_file(cf_t *arg_file) debug("Saving %s...", file->cf_user); - /* open file */ - fd = open(file->cf_user, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR|S_IWUSR); - if ( fd == -1 ) { - error_e("Could not open %s", file->cf_user); - } - else { - - /* chown the file to root:root : this file should only be read and - * modified by fcron (not fcrontab) */ - if (fchown(fd, ROOTUID, ROOTGID) != 0) { - error_e("Could not fchown \"%s\"", file->cf_user); - close(fd); - } - else { - /* save file : */ - if ( write_file_to_disk(fd, file, now) == ERR ) { - close(fd); - remove(file->cf_user); - } - else - close(fd); - } - } + /* save the file safely : save it to a temporary name, then rename() it */ + save_file_safe(file, file->cf_user, "fcron"); if (arg_file != NULL) /* we have to save only a single file */ diff --git a/convert-fcrontab.c b/convert-fcrontab.c index a220d03..5813a8a 100644 --- a/convert-fcrontab.c +++ b/convert-fcrontab.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: convert-fcrontab.c,v 1.14 2002-10-28 17:56:09 thib Exp $ */ + /* $Id: convert-fcrontab.c,v 1.15 2002-11-01 18:17:39 thib Exp $ */ #include "global.h" @@ -30,7 +30,7 @@ #include "log.h" #include "subs.h" -char rcs_info[] = "$Id: convert-fcrontab.c,v 1.14 2002-10-28 17:56:09 thib Exp $"; +char rcs_info[] = "$Id: convert-fcrontab.c,v 1.15 2002-11-01 18:17:39 thib Exp $"; void info(void); void usage(void); @@ -46,6 +46,8 @@ char foreground = 1; pid_t daemon_pid = 0; char debug_opt = 0; char dosyslog = 1; +time_t t_save = 0; +struct stat file_stat; void info(void) @@ -135,6 +137,41 @@ delete_file(cf_t *file) } +/* this function is called in save.c */ +int +save_one_file(cf_t *file, char *path) +/* save a given file to disk */ +{ + int fd; + + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC); + if ( fd == -1 ) { + error_e("Could not open %s", path); + return ERR; + } + + if ( fchown(fd, file_stat.st_uid, file_stat.st_gid) != 0 ) { + error_e("Could not fchown %s", path); + return ERR; + } + + if ( fchmod(fd, file_stat.st_mode) != 0 ) { + error_e("Could not fchmod %s", path); + return ERR; + } + + if ( write_file_to_disk(fd, file, t_save) == ERR ) { + close(fd); + remove(path); + return ERR; + } + + close(fd); + + return OK; + +} + void convert_file(char *file_name) /* this functions is a mix of read_file() from version 1.0.3 and save_file(), @@ -144,10 +181,7 @@ convert_file(char *file_name) cl_t *line = NULL; env_t *env = NULL; FILE *f = NULL; - int fd; - struct stat file_stat; char buf[LINE_LEN]; - time_t t_save = 0; explain("Converting %s's fcrontab ...", file_name); @@ -220,28 +254,13 @@ convert_file(char *file_name) /* open a temp file in write mode and truncate it */ strcpy(buf, "tmp_"); strncat(buf, file_name, sizeof(buf) - sizeof("tmp_") - 1); - fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC); - if ( fd == -1 ) - die_e("Could not open %s", buf); - - if ( fchown(fd, file_stat.st_uid, file_stat.st_gid) != 0 ) - die_e("Could not fchown %s", buf); - if ( fchmod(fd, file_stat.st_mode) != 0 ) - die_e("Could not fchmod %s", buf); - - if ( write_file_to_disk(fd, file, t_save) == ERR ) { - close(fd); - remove(buf); - exit(EXIT_ERR); - } - - close(fd); - /* everything's ok : we can override the src file safely */ if ( rename(buf, file_name) != 0 ) error_e("Could not rename %s to %s", buf, file_name); + save_file_safe(file, file_name, "convert-fcrontab"); + delete_file(file); } diff --git a/save.c b/save.c index c9d47d4..902a978 100644 --- a/save.c +++ b/save.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: save.c,v 1.3 2002-10-28 17:56:29 thib Exp $ */ + /* $Id: save.c,v 1.4 2002-11-01 18:17:44 thib Exp $ */ #include "global.h" #include "save.h" @@ -35,6 +35,8 @@ int save_str(int fd, short int type, char *str, char *write_buf, int *buf_used); int save_strn(int fd, short int type, char *str, short int size, char *write_buf, int *buf_used); int save_lint(int fd, short int type, long int value, char *write_buf, int *buf_used); +extern int save_one_file(cf_t *file, char *filename); + int save_type(int fd, short int type, char *write_buf, int *buf_used) @@ -143,7 +145,7 @@ write_buf_to_disk(int fd, char *write_buf, int *buf_used) } /* */ - debug("write_buf_to_disk() : written %d/%d, %d retry(ies)", written, to_write, + debug("write_buf_to_disk() : written %d/%d, %d (re)try(ies)", written, to_write, num_retries); /* */ @@ -286,3 +288,41 @@ write_file_to_disk(int fd, struct cf_t *file, time_t time_date) return OK; } + + +int +save_file_safe(cf_t *file, char *final_path, char *prog_name) +/* save a file to a temp path, and then rename it (safely) to avoid loss of data + * if a system crash, hardware failure, etc happens. */ +{ + char temp_path[PATH_LEN+4]; + int final_path_len, temp_path_index; + char *tmp_str = ".tmp"; + + final_path_len = strlen(final_path); + strncpy(temp_path, final_path, sizeof(temp_path)-sizeof(tmp_str)); + temp_path_index = ( final_path_len > sizeof(temp_path)-sizeof(tmp_str) ) ? + sizeof(temp_path)-sizeof(tmp_str) : final_path_len; + strcpy(&temp_path[temp_path_index], ".tmp"); + + /* save_one_file() is defined in conf.c for fcron, fileconf.c for fcrondyn */ + if ( save_one_file(file, temp_path) == OK ) { + if ( rename(temp_path, final_path) != 0 ) { + error_e("Cannot rename %s to %s", temp_path, final_path); + error("%s will try to save the name to its definitive filename " + "directly.", prog_name); + error("If there is an error, root may consider to replace %s (which is " + "a valid copy) by %s manually.", final_path, temp_path); + if ( save_one_file(file, final_path) == ERR ) + return ERR; + } + } + else { + error("Since %s has not been able to save %s's file, it will keep " + "the previous version (if any) of %s.", prog_name, final_path); + return ERR; + } + + return OK; + +} diff --git a/save.h b/save.h index b1f9442..f97cd53 100644 --- a/save.h +++ b/save.h @@ -21,13 +21,15 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: save.h,v 1.7 2002-10-28 17:56:40 thib Exp $ */ + /* $Id: save.h,v 1.8 2002-11-01 18:17:59 thib Exp $ */ #ifndef __SAVE_H__ #define __SAVE_H__ /* functions defined by save.c */ extern int write_file_to_disk(int fd, struct cf_t *file, time_t time_date); +extern int save_file_safe(cf_t *file, char *final_path, char *fcron_suffix); + /* here is the format fcron(tab) uses to save the fcrontabs : * type(short int) -- 2.40.0