2020-09-17 23:02:40 +03:00
|
|
|
// Copyright (c) Vitaliy Filippov, 2019+
|
2021-02-06 01:26:07 +03:00
|
|
|
// License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details)
|
2020-09-17 23:02:40 +03:00
|
|
|
|
2020-02-09 18:22:29 +03:00
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
2022-01-15 23:55:10 +03:00
|
|
|
#include <stdint.h>
|
2020-02-09 18:22:29 +03:00
|
|
|
#include <stdio.h>
|
2021-12-27 02:05:29 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
2020-02-09 18:22:29 +03:00
|
|
|
|
|
|
|
#include "rw_blocking.h"
|
|
|
|
|
|
|
|
int read_blocking(int fd, void *read_buf, size_t remaining)
|
|
|
|
{
|
|
|
|
size_t done = 0;
|
|
|
|
while (done < remaining)
|
|
|
|
{
|
2023-03-14 20:36:49 +03:00
|
|
|
ssize_t r = read(fd, read_buf, remaining-done);
|
2020-02-09 18:22:29 +03:00
|
|
|
if (r <= 0)
|
|
|
|
{
|
|
|
|
if (!errno)
|
|
|
|
{
|
|
|
|
// EOF
|
|
|
|
return done;
|
|
|
|
}
|
2022-01-22 23:59:37 +03:00
|
|
|
else if (errno != EINTR && errno != EAGAIN && errno != EPIPE)
|
2020-02-09 18:22:29 +03:00
|
|
|
{
|
|
|
|
perror("read");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
done += r;
|
2022-01-15 23:55:10 +03:00
|
|
|
read_buf = (uint8_t*)read_buf + r;
|
2020-02-09 18:22:29 +03:00
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
int write_blocking(int fd, void *write_buf, size_t remaining)
|
|
|
|
{
|
|
|
|
size_t done = 0;
|
|
|
|
while (done < remaining)
|
|
|
|
{
|
2023-03-14 20:36:49 +03:00
|
|
|
ssize_t r = write(fd, write_buf, remaining-done);
|
2020-02-09 18:22:29 +03:00
|
|
|
if (r < 0)
|
|
|
|
{
|
2022-01-22 23:59:37 +03:00
|
|
|
if (errno != EINTR && errno != EAGAIN && errno != EPIPE)
|
2020-02-09 18:22:29 +03:00
|
|
|
{
|
|
|
|
perror("write");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
done += r;
|
2022-01-15 23:55:10 +03:00
|
|
|
write_buf = (uint8_t*)write_buf + r;
|
2020-02-09 18:22:29 +03:00
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
2020-03-02 21:17:17 +03:00
|
|
|
|
2020-06-08 01:54:36 +03:00
|
|
|
int readv_blocking(int fd, iovec *iov, int iovcnt)
|
|
|
|
{
|
|
|
|
int v = 0;
|
|
|
|
int done = 0;
|
|
|
|
while (v < iovcnt)
|
|
|
|
{
|
2021-12-12 23:12:34 +03:00
|
|
|
ssize_t r = readv(fd, iov+v, iovcnt-v);
|
2020-06-08 01:54:36 +03:00
|
|
|
if (r < 0)
|
|
|
|
{
|
2022-01-22 23:59:37 +03:00
|
|
|
if (errno != EINTR && errno != EAGAIN && errno != EPIPE)
|
2020-06-08 01:54:36 +03:00
|
|
|
{
|
|
|
|
perror("writev");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2021-12-12 23:12:34 +03:00
|
|
|
done += r;
|
2020-06-08 01:54:36 +03:00
|
|
|
while (v < iovcnt)
|
|
|
|
{
|
|
|
|
if (iov[v].iov_len > r)
|
|
|
|
{
|
|
|
|
iov[v].iov_len -= r;
|
2022-01-15 23:55:10 +03:00
|
|
|
iov[v].iov_base = (uint8_t*)iov[v].iov_base + r;
|
2020-06-08 01:54:36 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-12 23:12:34 +03:00
|
|
|
r -= iov[v].iov_len;
|
2020-06-08 01:54:36 +03:00
|
|
|
v++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
2020-03-02 21:17:17 +03:00
|
|
|
int writev_blocking(int fd, iovec *iov, int iovcnt)
|
|
|
|
{
|
|
|
|
int v = 0;
|
|
|
|
int done = 0;
|
|
|
|
while (v < iovcnt)
|
|
|
|
{
|
2021-12-12 23:12:34 +03:00
|
|
|
ssize_t r = writev(fd, iov+v, iovcnt-v);
|
2020-03-02 21:17:17 +03:00
|
|
|
if (r < 0)
|
|
|
|
{
|
2022-01-22 23:59:37 +03:00
|
|
|
if (errno != EINTR && errno != EAGAIN && errno != EPIPE)
|
2020-03-02 21:17:17 +03:00
|
|
|
{
|
|
|
|
perror("writev");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2021-12-12 23:12:34 +03:00
|
|
|
done += r;
|
2020-03-02 21:17:17 +03:00
|
|
|
while (v < iovcnt)
|
|
|
|
{
|
|
|
|
if (iov[v].iov_len > r)
|
|
|
|
{
|
|
|
|
iov[v].iov_len -= r;
|
2022-01-15 23:55:10 +03:00
|
|
|
iov[v].iov_base = (uint8_t*)iov[v].iov_base + r;
|
2020-03-02 21:17:17 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-12 23:12:34 +03:00
|
|
|
r -= iov[v].iov_len;
|
2020-03-02 21:17:17 +03:00
|
|
|
v++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
2021-12-27 02:05:29 +03:00
|
|
|
|
|
|
|
int sendv_blocking(int fd, iovec *iov, int iovcnt, int flags)
|
|
|
|
{
|
|
|
|
struct msghdr msg = { 0 };
|
|
|
|
int v = 0;
|
|
|
|
int done = 0;
|
|
|
|
while (v < iovcnt)
|
|
|
|
{
|
|
|
|
msg.msg_iov = iov+v;
|
|
|
|
msg.msg_iovlen = iovcnt-v;
|
|
|
|
ssize_t r = sendmsg(fd, &msg, flags);
|
|
|
|
if (r < 0)
|
|
|
|
{
|
2022-01-22 23:59:37 +03:00
|
|
|
if (errno != EINTR && errno != EAGAIN && errno != EPIPE)
|
2021-12-27 02:05:29 +03:00
|
|
|
{
|
|
|
|
perror("sendmsg");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
done += r;
|
|
|
|
while (v < iovcnt)
|
|
|
|
{
|
|
|
|
if (iov[v].iov_len > r)
|
|
|
|
{
|
|
|
|
iov[v].iov_len -= r;
|
2022-01-15 23:55:10 +03:00
|
|
|
iov[v].iov_base = (uint8_t*)iov[v].iov_base + r;
|
2021-12-27 02:05:29 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r -= iov[v].iov_len;
|
|
|
|
v++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|