• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com>
4  * Copyright (c) Linux Test Project, 2015-2024
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Verify that
11  *
12  * 1. kcmp() returns 0 with two process and two file descriptors refering to the
13  * same open file
14  * 2. kcmp() doesn't return 0 with two process and two file descriptors not
15  * refering to the same open file
16  */
17 
18 #define _GNU_SOURCE
19 
20 #include "tst_test.h"
21 #include "lapi/fcntl.h"
22 #include "lapi/kcmp.h"
23 
24 #define TEST_FILE "test_file"
25 #define TEST_FILE2 "test_file2"
26 
27 static int fd1;
28 static int fd2;
29 static int fd3;
30 static int pid1;
31 static int pid2;
32 
33 static struct test_case {
34 	int *pid1;
35 	int *pid2;
36 	int type;
37 	int *fd1;
38 	int *fd2;
39 	int exp_different;
40 } test_cases[] = {
41 	{&pid1, &pid1, KCMP_FILE, &fd1, &fd1, 0},
42 	{&pid2, &pid2, KCMP_FILE, &fd1, &fd2, 0},
43 	{&pid1, &pid2, KCMP_FILE, &fd1, &fd1, 0},
44 	{&pid1, &pid2, KCMP_FILE, &fd1, &fd2, 0},
45 	{&pid1, &pid2, KCMP_FILE, &fd1, &fd3, 1},
46 };
47 
setup(void)48 static void setup(void)
49 {
50 	fd1 = SAFE_OPEN(TEST_FILE, O_CREAT | O_RDWR | O_TRUNC, 0666);
51 }
52 
cleanup(void)53 static void cleanup(void)
54 {
55 	if (fd1 > 0)
56 		SAFE_CLOSE(fd1);
57 }
58 
do_child(const struct test_case * test)59 static void do_child(const struct test_case *test)
60 {
61 	pid2 = getpid();
62 
63 	fd3 = SAFE_OPEN(TEST_FILE2, O_CREAT | O_RDWR, 0666);
64 
65 	fd2 = dup(fd1);
66 	if (fd2 == -1) {
67 		tst_res(TFAIL | TERRNO, "dup() failed unexpectedly");
68 		SAFE_CLOSE(fd3);
69 		return;
70 	}
71 
72 	TEST(kcmp(*(test->pid1), *(test->pid2), test->type,
73 		  *(test->fd1), *(test->fd2)));
74 
75 	SAFE_CLOSE(fd2);
76 	SAFE_CLOSE(fd3);
77 
78 	if (TST_RET == -1) {
79 		tst_res(TFAIL | TTERRNO, "kcmp() failed unexpectedly");
80 		return;
81 	}
82 
83 	if ((test->exp_different && TST_RET == 0)
84 		|| (test->exp_different == 0 && TST_RET)) {
85 		tst_res(TFAIL, "kcmp() returned %lu instead of %d",
86 			TST_RET, test->exp_different);
87 		return;
88 	}
89 
90 	tst_res(TPASS, "kcmp() returned the expected value");
91 }
92 
verify_kcmp(unsigned int n)93 static void verify_kcmp(unsigned int n)
94 {
95 	struct test_case *tc = &test_cases[n];
96 
97 	pid1 = getpid();
98 
99 	pid2 = SAFE_FORK();
100 	if (!pid2)
101 		do_child(tc);
102 }
103 
104 static struct tst_test test = {
105 	.tcnt = ARRAY_SIZE(test_cases),
106 	.setup = setup,
107 	.cleanup = cleanup,
108 	.forks_child = 1,
109 	.test = verify_kcmp,
110 	.needs_tmpdir = 1,
111 };
112