#ifndef __API_IO__
 #define __API_IO__
 
+#include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 struct io {
        }
 }
 
+/* Read up to and including the first newline following the pattern of getline. */
+static inline ssize_t io__getline(struct io *io, char **line_out, size_t *line_len_out)
+{
+       char buf[128];
+       int buf_pos = 0;
+       char *line = NULL, *temp;
+       size_t line_len = 0;
+       int ch = 0;
+
+       /* TODO: reuse previously allocated memory. */
+       free(*line_out);
+       while (ch != '\n') {
+               ch = io__get_char(io);
+
+               if (ch < 0)
+                       break;
+
+               if (buf_pos == sizeof(buf)) {
+                       temp = realloc(line, line_len + sizeof(buf));
+                       if (!temp)
+                               goto err_out;
+                       line = temp;
+                       memcpy(&line[line_len], buf, sizeof(buf));
+                       line_len += sizeof(buf);
+                       buf_pos = 0;
+               }
+               buf[buf_pos++] = (char)ch;
+       }
+       temp = realloc(line, line_len + buf_pos + 1);
+       if (!temp)
+               goto err_out;
+       line = temp;
+       memcpy(&line[line_len], buf, buf_pos);
+       line[line_len + buf_pos] = '\0';
+       line_len += buf_pos;
+       *line_out = line;
+       *line_len_out = line_len;
+       return line_len;
+err_out:
+       free(line);
+       return -ENOMEM;
+}
+
 #endif /* __API_IO__ */
 
        return ret;
 }
 
+static int test_get_line(void)
+{
+       char path[PATH_MAX];
+       struct io io;
+       char test_string[1024];
+       char *line = NULL;
+       size_t i, line_len = 0;
+       size_t buf_size = 128;
+       int ret = 0;
+
+       for (i = 0; i < 512; i++)
+               test_string[i] = 'a';
+       test_string[512] = '\n';
+       for (i = 513; i < 1023; i++)
+               test_string[i] = 'b';
+       test_string[1023] = '\0';
+
+       if (setup_test(path, test_string, buf_size, &io))
+               return -1;
+
+       EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 513);
+       EXPECT_EQUAL((int)strlen(line), 513);
+       for (i = 0; i < 512; i++)
+               EXPECT_EQUAL(line[i], 'a');
+       EXPECT_EQUAL(line[512], '\n');
+       EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 510);
+       for (i = 0; i < 510; i++)
+               EXPECT_EQUAL(line[i], 'b');
+
+       free(line);
+       cleanup_test(path, &io);
+       return ret;
+}
+
 static int test__api_io(struct test_suite *test __maybe_unused,
                        int subtest __maybe_unused)
 {
                ret = TEST_FAIL;
        if (test_get_dec())
                ret = TEST_FAIL;
+       if (test_get_line())
+               ret = TEST_FAIL;
        return ret;
 }