summaryrefslogtreecommitdiff
path: root/usr.bin/rsync
diff options
context:
space:
mode:
authorJob Snijders <job@cvs.openbsd.org>2022-08-02 18:09:21 +0000
committerJob Snijders <job@cvs.openbsd.org>2022-08-02 18:09:21 +0000
commitc7ac62360d677f281941a2dbc128fd1bdbba99f4 (patch)
treeb84f800ba25974ecf42403b91549073fb132c777 /usr.bin/rsync
parent39260e6019d8d99ec28629e5357be6dbd834b1e4 (diff)
Add --contimeout functionality.
Input from deraadt@ OK claudio@
Diffstat (limited to 'usr.bin/rsync')
-rw-r--r--usr.bin/rsync/extern.h7
-rw-r--r--usr.bin/rsync/main.c29
-rw-r--r--usr.bin/rsync/rsync.19
-rw-r--r--usr.bin/rsync/socket.c51
4 files changed, 68 insertions, 28 deletions
diff --git a/usr.bin/rsync/extern.h b/usr.bin/rsync/extern.h
index 3a612722b9a..7de0211ba7b 100644
--- a/usr.bin/rsync/extern.h
+++ b/usr.bin/rsync/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.43 2021/10/29 08:00:59 claudio Exp $ */
+/* $OpenBSD: extern.h,v 1.44 2022/08/02 18:09:20 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -70,6 +70,11 @@
extern int poll_timeout;
/*
+ * Use this for --contimeout.
+ */
+extern int poll_contimeout;
+
+/*
* Operating mode for a client or a server.
* Sender means we synchronise local files with those from remote.
* Receiver is the opposite.
diff --git a/usr.bin/rsync/main.c b/usr.bin/rsync/main.c
index e7713cc548a..36ed383345b 100644
--- a/usr.bin/rsync/main.c
+++ b/usr.bin/rsync/main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: main.c,v 1.63 2021/11/03 14:42:12 deraadt Exp $ */
+/* $OpenBSD: main.c,v 1.64 2022/08/02 18:09:20 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -31,6 +31,7 @@
#include "extern.h"
int verbose;
+int poll_contimeout;
int poll_timeout;
/*
@@ -286,6 +287,7 @@ static struct opts opts;
#define OP_LINK_DEST 1011
#define OP_MAX_SIZE 1012
#define OP_MIN_SIZE 1013
+#define OP_CONTIMEOUT 1014
const struct option lopts[] = {
{ "address", required_argument, NULL, OP_ADDRESS },
@@ -296,6 +298,7 @@ const struct option lopts[] = {
{ "link-dest", required_argument, NULL, OP_LINK_DEST },
#endif
{ "compress", no_argument, NULL, 'z' },
+ { "contimeout", required_argument, NULL, OP_CONTIMEOUT },
{ "del", no_argument, &opts.del, 1 },
{ "delete", no_argument, &opts.del, 1 },
{ "devices", no_argument, &opts.devices, 1 },
@@ -411,6 +414,12 @@ main(int argc, char *argv[])
case OP_ADDRESS:
opts.address = optarg;
break;
+ case OP_CONTIMEOUT:
+ poll_contimeout = strtonum(optarg, 0, 60*60, &errstr);
+ if (errstr != NULL)
+ errx(ERR_SYNTAX, "timeout is %s: %s",
+ errstr, optarg);
+ break;
case OP_PORT:
opts.port = optarg;
break;
@@ -503,9 +512,16 @@ basedir:
if (opts.port == NULL)
opts.port = "rsync";
+ /* by default and for --contimeout=0 disable poll_contimeout */
+ if (poll_contimeout == 0)
+ poll_contimeout = -1;
+ else
+ poll_contimeout *= 1000;
+
/* by default and for --timeout=0 disable poll_timeout */
if (poll_timeout == 0)
- poll_timeout = -1; else
+ poll_timeout = -1;
+ else
poll_timeout *= 1000;
/*
@@ -614,10 +630,11 @@ basedir:
usage:
fprintf(stderr, "usage: %s"
" [-aDglnoprtvx] [-e program] [--address=sourceaddr]\n"
- "\t[--compare-dest=dir] [--del] [--exclude] [--exclude-from=file]\n"
- "\t[--include] [--include-from=file] [--no-motd] [--numeric-ids]\n"
- "\t[--port=portnumber] [--rsync-path=program] [--timeout=seconds]\n"
- "\t[--version] source ... directory\n",
+ "\t[--contimeout=seconds [--compare-dest=dir] [--del] [--exclude]\n"
+ "\t[--exclude-from=file] [--include] [--include-from=file]\n"
+ "\t[--no-motd] [--numeric-ids] [--port=portnumber]\n"
+ "\t[--rsync-path=program] [--timeout=seconds] [--version]\n"
+ "\tsource ... directory\n",
getprogname());
exit(ERR_SYNTAX);
}
diff --git a/usr.bin/rsync/rsync.1 b/usr.bin/rsync/rsync.1
index 8144754695a..d96c4a0da25 100644
--- a/usr.bin/rsync/rsync.1
+++ b/usr.bin/rsync/rsync.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: rsync.1,v 1.29 2021/11/26 03:41:39 jsg Exp $
+.\" $OpenBSD: rsync.1,v 1.30 2022/08/02 18:09:20 job Exp $
.\"
.\" Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: November 26 2021 $
+.Dd $Mdocdate: August 2 2022 $
.Dt OPENRSYNC 1
.Os
.Sh NAME
@@ -26,6 +26,7 @@
.Op Fl e Ar program
.Op Fl -address Ns = Ns Ar sourceaddr
.Op Fl -compare-dest Ns = Ns Ar directory
+.Op Fl -contimeout Ns = Ns Ar seconds
.Op Fl -del
.Op Fl -exclude Ar pattern
.Op Fl -exclude-from Ns = Ns Ar file
@@ -77,6 +78,10 @@ directories may be provided.
If
.Ar directory
is a relative path, it is relative to the destination directory.
+.It Fl -contimeout Ns = Ns Ar seconds
+Set the connection timeout in seconds.
+Exit if no connection established within the specified time.
+The default is 0, which means no timeout.
.It Fl D
Also transfer device and special files.
Shorthand for
diff --git a/usr.bin/rsync/socket.c b/usr.bin/rsync/socket.c
index 953b229afbc..c063346de61 100644
--- a/usr.bin/rsync/socket.c
+++ b/usr.bin/rsync/socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: socket.c,v 1.31 2021/06/30 13:10:04 claudio Exp $ */
+/* $OpenBSD: socket.c,v 1.32 2022/08/02 18:09:20 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -75,14 +75,18 @@ static int
inet_connect(int *sd, const struct source *src, const char *host,
const struct source *bsrc, size_t bsrcsz)
{
- int c, flags;
+ struct pollfd pfd;
+ socklen_t optlen;
+ int c;
+ int optval;
if (*sd != -1)
close(*sd);
LOG2("trying: %s, %s", src->ip, host);
- if ((*sd = socket(src->family, SOCK_STREAM, 0)) == -1) {
+ if ((*sd = socket(src->family, SOCK_STREAM | SOCK_NONBLOCK, 0))
+ == -1) {
ERR("socket");
return -1;
}
@@ -94,34 +98,43 @@ inet_connect(int *sd, const struct source *src, const char *host,
/*
* Initiate blocking connection.
- * We use the blocking connect() instead of passing NONBLOCK to
- * the socket() function because we don't need to do anything
- * while waiting for this to finish.
+ * We use non-blocking connect() so we can poll() for contimeout.
*/
- c = connect(*sd, (const struct sockaddr *)&src->sa, src->salen);
+ if ((c = connect(*sd, (const struct sockaddr *)&src->sa, src->salen))
+ != 0 && errno == EINPROGRESS) {
+ pfd.fd = *sd;
+ pfd.events = POLLOUT;
+ switch (c = poll(&pfd, 1, poll_contimeout)) {
+ case 1:
+ optlen = sizeof(optval);
+ if ((c = getsockopt(*sd, SOL_SOCKET, SO_ERROR, &optval,
+ &optlen)) == 0) {
+ errno = optval;
+ if (optval != 0)
+ c = -1;
+ }
+ break;
+ case 0:
+ errno = ETIMEDOUT;
+ WARNX("connect timeout: %s, %s", src->ip, host);
+ return 0;
+ default:
+ ERR("poll failed");
+ return -1;
+ }
+ }
if (c == -1) {
if (errno == EADDRNOTAVAIL)
return 0;
if (errno == ECONNREFUSED || errno == EHOSTUNREACH) {
- WARNX("connect refused: %s, %s",
- src->ip, host);
+ WARNX("connect refused: %s, %s", src->ip, host);
return 0;
}
ERR("connect");
return -1;
}
- /* Set up non-blocking mode. */
-
- if ((flags = fcntl(*sd, F_GETFL, 0)) == -1) {
- ERR("fcntl");
- return -1;
- } else if (fcntl(*sd, F_SETFL, flags|O_NONBLOCK) == -1) {
- ERR("fcntl");
- return -1;
- }
-
return 1;
}