| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * tools/testing/selftests/kvm/lib/io.c |
| * |
| * Copyright (C) 2018, Google LLC. |
| */ |
| |
| #include "test_util.h" |
| |
| /* Test Write |
| * |
| * A wrapper for write(2), that automatically handles the following |
| * special conditions: |
| * |
| * + Interrupted system call (EINTR) |
| * + Write of less than requested amount |
| * + Non-block return (EAGAIN) |
| * |
| * For each of the above, an additional write is performed to automatically |
| * continue writing the requested data. |
| * There are also many cases where write(2) can return an unexpected |
| * error (e.g. EIO). Such errors cause a TEST_ASSERT failure. |
| * |
| * Note, for function signature compatibility with write(2), this function |
| * returns the number of bytes written, but that value will always be equal |
| * to the number of requested bytes. All other conditions in this and |
| * future enhancements to this function either automatically issue another |
| * write(2) or cause a TEST_ASSERT failure. |
| * |
| * Args: |
| * fd - Opened file descriptor to file to be written. |
| * count - Number of bytes to write. |
| * |
| * Output: |
| * buf - Starting address of data to be written. |
| * |
| * Return: |
| * On success, number of bytes written. |
| * On failure, a TEST_ASSERT failure is caused. |
| */ |
| ssize_t test_write(int fd, const void *buf, size_t count) |
| { |
| ssize_t rc; |
| ssize_t num_written = 0; |
| size_t num_left = count; |
| const char *ptr = buf; |
| |
| /* Note: Count of zero is allowed (see "RETURN VALUE" portion of |
| * write(2) manpage for details. |
| */ |
| TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count); |
| |
| do { |
| rc = write(fd, ptr, num_left); |
| |
| switch (rc) { |
| case -1: |
| TEST_ASSERT(errno == EAGAIN || errno == EINTR, |
| "Unexpected write failure,\n" |
| " rc: %zi errno: %i", rc, errno); |
| continue; |
| |
| case 0: |
| TEST_ASSERT(false, "Unexpected EOF,\n" |
| " rc: %zi num_written: %zi num_left: %zu", |
| rc, num_written, num_left); |
| break; |
| |
| default: |
| TEST_ASSERT(rc >= 0, "Unexpected ret from write,\n" |
| " rc: %zi errno: %i", rc, errno); |
| num_written += rc; |
| num_left -= rc; |
| ptr += rc; |
| break; |
| } |
| } while (num_written < count); |
| |
| return num_written; |
| } |
| |
| /* Test Read |
| * |
| * A wrapper for read(2), that automatically handles the following |
| * special conditions: |
| * |
| * + Interrupted system call (EINTR) |
| * + Read of less than requested amount |
| * + Non-block return (EAGAIN) |
| * |
| * For each of the above, an additional read is performed to automatically |
| * continue reading the requested data. |
| * There are also many cases where read(2) can return an unexpected |
| * error (e.g. EIO). Such errors cause a TEST_ASSERT failure. Note, |
| * it is expected that the file opened by fd at the current file position |
| * contains at least the number of requested bytes to be read. A TEST_ASSERT |
| * failure is produced if an End-Of-File condition occurs, before all the |
| * data is read. It is the callers responsibility to assure that sufficient |
| * data exists. |
| * |
| * Note, for function signature compatibility with read(2), this function |
| * returns the number of bytes read, but that value will always be equal |
| * to the number of requested bytes. All other conditions in this and |
| * future enhancements to this function either automatically issue another |
| * read(2) or cause a TEST_ASSERT failure. |
| * |
| * Args: |
| * fd - Opened file descriptor to file to be read. |
| * count - Number of bytes to read. |
| * |
| * Output: |
| * buf - Starting address of where to write the bytes read. |
| * |
| * Return: |
| * On success, number of bytes read. |
| * On failure, a TEST_ASSERT failure is caused. |
| */ |
| ssize_t test_read(int fd, void *buf, size_t count) |
| { |
| ssize_t rc; |
| ssize_t num_read = 0; |
| size_t num_left = count; |
| char *ptr = buf; |
| |
| /* Note: Count of zero is allowed (see "If count is zero" portion of |
| * read(2) manpage for details. |
| */ |
| TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count); |
| |
| do { |
| rc = read(fd, ptr, num_left); |
| |
| switch (rc) { |
| case -1: |
| TEST_ASSERT(errno == EAGAIN || errno == EINTR, |
| "Unexpected read failure,\n" |
| " rc: %zi errno: %i", rc, errno); |
| break; |
| |
| case 0: |
| TEST_ASSERT(false, "Unexpected EOF,\n" |
| " rc: %zi num_read: %zi num_left: %zu", |
| rc, num_read, num_left); |
| break; |
| |
| default: |
| TEST_ASSERT(rc > 0, "Unexpected ret from read,\n" |
| " rc: %zi errno: %i", rc, errno); |
| num_read += rc; |
| num_left -= rc; |
| ptr += rc; |
| break; |
| } |
| } while (num_read < count); |
| |
| return num_read; |
| } |