162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * tools/testing/selftests/kvm/lib/io.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2018, Google LLC.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "test_util.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/* Test Write
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * A wrapper for write(2), that automatically handles the following
1362306a36Sopenharmony_ci * special conditions:
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci *   + Interrupted system call (EINTR)
1662306a36Sopenharmony_ci *   + Write of less than requested amount
1762306a36Sopenharmony_ci *   + Non-block return (EAGAIN)
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * For each of the above, an additional write is performed to automatically
2062306a36Sopenharmony_ci * continue writing the requested data.
2162306a36Sopenharmony_ci * There are also many cases where write(2) can return an unexpected
2262306a36Sopenharmony_ci * error (e.g. EIO).  Such errors cause a TEST_ASSERT failure.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Note, for function signature compatibility with write(2), this function
2562306a36Sopenharmony_ci * returns the number of bytes written, but that value will always be equal
2662306a36Sopenharmony_ci * to the number of requested bytes.  All other conditions in this and
2762306a36Sopenharmony_ci * future enhancements to this function either automatically issue another
2862306a36Sopenharmony_ci * write(2) or cause a TEST_ASSERT failure.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * Args:
3162306a36Sopenharmony_ci *  fd    - Opened file descriptor to file to be written.
3262306a36Sopenharmony_ci *  count - Number of bytes to write.
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * Output:
3562306a36Sopenharmony_ci *  buf   - Starting address of data to be written.
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * Return:
3862306a36Sopenharmony_ci *  On success, number of bytes written.
3962306a36Sopenharmony_ci *  On failure, a TEST_ASSERT failure is caused.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_cissize_t test_write(int fd, const void *buf, size_t count)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	ssize_t rc;
4462306a36Sopenharmony_ci	ssize_t num_written = 0;
4562306a36Sopenharmony_ci	size_t num_left = count;
4662306a36Sopenharmony_ci	const char *ptr = buf;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* Note: Count of zero is allowed (see "RETURN VALUE" portion of
4962306a36Sopenharmony_ci	 * write(2) manpage for details.
5062306a36Sopenharmony_ci	 */
5162306a36Sopenharmony_ci	TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	do {
5462306a36Sopenharmony_ci		rc = write(fd, ptr, num_left);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci		switch (rc) {
5762306a36Sopenharmony_ci		case -1:
5862306a36Sopenharmony_ci			TEST_ASSERT(errno == EAGAIN || errno == EINTR,
5962306a36Sopenharmony_ci				    "Unexpected write failure,\n"
6062306a36Sopenharmony_ci				    "  rc: %zi errno: %i", rc, errno);
6162306a36Sopenharmony_ci			continue;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci		case 0:
6462306a36Sopenharmony_ci			TEST_FAIL("Unexpected EOF,\n"
6562306a36Sopenharmony_ci				  "  rc: %zi num_written: %zi num_left: %zu",
6662306a36Sopenharmony_ci				  rc, num_written, num_left);
6762306a36Sopenharmony_ci			break;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci		default:
7062306a36Sopenharmony_ci			TEST_ASSERT(rc >= 0, "Unexpected ret from write,\n"
7162306a36Sopenharmony_ci				"  rc: %zi errno: %i", rc, errno);
7262306a36Sopenharmony_ci			num_written += rc;
7362306a36Sopenharmony_ci			num_left -= rc;
7462306a36Sopenharmony_ci			ptr += rc;
7562306a36Sopenharmony_ci			break;
7662306a36Sopenharmony_ci		}
7762306a36Sopenharmony_ci	} while (num_written < count);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return num_written;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/* Test Read
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci * A wrapper for read(2), that automatically handles the following
8562306a36Sopenharmony_ci * special conditions:
8662306a36Sopenharmony_ci *
8762306a36Sopenharmony_ci *   + Interrupted system call (EINTR)
8862306a36Sopenharmony_ci *   + Read of less than requested amount
8962306a36Sopenharmony_ci *   + Non-block return (EAGAIN)
9062306a36Sopenharmony_ci *
9162306a36Sopenharmony_ci * For each of the above, an additional read is performed to automatically
9262306a36Sopenharmony_ci * continue reading the requested data.
9362306a36Sopenharmony_ci * There are also many cases where read(2) can return an unexpected
9462306a36Sopenharmony_ci * error (e.g. EIO).  Such errors cause a TEST_ASSERT failure.  Note,
9562306a36Sopenharmony_ci * it is expected that the file opened by fd at the current file position
9662306a36Sopenharmony_ci * contains at least the number of requested bytes to be read.  A TEST_ASSERT
9762306a36Sopenharmony_ci * failure is produced if an End-Of-File condition occurs, before all the
9862306a36Sopenharmony_ci * data is read.  It is the callers responsibility to assure that sufficient
9962306a36Sopenharmony_ci * data exists.
10062306a36Sopenharmony_ci *
10162306a36Sopenharmony_ci * Note, for function signature compatibility with read(2), this function
10262306a36Sopenharmony_ci * returns the number of bytes read, but that value will always be equal
10362306a36Sopenharmony_ci * to the number of requested bytes.  All other conditions in this and
10462306a36Sopenharmony_ci * future enhancements to this function either automatically issue another
10562306a36Sopenharmony_ci * read(2) or cause a TEST_ASSERT failure.
10662306a36Sopenharmony_ci *
10762306a36Sopenharmony_ci * Args:
10862306a36Sopenharmony_ci *  fd    - Opened file descriptor to file to be read.
10962306a36Sopenharmony_ci *  count - Number of bytes to read.
11062306a36Sopenharmony_ci *
11162306a36Sopenharmony_ci * Output:
11262306a36Sopenharmony_ci *  buf   - Starting address of where to write the bytes read.
11362306a36Sopenharmony_ci *
11462306a36Sopenharmony_ci * Return:
11562306a36Sopenharmony_ci *  On success, number of bytes read.
11662306a36Sopenharmony_ci *  On failure, a TEST_ASSERT failure is caused.
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_cissize_t test_read(int fd, void *buf, size_t count)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	ssize_t rc;
12162306a36Sopenharmony_ci	ssize_t num_read = 0;
12262306a36Sopenharmony_ci	size_t num_left = count;
12362306a36Sopenharmony_ci	char *ptr = buf;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* Note: Count of zero is allowed (see "If count is zero" portion of
12662306a36Sopenharmony_ci	 * read(2) manpage for details.
12762306a36Sopenharmony_ci	 */
12862306a36Sopenharmony_ci	TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	do {
13162306a36Sopenharmony_ci		rc = read(fd, ptr, num_left);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci		switch (rc) {
13462306a36Sopenharmony_ci		case -1:
13562306a36Sopenharmony_ci			TEST_ASSERT(errno == EAGAIN || errno == EINTR,
13662306a36Sopenharmony_ci				    "Unexpected read failure,\n"
13762306a36Sopenharmony_ci				    "  rc: %zi errno: %i", rc, errno);
13862306a36Sopenharmony_ci			break;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci		case 0:
14162306a36Sopenharmony_ci			TEST_FAIL("Unexpected EOF,\n"
14262306a36Sopenharmony_ci				  "   rc: %zi num_read: %zi num_left: %zu",
14362306a36Sopenharmony_ci				  rc, num_read, num_left);
14462306a36Sopenharmony_ci			break;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci		default:
14762306a36Sopenharmony_ci			TEST_ASSERT(rc > 0, "Unexpected ret from read,\n"
14862306a36Sopenharmony_ci				    "  rc: %zi errno: %i", rc, errno);
14962306a36Sopenharmony_ci			num_read += rc;
15062306a36Sopenharmony_ci			num_left -= rc;
15162306a36Sopenharmony_ci			ptr += rc;
15262306a36Sopenharmony_ci			break;
15362306a36Sopenharmony_ci		}
15462306a36Sopenharmony_ci	} while (num_read < count);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	return num_read;
15762306a36Sopenharmony_ci}
158