1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
4f08c3bdfSopenharmony_ci * Author: Jinhui Huang <huangjh.jy@cn.fujitsu.com>
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci/*
7f08c3bdfSopenharmony_ci * Description:
8f08c3bdfSopenharmony_ci * Testcase to check the basic functionality of the pwritev2(2).
9f08c3bdfSopenharmony_ci * 1) If the file offset argument is not -1, pwritev2() should succeed
10f08c3bdfSopenharmony_ci *    in writing the expected content of data and the file offset is
11f08c3bdfSopenharmony_ci *    not changed after writing.
12f08c3bdfSopenharmony_ci * 2) If the file offset argument is -1, pwritev2() should succeed in
13f08c3bdfSopenharmony_ci *    writing the expected content of data and the current file offset
14f08c3bdfSopenharmony_ci *    is used and changed after writing.
15f08c3bdfSopenharmony_ci */
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#define _GNU_SOURCE
18f08c3bdfSopenharmony_ci#include <string.h>
19f08c3bdfSopenharmony_ci#include <sys/uio.h>
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci#include "tst_test.h"
22f08c3bdfSopenharmony_ci#include "lapi/pwritev2.h"
23f08c3bdfSopenharmony_ci#include "tst_safe_prw.h"
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci#define CHUNK	64
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_cistatic int fd;
28f08c3bdfSopenharmony_cistatic char initbuf[CHUNK * 2];
29f08c3bdfSopenharmony_cistatic char buf[CHUNK];
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_cistatic struct iovec wr_iovec[] = {
32f08c3bdfSopenharmony_ci	{buf, CHUNK},
33f08c3bdfSopenharmony_ci	{NULL, 0},
34f08c3bdfSopenharmony_ci};
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_cistatic struct tcase {
37f08c3bdfSopenharmony_ci	off_t seek_off;
38f08c3bdfSopenharmony_ci	int count;
39f08c3bdfSopenharmony_ci	off_t write_off;
40f08c3bdfSopenharmony_ci	ssize_t size;
41f08c3bdfSopenharmony_ci	off_t exp_off;
42f08c3bdfSopenharmony_ci} tcases[] = {
43f08c3bdfSopenharmony_ci	{0,     1, 0,          CHUNK, 0},
44f08c3bdfSopenharmony_ci	{CHUNK, 2, 0,          CHUNK, CHUNK},
45f08c3bdfSopenharmony_ci	{0,     1, CHUNK / 2,  CHUNK, 0},
46f08c3bdfSopenharmony_ci	{0,     1, -1,         CHUNK, CHUNK},
47f08c3bdfSopenharmony_ci	{0,     2, -1,         CHUNK, CHUNK},
48f08c3bdfSopenharmony_ci	{CHUNK, 1, -1,         CHUNK, CHUNK * 2},
49f08c3bdfSopenharmony_ci};
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_cistatic void verify_pwritev2(unsigned int n)
52f08c3bdfSopenharmony_ci{
53f08c3bdfSopenharmony_ci	int i;
54f08c3bdfSopenharmony_ci	char preadbuf[CHUNK];
55f08c3bdfSopenharmony_ci	struct tcase *tc = &tcases[n];
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	SAFE_PWRITE(1, fd, initbuf, sizeof(initbuf), 0);
58f08c3bdfSopenharmony_ci	SAFE_LSEEK(fd, tc->seek_off, SEEK_SET);
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci	TEST(pwritev2(fd, wr_iovec, tc->count, tc->write_off, 0));
61f08c3bdfSopenharmony_ci	if (TST_RET < 0) {
62f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO, "pwritev2() failed");
63f08c3bdfSopenharmony_ci		return;
64f08c3bdfSopenharmony_ci	}
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci	if (TST_RET != tc->size) {
67f08c3bdfSopenharmony_ci		tst_res(TFAIL, "pwritev2() wrote %li bytes, expected %zi",
68f08c3bdfSopenharmony_ci			 TST_RET, tc->size);
69f08c3bdfSopenharmony_ci		return;
70f08c3bdfSopenharmony_ci	}
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ci	if (SAFE_LSEEK(fd, 0, SEEK_CUR) != tc->exp_off) {
73f08c3bdfSopenharmony_ci		tst_res(TFAIL, "pwritev2() had changed file offset");
74f08c3bdfSopenharmony_ci		return;
75f08c3bdfSopenharmony_ci	}
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci	memset(preadbuf, 0, CHUNK);
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	if (tc->write_off != -1)
80f08c3bdfSopenharmony_ci		SAFE_PREAD(1, fd, preadbuf, tc->size, tc->write_off);
81f08c3bdfSopenharmony_ci	else
82f08c3bdfSopenharmony_ci		SAFE_PREAD(1, fd, preadbuf, tc->size, tc->seek_off);
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	for (i = 0; i < tc->size; i++) {
85f08c3bdfSopenharmony_ci		if (preadbuf[i] != 0x61)
86f08c3bdfSopenharmony_ci			break;
87f08c3bdfSopenharmony_ci	}
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	if (i != tc->size) {
90f08c3bdfSopenharmony_ci		tst_res(TFAIL, "buffer wrong at %i have %c expected 'a'",
91f08c3bdfSopenharmony_ci			 i, preadbuf[i]);
92f08c3bdfSopenharmony_ci		return;
93f08c3bdfSopenharmony_ci	}
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_ci	tst_res(TPASS, "pwritev2() wrote %zi bytes successfully "
96f08c3bdfSopenharmony_ci		 "with content 'a' expectedly ", tc->size);
97f08c3bdfSopenharmony_ci}
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_cistatic void setup(void)
100f08c3bdfSopenharmony_ci{
101f08c3bdfSopenharmony_ci	memset(buf, 0x61, CHUNK);
102f08c3bdfSopenharmony_ci	memset(initbuf, 0, CHUNK * 2);
103f08c3bdfSopenharmony_ci
104f08c3bdfSopenharmony_ci	fd = SAFE_OPEN("file", O_RDWR | O_CREAT, 0644);
105f08c3bdfSopenharmony_ci}
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_cistatic void cleanup(void)
108f08c3bdfSopenharmony_ci{
109f08c3bdfSopenharmony_ci	if (fd > 0)
110f08c3bdfSopenharmony_ci		SAFE_CLOSE(fd);
111f08c3bdfSopenharmony_ci}
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_cistatic struct tst_test test = {
114f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
115f08c3bdfSopenharmony_ci	.setup = setup,
116f08c3bdfSopenharmony_ci	.cleanup = cleanup,
117f08c3bdfSopenharmony_ci	.test = verify_pwritev2,
118f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
119f08c3bdfSopenharmony_ci};
120