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
34 static int fd;
35 static char buf[CHUNK];
36
37 static struct iovec rd_iovec[] = {
38 {buf, CHUNK},
39 {NULL, 0},
40 };
41
42 static 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
verify_preadv(unsigned int n)53 void 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
setup(void)96 void 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
cleanup(void)109 void cleanup(void)
110 {
111 if (fd > 0 && close(fd))
112 tst_res(TWARN | TERRNO, "Failed to close file");
113 }
114
115 static 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