mirror of
https://git.zx2c4.com/cgit
synced 2024-09-07 19:35:18 +00:00
cache: tolerate short writes in print_slot
sendfile() can return after a short read/write, so we may need to call it more than once. As suggested in the manual page, we fall back to read/write if sendfile fails with EINVAL or ENOSYS. On the read/write path, use write_in_full which deals with short writes. Signed-off-by: Hristo Venev <hristo@venev.name> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
4c520cefc9
commit
852cb3b0e2
45
cache.c
45
cache.c
@ -85,40 +85,45 @@ static int close_slot(struct cache_slot *slot)
|
||||
/* Print the content of the active cache slot (but skip the key). */
|
||||
static int print_slot(struct cache_slot *slot)
|
||||
{
|
||||
off_t off;
|
||||
#ifdef HAVE_LINUX_SENDFILE
|
||||
off_t start_off;
|
||||
int ret;
|
||||
off_t size;
|
||||
#endif
|
||||
|
||||
start_off = slot->keylen + 1;
|
||||
off = slot->keylen + 1;
|
||||
|
||||
#ifdef HAVE_LINUX_SENDFILE
|
||||
size = slot->cache_st.st_size;
|
||||
|
||||
do {
|
||||
ret = sendfile(STDOUT_FILENO, slot->cache_fd, &start_off,
|
||||
slot->cache_st.st_size - start_off);
|
||||
ssize_t ret;
|
||||
ret = sendfile(STDOUT_FILENO, slot->cache_fd, &off, size - off);
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
/* Fall back to read/write on EINVAL or ENOSYS */
|
||||
if (errno == EINVAL || errno == ENOSYS)
|
||||
break;
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
if (off == size)
|
||||
return 0;
|
||||
} while (1);
|
||||
#else
|
||||
ssize_t i, j;
|
||||
#endif
|
||||
|
||||
i = lseek(slot->cache_fd, slot->keylen + 1, SEEK_SET);
|
||||
if (i != slot->keylen + 1)
|
||||
if (lseek(slot->cache_fd, off, SEEK_SET) != off)
|
||||
return errno;
|
||||
|
||||
do {
|
||||
i = j = xread(slot->cache_fd, slot->buf, sizeof(slot->buf));
|
||||
if (i > 0)
|
||||
j = xwrite(STDOUT_FILENO, slot->buf, i);
|
||||
} while (i > 0 && j == i);
|
||||
|
||||
if (i < 0 || j != i)
|
||||
return errno;
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
ssize_t ret;
|
||||
ret = xread(slot->cache_fd, slot->buf, sizeof(slot->buf));
|
||||
if (ret < 0)
|
||||
return errno;
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
if (write_in_full(STDOUT_FILENO, slot->buf, ret) < 0)
|
||||
return errno;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* Check if the slot has expired */
|
||||
|
Loading…
Reference in New Issue
Block a user