1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2014 Fujitsu Ltd.
4f08c3bdfSopenharmony_ci * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * DESCRIPTION
7f08c3bdfSopenharmony_ci *  Verify that,
8f08c3bdfSopenharmony_ci *   1. fd is not a valid file descriptor, EBADF would return.
9f08c3bdfSopenharmony_ci *   2. curr_value is not valid a pointer, EFAULT would return.
10f08c3bdfSopenharmony_ci *   3. fd is not a valid timerfd file descriptor, EINVAL would return.
11f08c3bdfSopenharmony_ci */
12f08c3bdfSopenharmony_ci
13f08c3bdfSopenharmony_ci#define _GNU_SOURCE
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ci#include "time64_variants.h"
16f08c3bdfSopenharmony_ci#include "tst_timer.h"
17f08c3bdfSopenharmony_ci#include "tst_safe_timerfd.h"
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_cichar *TCID = "timerfd_gettime01";
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_cistatic int bad_clockfd = -1;
22f08c3bdfSopenharmony_cistatic int clockfd;
23f08c3bdfSopenharmony_cistatic int fd;
24f08c3bdfSopenharmony_cistatic void *bad_addr;
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_cistatic struct test_case_t {
27f08c3bdfSopenharmony_ci	int *fd;
28f08c3bdfSopenharmony_ci	struct tst_its *curr_value;
29f08c3bdfSopenharmony_ci	int exp_errno;
30f08c3bdfSopenharmony_ci} test_cases[] = {
31f08c3bdfSopenharmony_ci	{&bad_clockfd, NULL, EBADF},
32f08c3bdfSopenharmony_ci	{&clockfd, NULL, EFAULT},
33f08c3bdfSopenharmony_ci	{&fd, NULL, EINVAL},
34f08c3bdfSopenharmony_ci};
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_cistatic struct time64_variants variants[] = {
37f08c3bdfSopenharmony_ci#if (__NR_timerfd_gettime != __LTP__NR_INVALID_SYSCALL)
38f08c3bdfSopenharmony_ci	{ .tfd_gettime = sys_timerfd_gettime, .desc = "syscall with old kernel spec"},
39f08c3bdfSopenharmony_ci#endif
40f08c3bdfSopenharmony_ci
41f08c3bdfSopenharmony_ci#if (__NR_timerfd_gettime64 != __LTP__NR_INVALID_SYSCALL)
42f08c3bdfSopenharmony_ci	{ .tfd_gettime = sys_timerfd_gettime64, .desc = "syscall time64 with kernel spec"},
43f08c3bdfSopenharmony_ci#endif
44f08c3bdfSopenharmony_ci};
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cistatic void setup(void)
47f08c3bdfSopenharmony_ci{
48f08c3bdfSopenharmony_ci	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
49f08c3bdfSopenharmony_ci	bad_addr = tst_get_bad_addr(NULL);
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_ci	clockfd = timerfd_create(CLOCK_REALTIME, 0);
52f08c3bdfSopenharmony_ci	if (clockfd == -1) {
53f08c3bdfSopenharmony_ci		tst_brk(TFAIL | TERRNO, "timerfd_create() fail");
54f08c3bdfSopenharmony_ci		return;
55f08c3bdfSopenharmony_ci	}
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	fd = SAFE_OPEN("test_file", O_RDWR | O_CREAT, 0644);
58f08c3bdfSopenharmony_ci}
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_cistatic void cleanup(void)
61f08c3bdfSopenharmony_ci{
62f08c3bdfSopenharmony_ci	if (clockfd > 0)
63f08c3bdfSopenharmony_ci		close(clockfd);
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci	if (fd > 0)
66f08c3bdfSopenharmony_ci		close(fd);
67f08c3bdfSopenharmony_ci}
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_cistatic void run(unsigned int n)
70f08c3bdfSopenharmony_ci{
71f08c3bdfSopenharmony_ci	struct time64_variants *tv = &variants[tst_variant];
72f08c3bdfSopenharmony_ci	struct test_case_t *test = &test_cases[n];
73f08c3bdfSopenharmony_ci	void *its;
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci	if (test->exp_errno == EFAULT)
76f08c3bdfSopenharmony_ci		its = bad_addr;
77f08c3bdfSopenharmony_ci	else
78f08c3bdfSopenharmony_ci		its = tst_its_get(test->curr_value);
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	TEST(tv->tfd_gettime(*test->fd, its));
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci	if (TST_RET != -1) {
83f08c3bdfSopenharmony_ci		tst_res(TFAIL, "timerfd_gettime() succeeded unexpectedly");
84f08c3bdfSopenharmony_ci		return;
85f08c3bdfSopenharmony_ci	}
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci	if (TST_ERR == test->exp_errno) {
88f08c3bdfSopenharmony_ci		tst_res(TPASS | TTERRNO,
89f08c3bdfSopenharmony_ci			"timerfd_gettime() failed as expected");
90f08c3bdfSopenharmony_ci	} else {
91f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO,
92f08c3bdfSopenharmony_ci			"timerfd_gettime() failed unexpectedly; expected: "
93f08c3bdfSopenharmony_ci			"%d - %s", test->exp_errno, strerror(test->exp_errno));
94f08c3bdfSopenharmony_ci	}
95f08c3bdfSopenharmony_ci}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_cistatic struct tst_test test = {
98f08c3bdfSopenharmony_ci	.test = run,
99f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(test_cases),
100f08c3bdfSopenharmony_ci	.test_variants = ARRAY_SIZE(variants),
101f08c3bdfSopenharmony_ci	.setup = setup,
102f08c3bdfSopenharmony_ci	.cleanup = cleanup,
103f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
104f08c3bdfSopenharmony_ci};
105