brcompat: Write temporary file to same directory as config file.
authorBen Pfaff <blp@nicira.com>
Tue, 30 Dec 2008 21:25:35 +0000 (13:25 -0800)
committerBen Pfaff <blp@nicira.com>
Tue, 30 Dec 2008 21:25:35 +0000 (13:25 -0800)
Otherwise, we will write it in the current working directory, which will
be / if we're running as a daemon (see daemonize()).  We shouldn't assume
that we can write to that directory, and it might not be in the same
file system as the output file anyhow.

vswitchd/brcompat.c

index a9a7085404d3f53bc3f3e8e1b20642b3963186ab..5c432da4b6e139787277c5210fe4a976a30763e3 100644 (file)
@@ -66,9 +66,6 @@
 #include "vlog.h"
 #define THIS_MODULE VLM_brcompat
 
-/* Name of temporary file used during a configuration update. */
-#define TMP_CONFIG_NAME  ".brcompat.conf"
-
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 60);
 
 /* Used for creating kernel datapaths */
@@ -158,16 +155,25 @@ static const struct nl_policy brc_dp_policy[] = {
 static int 
 brc_write_config(struct svec *new_cfg)
 {
+    char *tmp_name;
     int fd;
     size_t i;
 
     svec_sort(new_cfg);
     svec_unique(new_cfg);
 
-    fd = open(TMP_CONFIG_NAME, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
+    /* Put the temporary file in the same directory as config_name, so that
+     * they are guaranteed to be in the same file system and therefore we can
+     * rename() tmp_name over config_name, and put "~" in its name so that
+     * cfg.c will ignore it if it is reading all the files in that
+     * directory.  */
+    tmp_name = xasprintf("%s.~tmp~", config_name);
+
+    fd = open(tmp_name, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
     if (fd == -1) {
         VLOG_WARN_RL(&rl, "could not open temp config file for writing: %s", 
                 strerror(errno));
+        free(tmp_name);
         return errno;
     }
 
@@ -178,16 +184,19 @@ brc_write_config(struct svec *new_cfg)
         if (retval != strlen(entry)) {
             VLOG_WARN_RL(&rl, "problem writing to temp config file %d: %s", 
                     retval, strerror(errno));
+            free(tmp_name);
             return errno;
         }
     }
     close(fd);
 
-    if (rename(TMP_CONFIG_NAME, config_name) < 0) {
+    if (rename(tmp_name, config_name) < 0) {
         VLOG_WARN_RL(&rl, "could not rename temp config file: %s", 
                 strerror(errno));
+        free(tmp_name);
         return errno;
     }
+    free(tmp_name);
 
     return 0;
 }