diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-02-09 09:26:58 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-02-09 09:26:58 -0500 |
| commit | b7671f356aee0ce21e6e006e7b4ee57bd8e00b3d (patch) | |
| tree | 253490726e4fca72b9391e81dbf146b0e005cad2 /lib/command.c | |
| parent | cf80f28161ec05430723d6fb7bc5928bdc21f825 (diff) | |
| parent | 1520d0aca9acf42faf0433cbe8f66ef9cd97bd0e (diff) | |
Merge pull request #190 from opensourcerouting/config-write-sync-stable
[stable] lib: use fsync() for config writes, plug fd leak
Diffstat (limited to 'lib/command.c')
| -rw-r--r-- | lib/command.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/lib/command.c b/lib/command.c index 1dcb232c32..6176640bf6 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3139,9 +3139,9 @@ DEFUN (config_write_file, "Write to configuration file\n") { unsigned int i; - int fd; + int fd, dirfd; struct cmd_node *node; - char *config_file; + char *config_file, *slash; char *config_file_tmp = NULL; char *config_file_sav = NULL; int ret = CMD_WARNING; @@ -3161,7 +3161,22 @@ DEFUN (config_write_file, /* Get filename. */ config_file = host.config; - + +#ifndef O_DIRECTORY +#define O_DIRECTORY 0 +#endif + slash = strrchr (config_file, '/'); + if (slash) + { + char *config_dir = XSTRDUP (MTYPE_TMP, config_file); + config_dir[slash - config_file] = '\0'; + dirfd = open(config_dir, O_DIRECTORY | O_RDONLY); + XFREE (MTYPE_TMP, config_dir); + } + else + dirfd = open(".", O_DIRECTORY | O_RDONLY); + /* if dirfd is invalid, directory sync fails, but we're still OK */ + config_file_sav = XMALLOC (MTYPE_TMP, strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1); strcpy (config_file_sav, config_file); @@ -3179,7 +3194,14 @@ DEFUN (config_write_file, VTY_NEWLINE); goto finished; } - + + if (fchmod (fd, CONFIGFILE_MASK) != 0) + { + vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s", + config_file_tmp, safe_strerror(errno), errno, VTY_NEWLINE); + goto finished; + } + /* Make vty for configuration file. */ file_vty = vty_new (); file_vty->wfd = fd; @@ -3208,40 +3230,29 @@ DEFUN (config_write_file, goto finished; } if (link (config_file, config_file_sav) != 0) - { - vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav, - VTY_NEWLINE); - goto finished; - } - sync (); - if (unlink (config_file) != 0) - { - vty_out (vty, "Can't unlink configuration file %s.%s", config_file, - VTY_NEWLINE); - goto finished; - } + { + vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav, + VTY_NEWLINE); + goto finished; + } + fsync (dirfd); } - if (link (config_file_tmp, config_file) != 0) + if (rename (config_file_tmp, config_file) != 0) { vty_out (vty, "Can't save configuration file %s.%s", config_file, VTY_NEWLINE); goto finished; } - sync (); - - if (chmod (config_file, CONFIGFILE_MASK) != 0) - { - vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s", - config_file, safe_strerror(errno), errno, VTY_NEWLINE); - goto finished; - } + fsync (dirfd); vty_out (vty, "Configuration saved to %s%s", config_file, VTY_NEWLINE); ret = CMD_SUCCESS; finished: - unlink (config_file_tmp); + if (ret != CMD_SUCCESS) + unlink (config_file_tmp); + close (dirfd); XFREE (MTYPE_TMP, config_file_tmp); XFREE (MTYPE_TMP, config_file_sav); return ret; |
