summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/kvm/lib/io.c
blob: cff869ffe6eefb513565af95d4b18d4f56e4dc5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * tools/testing/selftests/kvm/lib/io.c
 *
 * Copyright (C) 2018, Google LLC.
 *
 * This work is licensed under the terms of the GNU GPL, version 2.
 */

#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;
}