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
33static char buf[CHUNK];
34static char initbuf[CHUNK * 2];
35static char preadbuf[CHUNK];
36static int fd;
37
38static struct iovec wr_iovec[] = {
39	{buf, CHUNK},
40	{NULL, 0},
41};
42
43static 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
53static 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
96static void setup(void)
97{
98	memset(&buf, 0x61, CHUNK);
99
100	fd = SAFE_OPEN("file", O_RDWR | O_CREAT, 0644);
101}
102
103static void cleanup(void)
104{
105	if (fd > 0 && close(fd))
106		tst_res(TWARN | TERRNO, "failed to close file");
107}
108
109static 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