Merge remote-tracking branch 'refs/remotes/tmux-openbsd/master'

* refs/remotes/tmux-openbsd/master:
  If writing a file fails, propagate the error to the server via a new message. Use a client flag rather than bumping the protocol version. GitHub issue 5451.
  Add default terminal features for Rio, GitHub issue 5489 from Raphael Amorim.
This commit is contained in:
tmux update bot
2026-08-17 09:45:11 +00:00
7 changed files with 102 additions and 27 deletions

86
file.c
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: file.c,v 1.21 2026/07/26 15:08:15 nicm Exp $ */
/* $OpenBSD: file.c,v 1.22 2026/08/17 07:56:56 nicm Exp $ */
/*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -502,7 +502,8 @@ file_push(struct client_file *cf)
} else if (cf->stream > 2) {
close.stream = cf->stream;
proc_send(cf->peer, MSG_WRITE_CLOSE, -1, &close, sizeof close);
file_fire_done(cf);
if (cf->c == NULL || (~cf->c->flags & CLIENT_WRITE_ACK))
file_fire_done(cf);
}
free(msg);
}
@@ -527,14 +528,48 @@ file_write_left(struct client_files *files)
return (waiting != 0);
}
/* Finish writing a client file. */
static void
file_write_finished(struct client_file *cf)
{
struct msg_write_done msg;
if (cf->event != NULL) {
bufferevent_free(cf->event);
cf->event = NULL;
}
if (cf->fd != -1) {
if (close(cf->fd) != 0 && cf->error == 0)
cf->error = errno;
cf->fd = -1;
}
msg.stream = cf->stream;
msg.error = cf->error;
proc_send(cf->peer, MSG_WRITE_DONE, -1, &msg, sizeof msg);
if (cf->cb != NULL)
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
file_free(cf);
}
/* Client file write error callback. */
static void
file_write_error_callback(__unused struct bufferevent *bev, __unused short what,
file_write_error_callback(__unused struct bufferevent *bev, short what,
void *arg)
{
struct client_file *cf = arg;
int error;
if (what & EVBUFFER_ERROR)
error = errno;
else
error = EIO;
if (error == 0)
error = EIO;
log_debug("write error file %d", cf->stream);
cf->error = error;
bufferevent_free(cf->event);
cf->event = NULL;
@@ -542,7 +577,9 @@ file_write_error_callback(__unused struct bufferevent *bev, __unused short what,
close(cf->fd);
cf->fd = -1;
if (cf->cb != NULL)
if (cf->closed)
file_write_finished(cf);
else if (cf->cb != NULL)
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
}
@@ -554,15 +591,10 @@ file_write_callback(__unused struct bufferevent *bev, void *arg)
log_debug("write check file %d", cf->stream);
if (cf->cb != NULL)
if (cf->closed && EVBUFFER_LENGTH(cf->event->output) == 0)
file_write_finished(cf);
else if (cf->cb != NULL)
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
if (cf->closed && EVBUFFER_LENGTH(cf->event->output) == 0) {
bufferevent_free(cf->event);
close(cf->fd);
RB_REMOVE(client_files, cf->tree, cf);
file_free(cf);
}
}
/* Handle a file write open message (client). */
@@ -663,14 +695,10 @@ file_write_close(struct client_files *files, struct imsg *imsg)
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
fatalx("unknown stream number");
log_debug("close file %d", cf->stream);
cf->closed = 1;
if (cf->event == NULL || EVBUFFER_LENGTH(cf->event->output) == 0) {
if (cf->event != NULL)
bufferevent_free(cf->event);
if (cf->fd != -1)
close(cf->fd);
RB_REMOVE(client_files, files, cf);
file_free(cf);
file_write_finished(cf);
}
}
@@ -829,6 +857,28 @@ file_write_ready(struct client_files *files, struct imsg *imsg)
return (0);
}
/* Handle a write done message (server). */
int
file_write_done(struct client_files *files, struct imsg *imsg)
{
struct msg_write_done *msg = imsg->data;
size_t msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
struct client_file find, *cf;
if (msglen != sizeof *msg)
return (-1);
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
return (0);
if (cf->c == NULL || (~cf->c->flags & CLIENT_WRITE_ACK))
return (0);
log_debug("file %d write done", cf->stream);
cf->error = msg->error;
file_fire_done(cf);
return (0);
}
/* Handle read data message (server). */
int
file_read_data(struct client_files *files, struct imsg *imsg)