1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-06-28 12:27:37 +03:00

Make app setting file writes durable

The atomic write replaces the old with the new file, but unless we sync
the parent directory, that replacement is not permanent yet.
This commit is contained in:
Maarten ter Huurne 2014-08-18 15:51:37 +02:00
parent fc4582a61f
commit 9f1827dc24
3 changed files with 42 additions and 1 deletions

View File

@ -348,7 +348,17 @@ bool LinkApp::save() {
if (out.tellp() > 0) {
DEBUG("Saving app settings: %s\n", file.c_str());
return writeStringToFile(file, out.str());
if (writeStringToFile(file, out.str())) {
string dir = parentDir(file);
if (!syncDir(dir)) {
ERROR("Failed to sync dir: %s\n", dir.c_str());
// Note: Even if syncDir fails, the app settings have been
// written, so have save() return true.
}
return true;
} else {
return false;
}
} else {
DEBUG("Empty app settings: %s\n", file.c_str());
return unlink(file.c_str()) == 0 || errno == ENOENT;

View File

@ -112,6 +112,31 @@ bool writeStringToFile(string const& filename, string const& data) {
return ok;
}
constexpr int dirOpenFlags =
#ifdef O_DIRECTORY
O_DIRECTORY | O_RDONLY; // Linux specific
#else
O_RDONLY;
#endif
bool syncDir(string const& dirname)
{
int fd = open(dirname.c_str(), dirOpenFlags);
if (fd < 0) {
return false;
}
bool ok = fsync(fd) == 0;
while (close(fd)) {
if (errno != EINTR) {
return false;
}
}
return ok;
}
string parentDir(string const& dir) {
// Note that size() is unsigned, so for short strings the '- 2' wraps
// around and as a result the entire string is searched, which is fine.

View File

@ -57,6 +57,12 @@ std::string readFileAsString(std::string const& filename);
*/
bool writeStringToFile(std::string const& filename, std::string const& data);
/**
* Tells the file system to commit the given directory to disk.
* @return True iff the sync was successful.
*/
bool syncDir(std::string const& dirname);
std::string strreplace(std::string orig, const std::string &search, const std::string &replace);
std::string cmdclean(std::string cmdline);