Make sure configuration is saved to storage device
authorMitchell Wills <mwills@google.com>
Tue, 25 Aug 2015 00:24:30 +0000 (17:24 -0700)
committerJouni Malinen <j@w1.fi>
Thu, 27 Aug 2015 15:06:05 +0000 (18:06 +0300)
Config file is written to a temp file and then it is renamed to the
original config file. However, it is possible that the rename operation
will be commited to storage while file data will be still in cache
causing original config file to be empty or partially written in case of
a system reboot without a clean shutdown. Make this less likely to occur
by forcing the data to be written to the storage device before renaming
the file.

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
src/utils/os.h
src/utils/os_internal.c
src/utils/os_none.c
src/utils/os_unix.c
src/utils/os_win32.c
wpa_supplicant/config_file.c

index 2c24631..9e496fb 100644 (file)
@@ -247,6 +247,13 @@ char * os_readfile(const char *name, size_t *len);
 int os_file_exists(const char *fname);
 
 /**
+ * os_fdatasync - Sync a file's (for a given stream) state with storage device
+ * @stream: the stream to be flushed
+ * Returns: 0 if the operation succeeded or -1 on failure
+ */
+int os_fdatasync(FILE *stream);
+
+/**
  * os_zalloc - Allocate and zero memory
  * @size: Number of bytes to allocate
  * Returns: Pointer to allocated and zeroed memory or %NULL on failure
index 77733ad..ed6eb3c 100644 (file)
@@ -243,6 +243,12 @@ char * os_readfile(const char *name, size_t *len)
 }
 
 
+int os_fdatasync(FILE *stream)
+{
+       return 0;
+}
+
+
 void * os_zalloc(size_t size)
 {
        void *n = os_malloc(size);
index 83fe025..0c3214d 100644 (file)
@@ -102,6 +102,12 @@ char * os_readfile(const char *name, size_t *len)
 }
 
 
+int os_fdatasync(FILE *stream)
+{
+       return 0;
+}
+
+
 void * os_zalloc(size_t size)
 {
        return NULL;
index 089b880..4754dd7 100644 (file)
@@ -418,6 +418,14 @@ int os_file_exists(const char *fname)
 }
 
 
+int os_fdatasync(FILE *stream)
+{
+       if (!fflush(stream))
+               return fdatasync(fileno(stream));
+       return -1;
+}
+
+
 #ifndef WPA_TRACE
 void * os_zalloc(size_t size)
 {
index 296ea13..dea27b9 100644 (file)
@@ -216,6 +216,24 @@ char * os_readfile(const char *name, size_t *len)
 }
 
 
+int os_fdatasync(FILE *stream)
+{
+       HANDLE h;
+
+       if (stream == NULL)
+               return -1;
+
+       h = (HANDLE) _get_osfhandle(_fileno(stream));
+       if (h == INVALID_HANDLE_VALUE)
+               return -1;
+
+       if (!FlushFileBuffers(h))
+               return -1;
+
+       return 0;
+}
+
+
 void * os_zalloc(size_t size)
 {
        return calloc(1, size);
index 2af187d..fb438ea 100644 (file)
@@ -1361,6 +1361,8 @@ int wpa_config_write(const char *name, struct wpa_config *config)
        }
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 
+       os_fdatasync(f);
+
        fclose(f);
 
        if (tmp_name) {