1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2001
4f08c3bdfSopenharmony_ci * 07/2001 Ported by Wayne Boyer
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci/*\
8f08c3bdfSopenharmony_ci * [Description]
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * Test whether the access mode are the same for both file descriptors.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Create file with mode, dup2, [change mode], check mode
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * - read only, dup2, read only ? "0444"
15f08c3bdfSopenharmony_ci * - write only, dup2, write only ? "0222"
16f08c3bdfSopenharmony_ci * - read/write, dup2 read/write ? "0666"
17f08c3bdfSopenharmony_ci * - read/write/execute, dup2, set read only, read only ? "0444"
18f08c3bdfSopenharmony_ci * - read/write/execute, dup2, set write only, write only ? "0222"
19f08c3bdfSopenharmony_ci * - read/write/execute, dup2, set read/write, read/write ? "0666"
20f08c3bdfSopenharmony_ci */
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci#include <errno.h>
23f08c3bdfSopenharmony_ci#include <stdio.h>
24f08c3bdfSopenharmony_ci#include <unistd.h>
25f08c3bdfSopenharmony_ci#include "tst_test.h"
26f08c3bdfSopenharmony_ci#include "tst_safe_macros.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_cistatic char testfile[40];
29f08c3bdfSopenharmony_cistatic int ofd = -1, nfd = -1;
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_ci/* set these to a known index into our local file descriptor table */
32f08c3bdfSopenharmony_cistatic int duprdo, dupwro, duprdwr;
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_cistatic struct tcase {
35f08c3bdfSopenharmony_ci	int *nfd;
36f08c3bdfSopenharmony_ci	mode_t mode;
37f08c3bdfSopenharmony_ci	/* 0 - set mode before dup2, 1 - change mode after dup2 */
38f08c3bdfSopenharmony_ci	int flag;
39f08c3bdfSopenharmony_ci} tcases[] = {
40f08c3bdfSopenharmony_ci	{&duprdo, 0444, 0},
41f08c3bdfSopenharmony_ci	{&dupwro, 0222, 0},
42f08c3bdfSopenharmony_ci	{&duprdwr, 0666, 0},
43f08c3bdfSopenharmony_ci	{&duprdo, 0444, 1},
44f08c3bdfSopenharmony_ci	{&dupwro, 0222, 1},
45f08c3bdfSopenharmony_ci	{&duprdwr, 0666, 1},
46f08c3bdfSopenharmony_ci};
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_cistatic void setup(void)
49f08c3bdfSopenharmony_ci{
50f08c3bdfSopenharmony_ci	int nextfd;
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci	umask(0);
53f08c3bdfSopenharmony_ci	sprintf(testfile, "dup202.%d", getpid());
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci	/* Pick up fds that are known not to collide with creat */
56f08c3bdfSopenharmony_ci	nextfd = SAFE_CREAT(testfile, 0777);
57f08c3bdfSopenharmony_ci	duprdo = SAFE_DUP(nextfd);
58f08c3bdfSopenharmony_ci	dupwro = SAFE_DUP(nextfd);
59f08c3bdfSopenharmony_ci	duprdwr = SAFE_DUP(nextfd);
60f08c3bdfSopenharmony_ci	/* SAFE_CLOSE will set fd to -1 */
61f08c3bdfSopenharmony_ci	close(duprdwr);
62f08c3bdfSopenharmony_ci	close(dupwro);
63f08c3bdfSopenharmony_ci	close(duprdo);
64f08c3bdfSopenharmony_ci	SAFE_CLOSE(nextfd);
65f08c3bdfSopenharmony_ci	SAFE_UNLINK(testfile);
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_ci}
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_cistatic void cleanup(void)
70f08c3bdfSopenharmony_ci{
71f08c3bdfSopenharmony_ci	close(ofd);
72f08c3bdfSopenharmony_ci	close(nfd);
73f08c3bdfSopenharmony_ci}
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_cistatic void run(unsigned int i)
76f08c3bdfSopenharmony_ci{
77f08c3bdfSopenharmony_ci	struct stat oldbuf, newbuf;
78f08c3bdfSopenharmony_ci	struct tcase *tc = tcases + i;
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	if (tc->flag)
81f08c3bdfSopenharmony_ci		ofd = SAFE_CREAT(testfile, 0777);
82f08c3bdfSopenharmony_ci	else
83f08c3bdfSopenharmony_ci		ofd = SAFE_CREAT(testfile, tc->mode);
84f08c3bdfSopenharmony_ci	nfd = *tc->nfd;
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci	TEST(dup2(ofd, nfd));
87f08c3bdfSopenharmony_ci	if (TST_RET == -1) {
88f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO, "call failed unexpectedly");
89f08c3bdfSopenharmony_ci		goto free;
90f08c3bdfSopenharmony_ci	}
91f08c3bdfSopenharmony_ci	if (tc->flag) {
92f08c3bdfSopenharmony_ci		SAFE_CHMOD(testfile, tc->mode);
93f08c3bdfSopenharmony_ci		tst_res(TINFO, "original mode 0777, new mode 0%o after chmod", tc->mode);
94f08c3bdfSopenharmony_ci	}
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	SAFE_FSTAT(ofd, &oldbuf);
97f08c3bdfSopenharmony_ci
98f08c3bdfSopenharmony_ci	SAFE_FSTAT(nfd, &newbuf);
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_ci	if (oldbuf.st_mode != newbuf.st_mode)
101f08c3bdfSopenharmony_ci		tst_res(TFAIL, "original(%o) and duped(%o) are not same mode",
102f08c3bdfSopenharmony_ci			oldbuf.st_mode, newbuf.st_mode);
103f08c3bdfSopenharmony_ci	else
104f08c3bdfSopenharmony_ci		tst_res(TPASS, "original(%o) and duped(%o) are the same mode",
105f08c3bdfSopenharmony_ci			oldbuf.st_mode, newbuf.st_mode);
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	SAFE_CLOSE(nfd);
108f08c3bdfSopenharmony_cifree:
109f08c3bdfSopenharmony_ci	SAFE_CLOSE(ofd);
110f08c3bdfSopenharmony_ci	SAFE_UNLINK(testfile);
111f08c3bdfSopenharmony_ci}
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_cistatic struct tst_test test = {
114f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
115f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
116f08c3bdfSopenharmony_ci	.test = run,
117f08c3bdfSopenharmony_ci	.setup = setup,
118f08c3bdfSopenharmony_ci	.cleanup = cleanup,
119f08c3bdfSopenharmony_ci};
120