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>
This commit is contained in:
Mitchell Wills 2015-08-24 17:24:30 -07:00 committed by Jouni Malinen
parent 6aaa661af1
commit a218e1ded4
6 changed files with 47 additions and 0 deletions

View file

@ -246,6 +246,13 @@ char * os_readfile(const char *name, size_t *len);
*/ */
int os_file_exists(const char *fname); 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 * os_zalloc - Allocate and zero memory
* @size: Number of bytes to allocate * @size: Number of bytes to allocate

View 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 * os_zalloc(size_t size)
{ {
void *n = os_malloc(size); void *n = os_malloc(size);

View 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) void * os_zalloc(size_t size)
{ {
return NULL; return NULL;

View 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 #ifndef WPA_TRACE
void * os_zalloc(size_t size) void * os_zalloc(size_t size)
{ {

View 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) void * os_zalloc(size_t size)
{ {
return calloc(1, size); return calloc(1, size);

View file

@ -1361,6 +1361,8 @@ int wpa_config_write(const char *name, struct wpa_config *config)
} }
#endif /* CONFIG_NO_CONFIG_BLOBS */ #endif /* CONFIG_NO_CONFIG_BLOBS */
os_fdatasync(f);
fclose(f); fclose(f);
if (tmp_name) { if (tmp_name) {