diff --git a/src/commands.cc b/src/commands.cc index 0a24742d..6cc48dbf 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -328,7 +328,7 @@ const ParameterDesc write_params{ ParameterDesc::Flags::SwitchesOnlyAtStart, 0, 1 }; -void do_write_buffer(Context& context, Optional filename, bool sync_file, bool force) +void do_write_buffer(Context& context, Optional filename, WriteFlags flags) { Buffer& buffer = context.buffer(); @@ -344,7 +344,7 @@ void do_write_buffer(Context& context, Optional filename, bool sync_file auto effective_filename = not filename ? buffer.name() : parse_filename(*filename); context.hooks().run_hook(Hook::BufWritePre, effective_filename, context); - write_buffer_to_file(buffer, effective_filename, force, sync_file); + write_buffer_to_file(buffer, effective_filename, flags); context.hooks().run_hook(Hook::BufWritePost, effective_filename, context); } @@ -353,7 +353,8 @@ void write_buffer(const ParametersParser& parser, Context& context, const ShellC { return do_write_buffer(context, parser.positional_count() > 0 ? parser[0] : Optional{}, - (bool)parser.get_switch("sync"), force); + (parser.get_switch("sync") ? WriteFlags::Sync : WriteFlags::None) | + (force ? WriteFlags::Force : WriteFlags::None)); } const CommandDesc write_cmd = { @@ -395,7 +396,7 @@ void write_all_buffers(Context& context, bool sync = false) and !(buffer->flags() & Buffer::Flags::ReadOnly)) { buffer->run_hook_in_own_context(Hook::BufWritePre, buffer->name(), context.name()); - write_buffer_to_file(*buffer, buffer->name(), sync); + write_buffer_to_file(*buffer, buffer->name(), sync ? WriteFlags::Sync : WriteFlags::None); buffer->run_hook_in_own_context(Hook::BufWritePost, buffer->name(), context.name()); } } @@ -520,7 +521,7 @@ template void write_quit(const ParametersParser& parser, Context& context, const ShellContext& shell_context) { - do_write_buffer(context, {}, (bool)parser.get_switch("sync"), false); + do_write_buffer(context, {}, parser.get_switch("sync") ? WriteFlags::Sync : WriteFlags::None); quit(parser, context, shell_context); } diff --git a/src/file.cc b/src/file.cc index ce6e00b5..d5e73bed 100644 --- a/src/file.cc +++ b/src/file.cc @@ -257,7 +257,7 @@ void write(int fd, StringView data) } } -void write_buffer_to_fd(Buffer& buffer, int fd, bool sync) +void write_buffer_to_fd(Buffer& buffer, int fd) { auto eolformat = buffer.options()["eolformat"].get(); StringView eoldata; @@ -278,38 +278,35 @@ void write_buffer_to_fd(Buffer& buffer, int fd, bool sync) write(fd, linedata.substr(0, linedata.length()-1)); write(fd, eoldata); } - - if (sync) - ::fsync(fd); } -void write_buffer_to_file(Buffer& buffer, StringView filename, bool force, bool sync) +void write_buffer_to_file(Buffer& buffer, StringView filename, WriteFlags flags) { struct stat st; auto zfilename = filename.zstr(); - if (force) + if (flags & WriteFlags::Force and ::stat(zfilename, &st) == 0) { - if (::stat(zfilename, &st) == 0) - { - if (::chmod(zfilename, st.st_mode | S_IWUSR) < 0) - throw runtime_error("unable to change file permissions"); - } - else - force = false; + if (::chmod(zfilename, st.st_mode | S_IWUSR) < 0) + throw runtime_error("unable to change file permissions"); } + else + flags |= ~WriteFlags::Force; + auto restore_mode = on_scope_end([&]{ - if (force and ::chmod(zfilename, st.st_mode) < 0) + if (flags & WriteFlags::Force and ::chmod(zfilename, st.st_mode) < 0) throw runtime_error("unable to restore file permissions"); }); - int fd = open(zfilename, O_CREAT | O_WRONLY | O_TRUNC, 0644); + const int fd = open(zfilename, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd == -1) throw file_access_error(filename, strerror(errno)); { auto close_fd = on_scope_end([fd]{ close(fd); }); - write_buffer_to_fd(buffer, fd, sync); + write_buffer_to_fd(buffer, fd); + if (flags & WriteFlags::Sync) + ::fsync(fd); } if ((buffer.flags() & Buffer::Flags::File) and diff --git a/src/file.hh b/src/file.hh index 963cbce2..db4ac6ff 100644 --- a/src/file.hh +++ b/src/file.hh @@ -51,8 +51,17 @@ struct MappedFile struct stat st {}; }; -void write_buffer_to_file(Buffer& buffer, StringView filename, bool force = false, bool sync = false); -void write_buffer_to_fd(Buffer& buffer, int fd, bool sync = false); +enum class WriteFlags +{ + None = 0, + Force = 0b01, + Sync = 0b10 +}; +constexpr bool with_bit_ops(Meta::Type) { return true; } + +void write_buffer_to_file(Buffer& buffer, StringView filename, + WriteFlags flags); +void write_buffer_to_fd(Buffer& buffer, int fd); void write_buffer_to_backup_file(Buffer& buffer); String find_file(StringView filename, StringView buf_dir, ConstArrayView paths); diff --git a/src/main.cc b/src/main.cc index 40fee26b..95d5ca41 100644 --- a/src/main.cc +++ b/src/main.cc @@ -847,9 +847,11 @@ int run_filter(StringView keystr, ConstArrayView files, bool quiet, { Buffer* buffer = open_file_buffer(file, Buffer::Flags::NoHooks); if (not suffix_backup.empty()) - write_buffer_to_file(*buffer, buffer->name() + suffix_backup); + write_buffer_to_file(*buffer, buffer->name() + suffix_backup, + WriteFlags::None); apply_to_buffer(*buffer); - write_buffer_to_file(*buffer, buffer->name()); + write_buffer_to_file(*buffer, buffer->name(), + WriteFlags::None); buffer_manager.delete_buffer(*buffer); } if (not isatty(0))