summaryrefslogtreecommitdiff
path: root/atomicio.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-09-24 22:15:11 +1000
committerDamien Miller <djm@mindrot.org>2010-09-24 22:15:11 +1000
commit65e42f87fe945a2bf30d7e02358554dbaefa8a4c (patch)
tree102c10a0b5328a40c79dca19d208f0ca0c1671b5 /atomicio.c
parent7fe2b1fec3b364faf952828f3875b8e7eed8feb4 (diff)
- djm@cvs.openbsd.org 2010/09/22 22:58:51
[atomicio.c atomicio.h misc.c misc.h scp.c sftp-client.c] [sftp-client.h sftp.1 sftp.c] add an option per-read/write callback to atomicio factor out bandwidth limiting code from scp(1) into a generic bandwidth limiter that can be attached using the atomicio callback mechanism add a bandwidth limit option to sftp(1) using the above "very nice" markus@
Diffstat (limited to 'atomicio.c')
-rw-r--r--atomicio.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/atomicio.c b/atomicio.c
index a6b2d127..601b3c37 100644
--- a/atomicio.c
+++ b/atomicio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atomicio.c,v 1.25 2007/06/25 12:02:27 dtucker Exp $ */
+/* $OpenBSD: atomicio.c,v 1.26 2010/09/22 22:58:51 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
@@ -48,7 +48,8 @@
* ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
-atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
+atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
+ int (*cb)(void *, size_t), void *cb_arg)
{
char *s = _s;
size_t pos = 0;
@@ -73,17 +74,28 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
return pos;
default:
pos += (size_t)res;
+ if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
+ errno = EINTR;
+ return pos;
+ }
}
}
- return (pos);
+ return pos;
+}
+
+size_t
+atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
+{
+ return atomicio6(f, fd, _s, n, NULL, NULL);
}
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
-atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
- const struct iovec *_iov, int iovcnt)
+atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
+ const struct iovec *_iov, int iovcnt,
+ int (*cb)(void *, size_t), void *cb_arg)
{
size_t pos = 0, rem;
ssize_t res;
@@ -137,6 +149,17 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
iov[0].iov_len -= rem;
}
+ if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
+ errno = EINTR;
+ return pos;
+ }
}
return pos;
}
+
+size_t
+atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
+ const struct iovec *_iov, int iovcnt)
+{
+ return atomiciov6(f, fd, _iov, iovcnt, NULL, NULL);
+}