Browse Source

Make sure configuration is saved to storage device

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>
Mitchell Wills 9 years ago
parent
commit
a218e1ded4
6 changed files with 47 additions and 0 deletions
  1. 7 0
      src/utils/os.h
  2. 6 0
      src/utils/os_internal.c
  3. 6 0
      src/utils/os_none.c
  4. 8 0
      src/utils/os_unix.c
  5. 18 0
      src/utils/os_win32.c
  6. 2 0
      wpa_supplicant/config_file.c

+ 7 - 0
src/utils/os.h

@@ -246,6 +246,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

+ 6 - 0
src/utils/os_internal.c

@@ -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);

+ 6 - 0
src/utils/os_none.c

@@ -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;

+ 8 - 0
src/utils/os_unix.c

@@ -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)
 {

+ 18 - 0
src/utils/os_win32.c

@@ -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);

+ 2 - 0
wpa_supplicant/config_file.c

@@ -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) {