summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2017-04-20 16:25:24 +0100
committerMaxime Coste <mawww@kakoune.org>2017-04-20 16:25:24 +0100
commitab3a255d58c82ef572468de93f7c625c3f618bda (patch)
tree558d97bb74e891516787419531955d738097e00b /src
parentdbcddafbfdc8808e8823812b1a5c40d4aedcdf90 (diff)
parent51ab59cd3624476832272112ae5814fecef12f69 (diff)
Merge remote-tracking branch 'lenormf/command-force-write'
Diffstat (limited to 'src')
-rw-r--r--src/commands.cc16
-rw-r--r--src/file.cc22
-rw-r--r--src/file.hh2
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);