summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2021-07-20 22:06:57 +1000
committerMaxime Coste <mawww@kakoune.org>2021-07-20 22:30:41 +1000
commit40e3614cf458a982c783e899143bef81736faa27 (patch)
tree6cf74d1fa2043b7a0a2419c449cec49189f3b41f /src
parent4d99434ddd9aa0acec91ea9790daf1b0610b087f (diff)
Prevent overwriting existing file in :write <explicit filename>
Add a -force (equivalent to w!) switch that enables overwriting.
Diffstat (limited to 'src')
-rw-r--r--src/commands.cc10
-rw-r--r--src/file.cc7
-rw-r--r--src/file.hh1
3 files changed, 16 insertions, 2 deletions
diff --git a/src/commands.cc b/src/commands.cc
index 3a805756..99859127 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -460,6 +460,7 @@ const ParameterDesc write_params{
{
{ "sync", { false, "force the synchronization of the file onto the filesystem" } },
{ "method", { true, "explicit writemethod (replace|overwrite)" } },
+ { "force", { false, "Allow overwriting existing file with explicit filename" } },
},
ParameterDesc::Flags::SwitchesOnlyAtStart, 0, 1
};
@@ -488,7 +489,12 @@ void do_write_buffer(Context& context, Optional<String> filename, WriteFlags fla
(not filename or real_path(*filename) == buffer.name()))
throw runtime_error("cannot overwrite the buffer when in readonly mode");
- auto effective_filename = not filename ? buffer.name() : parse_filename(*filename);
+ auto effective_filename = filename ? parse_filename(*filename) : buffer.name();
+ if (filename and not (flags & WriteFlags::Force) and
+ real_path(effective_filename) != buffer.name() and
+ regular_file_exists(effective_filename))
+ throw runtime_error("cannot overwrite existing file without -force");
+
auto method = write_method.value_or_compute([&] { return context.options()["writemethod"].get<WriteMethod>(); });
context.hooks().run_hook(Hook::BufWritePre, effective_filename, context);
@@ -502,7 +508,7 @@ void write_buffer(const ParametersParser& parser, Context& context, const ShellC
return do_write_buffer(context,
parser.positional_count() > 0 ? parser[0] : Optional<String>{},
(parser.get_switch("sync") ? WriteFlags::Sync : WriteFlags::None) |
- (force ? WriteFlags::Force : WriteFlags::None),
+ (parser.get_switch("force") or force ? WriteFlags::Force : WriteFlags::None),
parser.get_switch("method").map(parse_write_method));
}
diff --git a/src/file.cc b/src/file.cc
index 89dee9a3..4c7658be 100644
--- a/src/file.cc
+++ b/src/file.cc
@@ -247,6 +247,13 @@ bool file_exists(StringView filename)
return stat(filename.zstr(), &st) == 0;
}
+bool regular_file_exists(StringView filename)
+{
+ struct stat st;
+ return stat(filename.zstr(), &st) == 0 and
+ (st.st_mode & S_IFMT) == S_IFREG;
+}
+
void write(int fd, StringView data)
{
const char* ptr = data.data();
diff --git a/src/file.hh b/src/file.hh
index aa32b01d..849b14f4 100644
--- a/src/file.hh
+++ b/src/file.hh
@@ -81,6 +81,7 @@ void write_buffer_to_backup_file(Buffer& buffer);
String find_file(StringView filename, StringView buf_dir, ConstArrayView<String> paths);
bool file_exists(StringView filename);
+bool regular_file_exists(StringView filename);
Vector<String> list_files(StringView directory);