diff options
| author | Maxime Coste <mawww@kakoune.org> | 2017-04-20 16:25:24 +0100 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2017-04-20 16:25:24 +0100 |
| commit | ab3a255d58c82ef572468de93f7c625c3f618bda (patch) | |
| tree | 558d97bb74e891516787419531955d738097e00b /src | |
| parent | dbcddafbfdc8808e8823812b1a5c40d4aedcdf90 (diff) | |
| parent | 51ab59cd3624476832272112ae5814fecef12f69 (diff) | |
Merge remote-tracking branch 'lenormf/command-force-write'
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands.cc | 16 | ||||
| -rw-r--r-- | src/file.cc | 22 | ||||
| -rw-r--r-- | src/file.hh | 2 |
3 files changed, 36 insertions, 4 deletions
diff --git a/src/commands.cc b/src/commands.cc index 6143179d..355f560d 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -309,6 +309,7 @@ const CommandDesc force_edit_cmd = { edit<true> }; +template<bool force = false> void write_buffer(const ParametersParser& parser, Context& context, const ShellContext&) { Buffer& buffer = context.buffer(); @@ -326,7 +327,7 @@ void write_buffer(const ParametersParser& parser, Context& context, const ShellC buffer.name() : parse_filename(parser[0]); context.hooks().run_hook("BufWritePre", filename, context); - write_buffer_to_file(buffer, filename); + write_buffer_to_file(buffer, filename, force); context.hooks().run_hook("BufWritePost", filename, context); } @@ -342,6 +343,18 @@ const CommandDesc write_cmd = { write_buffer, }; +const CommandDesc force_write_cmd = { + "write!", + "w!", + "write [filename]: write the current buffer to its file " + "or to [filename] if specified, even when the file is write protected", + single_optional_param, + CommandFlags::None, + CommandHelper{}, + filename_completer, + write_buffer<true>, +}; + void write_all_buffers(Context& context) { // Copy buffer list because hooks might be creating/deleting buffers @@ -2102,6 +2115,7 @@ void register_commands() register_command(edit_cmd); register_command(force_edit_cmd); register_command(write_cmd); + register_command(force_write_cmd); register_command(write_all_cmd); register_command(write_all_quit_cmd); register_command(kill_cmd); diff --git a/src/file.cc b/src/file.cc index bf592689..49fa00e5 100644 --- a/src/file.cc +++ b/src/file.cc @@ -278,9 +278,27 @@ void write_buffer_to_fd(Buffer& buffer, int fd) } } -void write_buffer_to_file(Buffer& buffer, StringView filename) +void write_buffer_to_file(Buffer& buffer, StringView filename, bool force) { - int fd = open(filename.zstr(), O_CREAT | O_WRONLY | O_TRUNC, 0644); + struct stat st; + auto zfilename = filename.zstr(); + + if (force) + { + if (::stat(zfilename, &st) == 0) + { + if (::chmod(zfilename, st.st_mode | S_IWUSR) < 0) + throw runtime_error("couldn't change file permissions"); + } + else + force = false; + } + auto restore_mode = on_scope_end([&]{ + if (force and ::chmod(zfilename, st.st_mode) < 0) + throw runtime_error("couldn't restore file permissions"); + }); + + int fd = open(zfilename, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd == -1) throw file_access_error(filename, strerror(errno)); diff --git a/src/file.hh b/src/file.hh index 7cb5f88c..23fbe0a2 100644 --- a/src/file.hh +++ b/src/file.hh @@ -49,7 +49,7 @@ struct MappedFile struct stat st {}; }; -void write_buffer_to_file(Buffer& buffer, StringView filename); +void write_buffer_to_file(Buffer& buffer, StringView filename, bool force = false); void write_buffer_to_fd(Buffer& buffer, int fd); void write_buffer_to_backup_file(Buffer& buffer); |
