summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-05-11 11:47:22 -0400
committerpommicket <pommicket@gmail.com>2023-05-11 11:47:22 -0400
commit8ae9e18c008dba7e47c5750f7feb91df8bf723df (patch)
treeac80b1663cfe9f6b4c8a772319006eca2e16bd50
parent79724dc47d0fe9b6ceaa21cd3af1052bdcaea653 (diff)
fix backups wrt hard links, add crlf-windows setting
-rw-r--r--buffer.c85
-rw-r--r--config.c2
-rw-r--r--main.c3
-rw-r--r--ted.cfg8
-rw-r--r--ted.h2
5 files changed, 55 insertions, 45 deletions
diff --git a/buffer.c b/buffer.c
index 5090306..f607f10 100644
--- a/buffer.c
+++ b/buffer.c
@@ -2666,44 +2666,13 @@ void buffer_new_file(TextBuffer *buffer, const char *path) {
buffer->nlines = 1;
}
-bool buffer_save(TextBuffer *buffer) {
+static bool buffer_write_to_file(TextBuffer *buffer, const char *path) {
const Settings *settings = buffer_settings(buffer);
-
- if (!buffer_is_named_file(buffer)) {
- // user tried to save line buffer. whatever
- return true;
- }
- if (buffer->view_only) {
- buffer_error(buffer, "Can't save view-only file.");
- return false;
- }
- char tmp_path[TED_PATH_MAX+10];
- strbuf_printf(tmp_path, "%s.ted-tmp", buffer->path);
- if (strlen(tmp_path) != strlen(buffer->path) + 8) {
- buffer_error(buffer, "File name too long.");
- return false;
- }
-
-
- FILE *out = fopen(tmp_path, "wb");
+ FILE *out = fopen(path, "wb");
if (!out) {
- buffer_error(buffer, "Couldn't open file %s for writing: %s.", buffer->path, strerror(errno));
+ buffer_error(buffer, "Couldn't open file %s for writing: %s.", path, strerror(errno));
return false;
}
- #if __unix__
- // preserve permissions
- struct stat statbuf = {0};
- if (stat(buffer->path, &statbuf) == 0) {
- mode_t mode = statbuf.st_mode;
- if (!(mode & 0222)) {
- // we won't be able to write to buffer->path
- buffer_error(buffer, "Can't write to %s (file has permissions %04o)", buffer->path, mode);
- fclose(out);
- return false;
- }
- fchmod(fileno(out), mode);
- }
- #endif
if (settings->auto_add_newline) {
Line *last_line = &buffer->lines[buffer->nlines - 1];
if (last_line->len) {
@@ -2723,34 +2692,66 @@ bool buffer_save(TextBuffer *buffer) {
size_t bytes = unicode_utf32_to_utf8(utf8, *p);
if (bytes != (size_t)-1) {
if (fwrite(utf8, 1, bytes, out) != bytes) {
- buffer_error(buffer, "Couldn't write to %s.", tmp_path);
+ buffer_error(buffer, "Couldn't write to %s.", path);
success = false;
}
}
}
if (i != buffer->nlines-1) {
+ #if _WIN32
+ if (settings->crlf_windows)
+ putc('\r', out);
+ #endif
putc('\n', out);
}
}
if (ferror(out)) {
if (!buffer_has_error(buffer))
- buffer_error(buffer, "Couldn't write to %s.", tmp_path);
+ buffer_error(buffer, "Couldn't write to %s.", path);
success = false;
}
if (fclose(out) != 0) {
if (!buffer_has_error(buffer))
- buffer_error(buffer, "Couldn't close file %s.", tmp_path);
+ buffer_error(buffer, "Couldn't close file %s.", path);
success = false;
}
- if (success) {
- if (os_rename_overwrite(tmp_path, buffer->path) < 0) {
- if (!buffer_has_error(buffer))
- buffer_error(buffer, "Couldn't rename %s => %s.", tmp_path, buffer->path);
- success = false;
+
+ return success;
+}
+
+bool buffer_save(TextBuffer *buffer) {
+ const Settings *settings = buffer_settings(buffer);
+
+ if (!buffer_is_named_file(buffer)) {
+ // user tried to save line buffer. whatever
+ return true;
+ }
+ if (buffer->view_only) {
+ buffer_error(buffer, "Can't save view-only file.");
+ return false;
+ }
+
+ char backup_path[TED_PATH_MAX+10];
+ *backup_path = '\0';
+
+ if (settings->save_backup) {
+ strbuf_printf(backup_path, "%s.ted-bk", buffer->path);
+ if (strlen(backup_path) != strlen(buffer->path) + 7) {
+ buffer_error(buffer, "File name too long.");
+ return false;
}
+
}
+
+ bool success = true;
+ if (*backup_path)
+ success &= buffer_write_to_file(buffer, backup_path);
+ if (success)
+ success &= buffer_write_to_file(buffer, buffer->path);
+ if (success && *backup_path)
+ remove(backup_path);
buffer->last_write_time = timespec_to_seconds(time_last_modified(buffer->path));
if (success) {
buffer->undo_history_write_pos = arr_len(buffer->undo_history);
diff --git a/config.c b/config.c
index 81fac91..5baa772 100644
--- a/config.c
+++ b/config.c
@@ -97,6 +97,8 @@ static const SettingBool settings_bool[] = {
{"vsync", &settings_zero.vsync, false},
{"highlight-enabled", &settings_zero.highlight_enabled, true},
{"highlight-auto", &settings_zero.highlight_auto, true},
+ {"save-backup", &settings_zero.save_backup, true},
+ {"crlf-windows", &settings_zero.crlf_windows, true},
};
static const SettingU8 settings_u8[] = {
{"tab-width", &settings_zero.tab_width, 1, 100, true},
diff --git a/main.c b/main.c
index f09efcf..23d0d07 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,5 @@
/*
TODO:
-- fix backup file creation wrt hard links (right now saving a hard-linked file creates a new link)
- idea: just copy to the backup file, then overwrite the original.
- also, add a setting for whether or not to back up.
- option for whether to jump to build error when the build command finishes, and maybe :build-jump, :build-nojump commands
- highlight TODO, FIXME, XXX, others(?) in comments
- :go-to-matching-bracket
diff --git a/ted.cfg b/ted.cfg
index 592cfb4..408c9b3 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -99,6 +99,14 @@ regenerate-tags-if-not-found = yes
# if no identifying files are found, the directory containing the current file is used.
root-identifiers = .ted-root, .ted-root.out, Cargo.toml, make.bat, CMakeLists.txt, Makefile, go.mod, .git
+# whether or not to save a backup copy of files before
+# writing to the file (prevents loss of data if power goes out mid-write or something).
+# the backups are deleted immediately after writing.
+save-backup = yes
+# whether to default to \r\n line endings.
+# this setting is ignored on non-Windows operating system.
+crlf-windows = no
+
# you can make your own custom background for ted using a shader.
# an example is provided here. you will have access to the following variables:
# t_pos - screen position of fragment (0,0) to (1,1)
diff --git a/ted.h b/ted.h
index 0852669..e1a571b 100644
--- a/ted.h
+++ b/ted.h
@@ -271,6 +271,8 @@ typedef struct {
bool highlight_enabled;
bool highlight_auto;
bool vsync;
+ bool save_backup;
+ bool crlf_windows;
KeyCombo hover_key;
KeyCombo highlight_key;
u8 tab_width;