]> granicus.if.org Git - fcron/commitdiff
save file to a temp name, then rename it
authorthib <thib>
Fri, 1 Nov 2002 18:13:49 +0000 (18:13 +0000)
committerthib <thib>
Fri, 1 Nov 2002 18:13:49 +0000 (18:13 +0000)
conf.c
convert-fcrontab.c
save.c
save.h

diff --git a/conf.c b/conf.c
index ebf1cb5849c36ff99ad30409e90563ba3bd175d9..58120d82e718e51ab6574fec2b738024c706dacd 100644 (file)
--- 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 */
index a220d0338610c9b32f26126f835f2bb881ba3c8e..5813a8a663eddced50fa25cede5bbf4724c46b80 100644 (file)
@@ -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 c9d47d4d0f8fcfa176ee44512e74cee0021bc4d8..902a97808f497d5d3eb0c6438152543d252eac2c 100644 (file)
--- 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 b1f9442797ba71639e0e7962cd3e7014a563f2a1..f97cd539bc705a2cfb7b6b3f0e15ea78295d6539 100644 (file)
--- a/save.h
+++ b/save.h
  *  `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)