summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buffer_utils.cc48
-rw-r--r--src/commands.cc8
-rw-r--r--test/regression/3398-readonly-fifo-failure/cmd1
-rw-r--r--test/regression/3398-readonly-fifo-failure/out1
-rw-r--r--test/regression/3398-readonly-fifo-failure/rc2
-rw-r--r--test/regression/3398-readonly-fifo-failure/script8
6 files changed, 44 insertions, 24 deletions
diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc
index cbead31d..0162822c 100644
--- a/src/buffer_utils.cc
+++ b/src/buffer_utils.cc
@@ -143,32 +143,38 @@ Buffer* create_fifo_buffer(String name, int fd, Buffer::Flags flags, bool scroll
char data[buffer_size];
BufferCoord insert_coord = m_buffer.back_coord();
const int fifo = fd();
- do
+
{
- const ssize_t count = ::read(fifo, data, buffer_size);
- if (count <= 0)
+ auto restore_flags = on_scope_end([this, flags=m_buffer.flags()] { m_buffer.flags() = flags; });
+ m_buffer.flags() &= ~Buffer::Flags::ReadOnly;
+ do
{
- closed = true;
- break;
- }
-
- auto pos = m_buffer.back_coord();
- const bool prevent_scrolling = pos == BufferCoord{0,0} and not m_scroll;
- if (prevent_scrolling)
- pos = m_buffer.next(pos);
- m_buffer.insert(pos, StringView(data, data+count));
-
- if (prevent_scrolling)
- {
- m_buffer.erase({0,0}, m_buffer.next({0,0}));
- // in the other case, the buffer will have automatically
- // inserted a \n to guarantee its invariant.
- if (data[count-1] == '\n')
- m_buffer.insert(m_buffer.end_coord(), "\n");
+ const ssize_t count = ::read(fifo, data, buffer_size);
+ if (count <= 0)
+ {
+ closed = true;
+ break;
+ }
+
+ auto pos = m_buffer.back_coord();
+ const bool prevent_scrolling = pos == BufferCoord{0,0} and not m_scroll;
+ if (prevent_scrolling)
+ pos = m_buffer.next(pos);
+
+ m_buffer.insert(pos, StringView(data, data+count));
+
+ if (prevent_scrolling)
+ {
+ m_buffer.erase({0,0}, m_buffer.next({0,0}));
+ // in the other case, the buffer will have automatically
+ // inserted a \n to guarantee its invariant.
+ if (data[count-1] == '\n')
+ m_buffer.insert(m_buffer.end_coord(), "\n");
+ }
}
+ while (++loop < max_loop and fd_readable(fifo));
}
- while (++loop < max_loop and fd_readable(fifo));
if (insert_coord != m_buffer.back_coord())
m_buffer.run_hook_in_own_context(
diff --git a/src/commands.cc b/src/commands.cc
index ee45bcde..09e73ce3 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -472,14 +472,16 @@ const ParameterDesc write_params{
void do_write_buffer(Context& context, Optional<String> filename, WriteFlags flags, bool atomic = false)
{
Buffer& buffer = context.buffer();
+ const bool is_file = (bool)(buffer.flags() & Buffer::Flags::File);
- if (not filename and !(buffer.flags() & Buffer::Flags::File))
+ if (not filename and !is_file)
throw runtime_error("cannot write a non file buffer without a filename");
+ const bool is_readonly = (bool)(context.buffer().flags() & Buffer::Flags::ReadOnly);
// if the buffer is in read-only mode and we try to save it directly
// or we try to write to it indirectly using e.g. a symlink, throw an error
- if ((context.buffer().flags() & Buffer::Flags::ReadOnly)
- and (not filename or real_path(*filename) == buffer.name()))
+ if (is_file and is_readonly and
+ (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);
diff --git a/test/regression/3398-readonly-fifo-failure/cmd b/test/regression/3398-readonly-fifo-failure/cmd
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/test/regression/3398-readonly-fifo-failure/cmd
@@ -0,0 +1 @@
+
diff --git a/test/regression/3398-readonly-fifo-failure/out b/test/regression/3398-readonly-fifo-failure/out
new file mode 100644
index 00000000..907b3081
--- /dev/null
+++ b/test/regression/3398-readonly-fifo-failure/out
@@ -0,0 +1 @@
+blah
diff --git a/test/regression/3398-readonly-fifo-failure/rc b/test/regression/3398-readonly-fifo-failure/rc
new file mode 100644
index 00000000..67641227
--- /dev/null
+++ b/test/regression/3398-readonly-fifo-failure/rc
@@ -0,0 +1,2 @@
+nop %sh{ mkfifo test-fifo; ( printf 'blah' > test-fifo ) </dev/null >/dev/null 2>&1 & }
+edit -readonly -fifo test-fifo out
diff --git a/test/regression/3398-readonly-fifo-failure/script b/test/regression/3398-readonly-fifo-failure/script
new file mode 100644
index 00000000..f86cd7c2
--- /dev/null
+++ b/test/regression/3398-readonly-fifo-failure/script
@@ -0,0 +1,8 @@
+ui_out '{ "jsonrpc": "2.0", "method": "set_ui_options", "params": [{}] }'
+ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "cyan", "attributes": [] }, "contents": "\u000a" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] }'
+ui_out '{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] }'
+ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }'
+ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "[scratch][fifo]" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] }'
+ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
+ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
+ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": "b" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "lah\u000a" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] }'