aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/history.cc30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/history.cc b/src/history.cc
index 4b3eba1..1fb18ed 100644
--- a/src/history.cc
+++ b/src/history.cc
@@ -7,6 +7,7 @@
#include <unistd.h>
#include <fstream>
#include <iostream>
+#include <sys/stat.h>
#include "util/io.h"
@@ -54,18 +55,18 @@ void load_history(const string &path)
void save_history(const string &path)
{
- int fd = open(path.c_str(), O_WRONLY | O_CREAT);
+ string tmp_path = path + ".tmp";
+ int fd = open(tmp_path.c_str(), (O_WRONLY | O_CREAT | O_TRUNC), (S_IRUSR | S_IWUSR));
if (fd == -1)
{
loggerln("save_history: fail to open() history");
return;
}
- char f_mode = 'w';
- FILE *f = fdopen(fd, &f_mode);
+ FILE *f = fdopen(fd, "w");
if (f == nullptr)
{
- loggerln("save_history: fail to fdopen() history");
close(fd);
+ loggerln("save_history: fail to fdopen() history");
return;
}
@@ -74,9 +75,24 @@ void save_history(const string &path)
println(f, "{}", c);
}
- fflush(f);
- fsync(fd);
- fclose(f);
+
+ bool success_write = true;
+ if (fflush(f) != 0) success_write = false;
+ if (fsync(fd) != 0) success_write = false;
+ if (fclose(f) != 0) success_write = false;
+
+ if (!success_write)
+ {
+ loggerln("save_history: fail to write");
+ return;
+ }
+
+ // atomic rename (replace)
+ if (rename(tmp_path.c_str(), path.c_str()) != 0)
+ {
+ loggerln("save_history: fail to rename");
+ return;
+ }
}
}