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: pwritev01
19 *
20 * Test Description:
21 * Testcase to check the basic functionality of the pwritev(2).
22 * pwritev(2) should succeed to write the expected content of data
23 * and after writing the file, the file offset is not changed.
24 */
25 
26 #include <string.h>
27 #include <sys/uio.h>
28 #include "tst_test.h"
29 #include "pwritev.h"
30 
31 #define	CHUNK		64
32 
33 static char buf[CHUNK];
34 static char initbuf[CHUNK * 2];
35 static char preadbuf[CHUNK];
36 static int fd;
37 
38 static struct iovec wr_iovec[] = {
39 	{buf, CHUNK},
40 	{NULL, 0},
41 };
42 
43 static struct tcase {
44 	int count;
45 	off_t offset;
46 	ssize_t size;
47 } tcases[] = {
48 	{1, 0, CHUNK},
49 	{2, 0, CHUNK},
50 	{1, CHUNK/2, CHUNK},
51 };
52 
verify_pwritev(unsigned int n)53 static void verify_pwritev(unsigned int n)
54 {
55 	int i;
56 	struct tcase *tc = &tcases[n];
57 
58 	SAFE_PWRITE(1, fd, initbuf, sizeof(initbuf), 0);
59 
60 	SAFE_LSEEK(fd, 0, SEEK_SET);
61 
62 	TEST(pwritev(fd, wr_iovec, tc->count, tc->offset));
63 	if (TEST_RETURN < 0) {
64 		tst_res(TFAIL | TTERRNO, "pwritev() failed");
65 		return;
66 	}
67 
68 	if (TEST_RETURN != tc->size) {
69 		tst_res(TFAIL, "pwritev() wrote %li bytes, expected %li",
70 			 TEST_RETURN, tc->size);
71 		return;
72 	}
73 
74 	if (SAFE_LSEEK(fd, 0, SEEK_CUR) != 0) {
75 		tst_res(TFAIL, "pwritev() had changed file offset");
76 		return;
77 	}
78 
79 	SAFE_PREAD(1, fd, preadbuf, tc->size, tc->offset);
80 
81 	for (i = 0; i < tc->size; i++) {
82 		if (preadbuf[i] != 0x61)
83 			break;
84 	}
85 
86 	if (i != tc->size) {
87 		tst_res(TFAIL, "buffer wrong at %i have %02x expected 61",
88 			 i, preadbuf[i]);
89 		return;
90 	}
91 
92 	tst_res(TPASS, "writev() wrote %li bytes successfully "
93 		 "with content 'a' expectedly ", tc->size);
94 }
95 
setup(void)96 static void setup(void)
97 {
98 	memset(&buf, 0x61, CHUNK);
99 
100 	fd = SAFE_OPEN("file", O_RDWR | O_CREAT, 0644);
101 }
102 
cleanup(void)103 static void cleanup(void)
104 {
105 	if (fd > 0 && close(fd))
106 		tst_res(TWARN | TERRNO, "failed to close file");
107 }
108 
109 static struct tst_test test = {
110 	.tid = "pwritev01",
111 	.tcnt = ARRAY_SIZE(tcases),
112 	.setup = setup,
113 	.cleanup = cleanup,
114 	.test = verify_pwritev,
115 	.min_kver = "2.6.30",
116 	.needs_tmpdir = 1,
117 };
118