1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) International Business Machines Corp., 2001
4 * Ported to LTP: Wayne Boyer
5 */
6
7/*
8 * Test Description :
9 *   Testcase to check the basic functionality of the readlink(2),
10 *   readlink() will succeed to read the contents of the symbolic link.
11 */
12
13#include <pwd.h>
14#include <errno.h>
15#include <string.h>
16
17#include "tst_test.h"
18
19#define TESTFILE "test_file"
20#define SYMFILE	"slink_file"
21
22static uid_t nobody_uid;
23
24static void test_readlink(void)
25{
26	char buffer[256];
27	int exp_val = strlen(TESTFILE);
28
29	TEST(readlink(SYMFILE, buffer, sizeof(buffer)));
30	if (TST_RET == -1) {
31		tst_res(TFAIL | TTERRNO, "readlink() on %s failed", SYMFILE);
32		return;
33	}
34
35	if (TST_RET != exp_val) {
36		tst_res(TFAIL, "readlink() returned value %ld "
37			"did't match, Expected %d", TST_RET, exp_val);
38		return;
39	}
40
41	if (memcmp(buffer, TESTFILE, exp_val) != 0) {
42		tst_res(TFAIL, "Pathname %s and buffer contents %s differ",
43			TESTFILE, buffer);
44	} else {
45		tst_res(TPASS, "readlink() functionality on '%s' was correct",
46			SYMFILE);
47	}
48}
49
50static void verify_readlink(unsigned int n)
51{
52	pid_t pid;
53
54	if (n) {
55		tst_res(TINFO, "Running test as nobody");
56		pid = SAFE_FORK();
57
58		if (!pid) {
59			SAFE_SETUID(nobody_uid);
60			test_readlink();
61			return;
62		}
63	} else {
64		tst_res(TINFO, "Running test as root");
65		test_readlink();
66	}
67}
68
69static void setup(void)
70{
71	int fd;
72	struct passwd *pw;
73
74	pw = SAFE_GETPWNAM("nobody");
75
76	nobody_uid = pw->pw_uid;
77
78	fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, 0444);
79	SAFE_CLOSE(fd);
80	SAFE_SYMLINK(TESTFILE, SYMFILE);
81}
82
83static struct tst_test test = {
84	.test = verify_readlink,\
85	.tcnt = 2,
86	.setup = setup,
87	.forks_child = 1,
88	.needs_root = 1,
89	.needs_tmpdir = 1,
90};
91