1/*
2* Copyright (c) 2015 Fujitsu Ltd.
3* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
4*
5* This program is free software; you can redistribute it and/or modify it
6* under the terms of version 2 of the GNU General Public License as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it would be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12*
13* You should have received a copy of the GNU General Public License
14* alone with this program.
15*/
16
17/*
18* Test Name: preadv01
19*
20* Test Description:
21* Testcase to check the basic functionality of the preadv(2).
22* Preadv(2) should succeed to read the expected content of data
23* and after reading the file, the file offset is not changed.
24*/
25
26#include <string.h>
27#include <sys/uio.h>
28
29#include "tst_test.h"
30#include "preadv.h"
31
32#define CHUNK           64
33
34static int fd;
35static char buf[CHUNK];
36
37static struct iovec rd_iovec[] = {
38	{buf, CHUNK},
39	{NULL, 0},
40};
41
42static struct tcase {
43	int count;
44	off_t offset;
45	ssize_t size;
46	char content;
47} tcases[] = {
48	{1, 0, CHUNK, 'a'},
49	{2, 0, CHUNK, 'a'},
50	{1, CHUNK*3/2, CHUNK/2, 'b'}
51};
52
53void verify_preadv(unsigned int n)
54{
55	int i;
56	char *vec;
57	struct tcase *tc = &tcases[n];
58
59	vec = rd_iovec[0].iov_base;
60	memset(vec, 0x00, CHUNK);
61
62	SAFE_LSEEK(fd, 0, SEEK_SET);
63
64	TEST(preadv(fd, rd_iovec, tc->count, tc->offset));
65	if (TEST_RETURN < 0) {
66		tst_res(TFAIL | TTERRNO, "Preadv(2) failed");
67		return;
68	}
69
70	if (TEST_RETURN != tc->size) {
71		tst_res(TFAIL, "Preadv(2) read %li bytes, expected %li",
72			 TEST_RETURN, tc->size);
73		return;
74	}
75
76	for (i = 0; i < tc->size; i++) {
77		if (vec[i] != tc->content)
78			break;
79	}
80
81	if (i < tc->size) {
82		tst_res(TFAIL, "Buffer wrong at %i have %02x expected %02x",
83			 i, vec[i], tc->content);
84		return;
85	}
86
87	if (SAFE_LSEEK(fd, 0, SEEK_CUR) != 0) {
88		tst_res(TFAIL, "Preadv(2) has changed file offset");
89		return;
90	}
91
92	tst_res(TPASS, "Preadv(2) read %li bytes successfully "
93		 "with content '%c' expectedly", tc->size, tc->content);
94}
95
96void setup(void)
97{
98	char buf[CHUNK];
99
100	fd = SAFE_OPEN("file", O_RDWR | O_CREAT, 0644);
101
102	memset(buf, 'a', sizeof(buf));
103	SAFE_WRITE(1, fd, buf, sizeof(buf));
104
105	memset(buf, 'b', sizeof(buf));
106	SAFE_WRITE(1, fd, buf, sizeof(buf));
107}
108
109void cleanup(void)
110{
111	if (fd > 0 && close(fd))
112		tst_res(TWARN | TERRNO, "Failed to close file");
113}
114
115static struct tst_test test = {
116	.tid = "preadv01",
117	.tcnt = ARRAY_SIZE(tcases),
118	.setup = setup,
119	.cleanup = cleanup,
120	.test = verify_preadv,
121	.min_kver = "2.6.30",
122	.needs_tmpdir = 1,
123};
124